Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

AVR GCC - Any comfortable way of controlling single IO pins ?

Status
Not open for further replies.

ItsMike

New Member
Hey everyone.

I'm looking for a macro/function with no (or minimal) performance loss to control single IO pins using this syntax:

Writing:

PB0=<value>;
Where value can be anything, any value not 0 would be regarded as 1 (logic high).

Reading:

<variable>=PB0;
 
Last edited:
Such functions already exist within C, for both read and write. If you need anything within a few cycles of the chip speed for importance you can't use C, you'd have to use ASM.
 
You can have some fun with this.

Compilers should know how to use bit set, clear, and test instructions. But having any non zero value as one prevents the use of bit test.

For fun compile this code and see which line results in the fewest instructions by looking at the ASM listing generated.

Code:
  char a;
  PB0 = !!a; // first logical not converts to inverted bool, second un-inverts the value
  PB0 = ~!a; // first logical not converts to inverted bool, bit not un-inverts
  PB0 = a>0;

All 3 lines should give the same result but the compiler is free to figure out how. Be sure to try it with optimization too.
 
In Code Vision you can do this by PORTB.0=1; // Will set the first Pin of PORTB
If that should effect at GCC you should try yourself.
 
Code:
//Macro's
#define SetPin(Port, Bit)    Port |= (1 << Bit)
#define ClearPin(Port, Bit)    Port &= ~(1 << Bit)

//Allows you to do the following in code...
SetPin(PORTB, PB3);   //Sets bit 3 on port B
ClearPin(PORTA, PA1);  //Clears bit 1 on port A

Accessing a single bit as a complete variable (as in PB0 = 0 for example) is not possible in true C. It's an extra gimmick added to some compilers but avr-gcc follows the true C standard so the above method is the only option. It does end up as sbi, cbi instructions tough, the compiler is smart enough for that.

In order to set the pin on any nonzero value , and clear it when zero do the following:
Code:
if (Value)
    SetPin(PORTA, PA1);
else
    ClearPin(PORTA, PA1);

If you need to use this a lot, you can put the whole thing in a macro like this:
Code:
#define PinVal(Port, Bit, Val)    Port = Val ? Port | (1 << Bit) : Port & ~(1 << Bit);

//Allows you to do the following in code
PinVal(PORTB, PB3, Value); //Will set bit 3 on port B if Value is nonzero, clear otherwise.
 
Last edited:
These are my macros:

Code:
#ifndef cb
    #define cb(reg, bit)    reg &= ~(1<<bit) //clear bit
#endif

#ifndef sb
    #define sb(reg, bit)    reg |= (1<<bit) //set bit
#endif

#ifndef rb
    #define rb(reg, bit)    (reg & (1<<bit)) //read bit
#endif

and examples of use:

Code:
int main(void)
{
    sb(DDRB, 0); //port b 0 as output for led

    while(1)
    {
        if( rb(PIND, 2) )
        {
            sb(PORTB, 0); //led on
        }
        else
        {
            cb(PORTB, 0); //led off
        }
    }
}
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top