UART SPI I2C PIC16F876A MPLAB XC8 working library

Thread Starter

g-C0d3

Joined May 4, 2019
6
This is my first post here, and I am eager to jump in. Unfortunately, my first post isn't to help, but to gain assistance. Therefore, I owe one to the universe.

I'm working with a pretty old chip right now, PIC16F876A. It's the only thing I have around until I can get some money to buy a new chip. I'm eyeing the enhanced mid range PIC16F1719. In the meantime, since I started on this journey I would like to solve some problems I have with the PIC16F876A. Is there a place in this forum where I can get access to some working code along with schematics related to that code? My current interest is communication. Working example of:

** the more comments in the code, the better for me.
  • USART or UART
  • SPI
  • I2C

So that I don't have to convert to much, because I am surely capable of making several errors (on my own - lol), I'll share with you the IDE and compiler I am using. I'm programing in C using MPLAB X IDE v5.15 (XC8-CC v2.05 @ C Standard C 90). I'm running several different projects from this one chip, so learning these communication systems and getting a working library is crucial.

I saw a post from Picbuster from 2017 and was going to ask him directly but unfortunately that conversation is too old. I don't see anywhere on this forum where you can DM a member. Here is the link and what I wanted to ask him directly, since he had the SPI component portion of my query already worked out...
https://forum.allaboutcircuits.com/threads/software-i2c-using-xc8-mplab-x.138847/
Difficult to identify problem.
This was written for old xc8 compiler changes did take place especially in the usart and eusart libs.
If you are using above 1.34 you could face that problem.
I will dive into my own libs and try to find a working program for the pic16.
SPI I do have for Pic16 that's for sure but uncertain about I2c.
Picbuster
I am currently working on SPI communication with an older chip, PIC16F876A. If you don't mind sharing your SPI library, for the PIC16, that would be great.

If you've ever found that I2C, that would be a bonus.

I have been working on both for the past weeks, trying to do something simple. Like get a text to speech module to talk; and I've only managed to lose hair and sleep (to say the least). I assure you, I am not just bumming code, I have put in substantial work and research and I'm coming up with ZERO success, any help would be appreciated. Thanks in advance.

Any help would be highly appreciated. Thanks in advance.
 

Ian Rogers

Joined Dec 12, 2012
663
The libraries shipped with XC8 work fine... You may need to change the headers for the individual chip... I have used USART SPI and I2C on this and many other pic's with no issue at all..
 

Thread Starter

g-C0d3

Joined May 4, 2019
6
The libraries shipped with XC8 work fine... You may need to change the headers for the individual chip... I have used USART SPI and I2C on this and many other pic's with no issue at all..
I'm new to MPLAB IDE and the compiler. I'm an old school programmer. I've written code for SPI and UART and been testing it over the last weeks to no avail. Trust me, if I didn't need the help - I probably wouldn't ask for it.

I haven't probed around with the built in library to spit out some code for me, because I'm using the basics of the IDE.
If you don't mind setting it up quickly for me for I2C, I'd love to see it.

My current UART and SPI make-shift codes are borrows from what I read on the internet and many hours of studying. I'm not sure if they are working perfectly so I wanted something to compare it to; from someone who knows what they are doing. As I feel I am poking around in the dark.

If you could provide a working I2C with schematic, that would be much appreciated. If you could add SPI and UART, that would be awesome. Thank you for your time and sharing.
 

Ian Rogers

Joined Dec 12, 2012
663
SPI is extremely easy... Usart requires a bit more thought but I2C has a lot of low level stuff to be written.

Why don't you post your code and I'll tell you if it works and / or tell you how to fix it!.. I'll even explain it... I need you to show me what you've got so I can see where you are... Me just doing it seems pointless and you can get working code from the web

USART
https://circuitdigest.com/microcontroller-projects/uart-communication-using-pic16f877a/
SPI
https://www.teachmemicro.com/pic16-spi/

I'll let you find the I2C...
 

Thread Starter

g-C0d3

