C code/shift bit question for mega16 application

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,
I'm working with the USART of the atmega 16, and I ran into some code in the manual which I didn't understand. The code is used for receiving a character. The code:

unsigned char receive_char(void)
{
while( !(UCSRA & (1<<RXC))
;
return UDR
}

UCSRA is an eight bit register. When receive is complete (and no errors), the register will equal 0x00. RXC is bit 7 of the UCSRA register.

So, what does 1<<RXC mean?

thanks
AG

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

there's a tutorial in the tutorial section that covers this. Something like 'bit twiddling 101'

Nevertheless, RXC will have a #define somewhere equalling it to 7, so if you move a '1' bit to the seventh position it will end up equalling 0x80

I think you'll find that RXC will equal '1' when there is a character available.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The "1<<RXC" has the same meaning as 0x80. Somewhere in a header file, you will see something like this:

#define RXC 7

So 1<<RXC means 1<<7 or 0x01 shifted left 7 bits (0x80)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

agentile wrote:

So, what does 1<<RXC mean?

thanks
AG

Check your C programming text, under bit shifts

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your help. So it is a left shift. The function of the code is obvious. I don't see why they didn't just write !(UCSRA & 0x80). Anyway, thanks again for your help.

AG

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

agentile wrote:
I don't see why they didn't just write !(UCSRA & 0x80)
Will you remember what bit 0x80 stands for in a week or two?

Stealing Proteus doesn't make you an engineer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

actually it should be !(reg()0x0098 & 0x80). this makes it perfectly obvious for the processor!

This is referred to in the computer game as 'magic numbers' - what does the number mean? who knows - it's magic of course.
The book 'Code Complete' has a very good explanation of why you want to avoid such things as well as other nasty practices.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i search alot of time to find some thing like "#define RXC 7" but i didn't find it   so for me i can't understand  "1<<RXC" = (0x80)

 

Please advise 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ahmed.ben.kamal wrote:

i search alot of time to find some thing like "#define RXC 7" but i didn't find it   so for me i can't understand  "1<<RXC" = (0x80)

 

Please advise 

Did you follow the link provided in #5 above?

For each MPU type (m328, m8, t25, ect..) there is a header file that defines the bit mask for each register and bit using the name found in the data sheet.

Look in the /include directory of your toolchain to find the defines.  But if you just use the bit name and register name found in the Datasheet, it should work for you. 

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

agentile wrote:
Thanks for your help. So it is a left shift. The function of the code is obvious. I don't see why they didn't just write !(UCSRA & 0x80). Anyway, thanks again for your help. AG

Because "Magic Numbers" (raw constants with no intrinsic meaning) are Evil. :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:
Because "Magic Numbers" (raw constants with no intrinsic meaning) are Evil. :)

 

Well, maybe not "Evil", but will you remember what the meaning of that constant is a few weeks (days, years) from now.

By using the Bit name, it makes it easy for you (or anyone else) to read the meaning of its use, with out opening up the datasheet and searching for it's meaning.

It took me awhile to break that habit of using "magic numbers", so best to not start, and learn the correct way to code.

Now if I could only stop using "char, int, long" and start using standard int's (i.e.  int8_t, int16_t), I'm working on it, really!

 

Hope that helps.

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ahmed.ben.kamal wrote:
i search alot of time to find some thing like "#define RXC 7" but i didn't find it
Where were you looking exactly?....

C:\SysGCC\avr\avr\include\avr>grep -w RXC *.h
io2313.h:#define    RXC     7
io2333.h:#define    RXC        7
io43u32x.h:#define    RXC          7
io4414.h:#define    RXC          7
io4433.h:#define    RXC        7
io4434.h:#define    RXC      7
io8515.h:#define    RXC          7
io8535.h:#define    RXC      7
io90pwm216.h:#define RXC     7   /* USART Receive Complete */
io90pwm2b.h:#define RXC 7
io90pwm316.h:#define RXC     7   /* USART Receive Complete */
io90pwm3b.h:#define RXC 7
io90pwmx.h:#define RXC     7   /* USART Receive Complete */
iocanxx.h:#define    RXC          7
iom103.h:#define    RXC          7
iom128.h:#define    RXC          7
iom16.h:#define RXC     7
iom161.h:#define RXC    7
iom163.h:#define RXC    7
iom165.h:#define RXC     7
iom169.h:#define RXC    7
iom16a.h:#define RXC 7
iom32.h:#define RXC     7
iom323.h:#define RXC    7
iom32a.h:#define RXC     7
iom64.h:#define    RXC          7
iom8.h:#define RXC      7
iom8515.h:#define    RXC          7
iom8535.h:#define    RXC          7
iom8a.h:#define RXC     7
iotn2313.h:#define RXC     7
iotn2313a.h:#define RXC 7
iotn4313.h:#define RXC 7
iotn828.h:#define RXC     7

Now admittedly that is for avr-gcc but I think you are going to find that most C compilers have something very similar.

 

When you write code for AVR (in avr-gcc) you start most programs with:

#include <avr/io.h>

uint8_t UART_get() {
    while(!(UCSRA & (1 << RXC)));
    return UDR;
}

That <avr/io.h> includes a header file that works for ALL the AVRs. However when you build you also say something like -mmcu=atmega16. In turn that leads the compiler to internally define a symbol "__AVR_ATmega16__" and within avr/io.h it has something like:

#elif defined (__AVR_ATmega16__)
#  include <avr/iom16.h>
...

so for atmega16 that causes iom16.h to be used and then finally (from my search above):

iom16.h:#define RXC     7

So when building for an atmega16 the symbol RXC is defined as 7. So in my code:

uint8_t UART_get() {
    while(!(UCSRA & (1 << RXC)));
    return UDR;
}

the RXC here is replaced with 7 so this becomes:

uint8_t UART_get() {
    while(!(UCSRA & (1 << 7)));
    return UDR;
}

and (1 << 7) is the value 0x80. So this is the same as:

uint8_t UART_get() {
    while(!(UCSRA & 0x80));
    return UDR;
}

But (1 << RXC) is so much more useful to the reader. He might not have a clue what 0x80 means but reading (1 << RXC) there is little doubt this is the Receive Complete (RXC) bit that is being tested.

Last Edited: Thu. Oct 5, 2017 - 03:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ahmed.ben.kamal wrote:
i search alot of time to find some thing like "#define RXC 7" but i didn't find it 

Really?

 

What IDE are you using?

 

Any decent IDE today would have the facility to simply select an identifier and "Go To Definition". If your can't do that, then throw it away and get a decent one!