• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

UART Transmitting Problem

Status
Not open for further replies.

winson

New Member
Hello everybody,

I was trying to write a UART program to send out few bytes of data by using PIC16F877A, CCS C compiler, MPLAB IDE, MPLAB SIM. The problem of my program is the code fail to transmit out the data to pin RC6 of Port C. So far i am just use MPLAB SIM to simulate my program and using Watch window to monitor all the register and symbol. To simulate the program i was pressing the "step into" button, and the first 2 bytes of data was load to TXREG and TSR but after that not able to load the third bytes of data beacuse TXIF flag is not set, this showing that TXREG was still full and the data look like "jam" already. from the Watch window the Port C does not show any value(0x00), i also try to press "animate" and let the program run for few minutes but still no data was show on Port C. Anybody can help to solve the problem or give some suggestion?

Below is my program,

#include <16F877A.h>

//***** Function prototype ******//
void init(void);
void transmit (void);
void transmit_empty (void);

//*****variable declaration******//
unsigned char TXSTA,RCSTA,SPBRG,INTCON,PIR1,PIE1,TXREG,PORTC,TRISC;
int count;

//****** define sfr address *****//
#byte TXSTA = 0x98
#byte RCSTA = 0x18
#byte SPBRG = 0x99
#byte PIE1 = 0x8c
#byte INTCON = 0x8b
#byte TXREG = 0x19
#byte RCREG = 0x1A
#byte PIR1 = 0x0c
#byte PORTC = 0x07
#byte TRISC = 0x87



char ucIPOD_packet_origin[2][7]={
{0xff,0x55,0x03,0x02,0x00,0x01,0xfa}, /* " play/pause " */
{0xff,0x55,0x03,0x02,0x00,0x08,0xf3} /* " fwd " */
};


/********************************************************************
FUNCTION : main()
DESCRIPTION : main loop
INPUT : Null
OUTPUT : Null
CREATE :
DATE : 07/10/08
********************************************************************/
void main()
{
init ();
transmit ();
while (1)
{
}
}


/********************************************************************
FUNCTION : init()
DESCRIPTION : sfr initialization
INPUT : Null
OUTPUT : Null
CREATE :
DATE : 07/10/08
********************************************************************/
void init ()
{
PORTC = 0x00; //0b 0000 0000 //Clear Port C

TRISC = 0xFF; //0b 1111 1111 //Enable USART Transmitter

TXSTA = 0x24; //0b 0010 0100 //Transmit Enable //SYNC = 0, Asynchronous Mode

RCSTA = 0x90; //0b 1001 0000 //Receive Enable //Serial Port Enable

SPBRG = 0x40; //0b 0100 0000 //SPBRG = 64, Baudrate = 19.231KBAUD, High Baud Rate

INTCON = 0x00; //0b 0000 0000 //Disable Global and Peripheral Interrupt

PIR1 = 0x10; //0b 0001 0000 //USART transmit/Receive Interrupt Flag bit

PIE1 = 0x00; //0b 0000 0000; //Individual enable bits for the peripheral interrupts.

count = 0;
}


/********************************************************************
FUNCTION : transmit()
DESCRIPTION : uart transmission
INPUT : Null
OUTPUT : Null
CREATE :
DATE : 07/10/08
********************************************************************/
void transmit ()
{
while (1) //Keep on looping
{
if (PIR1 == 0x10) //Check TXIF flag
{ //If TXREG is empty

TXREG = ucIPOD_packet_origin[0][count]; //Load data

count++; //Counter increment
}
}
}

[/code]

I am really no idea why such condition happen, everything look like set properly but it is not run.
Is it my simualtion methods is wrong or my code was having problem?

Any suggestion is appreciate.

Thanks
 

Diver300

Well-Known Member
Most Helpful Member
The TXIF goes high when the USART transmit buffer is full. I think that you are testing it the wrong way round. You should wait for it to go low not high before sending another byte.

When you test bit 4 of the PIR, you shouldn't test the whole register. PIR consists of

PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF

so that will only be 0x10 if all the other bits are 0.

I don't write in C so I can't tell you how to just test bit 4. In assembly I would write:-

Code:
      btfsc      PIR, TXIF
      goto       [transmit next byte]
      [whatever needs to be done instead of transmitting byte]
I don't know if the simulator works with the USART. I use the simulator to make sure that the correct bytes are transmitted, but I don't really see how it can simulate the actual transmission.
 

Pommie

Well-Known Member
Most Helpful Member
Diver,
The TXIF goes high when the transmit buffer is empty. This generates an interrupt and allows you to load the next byte. It cannot be cleared in software and the only way to clear it is to write to TXREG.

