Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

Re: [AVR-Chat] Some C help please !

2007-03-13 by Ivan Vernot

Hein,
The line  while ((UCSRA & (1<<UDRE))==0); 'decodes' as follows

Somewhere in you compilers include files there will be a definition like
#define  UDRE    5
thus  1<<UDRE is actually 1<<5

You should know that << means shift right in C.  So
1       = 0000 0001
1<<5 = 0010 0000 =  0x20

so the statement  evaluates to 'UCSRA & 0x20'
which means - read the UCSRA register and perform a logical AND with the 
value 0x20
so.
if  UCSRA = 0x10     then 0x10 & 0x20 = 0x00
if  UCSRA = 0x20     then 0x20 & 0x20 = 0x20

so,
while ((UCSRA & (1<<UDRE))==0);
means

loop while bit 5 in UCSRA  is 0
ie. wait for bit 5 in UCSRA to go high.

Why do you care abut bit 5 high? Well you'll need to look at the data sheet 
as it depends on how UCSRA  and UDRE are defined for YOUR micro.
Having said that, it is most probably that you are simply waiting for the 
UART Receive Register to be filled
ie For a byte to be received by the uart. :-)

Although it may look complicated this construct is common and a decent 
compiler will generate a very compact 'bit test then branch' code sequence

You can use a similar construct to Set and Clear bit in a byte value in 
compact and elegant manner.
For example I have macros like
#define SET_BIT(reg,bit)    (  (reg) |=     (1<<(bit)) )
#define CLR_BIT(reg,bit)    ( (reg) &= ~(1<<(bit)) )

Which allows me to set and clear bit in a more intuitive manner
i.e. You can do something like
SET_BIT(PORTA,3)
CLR_BIT(PORTC,0)

An event better approach is to use the technique to 'abstract' the control 
of I/O  doe the hardware specifics
#define LED_PKT_RXD()                (CLR_BIT(PORTC,3))    // turn on green 
led - active low drive)
#define LED_LINK_FAIL()              (CLR_BIT(PORTD,0))    // turn on RED 
led - active low drive)
#define LED_LINK_GOOD()           (SET_BIT(PORTD,0))    // turn OFF RED 
led - active low drive)

#define MOTOR_ON()                      (SET_BIT(PORTA,7))    //  active 
high drive)

#define IS_BUTTON_PRESSED()    ((PINA & (BIT(1))== 0)    // true when button 
is pressed - active low)

so in my code is have

if(IS_BUTTON_PRESSED())
{
    MOTOR_ON();
}
if(pkt_received ==TRUE)
{
    LED_PKT_RXD() ;
    LED_LINK_GOOD();
}
else
{
    LED_LINK_FAIL();
}

Thus if the hardware I/O changes I change the macros in an include file and 
no more search and replace looking for individual bit sets and bit clears


Finally a comment on 'style'
IMO having a ; at the end of the while() is to prone to error
Consider the fragment

while ((UCSRA & (1<<UDRE))==0);
{
    i++;
    printf("Waiting:%d\n",i);
}

one has to look very carefully to realise that we will not be printing  lots 
of 'Waiting N' lines!!!

When a while() is just 'spinning busy' I much prefer to explicitly show it - 
ie

while ((UCSRA & (1<<UDRE))==0)
{
    // do nothing
}


HTH
Ivan Vernot





----- Original Message ----- 
From: "kernels_nz" <kernels@slingshot.co.nz>
To: <AVR-Chat@yahoogroups.com>
Sent: Wednesday, March 14, 2007 8:52 AM
Subject: [AVR-Chat] Some C help please !


> Hi guys, Ive been programming in C for a while now, but my C tends to
> be "baby C",  in that I probably don't write things as simple as they
> can be written. . . Could someone please explain the entire purpose of
> the following line, particularly the 1<<UDRE and why a bitwise AND is
> being performed with UCSRA. I understand what the code does in the
> microcontroller, just not what the statement in the brackets is saying.
>
> while ((UCSRA & (1<<UDRE))==0);
>
> Please dont be afraid to insult me by explaining it simple, im very
> keen to improve my coding level as my jobs become more complex.
>
> Thanks
> Hein B
> Auckland, NZ
>
>
>
>
>
> Yahoo! Groups Links
>
>
>
>

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.