ATmega328p UART framing error does not occur!

Thread Starter

m.majid

Joined May 28, 2008
53
There is a protocole over serial port as following:
1. no signal (idle) is High (+5V).
2. reset signal is a 60 us Low (0v) pulse.
3. data signal is : 250 kbps/8 bits/2 stop/no parity

I want to detect reset signal using Frame Error capability of MCU (ATmega328p)

250 kbps so 1 bit is 4us,
serial packet is 11 bit = 44 us
the farme format is = start-b0-b1-b2-b3-b4-b5-b6-b7-stop1-stop2
for normal data = 0-x-x-x-x-x-x-x-x-1-1
for reset pulse = 0-0-0-0-0-0-0-0-0-0-0-0-0-0-0

According page 245 of the data sheet, if 1st Stop bit of RX data is zero, FE0 (bit4) of UCSR0A register is set by MCU
But it does not occur for me!

please explain why frame error does not occur?
please do not offer alternative methods to detect reset signal!
I am just curious why Frame Error does not occur, whilst the datasheet says it occures!
 

Papabravo

Joined Feb 24, 2006
21,228
There is a protocole over serial port as following:
1. no signal (idle) is High (+5V).
2. reset signal is a 60 us Low (0v) pulse.
3. data signal is : 250 kbps/8 bits/2 stop/no parity

I want to detect reset signal using Frame Error capability of MCU (ATmega328p)

250 kbps so 1 bit is 4us,
serial packet is 11 bit = 44 us
the farme format is = start-b0-b1-b2-b3-b4-b5-b6-b7-stop1-stop2
for normal data = 0-x-x-x-x-x-x-x-x-1-1
for reset pulse = 0-0-0-0-0-0-0-0-0-0-0-0-0-0-0

According page 245 of the data sheet, if 1st Stop bit of RX data is zero, FE0 (bit4) of UCSR0A register is set by MCU
But it does not occur for me!

please explain why frame error does not occur?
please do not offer alternative methods to detect reset signal!
I am just curious why Frame Error does not occur, whilst the datasheet says it occures!
I guess we need to see your code.
If I had to guess it would be order of operations or a bad register address definition. Those are notoriously hard to find. After a while all of the Atmel peripheral register names start to look the same.
 

Thread Starter

m.majid

Joined May 28, 2008
53
I guess we need to see your code.
If I had to guess it would be order of operations or a bad register address definition. Those are notoriously hard to find. After a while all of the Atmel peripheral register names start to look the same.
thanks for reply

here is the code:
automatic code generated by CVAVR,
I didn't change the reading order of registers,
but changed if condition as my design

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status;
char data;

status=UCSR0A;
data=UDR0;

if (status & 0x10) // framing error
bReset = 1;
else
ucData[ucIndex++] = data;
}
 

MrChips

Joined Oct 2, 2009
30,824
The error is quite obvious.
Your statements:
Code:
char status;
char data;

status=UCSR0A;
data=UDR0;
is not the way to do this.

You want:
Code:
#define status UCSR0A
#define data UDR0
 

Thread Starter

m.majid

Joined May 28, 2008
53
The error is quite obvious.
Your statements:
Code:
char status;
char data;

status=UCSR0A;
data=UDR0;
is not the way to do this.

You want:
Code:
#define status UCSR0A
#define data UDR0
i read the register into variables then process them,
u say not to use variables process directly registers,
I have checked , result is the same
 

Papabravo

Joined Feb 24, 2006
21,228
CVAVR is a very good compiler, and the templates that I used from it always worked flawlessly.
I didn't mean the code fragment; I meant everything. Even the include files.
Your handling of ucIndex is also suspicious. What happens when it reaches the end of the buffer?
Also, what is the definition of bReset?
While we are at it can you show us the assembly language code for the RX interrupt routine that was generated by the compiler?
It seems like you might be assigning the literal value of the address of the registers to your variables.

