Yahoo Groups archive

AVR-Chat

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

Thread

accessing bits (e.g. of ports)

accessing bits (e.g. of ports)

2005-01-31 by stefan_trethan

Hi,

what is the easiest way to access single bits of ports (SFRs)?

i have found <http://lists.gnu.org/archive/html/avr-libc-dev/2003-08/
msg00020.html> with google.

This: 
PORTC |= _BV(0);.
is madness ;-). I'm doing this for a hobby and stuff like that causes 
me to loose my interest in it. I need to think 30 minutes until i know 
what i have to write, and then i probably got it wrong.

this:
bit_set(PORTC, _BV(0));
is better, but still complicated in a way that boggles my mind.

Why, and if yes how, can i get something like that:
PORTC.0 = 1;
or
PC0 = 1;
or if it must be
PORTC.BIT0 =1;

or whatever, just UNDERSTANDABLE for the mind of a non-programmer.

I do not shy the typing work, but even with comments if i don't 
understand the code it is like reading a book in a foreign language 
you don't speak using a dictionary. (But i'm trying to WRITE that 
book!!)

You see my problem, please help, i'm getting so frustrated here....

ST

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Paul Maddox

Stefan,

> Why, and if yes how, can i get something like that:
> PORTC.0 = 1;
> or
> PC0 = 1;
> or if it must be
> PORTC.BIT0 =1;

why don't you use #define?
to do some of this?

A lot depends on your compiler, for example CV-AVR is happy with ;-
PORTC.0 = 1;

PAul

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Paul Maddox

Sven

> #define setbit(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT)))
> #define clrbit(ADDRESS,BIT) ((ADDRESS) &= ~(1<<(BIT)))
> #define chkbit(ADDRESS,BIT) ((ADDRESS) & (1<<(BIT)))
> #define togglebit(ADDRESS,BIT) ((ADDRESS) ^= (1<<(BIT)))

a very neat soloution!

Paul

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Stefan Trethan

On Mon, 31 Jan 2005 12:31:51 -0000, Paul Maddox  
<P.Maddox@signal.qinetiq.com> wrote:

>
> Stefan,
>
>> Why, and if yes how, can i get something like that:
>> PORTC.0 = 1;
>> or
>> PC0 = 1;
>> or if it must be
>> PORTC.BIT0 =1;
> why don't you use #define?
> to do some of this?
> A lot depends on your compiler, for example CV-AVR is happy with ;-
> PORTC.0 = 1;
> PAul


I use gcc.
It doesn't accept PortC.0 = 1;

In the IO.H (for the chip) there is a section, e.g.


/* DDRB */
#define DDB7	7
#define DDB6	6
#define DDB5	5
#define DDB4	4
#define DDB3	3
#define DDB2	2
#define DDB1	1
#define DDB0	0

I wonder what it is good for?


I would use define if i could figure out how ;-)

ST

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Svenn Dahlstrøm

I use ICCAVR and do it this way :

#define setbit(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT)))
#define clrbit(ADDRESS,BIT) ((ADDRESS) &= ~(1<<(BIT)))
#define chkbit(ADDRESS,BIT) ((ADDRESS) & (1<<(BIT)))
#define togglebit(ADDRESS,BIT) ((ADDRESS) ^= (1<<(BIT)))

and write code like this :

setbit(PORTA, 2);
togglebit(PORTB, 6);
clrbit(DDRC, 0);

And this can be used to set, clear, check or toggle one bit on any register 
or variable.

Svenn
Show quoted textHide quoted text
>
>
> Hi,
>
> what is the easiest way to access single bits of ports (SFRs)?
>
> i have found <http://lists.gnu.org/archive/html/avr-libc-dev/2003-08/
> msg00020.html> with google.
>
> This:
> PORTC |= _BV(0);.
> is madness ;-). I'm doing this for a hobby and stuff like that causes
> me to loose my interest in it. I need to think 30 minutes until i know
> what i have to write, and then i probably got it wrong.
>
> this:
> bit_set(PORTC, _BV(0));
> is better, but still complicated in a way that boggles my mind.
>
> Why, and if yes how, can i get something like that:
> PORTC.0 = 1;
> or
> PC0 = 1;
> or if it must be
> PORTC.BIT0 =1;
>
> or whatever, just UNDERSTANDABLE for the mind of a non-programmer.
>
> I do not shy the typing work, but even with comments if i don't
> understand the code it is like reading a book in a foreign language
> you don't speak using a dictionary. (But i'm trying to WRITE that
> book!!)
>
> You see my problem, please help, i'm getting so frustrated here....
>
> ST
>
>
>
>
>
>
>
> Yahoo! Groups Links
>
>
>
>

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Stefan Trethan