Joined May 4, 2019
6
SPI is extremely easy... Usart requires a bit more thought but I2C has a lot of low level stuff to be written.

Why don't you post your code and I'll tell you if it works and / or tell you how to fix it!.. I'll even explain it... I need you to show me what you've got so I can see where you are... Me just doing it seems pointless and you can get working code from the web

USART
https://circuitdigest.com/microcontroller-projects/uart-communication-using-pic16f877a/
SPI
https://www.teachmemicro.com/pic16-spi/

I'll let you find the I2C...
Fair enough. I agree, posting my code might prove to be a straight line.

I've read that UART is the easiest, and I went into it thinking so; as well. When I hit that brick wall I had to disagree. I guess it is all remotely subjective, nonetheless.

I have read these two pages and have these working, but when I try to interface the workings with something else. It goes bonkers.

The forum rules say there is a certain way to post the code, so give me a moment and let me figure that out.

Thanks again for the offer...

** Edit **
P.S.
I forgot to mention, I don' t have any code to post for the I2C version. I'm on another website reading about it now. If I get it working then I'll only post the SPI and UART versions.
 

jpanhalt

Joined Jan 18, 2008
7,925
Post code like this: [code=c]<your code>[/code] The "=c" can be replaced with =text, =ASM, =MPASM, and maybe some others.

On PIC's, hardware SPI and UART are both simple and not worth worrying about which is more so.
 

Thread Starter

g-C0d3

Joined May 4, 2019
6
Post code like this: [code=c]<your code>[/code] The "=c" can be replaced with =text, =ASM, =MPASM, and maybe some others.

On PIC's, hardware SPI and UART are both simple and not worth worrying about which is more so.
Thanks jpanhalt...

Since, I've got the bread-board for the UART under aim, let's start there. I also included the schematic.

The virtual machine is in the schematic because I don't have the virtual part for the SP03.

I can get all this working flawlessly in picbasic, but for some reason my c-code isn't agreeing with me.

If you see any errors, please let me know straight away. Thanks in advance for all your support.

** Edit:
Forgot to add, the LCD routine is removed for space.
  • When sending to UART, I think it is sending in ascii, not HEX. So I switched to command 128 instead of 0x80.
  • When trying to read the return value from the UART TX line, I'm only getting 0x0 on the LCD 16x2. Not sure why??
So, I'm concluding that nothing is being sent properly.....???

C:
/*
* Program: Header file to
* Compiler: XC8 (v2.05, MPLAX X v5.15)
* Description:
* Interface PIC16F876A with SP03 with UART (USART Basic Communication) via MAX232
* IO Pins Defines (Mappings): see schematic
*/

// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
// End of configuration

#include <xc.h>
#include <stdint.h>

#define _XTAL_FREQ 20e6
#define Baud_rate 9600

// Functions Declarations
// transmit
void UART_TX_Init(void);
void UART_Write(uint8_t txData);
void speak(char *msg);
// receive
void UART_RX_Init(void);
uint8_t UART_Read(void);
void UART_Read_String(uint8_t *Output, uint16_t length);
void interrupt ISR (void);

uint16_t i;
uint8_t L;

//--------------------------------
// Main Routine
void main(void)
{
//--[ Peripherals & IO Configurations ]--
UART_TX_Init(); // Initialize The UART in Master Mode @ 9600bps

//---------------------------
while(1)
{
UART_Write(128); // 0x80
UART_Read(); // return 0x01
UART_Write(0); // 0x00
UART_Read(); // return 0x00
UART_Write(4); // 0x04
UART_Read(); // return 0x04
UART_Write(2);
UART_Read(); // return 0x02
speak("hello");
}
return;
}
//--------------------------------
// Functions Definitions

