UART read string question - Page 1
Forum section: electronics / beginners

author: DuncanSteel
author_rank: Contributor
timestamp: March 17, 2017, 11:35:09 pm
content: HiI would like to understand how can I retrieve a string from UART receiver of the UDR1 register (Atmega32u4). I`am able to do it 1 character at the time, but I cant figure out how to get a whole string.I mean how is the data stored in the UDR1? Does it always contain only 1 char?For example lets say i send 1x3n, what is inside UDR1 ?Code:char INPUT;ISR(USART1_RX_vect){for(int8_t i=0;i>=2;i++){char ch = UDR1;INPUT = ch;}UCSR1B = (0 <<RXCIE1)|(0 <<RXEN1)|(1<<TXEN1); // disable recieverUART_SendString(INPUT);}

author: rstofer
author_rank: Super Contributor
timestamp: March 17, 2017, 11:49:46 pm
content: Right, the UART only stores the most recent char. It is your responsibility to store it in an array (string) and terminate the string with a '\0'.There are two ways of doing this that don't block the program: First, use a superloop that calls all the external functions, one at a time. One of those will handle the UART. None of the external functions can take a lot of time. If they do, change them into a state machine and do one small part on each pass (switch statement and remember where you are).Second, and the right way to do it, is to have the UART interrupt on received char. The interrupt handler will put the char in a circular buffer and possibly increment a counter. If the counter is above 0 in the superloop test, grab one char (or more) and decrement the counter. You MUST disable interrupts before you manipulate the counter and enable after.There are other ways to implement a circular buffer, you can Google for them.

author: danadak
author_rank: Super Contributor
timestamp: March 18, 2017, 12:45:01 am
content: "Normally" one has an interrupt routine where the character isstored into a string variable in memory using a ptr. ptr is usedto minimize latency in the ISR. Declare any variables used in ISRexternally as volatile. Usually a flag is set and serviced external toISR to service the string memory. eg detection of end of string, overflow,clear, ptr reset......http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-KeywordVolatilehttp://www.embedded.com/design/programming-languages-and-tools/4397803/Interrupts-short-and-simple--Part-1---Good-programming-practicesAs an aside many high performance processors have DMA capabilities, whichcan automate handling of UART buffer and ancillary string buffer for use. LikeCypress PSOC 3 or 5LP families. Even detection of special characters and actingon their receipt. All done in HW. Or mixed code + HW.Regards, Dana.

author: FreddyVictor
author_rank: Regular Contributor
timestamp: March 18, 2017, 08:57:59 am
content: as mentioned by earlier posters, your best approach is to use an interrupt handlerwhich you have:Code:ISR(USART1_RX_vect){// some codechar c = UDR1;}if setup correctly, the above function will get called each time a character is received - but note this is when1 character is receivedtherefore, you will need to buffer/store these into an array for later processing.How do you know when you have received this string ?Well, strings are usually null-terminated, but, the null character is not usually sent - most put-string functions only send up until the null-character is found but then stop.The sender must append a 'string-end' character, typically a 0x0A (LineFeed) is used.So, you'll need to look for this character to trigger processing of the string held in your arrayYou need to make some decisions, how long is the string you expect (size of the array) to receive and make sure that it cannot overflow.when you receive the complete string, you'll need to decide what you want to do:whether you want to process the string immediately - ok if this is very shortcopy this string somewhere else for later processingor simply turn-off the Rx interrupt until you have processed the string - at risk of losing new data tho'HTH

author: DuncanSteel
author_rank: Contributor
timestamp: March 18, 2017, 10:09:32 am
content: Quote from: FreddyVictor on March 18, 2017, 08:57:59 amOh ok I get it, it generates interrupt every time a char is received. So if I send 1n3x5 it will generate 5 interrupts & UDR1 value will always be only 1 char. I was looking for this answer.Thank you for clarification.That code by the way gets stuck in an infinite loop for some reason.

author: danadak
author_rank: Super Contributor
timestamp: March 18, 2017, 11:26:41 am
content: Sounds like you did not clear UART isr flag or bitafter reading the character, so upon exit it re-interrupts. MostUARTS clear the flag upon byte read for you.Usually you disable the ISR when first entering the routine as well.Depends on part you are using. Vendor usually has example codeyou can look at to see how ISR UART is handled vs polled operation.http://www.avrfreaks.net/forum/tut-soft-using-usart-interrupt-driven-serial-comms?page=allRegards, Dana.

author: FreddyVictor
author_rank: Regular Contributor
timestamp: March 18, 2017, 02:06:29 pm
content: Quote from: DuncanSteel on March 18, 2017, 10:09:32 amOk 1st rule of coding wrt interrupts is: don't put any processing into an interrupt handler that takes any appreciable time !especially delays!by doing the delay, you will miss all other interrupts !best technique is to have a volatile flag which you set inside the ISR and then back in main function code check the status ofanother point:Code:PORTC = (1<<PORTC6); // this worksPORTC = (0<<PORTC6); // strangely this doesn't !!to clear a flag, you need to do this:PORTC &= ~(1<<PORTC6); // nb: this clears pin6 but leaves the rest as they wereregarding danadak's point "you did not clear UART isr flag or bit", this is not necessary for this particular chip, but it is a relevant point for other chips.The process of reading the UDR1 variable re-sets the flag.