On Mon, 31 Jan 2005 14:21:19 +0100, Svenn Dahlstrøm <svenn@symetrics.no>  
wrote:

> I use ICCAVR and do it this way :
> #define setbit(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT)))
> #define clrbit(ADDRESS,BIT) ((ADDRESS) &= ~(1<<(BIT)))
> #define chkbit(ADDRESS,BIT) ((ADDRESS) & (1<<(BIT)))
> #define togglebit(ADDRESS,BIT) ((ADDRESS) ^= (1<<(BIT)))
> and write code like this :
> setbit(PORTA, 2);
> togglebit(PORTB, 6);
> clrbit(DDRC, 0);
> And this can be used to set, clear, check or toggle one bit on any  
> register
> or variable.
> Svenn


i like that. It's still not as clear to me as e.g. PORTB.1 but it is a very
good solution already.

thanks

ST

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Leon Heller

----- Original Message ----- 
Show quoted textHide quoted text
From: "Stefan Trethan" <stefan_trethan@gmx.at>
To: <AVR-Chat@yahoogroups.com>
Sent: Monday, January 31, 2005 3:13 PM
Subject: Re: [AVR-Chat] accessing bits (e.g. of ports)


>
> On Mon, 31 Jan 2005 09:47:49 -0500 (EST), <ethan@bufbotics.org> wrote:
>
>>
>> <code>
>> if (turn_motor_on) {
>>    setbit(MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
>> } else {
>>    clrbit(MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
>> }
>> </code>
>> Personally, I would prefer something like.....
>> <code>
>> write_bit(turn_motor_on, MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
>> </code>
>
> You could make that with a define i think. I guess even i could figure out
> how eventually.
>
> But well, wouldn't it be great if one could just write
>
> MOTOR_ENABLE_PIN = turn motor on;
>
> or, if need be
>
> MOTOR_ENABLE_PORT.MOTOR_ENABLE_BIT = turn motor on;
>
>
> I have the same situation here.
> I don't understand why that doesn't work. I'm no programmer as everyone
> sees easily, but when reading various stuff i get the impression "well, if
> you don't use bit operations you aren't a proper programmer, get lost.".
> That might well be true, and i'm not a proper programmer, but i still
> don't understand why i must fight with &|!<< to change or read a single
> bit.
> I mean, life is hard enough, why make it any harder?
>
>
> Why exactly is't a bit just a variable like for example PORTB?
> I can write PORTB=0xFF; but can't do the same with bits.

In most languages, including C, you can't manipulate individual bits 
directly in the same way as other data types like ints, chars, etc. High 
level languages don't usually know about anything smaller than a byte. You 
can manipulate individual bits in assembler. For instance:

    sbi    portb,PB2

sets bit 2 of port B

and

    cbi    portb,PB2

clears bit 2 of port B

and many embedded C compilers have language extensions that let you use 
in-line assembler by writing something like:

    asm("sbi    portb,PB2");

Leon 



-- 
No virus found in this outgoing message.
Checked by AVG Anti-Virus.
Version: 7.0.300 / Virus Database: 265.8.2 - Release Date: 28/01/2005

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by ethan@bufbotics.org

While we're on this topic, I'll add in my own "grievance".


>> #define setbit(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT)))
>> #define clrbit(ADDRESS,BIT) ((ADDRESS) &= ~(1<<(BIT)))


I use sbi() and cbi() for this, pretty much the same thing as the setbit()
and clrbit() described by Svenn.  I think sbi & cbi are built into
avr-gcc, but I'm not sure if they're deprecated or what not. Either way,
they work fine for me.

The thing I dont like is having a separate command (function, macro,
whatever) for setting and clearing.  So in my code there's lots of things
like...

<code>

if (turn_motor_on) {
   setbit(MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
} else {
   clrbit(MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
}

</code>

Personally, I would prefer something like.....

<code>

write_bit(turn_motor_on, MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);

</code>

And that magic command "write_bit()" will use the proper sbi or cbi based
upon the value of the "turn_motor_on" flag.

Is there something easily usable to achieve this functionality?


Ethan
www.bufbotics.org

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Stefan Trethan

On Mon, 31 Jan 2005 09:47:49 -0500 (EST), <ethan@bufbotics.org> wrote:

>
> <code>
> if (turn_motor_on) {
>    setbit(MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
> } else {
>    clrbit(MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
> }
> </code>
> Personally, I would prefer something like.....
> <code>
> write_bit(turn_motor_on, MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
> </code>

You could make that with a define i think. I guess even i could figure out  
how eventually.

But well, wouldn't it be great if one could just write

MOTOR_ENABLE_PIN = turn motor on;

or, if need be

MOTOR_ENABLE_PORT.MOTOR_ENABLE_BIT = turn motor on;


I have the same situation here.
I don't understand why that doesn't work. I'm no programmer as everyone  
sees easily, but when reading various stuff i get the impression "well, if  
you don't use bit operations you aren't a proper programmer, get lost.".  
That might well be true, and i'm not a proper programmer, but i still  
don't understand why i must fight with &|!<< to change or read a single  
bit.
I mean, life is hard enough, why make it any harder?


Why exactly is't a bit just a variable like for example PORTB?
I can write PORTB=0xFF; but can't do the same with bits.

ST

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Mike Perks

Stefan,

I have been following this thread with interest so let me throw in my 2 
cents.

Different program languages and assembly languages have different pros 
and cons. Some make life easier generally at the expense of abstracting 
away detail. Without trying to over generalize here, programming in C is 
very close to programming in assembler although it does save quite a bit 
of work in other places. I just want to highlight to this group that 
there are other alternatives such as BasicX and BasCom for AVR chips.

As you can see from my email id I have become quite a fan of BasicX and 
you may also find that it is more productive than what you are using 
now. Here is the BasicX equivalent for what you wanted to do:

Const Motor_Enable_Pin as Byte = 22
Const Turn_Motor_On as Byte = bxOutputHigh
Const Turn_Motor_Off as Byte = bxOutputLow
...
Sub Main()
...
    call PutPin(Motor_Enable_Pin, Turn_Motor_On)
...
End Sub

Regards,
Mike


 Trethan wrote:
Show quoted textHide quoted text
>On Mon, 31 Jan 2005 09:47:49 -0500 (EST), <ethan@bufbotics.org> wrote:
>
>  
>
>><code>
>>if (turn_motor_on) {
>>   setbit(MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
>>} else {
>>   clrbit(MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
>>}
>></code>
>>Personally, I would prefer something like.....
>><code>
>>write_bit(turn_motor_on, MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
>></code>
>>    
>>
>
>You could make that with a define i think. I guess even i could figure out  
>how eventually.
>
>But well, wouldn't it be great if one could just write
>
>MOTOR_ENABLE_PIN = turn motor on;
>
>or, if need be
>
>MOTOR_ENABLE_PORT.MOTOR_ENABLE_BIT = turn motor on;
>
>
>I have the same situation here.
>I don't understand why that doesn't work. I'm no programmer as everyone  
>sees easily, but when reading various stuff i get the impression "well, if  
>you don't use bit operations you aren't a proper programmer, get lost.".  
>That might well be true, and i'm not a proper programmer, but i still  
>don't understand why i must fight with &|!<< to change or read a single  
>bit.
>I mean, life is hard enough, why make it any harder?
>
>
>Why exactly is't a bit just a variable like for example PORTB?
>I can write PORTB=0xFF; but can't do the same with bits.
>
>ST
>
>  
>

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Leon Heller

----- Original Message ----- 
Show quoted textHide quoted text
From: "Stefan Trethan" <stefan_trethan@gmx.at>
To: <AVR-Chat@yahoogroups.com>
Sent: Monday, January 31, 2005 4:29 PM
Subject: Re: [AVR-Chat] accessing bits (e.g. of ports)


>
> On Mon, 31 Jan 2005 15:44:06 -0000, Leon Heller
> <leon.heller@dsl.pipex.com> wrote:
>
>> In most languages, including C, you can't manipulate individual bits
>> directly in the same way as other data types like ints, chars, etc. High
>> level languages don't usually know about anything smaller than a byte.
>> You
>> can manipulate individual bits in assembler. For instance:
>>    sbi    portb,PB2
>> sets bit 2 of port B
>> and
>>    cbi    portb,PB2
>> clears bit 2 of port B
>> and many embedded C compilers have language extensions that let you use
>> in-line assembler by writing something like:
>>    asm("sbi    portb,PB2");
>> Leon
>
>
> Leon, that is something that i have known, but never understood.
> You see, i see no reason why a bit shouldn't be a data type. I mean if you
> can distinguish between 8 bit and 16 bit words why not make a bit type?
> But i have heared several good programmers complain about that 
> shortcoming.
>
> But regardless of what C wants, isn't there a way of fooling it into
> cooperation?
> Isn't there _any_ way of using bits like bytes? (e.g. PB0=1; ).

You can do something like that with bit-fields and memory-mapped I/O, but 
the technique won't work for I/O as it is implemented on the AVR.

Leon 



-- 
No virus found in this outgoing message.
Checked by AVG Anti-Virus.
Version: 7.0.300 / Virus Database: 265.8.2 - Release Date: 28/01/2005

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by ethan@bufbotics.org

Mike Perks said:
>
> Const Motor_Enable_Pin as Byte = 22
> Const Turn_Motor_On as Byte = bxOutputHigh
> Const Turn_Motor_Off as Byte = bxOutputLow
> ...
> Sub Main()
> ...
>     call PutPin(Motor_Enable_Pin, Turn_Motor_On)
> ...
> End Sub
>

Mike,

Thanks for the info.  The code you lay out is definitely more readable, I
like it.

Does anybody know how to do this in avr-gcc?

Also, the more I think about it, I might just start writing some more
specific routines (either functions or macros for simpler actions) for
doing all my I/O from AVR.

I'm a Java coder at heart, and we LOVE to completely hide all
implementation detail behind pretty interfaces.  So I could "pretend" I
have interfaces if I do all my I/O via some special macros/functions I
write.

The real reason I like this approach is because, when I'm first
prototyping, perhaps I use simple functionality like when I want to turn
off an LED, I just shut it off.  But when I go to my final "production"
version of the system, maybe I want the LED-off functionality to gently
dim the LED and then shut it off.  If I used a modular code design early
on in the process (when it seems stupid to be modular since the module is
one line long), then twould become nice and easy to add in my fun changes.


Ethan
www.bufbotics.org

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Stefan Trethan

On Mon, 31 Jan 2005 09:47:06 -0600, Mike Perks <basicx@austin.rr.com>  
wrote:

>
> Stefan,
> I have been following this thread with interest so let me throw in my 2
> cents.
> Different program languages and assembly languages have different pros
> and cons. Some make life easier generally at the expense of abstracting
> away detail. Without trying to over generalize here, programming in C is
> very close to programming in assembler although it does save quite a bit
> of work in other places. I just want to highlight to this group that
> there are other alternatives such as BasicX and BasCom for AVR chips.


Thanks for the information, but my last Basic experience is WAY, WAY back  
(7 years maybe) while i used C not too long ago, so i'm not going to  
change to Basic.

ST

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Stefan Trethan

On Mon, 31 Jan 2005 15:44:06 -0000, Leon Heller  
<leon.heller@dsl.pipex.com> wrote:

> In most languages, including C, you can't manipulate individual bits
> directly in the same way as other data types like ints, chars, etc. High
> level languages don't usually know about anything smaller than a byte.  
> You
> can manipulate individual bits in assembler. For instance:
>    sbi    portb,PB2
> sets bit 2 of port B
> and
>    cbi    portb,PB2
> clears bit 2 of port B
> and many embedded C compilers have language extensions that let you use
> in-line assembler by writing something like:
>    asm("sbi    portb,PB2");
> Leon


Leon, that is something that i have known, but never understood.
You see, i see no reason why a bit shouldn't be a data type. I mean if you  
can distinguish between 8 bit and 16 bit words why not make a bit type?
But i have heared several good programmers complain about that shortcoming.

But regardless of what C wants, isn't there a way of fooling it into  
cooperation?
Isn't there _any_ way of using bits like bytes? (e.g. PB0=1; ).

thanks

ST

RE: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Larry Barello

This is easy to do and produces optimal code on GCC (e.g. sbi/cbi when
appropriate):

typedef union	// Delclare a union that allows bit & byte access
{
	unsigned char byte;		// This is a byte for 8 bit access
	struct
	{
		unsigned char P0:1;	// These are bit-fields
		unsigned char P1:1;
		unsigned char P2:1;
		unsigned char P3:1;
		unsigned char P4:1;
		unsigned char P5:1;
		unsigned char P6:1;
		unsigned char P7:1;	// We can use an anonomous struct
	};					// because the bit names are unique.
} sfr_struct;

#define PORTB (*(sfr_struct *)0x38)	// Cast the sram address to the
structure

...

#define MOTOR_ENABLE_PIN PORTB.P2	// Now make an alias for your bit

...

MOTOR_ENABLE_PIN = TRUE;		// Now, just use it.

If you want to access the port as a byte value, then use:

PORTB.byte = ...
Show quoted textHide quoted text
-----Original Message-----
From: Stefan Trethan [mailto:stefan_trethan@gmx.at]
Sent: Monday, January 31, 2005 7:14 AM
To: AVR-Chat@yahoogroups.com
Subject: Re: [AVR-Chat] accessing bits (e.g. of ports)



On Mon, 31 Jan 2005 09:47:49 -0500 (EST), <ethan@bufbotics.org> wrote:

>
> <code>
> if (turn_motor_on) {
>    setbit(MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
> } else {
>    clrbit(MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
> }
> </code>
> Personally, I would prefer something like.....
> <code>
> write_bit(turn_motor_on, MOTOR_ENABLE_PORT, MOTOR_ENABLE_PIN);
> </code>

You could make that with a define i think. I guess even i could figure out
how eventually.

But well, wouldn't it be great if one could just write

MOTOR_ENABLE_PIN = turn motor on;

or, if need be

MOTOR_ENABLE_PORT.MOTOR_ENABLE_BIT = turn motor on;


I have the same situation here.
I don't understand why that doesn't work. I'm no programmer as everyone
sees easily, but when reading various stuff i get the impression "well, if
you don't use bit operations you aren't a proper programmer, get lost.".
That might well be true, and i'm not a proper programmer, but i still
don't understand why i must fight with &|!<< to change or read a single
bit.
I mean, life is hard enough, why make it any harder?


Why exactly is't a bit just a variable like for example PORTB?
I can write PORTB=0xFF; but can't do the same with bits.

ST



Yahoo! Groups Links

Re: [AVR-Chat] accessing bits (e.g. of ports)

2005-01-31 by Stefan Trethan

On Mon, 31 Jan 2005 12:13:18 -0800, Larry Barello <yahoo@barello.net>  
wrote:

>
> This is easy to do and produces optimal code on GCC (e.g. sbi/cbi when
> appropriate):
> typedef union// Delclare a union that allows bit & byte access
> {
> unsigned char byte;// This is a byte for 8 bit access
> struct
> {
> unsigned char P0:1;// These are bit-fields
> unsigned char P1:1;
> unsigned char P2:1;
> unsigned char P3:1;
> unsigned char P4:1;
> unsigned char P5:1;
> unsigned char P6:1;
> unsigned char P7:1;// We can use an anonomous struct
> };// because the bit names are unique.
> } sfr_struct;
> #define PORTB (*(sfr_struct *)0x38)// Cast the sram address to the
> structure
> ...
> #define MOTOR_ENABLE_PIN PORTB.P2// Now make an alias for your bit
> ...
> MOTOR_ENABLE_PIN = TRUE;// Now, just use it.
> If you want to access the port as a byte value, then use:
> PORTB.byte = ...


Now that one i like.
Thanks, i will certainly use it.

ST

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.