PS I never had this problem with CVAVR and the ATMega128 or the ATMega2561. The BREAK condition was always reliably detected as a framing error. I believe the UART peripheral is the same across all AT Mega family members.
 
Last edited:

MrChips

Joined Oct 2, 2009
30,824
i read the register into variables then process them,
u say not to use variables process directly registers,
I have checked , result is the same
I now see what you are doing. You are reading following an interrupt. I though you were polling.

Show us all of your code.
 

Thread Starter

m.majid

Joined May 28, 2008
53
I now see what you are doing. You are reading following an interrupt. I though you were polling.

Show us all of your code.
i need my code ignore reset pulse, just buffer input data, then send again buffered data
for normal data it works nice, every data is correct
but can not handle reset pulse, cause Frame Error not work,
and interprete reset pulse as 2 data : 00, E0

code is here :

C:
bit bReset;
unsigned char ucData[256];
unsigned char ucIndex, ucWriteIndex;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
    char status;
    char data;
  
    status=UCSR0A;
    data=UDR0;
  
    if (status & 0x10) // framing error
        bReset = 1;
    else
        ucData[ucIndex++] = data;
}

void main (void)
{
    bReset = 0;
    ucIndex = 0;
    ucWriteIndex = 0;
  
    while (1)
    {
        if (ucWriteIndex != ucIndex)
        {
            putchar(ucData[ucWriteIndex++]);
        }
      
        if (bReset)
        {
            ucWriteIndex = ucIndex;
            bReset = 0;
        }
    }
}
Moderators note: used code tags
 
Last edited by a moderator:

Papabravo

Joined Feb 24, 2006
21,228
That is still not the complete code. Where is the Uart Initialization? Where are you enabling the interrupt system?
When you execute the bReset code ucWriteIndex will be NOT EQUAL to ucIndex all the way from zero up to its present value. Pretty sloppy coding.
What is it about the word complete that you do not understand?
 

Thread Starter

m.majid

Joined May 28, 2008
53
That is still not the complete code. Where is the Uart Initialization? Where are you enabling the interrupt system?
When you execute the bReset code ucWriteIndex will be NOT EQUAL to ucIndex all the way from zero up to its present value. Pretty sloppy coding.
What is it about the word complete that you do not understand?
haha!, sloppy code?!
it is circular buffer nothing wrong with buffer, it WORKS nice for normal data i have checked,
just can not detect Frame Error , and interpretes 60us break (0V) as data and put in buffer by mistake
i need to ignore reset pulse

i skipped long auto code generated by CVAVR ,
here is complete code :

C:
#include <mega328p.h>

bit bReset;
unsigned char ucData[256];
unsigned char ucIndex, ucWriteIndex;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
    char status;
    char data;
  
    status=UCSR0A;
    data=UDR0;
  
    if (status & 0x10) // framing error
        bReset = 1;
    else
        ucData[ucIndex++] = data;
}

#include <stdio.h>

void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 250000
UCSR0A=0x00;
UCSR0B=0x98;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x03;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;

// Global enable interrupts
#asm("sei")

    bReset = 0;
    ucIndex = 0;
    ucWriteIndex = 0;
  
    while (1)
    {
        if (ucWriteIndex != ucIndex)
        {
            putchar(ucData[ucWriteIndex++]);
        }
      
        if (bReset)
        {
            ucWriteIndex = ucIndex;
            bReset = 0;
        }
    }
}
Moderators note: used code tags AGAIN
 

Thread Starter

m.majid

Joined May 28, 2008
53
I use proteus to trace the code step by step , it never goes to bReset = 1; bReset ramains 0 forever.
I am expecting Frame Error to occur when it receives 60us 0V pulse, but it does not occur
 

Papabravo

Joined Feb 24, 2006
21,228
I use proteus to trace the code step by step , it never goes to bReset = 1; bReset ramains 0 forever.
I am expecting Frame Error to occur when it receives 60us 0V pulse, but it does not occur
It only looked "sloppy" because I could not see everything in the file. That is one of the problems with code fragments.
did you ever get the assembly language for the RxInterrupt routine out of the compiler?
It is possible that Proteus does not simulate all features of the on-chip peripherals. Do you get the same behavior when you run the code on a real part?
 