void UART_TX_Init(void)
{
//****Setting I/O pins for UART****//
TRISC6 = 0; // TX Pin set as output
TRISC7 = 1; // RX Pin set as input
//________I/O pins set __________//

// RX Setting, 8bit, enable receive,
RCSTA = 0x90;
// TX Setting, 8bit, Asynchronous mode, High speed
TXSTA = 0x24;

/**Initialize SPBRG register for required
baud rate and set BRGH for fast baud_rate**/
SPBRG = ((_XTAL_FREQ/16)/Baud_rate) - 1;
BRGH = 1; // for high baud_rate
//_________End of baud_rate setting_________//

//****Enable Asynchronous serial port*******//
SYNC = 0; // Asynchronous
SPEN = 1; // Enable serial port pins
//_____Asynchronous serial port enabled_______//

//**Lets prepare for transmission & reception**//
TXEN = 1; // enable transmission
CREN = 1; // enable reception
//__UART module up and ready for transmission and reception__//

//**Select 8-bit mode**//
TX9 = 0; // 8-bit reception selected
RX9 = 0; // 8-bit reception mode selected
//__8-bit mode selected__//
}

void UART_Write(uint8_t txData)
{
while(0 == PIR1bits.TXIF) {}; //while(!TRMT);
TXREG = txData; // transmit
}

void speak(char *msg)
{
for(i=0;i<strlen(msg) ;i++)
{
if(msg[i]!='\0')
{ UART_Write(msg[i]);
__delay_ms(1);}
}
}

uint8_t UART_Read()
{
uint8_t str2[16];
while(!PIR1bits.RCIF){}; // while(!RCIF); // Wait Until a Data Frame is Received
if(1 == OERR)
{
// EUSART error ? restart
SPEN = 0;
SPEN = 1;
}
// display returned acknowledge byte returned from SP03
sprintf(str2,"%#X ",RCREG); // format output for hexadecimal
Lcd_Set_Cursor(2, 1);
Lcd_Write_String(str2);
// end display returned acknowledge byte returned from SP03
return RCREG;
}

void UART_Read_String(uint8_t *Output, uint16_t length)
{
uint16_t z;
for(int z=0;z<length;z++)
Output[z] = UART_Read();
}

// You Can Also Use The ISR If You Want To !
void interrupt ISR (void)
{
if (RCIF == 1)
{
// Read The RCREG Buffer Register...
RCIF = 0; // Clear The Flag
}
}
 

Attachments

Picbuster

Joined Dec 2, 2013
982
This is my first post here, and I am eager to jump in. Unfortunately, my first post isn't to help, but to gain assistance. Therefore, I owe one to the universe.

I'm working with a pretty old chip right now, PIC16F876A. It's the only thing I have around until I can get some money to buy a new chip. I'm eyeing the enhanced mid range PIC16F1719. In the meantime, since I started on this journey I would like to solve some problems I have with the PIC16F876A. Is there a place in this forum where I can get access to some working code along with schematics related to that code? My current interest is communication. Working example of:

** the more comments in the code, the better for me.
  • USART or UART
  • SPI
  • I2C

So that I don't have to convert to much, because I am surely capable of making several errors (on my own - lol), I'll share with you the IDE and compiler I am using. I'm programing in C using MPLAB X IDE v5.15 (XC8-CC v2.05 @ C Standard C 90). I'm running several different projects from this one chip, so learning these communication systems and getting a working library is crucial.

I saw a post from Picbuster from 2017 and was going to ask him directly but unfortunately that conversation is too old. I don't see anywhere on this forum where you can DM a member. Here is the link and what I wanted to ask him directly, since he had the SPI component portion of my query already worked out...
https://forum.allaboutcircuits.com/threads/software-i2c-using-xc8-mplab-x.138847/

I am currently working on SPI communication with an older chip, PIC16F876A. If you don't mind sharing your SPI library, for the PIC16, that would be great.

If you've ever found that I2C, that would be a bonus.

I have been working on both for the past weeks, trying to do something simple. Like get a text to speech module to talk; and I've only managed to lose hair and sleep (to say the least). I assure you, I am not just bumming code, I have put in substantial work and research and I'm coming up with ZERO success, any help would be appreciated. Thanks in advance.

