[TUT] [C] Bit manipulation (AKA "Programming 101")

225 posts / 0 new
Last post
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks all; I'm going to use most of the above for next yr's class. And another lesson you just taught. Show Dons, BenG, and then Bingos to show writing style and how they accomplish the same thing.
I couldn’t write (copy) the curriculum without this site.
Thanks for the help and making the world a better place,
John

Resistance is futile…… You will be compiled!

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

clawson wrote:
I think this tutorial is trying to be as generic as possible. Not all the AVR C compilers have all the bit names defined in the header files for each AVR part so

TCCR1B |= (1 << CS10);

won't necessarily work on all compilers.

There's no "magic" to it anyway, a typical part definition file that does include the bit positions simply has something like (for mega16):

#define CS10    0
#define CS11    1
#define CS12    2
#define WGM12   3
#define WGM13   4
#define ICES1   6
#define ICNC1   7


Where are the definitions in AVR GCC? I am guessing in the IO header file or each header has every single part defined for only the related registers.

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

Yup in GCC all your programs include and your Makefile will define a MCU=. As a consequence of these two things it will lead to io.h choosing to pull in one of the io????.h files in \winavr\avr\include\avr\

Cliff

 

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

clawson wrote:
Yup in GCC all your programs include and your Makefile will define a MCU=. As a consequence of these two things it will lead to io.h choosing to pull in one of the io????.h files in \winavr\avr\include\avr\

Cliff


I am guessing Avr Studio is handling the making the Makefile when I compile my program. Oddly enough I don't even think I defined the correct MCU when I first created the project. I defined it as a Mega 168 and only figured out that it was a Mega 48 when my Dragon complained that the parts didn't match up. Is this because the parts are in the same data sheet?

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

There's several MAJOR difference between 48 and 168. For example one uses RJMPs for its interrupt vectors and one uses JMPs (because the entire memory is no longer reachable with an RJMP). Far more worryingly the 168 has 1K of SRAM while the 48 has 512 bytes. So the RAMEND used to initialise the stack pointer will be different between the two. I'm therefore astonished that you found that code built for a 168 worked in a 48 !?!

 

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

clawson wrote:
There's several MAJOR difference between 48 and 168. For example one uses RJMPs for its interrupt vectors and one uses JMPs (because the entire memory is no longer reachable with an RJMP). Far more worryingly the 168 has 1K of SRAM while the 48 has 512 bytes. So the RAMEND used to initialise the stack pointer will be different between the two. I'm therefore astonished that you found that code built for a 168 worked in a 48 !?!

Well the code I wrote was only five lines long and didn't use interrupts. Though I might want to make sure that the I actually did program for the 168. I don't have access to the computer I wrote the code in at the moment.

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

Another thing I've just learned, you can toggle the PORTxn pins by writhing to the PINxn register.

So instead of toggling the bits with the XOR operator, you can write to the PINxn address.

Do not know if the compiler optimization already does that?

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

But that only works on the recent AVRs, not all of them.

 

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

Quote:
BenG wrote:
As an additional item to check if a bit is clear:

Code:
if(~(foo) & 0x80)
{
}
My 1st choice would be for the following which, IMHO, is easier to "read":
Code:
if ( ( foo & 0x80 ) == 0 )
{
...
}
should result in the same compiler generated code.

Don

and another way...


if (!( foo & 0x80 )) 
{ 
  ... 
} 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know this is compiler generic, but I do have a related question:

I've been using (1<<PIN_NAME) for some time in my code, but I am working on a project now where the developer is using _BV(PIN_NAME) all over. Is there a best practice on which to use?

Jim

Jim Brain

Pages