PIC16F877A UART Troubles

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Hi all,

I recently tried connecting the UART of my PIC16F877A to a PC to send some ASCII characters after successfully testing my MAX232.

I simulated the program in MPLAB SIM where it seems to work fine. When it comes to actual hardware though I ran into some trouble with the terminal screen filling up with seemingly random characters.

I felt it must be a Baud rate error and changed the Baud rate a couple of times but to no avail.

Here is my code:

Rich (BB code):
//main.c
//To set up a UART transmit connection between a PC and PIC16F877A

#include<htc.h>
#define _XTAL_FREQ 20000000
#define BAUD 9600
#define BRGR (_XTAL_FREQ)/(16*(129+1))

__CONFIG(FOSC_HS & CPD_OFF & CP_OFF & WDTE_OFF & BOREN_OFF & PWRTE_OFF & DEBUG_ON & LVP_OFF);


void UART_Init()
{
	//SET UP TX
	SPBRG=BRGR;				//Baud rate set at 9600 B/s and 20 MHz crystal
	BRGH=1;					//High speed Baud rate generator selected
	SPEN=1;					//Serial Port Enabled
	SYNC=0;				//No Sync Transmission
	TX9=0;			//8 Bit transmission
	TXEN=1;				//TXIF set; no data in TXREG
	//SET UP RX
	RX9=0;			//8 Bit reception



}

void UART_Write(unsigned char byte)
{
	while(!TXIF);						//if Transmit buffer is empty
	TXREG=byte;					//write to 8 bit tx buffer
	__delay_us(10);					//wait for some time
	
}	




void main()
{
	UART_Init();
	while(1)
	{
		UART_Write('0');
	}
}
NOTE: I just configured the reception. I am not actually receiving anything

Here's the random characters I captured off the terminal.

RRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒVÒVÒRÖRÒVÒVÖVÖVÖVÖVÖVÖVÖVÒVÒVÖRÖVÒVÒRÖVÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒVÒRÖVÒVÖRÖRÖVÖVÖVÖVÖVÖVÖVÖRÒVÖVÒRÒRÖVÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÒRÖRÒRÒV
I admit I might have messed it all up in the code somewhere. Please help me find it.

Thanks!
 

JohnInTX

Joined Jun 26, 2012
4,787
For 9600 baud at 20MHz SPBRG should be 31 (BRGH=0) or 129 (BRGH=1). Your calculation does not do that. See tables 10-3 and 10-4 in the databook.

If you have a scope send 'U' (55h) to the UART. The bit times are easy to see and should be 104us.
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Thanks for pointing that out. I made the change in my code and tried sending the data again but it made little change. Now, though the characters are not repeating as they should be, they are still not the right data I hope to see.

New code:

Rich (BB code):
//main.c
//To set up a UART transmit connection between a PC and PIC16F877A

#include<htc.h>
#define _XTAL_FREQ 20000000
#define BAUD 9600
#define BRGR (_XTAL_FREQ)/(16*(129+1))

__CONFIG(FOSC_HS & CPD_OFF & CP_OFF & WDTE_OFF & BOREN_OFF & PWRTE_OFF & DEBUG_ON & LVP_OFF);


void UART_Init()
{
	//SET UP TX
	SPBRG=129;				//Baud rate set at 9600 B/s and 20 MHz crystal
	BRGH=1;					//High speed Baud rate generator selected
	SPEN=1;					//Serial Port Enabled
	SYNC=0;				//No Sync Transmission
	TX9=0;			//8 Bit transmission
	TXEN=1;				//TXIF set; no data in TXREG
	//SET UP RX
	RX9=0;			//8 Bit reception



}

void UART_Write(unsigned char byte)
{
	
	while(!TXIF);						//if Transmit buffer is empty
	TXREG=byte;					//write to 8 bit tx buffer
	
	
}	




void main()
{
	UART_Init();
	while(1)
	{
		UART_Write("A");
	}
}
Also, the UART connection I made isn't very reliable and I need to redo the connections every once in a while to avoid running into a break condition on the terminal. Any workaround for this?

Thanks
 

JohnInTX

Joined Jun 26, 2012
4,787
Make sure RC7 and RC6 are set up as inputs in TRISC (SPEN will take over from there.)
Are you sure your oscillator freq is 20MHz?
Does the compiler know that you are compiling for an 'F877? I'm not familiar with HTC on midrange. I don't have htc.h for midrange but make sure that things like BRGH=1 actually evaluate to bsf TXSTA,2. It probably does but I always check the obvious when things that should work don't.

Also, the UART connection I made isn't very reliable and I need to redo the connections every once in a while to avoid running into a break condition on the terminal. Any workaround for this?
Yes, fix your hardware. Is it pinned correctly? Ground connected? With a logic '1' on TXD (UART idle) you should have some (-)volts on the RX input of the PC. (-) volts on the PC TX line should result in a logic '1' at the PIC RXD pin. Ground should be ground i.e. 0V between the PC box and Vss of the PIC.

Try writing only one char 'U' instead of many in a while(1) loop or use a long delay between writes so that you can scope / logic probe the PIC TXD pin. A scope should show the character. A logic probe should show logic high and blink on each character (won't find baudrate errors though). Use the MCLR to reset the PIC instead of cycling power. The MAX232 takes a bit of time to come up to volts.

Other than that, it should get at least a char out.

BTW: I like to set up config registers as a single binary byte write instead of individual bits. That way, I know all bits are configured and I haven't forgotten any. Sometimes there are hardware-specific reasons as well. Your way should work OK, though. (By config registers I mean things like peripheral control registers, not the PIC hardware config regs)
 
Last edited:
Top