Thread Starter

m.majid

Joined May 28, 2008
53
It only looked "sloppy" because I could not see everything in the file. That is one of the problems with code fragments.
did you ever get the assembly language for the RxInterrupt routine out of the compiler?
It is possible that Proteus does not simulate all features of the on-chip peripherals. Do you get the same behavior when you run the code on a real part?
only proteus is available for me to test,
I can do the real test in a few days...

I will share the result!

thanks everybody
 

Papabravo

Joined Feb 24, 2006
21,228
It would have been nice if you had told me that at the beginning of your chain of posts! I was under the mistaken impression that you were describing an actual hardware problem with the actual hardware. Now I find out this is a simulator problem. Sheesh -- thanks for wasting my time.
BTW I still need to see the header file "mega328p.h" to verify that the correct mapping of the UART registers was performed.
You should see something like:
C:
#define UCSR0A (*(unsigned char *) 0xc0)
The address probably won't be 0xc0 because that definition is for the ATMega2561.
EDIT: surprise surprise it is at address 0xC0 in the ATMega328p
 

Thread Starter

m.majid

Joined May 28, 2008
53
It would have been nice if you had told me that at the beginning of your chain of posts! I was under the mistaken impression that you were describing an actual hardware problem with the actual hardware. Now I find out this is a simulator problem. Sheesh -- thanks for wasting my time.
BTW I still need to see the header file "mega328p.h" to verify that the correct mapping of the UART registers was performed.
You should see something like:
C:
#define UCSR0A (*(unsigned char *) 0xc0)
The address probably won't be 0xc0 because that definition is for the ATMega2561.
EDIT: surprise surprise it is at address 0xC0 in the ATMega328p
I have just checked , yes it is :

#define UCSR0A (*(unsigned char *) 0xc0)

I m sorry not to tell about simulation!, I trusted CVAVR and Proteus and Datasheet,

this is first time I am planning to handle Frame Error, so naturally 1st suspect is my code,
now I start thinking 2nd suspect might be Proteus,
i will findout soon, after real hardware test. i m very curious
 

Papabravo

Joined Feb 24, 2006
21,228
I have just checked , yes it is :

#define UCSR0A (*(unsigned char *) 0xc0)

I m sorry not to tell about simulation!, I trusted CVAVR and Proteus and Datasheet,

this is first time I am planning to handle Frame Error, so naturally 1st suspect is my code,
now I start thinking 2nd suspect might be Proteus,
i will findout soon, after real hardware test. i m very curious
I am also curious, because I think I have done BREAK detection via the framing error bit in an ATMega family member, but I just can't put my hands on the code in my vast archive.
 

Thread Starter

m.majid

Joined May 28, 2008
53
I just did the test with ATmega88 and ATmega328P
my code works fine on real ICs
same code does not work on simulated models in proteus isis

it seems the simulated model does not support FE of USART
 

JohnInTX

Joined Jun 26, 2012
4,787
I just did the test with ATmega88 and ATmega328P
my code works fine on real ICs
same code does not work on simulated models in proteus isis
it seems the simulated model does not support FE of USART
You bring up an excellent point - simulators are just that and they frequently don't faithfully replicate the real thing. Another member here is getting his 8051 sim to light an LED by sourcing from port 1. It won't happen that way on a real chip. He gets to debug twice..

Thanks for the update. Good work tracking it down.
 

Papabravo

Joined Feb 24, 2006
21,228
I just did the test with ATmega88 and ATmega328P
my code works fine on real ICs
same code does not work on simulated models in proteus isis

it seems the simulated model does not support FE of USART
I'm am really glad to hear this. This would have been a real conundrum if it had been the chip behaving this way. I guess my bias is showing because in the early days of simulators we never assumed the simulation was complete or all that accurate.
 
Top