Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

understanding usart code

Status
Not open for further replies.

anhnha

Full Member level 6
Full Member level 6
Joined
Mar 8, 2012
Messages
322
Helped
4
Reputation
8
Reaction score
4
Trophy points
1,298
Activity points
3,684
Could anyone help me explain why the code in 2 is better than 1. I see no difference between them.
1)
UDR = ByteToSend; // Send out the byte value in the variable "ByteToSend"
while ((UCSRA & (1 << TXC)) == 0) {}; // Do nothing until transmission complete flag set
2)
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
UDR = ByteToSend; // Send out the byte value in the variable "ByteToSend"
This code is from this page: https://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=45341&start=0
it has a explaination but I still can't understand it.
 

hi, i think these codes are used inside a main loop and i think code 2 is better because it let's you do things while transmitting, but using code 1, you'd have to wait until after transmission to do anything else.

let's say it takes 1 second to transmit a byte.

using #1, you'd have to wait until after transmission is done to proceed with the next line of code, meaning you'd have to wait for 1 second before proceeding. you would have to wait for 1 second every time the main code loops and reaches this part of the code.

looking at #2, let's assume that you are transmitting a byte for the first time. using the second code, the program will immediately transmit a byte since UDRE is = 0 and UDR is still empty. it will take 1 second to transmit this byte but in the mean time, you can do other things and you wouldn't have to wait for the transmission to finish to proceed. if the rest of the code in the main loop takes less than 1 second to loop back to while ((UCSRA & (1 << UDRE)) == 0) {};, you'd still have to wait before proceeding since transmission is still not finished, but the time to wait would definitely be less than 1 second (or whatever the transmission time) which is why #2 is better than #1.
 
  • Like
Reactions: anhnha

    anhnha

    Points: 2
    Helpful Answer Positive Rating
Thanks for help!
I hope this doesn't make you angry, I still don't really get it.
For example with code #2:
Code:
void main()
{
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it 
UDR = ByteToSend; // Send out the byte value in the variable "ByteToSend"
//bellow is the code of main program
..........................................................................................................
..........................................................................................................
..........................................................................................................
}
let's again say it takes 1 second to transmit a byte. The program do nothing until UDR is ready for more data to be written to it. Then UDR register is empty ByteToSend is sent and it take 1 second to send it.
it will take 1 second to transmit this byte but in the mean time, you can do other things and you wouldn't have to wait for the transmission to finish to proceed.
Can you explain it more detail?I think that the program can't do anything else until the transmission of the byte is finished.
For code in #1:
Code:
UDR = ByteToSend; // Send out the byte value in the variable "ByteToSend" 
while ((UCSRA & (1 << TXC)) == 0) {}; // Do nothing until transmission complete flag set
Why this code work?
In my opinion, firstly ByteToSend is sent and it take 1 second to do it. But I don't understand why we need the code:
Code:
while ((UCSRA & (1 << UDRE)) == 0) {};
I think that after the statement UDR = ByteToSend; is finished then it is sure that UDR register is empty and therefore this code isn't work.
 

sorry, what i meant was that when these codes are used in a "never-ending loop" (wasn't really refering to main(){})
using code #2:

Code:
main(){

while(1){                                                //start of never-ending loop

while ((UCSRA & (1 << UDRE)) == 0) {};      // every time the program returns to this line, it determines if transmission is 
                                                           //already done. the 1 second required may already have elapsed and you no longer have to do any more waiting.  
UDR = ByteToSend;                                 // Send out the byte value in the variable "ByteToSend"
                                                            
//rest of the loop. notice that there is no 'waiting' done after the transmit instruction
 the program continues [I]while[/I] the byte is being transmitted, so while 
the 1 second required is ellapsing, other instructions can be carried performed. if this part takes longer than 1 second, than you can
be sure that by the time you return to the beginning of the loop, the usart module will be ready for transmission again and you no longer have to wait
..........................................................................................................
..........................................................................................................
..........................................................................................................
//


} //return to beginning of the loop. 

}
comparing it to #1:

Code:
main(){


while(1){                                                //start of never-ending loop

UDR = ByteToSend; // Send out the byte value in the variable "ByteToSend"
while ((UCSRA & (1 << TXC)) == 0) {}; // Do nothing until transmission complete flag set. everytime the loop
					//returns to this line, you will always have to wait until after tranmission
//is complete before proceeding. this is why it is less efficient than code #2 

//bellow is the rest of the loop

..........................................................................................................
..........................................................................................................
..........................................................................................................

} //return to beginning of loop

}


Why this code work?
In my opinion, firstly ByteToSend is sent and it take 1 second to do it. But I don't understand why we need the code:
Code:

while ((UCSRA & (1 << UDRE)) == 0) {};

I think that after the statement UDR = ByteToSend; is finished then it is sure that UDR register is empty and therefore this code isn't work.

no, UDR=ByteToSend; will only load the UDR register and begin transmission and will immediately proceed to the next instruction. that's why you check UDRE to make sure UDR is empty before transmitting again. the main difference between code #1 and #2 is that in code #1, the waiting is done after UDR is loaded, while in code #2 the waiting is done before UDR is loaded again.

code #1:
start of loop>>load UDR and begin transmission>>wait until transmission is done>>proceed with rest of loop>>return to beginning of loop

code #2:
start of loop>>check if UDR is empty before loading>>load UDR and begin transmission>>proceed with rest of loop>>return to beginning of loop
 
  • Like
Reactions: anhnha

    anhnha

    Points: 2
    Helpful Answer Positive Rating
Thank you for your time!
I get it now.:-D
I think that the most problem of my is that:
UDR=ByteToSend; will only load the UDR register and begin transmission and will immediately proceed to the next instruction. that's why you check UDRE to make sure UDR is empty before transmitting again.
After understanding it, I can easily get what you want to say.
Again thanks for great answer!
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top