winson,
I suspect Diver found your problem, namely how you test PIR1. The way to do this in C is compiler specific but you can try one of these,
Code:
	if(PIR1&1<<TXIF){
	if(PIR1.TXIF){
	if(PIR1Bits.TXIF){
The first one should work on any compiler.

Mike.
 

winson

New Member
My program is ok. I already successfully simulate my UART program by using Uart1 IO tab in MPLAB SIM. It is under Debugger > Settings > Uart1 IO. In Uart1 IO tab just click "Enable Uart IO" and select "Window" as output then press ok. After back to MPLAB main screen a "SIM Uart1" tab will exist in the output window. Press "run" to simulate the UART program and the transmitted data will show in output window as ASCII character, just have to refer ASCII table and verify the transmitted data.

Thanks everybody!
 

winson

New Member
Hi everybody.

I already try my UART transmiting program on the real hardware with a breadboard but the result is not successful. I was using an oscilloscope to trace the signal that send out from the USART Tx pin of 16F877A but the scope does not show any pulses and just maintain at 0V. This program is run well in MPLAB Simulation.

The peripheral circuitry of the 877A is simple, i was put the 20MHz crystal's leg to OSC1 and OSC2 with a 22pF capacitor from each crystal leg to ground. I connect 5V(3A) supply to the two VDD pin of 877A and 0V to the two VSS pin finally i also connect 5V supply to the MCLR pin for the reset purpose and i also try to put a 20k resistor to the VDD to limit the current but the result is still the same. This is all the thing that i do, but the scope does not show any digital pulses. Anybody can give me some suggestion or alert me some of the error that i done?
My latest version of code is show below, Thanks...

Code:
#include <16F877A.h>

//***** Function prototype ******//
void init(void);
void transmit (void);
void transmit_empty (void);

//*****variable declaration******//
unsigned char TXSTA,RCSTA,SPBRG,INTCON,PIR1,PIE1,TXREG,PORTC,TRISC;
int count, next;

//****** define sfr address *****//
#byte TXSTA		=  	0x98
#byte RCSTA		=	0x18
#byte SPBRG		=	0x99
#byte PIE1		=	0x8c
#byte INTCON		=	0x8b
#byte TXREG		=	0x19
#byte RCREG		=	0x1A
#byte PIR1		=	0x0c
#byte PORTC		=	0x07
#byte TRISC		= 	0x87
#bit  TXIF		=	PIR1.4
#bit  TRMT		=	TXSTA.1




char remote_command_basic[3][10]=
{
	{0xff,0x55,0x06,0x02,0x00,0x01,0x00,0x00,0x00,0xf7},	//0 Play/Pause
	{0xff,0x55,0x06,0x02,0x00,0x01,0x00,0x00,0x00,0xf7},	//1 Play/Pause
	{0xff,0x55,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0xf8}	//2 Release
};

	
/********************************************************************
FUNCTION   	: main()
DESCRIPTION : main loop
********************************************************************/
void main()
{
	init ();
	transmit ();
	while (1)
	{
	}
}


/********************************************************************
FUNCTION   	: init()
DESCRIPTION : sfr initialization
********************************************************************/
void init ()
{
   
	PORTC = 0x00;	//0b 0000 0000		//Clear Port C
	
	TRISC = 0xFF;	//0b 1111 1111		//Enable USART Transmitter and Receiver
	
	TXSTA = 0x24;	//0b 0010 0100		//Transmit Enable	//SYNC = 0, Asynchronous Mode
	RCSTA = 0x90;	//0b 1001 0000		//Receive Enable	//Serial Port Enable
	
	SPBRG = 0x40;	//0b 0100 0000		//SPBRG = 64, Baudrate = 19.231KBAUD, High Baud Rate
	                                                                                
	INTCON = 0x00;	//0b 0000 0000		//Global and Peripheral Interrupt Disable

	PIR1 = 0x10;	//0b 0001 0000		//USART transmit/Receive Interrupt Flag bit

	PIE1 = 0x00;	//0b 0000 0000;		//Individual enable bits for the peripheral interrupts.
					
	count = 0;
	next = 0;
}


/********************************************************************
FUNCTION   	: transmit()
DESCRIPTION : uart transmission
********************************************************************/
void transmit ()
{
	while (1)					//Keep on looping
	{
		if (TXIF == 1)				//Check TXIF flag			
		{						//If TXREG is empty 
			
			TXREG = remote_command_basic[next][count];//Load data
			delay_cycles( 1 );		//NOP
			delay_cycles( 1 );		
			delay_cycles( 1 );
			
			if (count > 8)			//After 10th byte
			{
				next++;				//Next packet
				if (next > 2)		//After 3rd packet
				{
					return;			//Return to main()
				}
			}
			count++;				//Counter increment
			if (count > 9)			//After 10th byte
			{
				count = 0;			//Reset counter
			}
		}		//End first if loop
	}		//End while loop
}
 
Last edited:

AtomSoft

Well-Known Member
its good to hear it works! also make sure you tie MCLR to VCC with at least a 10K resistor. Not straight to VCC.
 
Last edited:

winson

New Member
Thanks Jason!

Now i aware that a program will not work in a PIC chip if we do not set the configuration words in the program code. I have added the following line of code to my program:

Code:
#fuses hs, nowdt, nolvp, noprotect
Just one line of code, and the thing will work nicely. The program is work well in MPLAB SIM simulation because by default MPLAB already set the configuration words properly in Configuration > Configuration Bits > Set Configuration Bits in Code.

Normal 20MHz oscilloscope will not able to see the data waveform clearly, i have use a 100MHz digital oscilloscope to trace the data waveform.

Regards,
Winson
 
Last edited:
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top