Tips for multi µC code?

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

Hi 'freaks,

I can controll my LCD for error codes. Now I'm going to write a bit-bang communication to drive it. The functions will be included via .h and .c files into the "to be debugged" programm.

My question is: do you have tips for writing code that can be easily compiled for different (AVR) microcontrollers? I do know about the #if, #endif etc compiler instructions but never used them.

Well, maybe there is no need for #if at all, since I only bit-bang two GPIO pins and use some nops for timing. I'll use #define for the port names though. It's an interesting issue anyway and I appreciate any link or comment :)

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

As you appear to be using GCC then you can do the same trick that does:


#elif defined (__AVR_ATmega103__)
#  include 
#elif defined (__AVR_ATmega32__)
#  include 
#elif defined (__AVR_ATmega323__)
#  include 
#elif defined (__AVR_ATmega324P__)
#  include 
#elif defined (__AVR_ATmega325__)
#  include 

For ever model of AVR you'll see a __AVR_?????__ entry listed there. You can use these in your own code by using something like:

#ifdef __AVR_variant1__
 // code for variant 1
#elif defined (__AVR_variant2__)
 // code for variant 2
#endif

This works because somewhere in the Makefile or Project configuration the user identifies which model of AVR they are using (such as "ATmega16") then this is passed to the compiler as a "-mmcu=ATmega16" and a look-up table inside the compiler then translates this to the appropriate internal macro such as __AVR_ATmega16__ entry that you can then use in the #ifdef

Cliff

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

Thanks Cliff, this looks very usefull. Especially for hardware initializations like UART.

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

I use it quite a lot myself so I can build the same code both for the target AVR I actually want to use and also a second one that is supported by the much more accurate simulator V2. I then build the code for that "modern" AVR when I just want to check some operation in the simulator then just change the target of the build to the real silicon when building the actual program to put into the device. Modern AVRs (like 48/88/168) have things like UDR0 while older AVRs have just UDR so I'd use something like:

#ifdef __AVR_ATmega168__
  UDR0 = c;
#elif defined(__AVR_ATmega16__)
  UDR = c;
#endif

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

You can also write some #defines to "normalize" some of the register differences between devices. Doing so can reduce the amount of conditional code that appears in your .c files. For example:

#if !defined(UDR0)
#define UDR0 UDR
#endif

Similar #defines can be written for differences in timer registers, etc.

If you want to further reduce the use of conditionals in .c files you can write other macros to account for the differences between AVR devices as needed by your application. Of course, some would argue that this constitutes overuse of the preprocessor but it's up to you to choose the course that best meets your needs.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

Last Edited: Wed. Aug 19, 2009 - 02:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Overuse of the preprocessor... I once worked with a CANopen library that seemed to use macro and token pasting magic to turn a regular C compiler into a C++ one :)

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

uh yeah, that's a good idea. I saw some code that consisted to like 70% of preprocessor directives.

I heard another story like that, jayjay. Some guys were using ASM for a long time. They wrote so many macros that their ASM turned into some kind of C ^^

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

PS:
got my first selfmade precompiler directives working :)

#define DEBUG 1
#if (DEBUG == 1)
    #define short_time 0
#endif