1
\$\begingroup\$

I am trying to receive a string from USART but failed , i want to receive char by char and store them in an array until the user enter '\n' and finally display the string to LCD , here is my code:

char REC;
void USART_Init(unsigned int BAUD )
{                                                          
unsigned int ubrr;                                     
ubrr=F_CPU/16/BAUD-1;                                
/* Set baud rate */                                   
UBRRH = (unsigned char)(ubrr>>8);                   
UBRRL = (unsigned char)ubrr;                         
/* Enable receiver and transmitter */                 
UCSRB |= (1<<RXEN)|(1<<TXEN)|(1<<RXC);                 
/* Set frame format: 8data, 1stop bit */                 
UCSRC = (1<<URSEL)|(3<<UCSZ0);                         
sei();                                                 
}                                                          

ISR(USART_RXC_vect){
REC = UDR;
}

int main(void)
{ 
lcd_init(20);
USART_Init(9600);
char data[10];
while(1)
   {
    int i = 0;
    while (REC !='\n')
    {
        data[i++]=REC;
    }
    data[i]='\0';

    lcd_puts(data);

   }
 }
\$\endgroup\$
10
  • \$\begingroup\$ What are you sending it? Exactly? And perhaps whatever you use to send, is not sending an actual '\n' character.. \$\endgroup\$
    – KyranF
    Commented Mar 23, 2015 at 21:37
  • \$\begingroup\$ Where is your check to ensure array out of bounds errors do not occur? \$\endgroup\$
    – KyranF
    Commented Mar 23, 2015 at 21:37
  • \$\begingroup\$ have you got the ability to step-by-step debug this device? You should see it reading data from the hardware buffer (if there is one) char by char until something happens - be it bad or good! \$\endgroup\$
    – KyranF
    Commented Mar 23, 2015 at 21:38
  • \$\begingroup\$ oh and where do you actually update the value of REC? Or you just copy the value of the register? \$\endgroup\$
    – KyranF
    Commented Mar 23, 2015 at 21:39
  • \$\begingroup\$ As a first step i am just sending from virtual terminal in Proteus a string with no more than 20 character. \$\endgroup\$ Commented Mar 23, 2015 at 21:39

1 Answer 1

8
\$\begingroup\$

Straight off I see two issues - one sneaky, and one which shows a bit of a lack of understanding.

The sneaky one is this line:

char REC;

REC is used within your interrupt and also outside your interrupt. As such it has to be flagged as volatile or the compiler is at risk of optimizing it out as it doesn't know it's being changed by the ISR.

volatile char REC;

The second is how you deal with what's in REC:

while (REC !='\n')
{
    data[i++]=REC;
}

I send the letter "A" through the USART. REC gets set to A. Then in the main loop it goes:

  • Is REC different to "\n"?
  • Yes, it's A. Ok, I add that to data and increment i (i == 1).
  • Is REC different to "\n"?
  • Yes, it's A. Ok, I add that to data and increment i (i == 2).
  • Is REC different to "\n"?
  • Yes, it's A. Ok, I add that to data and increment i (i == 3).
  • Is REC different to "\n"?
  • Yes, it's A. Ok, I add that to data and increment i (i == 4).

... etc ...

  • Is REC different to "\n"?
  • Yes, it's A. Ok, I add that to data and increment i (i == 32767).
  • Is REC different to "\n"?
  • Yes, it's A. Ok, I add that to data and increment i (i == -32768).
  • Is REC different to "\n"?
  • Yes, it's A. Ok, I add that to data and increment i (i == -32767).

... and so on ...

You have nothing to say "I have used the character that is currently in REC".

What you should instead be doing is clearing REC after each time you have consumed a character:

if (REC != 0) {
    if (REC == '\n') {
        // do whatever you want with the array contents
        i =0;
        data[0] = 0;
    } else {
        data[i++] = REC;
    }
    REC = 0;
} 

You should also check that i never gets too big and overflows your array.

An even better system would be to add the incoming character direct to the data array in the interrupt routine. When you receive a \n you set a flag to tell the main loop that it's free to use the contents of the array (don't forget to clear that flag when you've used the contents).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.