Any help would be highly appreciated. Thanks in advance.
Here is a simple example SPI for a pic 16f690 it should work (Don't cry when it fails but let me know )
Make sure that the TRIS registers are set properly.

Picbuster

C:
// -------------------spi bus master ------------------
SSPSTAT= 0b01000000;
CKP=0; //0=idle clock state is low
CKE=1; //0=Data transmitted on falling edge of SCK
SMP=1; //1=SPI mode-Input data sampled at end of data output time
SSPM3=0; //FOSC/4
SSPM2=0; //FOSC/4
SSPM1=0; //FOSC/64
SSPM0=1; //FOSC/4 1=/16
SSPIE=1;

//----------------------------------------------
PEIE=1; // Enable peripheral int.
GIE=1; // Global int. Enable
//============ SPI interrupt =========================

if (SSPIF)
{
SSPIF=0; // flag off
Spi_rec[Spi_pointer]=SSPBUF;
Spi_pointer++;
}
// end of interrupt ===================================



//== sequence to receive data ==

// enable slave
// send dummy char null
// data will arrive in Spi_rec[ Spi_pointer]
// watch size Spi_rec[xx]
// ready ? Disable slave
//sending data
void Xt_SPI(unsigned char byte)
{
SSPEN=1; // enable
SPI_CLK=1; // clock on
while(!BF) { __delay_ms(1); } // wait time depending on pic/SPI & clock chip speed
SSPBUF=byte; // Send your byte
SPI_CLK=0; // remove when you want to send an array
SSPEN=0; // Disable remove when you want to send an array
// invoke the lines when xmit array is done.
}
Mod edit: code tags
 
Last edited by a moderator:

Thread Starter

g-C0d3

Joined May 4, 2019
6
Here is a simple example SPI for a pic 16f690 it should work (Don't cry when it fails but let me know )
Make sure that the TRIS registers are set properly.

Picbuster

// -------------------spi bus master ------------------
SSPSTAT= 0b01000000;
CKP=0; //0=idle clock state is low
CKE=1; //0=Data transmitted on falling edge of SCK
SMP=1; //1=SPI mode-Input data sampled at end of data output time
SSPM3=0; //FOSC/4
SSPM2=0; //FOSC/4
SSPM1=0; //FOSC/64
SSPM0=1; //FOSC/4 1=/16
SSPIE=1;

//----------------------------------------------
PEIE=1; // Enable peripheral int.
GIE=1; // Global int. Enable
//============ SPI interrupt =========================

if (SSPIF)
{
SSPIF=0; // flag off
Spi_rec[Spi_pointer]=SSPBUF;
Spi_pointer++;
}
// end of interrupt ===================================



//== sequence to receive data ==

// enable slave
// send dummy char null
// data will arrive in Spi_rec[ Spi_pointer]
// watch size Spi_rec[xx]
// ready ? Disable slave
//sending data
void Xt_SPI(unsigned char byte)
{
SSPEN=1; // enable
SPI_CLK=1; // clock on
while(!BF) { __delay_ms(1); } // wait time depending on pic/SPI & clock chip speed
SSPBUF=byte; // Send your byte
SPI_CLK=0; // remove when you want to send an array
SSPEN=0; // Disable remove when you want to send an array
// invoke the lines when xmit array is done.
}
Thanks, don't worry I won't. I'll try my best to work through it and let you know...
 

Thread Starter

g-C0d3

Joined May 4, 2019
6
Which sim do you use? I didn't catch your meaning about "All that going on in the uart read routine, I'm not surprized.."

But, yeah... Let me know what I missed. Thanks
 

Ian Rogers

Joined Dec 12, 2012
663
I use the same sim as you.... How is the LCD connected? Is this what is on the other side of the uart?

Also the way you have the terminal will not work as the RS323 circuitry is already in the model..

Also No! you are not sending ASCII so you won't see anything... The LCD needs ASCII as well.

Give me a brief outline of what you want to see and a full schematic with the LCD.. If you are using a RS232 display there are Milford instrument models so you can test this..
 
Top