Continue to Site

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.

  • 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 FIFO

Status
Not open for further replies.

YAN-1

New Member
Question. The FIFO of the RCREG in the UART mode of the PIC is 2 bytes deep, right? So when I first start receiving data, and the program goes into the ISR for the first time because of the RCIE interrupt flag, and I read the RCREG once, this is not the byte that just arrived, right? I am asking because I am trying to receive 2 bytes at a time, the LS and the MS bytes of a certain number. But I keep getting weird results. The only way it worked was when I assigned the MS bit of each byte a certain value that I check when I read the RCREG in order to differentiate between the LS and MS bytes. Please help.
 
Let me clarify the weird things that I receive. Actually, I read the 2 bytes and output the MS on PORTB and the LS on PORTD so that they light LEDs. However, the weird thing that I cannot explain is that the LS bit of both is not changing (RB0 and RD0 don't go on), whereas the rest of the bits of both bytes are received correctly and are changing as expected. The data is sent by another PIC. The ISR responsible for reading the bytes is:

void interrupt (){


switch (i){
case 0: {datalow = RCREG; i = 1; break;}
case 1: {datahigh = RCREG; i = 0;}
}

}


Any suggestions or ideas?
 
The thing is you don't receive two bytes at a time, you receive one, then the other, your program should have sufficient time to process the first byte while the UART is receiving the next (the advantage of a hardware UART).

It sounds like you may have a speed issue?, with the receive routine not being quite the same as the transmit one, or perhaps a polarity problem, so the wrong bit is being considered the start bit?.
 
Well I've decreased the baud to 9600 but still the same problem. It's weird. How can I check for the start bit thing?
 
Post your full pic code please, the snippet above is too vague.
Are you sure you are sending the right format to the pic (nr of Databits, parity, nr of stop bits) ??
 
YAN-1 said:
The FIFO of the RCREG in the UART mode of the PIC is 2 bytes deep, right? So when I first start receiving data, and the program goes into the ISR for the first time because of the RCIE interrupt flag, and I read the RCREG once, this is not the byte that just arrived, right?

Why wouldn't it be the byte that just arrived? If it weren't then RCIF is pointless, as it wouldn't allow sending just one byte. I've used receive interrupts and the byte it receives is indeed the byte that triggers the interrupt.

Mike
 
Hi. Sorry for replying that late. Here is the code. The PIC that receives the two bytes runs this prgram:

unsigned short datalow;
unsigned short datahigh;
unsigned short i;
unsigned short data;
unsigned short x;
unsigned short y;
unsigned short times;



void interrupt (){


if (times != 0){
switch (i){
case 0: {datalow = RCREG; i = 1; break;}
case 1: {datahigh = RCREG; i = 0;}
}
}




times = 1;
}

void main() {

times = 0;

i = 0;

TRISB = 0x00;
PORTB = 0x00;

TRISD = 0x00;
PORTD = 0x00;

ADCON1 = 0x06;
TRISA = 0x00;
PORTA = 0x00;

TRISC.F6 = 1;
TRISC.F7 = 1;

TXSTA = 0b00000100;
RCSTA = 0b10010000;
SPBRG = 129;

INTCON.F7 = 1;
INTCON.F6 = 1;
PIE1.F5 = 1;


data = 0x00;
TXSTA.F5 = 1;


do {

PORTB = datahigh;
PORTD = datalow;

if (TXSTA.F1 ==1){
TXREG = data;}

Delay_ms (200);
data = ~data;

}while(1);

}


-------------------------------------------------------------------------------------

The PIC that sends those bytes runs this program:
unsigned short low;
unsigned short high;
unsigned short i;
unsigned short data;


void interrupt (){

data = RCREG;

}

void main() {

i = 0;
TRISB = 0;
TRISD = 0;
ADCON1 = 0x06;
TRISA = 0;
PORTA = 0x00;

TRISC.F6 = 1;
TRISC.F7 = 1;

TXSTA = 0b00000100;
RCSTA = 0b10010000;
SPBRG = 129;

INTCON.F7 = 1;
INTCON.F6 = 1;
PIE1.F5 = 1;


TXSTA.F5 = 1;

low = 0b00000000;
high = 0b11111111;



do {

PORTB = data;

if ((TXSTA.F1 ==1)&& i ==0){
i = 1;
TXREG = low;}

Delay_us (5);

if ((TXSTA.F1 ==1)&& i ==1){
i = 0;
TXREG = high;}

Delay_ms(200);


low = low + 1;
high = high - 1;

}while(1);

}
-------------------------------------------------------------------------------------

As you can see, the first PIC also sends one byte to the second one; but this one is received correctly. Please help. Thanks.
 
Hi. Sorry for replying that late. Here is the code. The PIC that receives the two bytes runs this prgram:

unsigned short datalow;
unsigned short datahigh;
unsigned short i;
unsigned short data;
unsigned short x;
unsigned short y;
unsigned short times;



void interrupt (){



switch (i){
case 0: {datalow = RCREG; i = 1; break;}
case 1: {datahigh = RCREG; i = 0;}
}



}

void main() {


i = 0;

TRISB = 0x00;
PORTB = 0x00;

TRISD = 0x00;
PORTD = 0x00;

ADCON1 = 0x06;
TRISA = 0x00;
PORTA = 0x00;

TRISC.F6 = 1;
TRISC.F7 = 1;

TXSTA = 0b00000100;
RCSTA = 0b10010000;
SPBRG = 129;

INTCON.F7 = 1;
INTCON.F6 = 1;
PIE1.F5 = 1;


data = 0x00;
TXSTA.F5 = 1;


do {

PORTB = datahigh;
PORTD = datalow;

if (TXSTA.F1 ==1){
TXREG = data;}

Delay_ms (200);
data = ~data;

}while(1);

}


-------------------------------------------------------------------------------------

The PIC that sends those bytes runs this program:
unsigned short low;
unsigned short high;
unsigned short i;
unsigned short data;


void interrupt (){

data = RCREG;

}

void main() {

i = 0;
TRISB = 0;
TRISD = 0;
ADCON1 = 0x06;
TRISA = 0;
PORTA = 0x00;

TRISC.F6 = 1;
TRISC.F7 = 1;

TXSTA = 0b00000100;
RCSTA = 0b10010000;
SPBRG = 129;

INTCON.F7 = 1;
INTCON.F6 = 1;
PIE1.F5 = 1;


TXSTA.F5 = 1;

low = 0b00000000;
high = 0b11111111;



do {

PORTB = data;

if ((TXSTA.F1 ==1)&& i ==0){
i = 1;
TXREG = low;}

Delay_us (5);

if ((TXSTA.F1 ==1)&& i ==1){
i = 0;
TXREG = high;}

Delay_ms(200);


low = low + 1;
high = high - 1;

}while(1);

}
-------------------------------------------------------------------------------------

As you can see, the first PIC also sends one byte to the second one; but this one is received correctly. Please help. Thanks.
 
1 MAJOR error i can see is that variables wich are used in an interrupt routine AND in main code (datalow and datahigh for example) Should be declared volatile...

volatile unsigned short datalow;
volatile unsigned short datahigh;
 
What compiler are you using?

try changing your unsigned shorts to 'unsigned char' . That's the only good way to ask for a byte.
 
Well I've tried everything. I have figured out the problem but can't find a solution yet! The problem is not in the least significant bit. I only thought so because the bytes being sent by my program are counting up in binary so it appeared that everything is ok except the LSB. What happens is that the program sends a byte, doesn't send the next one, then sends the next byte, then doesn't send the one after that, ...etc. So it appears as though the byte is increasing 2 at a time, and not 1 (makes sense?)

I got the same thing when I connected the PIC to the serial port of a PC and read the bytes sent by the PIC. I read a tutorial from Microchip. In the transmission section, they had a warning about this. They had an example in which the program appears to be sending the characters 'A' then 'B' then 'C'. But what is actually received on the other end is 'A' then 'C'. This is because the write register flag indicates that it is full one instruction late so the user shouldn't check it immediately after a write procedure but should add some NOPs.

Well I've added a delay of 200ms after each sending and before checking for the appropriate flags (PIR1.TXIF and TXSTA.TMRT) and still no difference. I really want to be able to send those bytes correctly without missing any data and without having to use the interrupt. Any suggestions? Thanks.
 
I didnt check your transmit code, I assumed you'd tested it and it was fine.

You don't seem to set TXSTA.TXEN when you initialize.
You should poll TXIF to go high before sending something, not TRMT.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top