Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
gatoruss
PostPosted: Jan 01, 2010 - 02:56 PM
Wannabe


Joined: Feb 16, 2008
Posts: 75


First of all - I would like to wish a safe and happy new year and a prosperous 2010 to everyone.

I have a question about clearing bits. I am sorry if this is a stupid question, but I wanted to confirm that I am understanding the following concept regarding "clearing" a bit.

abcminiuser wrote:
To clear bit 0 in foo requires 2 bit operators:

Code:
foo = foo & ~0x01;


This uses the AND operator and the NOT operator. Why do we use the NOT operator? Most programmers find it easier to specify a mask wherein the bit that they are interested in changing, is set. However, this kind of mask can only be used in setting a bit (using the OR operator). To clear a bit, the mask must be inverted and then ANDed with the variable in question. It is up to the reader to do the math to show why this works in clearing the desired bit.

In the case of clearing the 0 bit, instead of "ANDing" the 0 bit against the complement of 0x01, couldn't you just "AND" it against 0x00? Further, if you were clearing the 3rd bit, for example, couldn't you "AND" it against 0b11111011?

Is the answer that you can do this, but it just isn't "good form?" And, as clawson says above:
clawson wrote:
Try to get away from 0b???????? - that's the whole point of bit shifts - you don't need to know or care what the other 7 bits are doing when you access just a single bit.


I am just trying to confirm that there isn't some other, more fundamental reason, why you need to "AND" the bit against the complement?

Thanks.

_________________
Russ
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Jan 01, 2010 - 08:28 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18520
Location: Lund, Sweden

Quote:

couldn't you just "AND" it against 0x00?

No, as that would clear the whole byte.
Quote:

if you were clearing the 3rd bit, for example, couldn't you "AND" it against 0b11111011?

Absolutely, but, I would consider that less clear than anding it with ~0b00000100, which in tuen is less clear than ANDing it with ~(1<<2).

I guess it is a matter of getting used to the notation. For a beginner it might be clearer with 0b00000100, but most of us think "I want to manipulate bit 2 and once you get used to 1<<2 for that, where the "two" is spelled out so to say, then this technique is less error prone.

Sooner or later you start to use symbolic bit number for a lot of things, eg the different bits in the registers for eg timer and then you start to write things like
Code:

((1<<WGM01) | (1<<WGM00))


which says a lot more about what you are doing than eg

Code:
0b00011000


Add to this that the "0b" notation is not standard C and the argument in favour of the shift-notation becomes rather strong.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
gatoruss
PostPosted: Jan 01, 2010 - 09:31 PM
Wannabe


Joined: Feb 16, 2008
Posts: 75


JohanEkdahl wrote:
Quote:

couldn't you just "AND" it against 0x00?

No, as that would clear the whole byte.

Embarassed Yes, I guess you would have to "AND" it against 0b11111110 or 0xFE.

Thanks, for your response. Doing it the way I suggested seems like it would be more work, as you would essentially be calculating the complement in your head.

_________________
Russ
 
 View user's profile Send private message  
Reply with quote Back to top
Internetwarrior
PostPosted: Jan 29, 2010 - 05:26 PM
Newbie


Joined: May 06, 2009
Posts: 12
Location: Stockholm, Sweden

Just for new users:
When a bit is checked, the "PINA" must be used.
I.E. #define foo_input PINA,0.

In the same manner "PORTA" are used when bits are set or cleared.
I.E. #define foo_output PORTA,1

Correct me someone if I'm wrong

/Sebastian
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Jan 29, 2010 - 08:33 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 13815
Location: Vancouver, BC

You are correct about the function of the ports is correct. But your defines will work only in assembly, not C which is the focus of this thread.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
Internetwarrior
PostPosted: Jan 31, 2010 - 10:08 PM
Newbie


Joined: May 06, 2009
Posts: 12
Location: Stockholm, Sweden

I'm not sure what you mean by this, please elaborate.
I have been coding C for some time and these kind of definitions work perfectly when I.E. C_CLEARBIT expects only one argument, which is the whole idea.

I might be wrong as usual, but it has worked for a few years now.
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Jan 31, 2010 - 10:18 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 13815
Location: Vancouver, BC

Quote:
I'm not sure what you mean by this, please elaborate.

In what context do you think that PINA,0 will generate legal C syntax? Perhaps it is you who should elaborate as to how C_CLEARBIT is defined.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
Internetwarrior
PostPosted: Jan 31, 2010 - 10:33 PM
Newbie


Joined: May 06, 2009
Posts: 12
Location: Stockholm, Sweden

These were defined earlier in the thread:
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define VARFROMCOMB(x, y) x
#define BITFROMCOMB(x, y) y
#define C_CLEARBIT(comb) CLEARBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))

"PORTA" replaces x which replaces ADDRESS while "1"
replaces y which replaces bit, both in the CLEARBIT definition ->

(PORTA &= ~(1<<1))

Bad syntax or good syntax, I dunno, it works though...
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Feb 01, 2010 - 01:58 AM
10k+ Postman


Joined: Nov 17, 2004
Posts: 13815
Location: Vancouver, BC

I guess it is just that I would not use such trash in my programs. I have never seen the point of using 5 separate macros to generate one very simple line of code, particularly when most of those macros are simply designed to get around the limitations of macros. The define of PINA,0 makes sense only in the very specific circumstance of this particular sequence of macros.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
Internetwarrior
PostPosted: Feb 01, 2010 - 07:26 AM
Newbie


Joined: May 06, 2009
Posts: 12
Location: Stockholm, Sweden

Sure, I agree, it is not pretty with all these macros.
However, it's nice to only use one simple argument when dealing with almost 100IO's, especially if I have to change pins.
But I don't have to tell you that.

If you have a simpler/prettier way of doing the very same thing please enlighten me.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Feb 01, 2010 - 09:32 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62220
Location: (using avr-gcc in) Finchingfield, Essex, England

I still don't get your argument. How is:
Code:
C_CLEARBIT(PORTA,5);

any clearer than:
Code:
PORTA&=~(1<<5);

It's actually MORE typing so it doesn't simplify the text entry for the programmer. Also the second line will be immediately familiar to any C programmer (perhaps once they've read this thread? Wink) while the former will require even the most seasoned professional to go digging through .h files to unwind the layers of the onion. This does not make for easily readable/maintainable code (which should be the goal of all programmers - especially those who plan to do it professionally).

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Feb 01, 2010 - 11:33 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18520
Location: Lund, Sweden

It has been argued here from time to time that the abstraction could be placed slightly higher than the "set/clear bit" level. Instead of letting you application code be full of

Code:
C_CLEARBIT(PORTx, n)


you would write a thin hardware abstraction layer, eg

Code:
LED_ON()


Now, the details on where the LED is wired up are in one place, and now it makes even less sense to use the C_CLEARBIT() construct, as you only in one place have (sketchy)

Code:
inline void LED_ON() { PORTB &= ~(1<<5); }
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Koshchi
PostPosted: Feb 01, 2010 - 07:25 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 13815
Location: Vancouver, BC

Not only is the method that Johan showed more readable, it is far more safe. With the macros you could easily do this:
Code:
C_CLEARBIT(foo_input);

and the preprocessor wouldn't bat an eye, even though the clearing of bit 0 in PINA doesn't make any sense at all.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
BadGranola
PostPosted: Mar 13, 2010 - 10:25 PM
Rookie


Joined: Sep 16, 2009
Posts: 39


what does it mean when the left shift operation is used in statements such as this?

Code:
REG |= (1<<BIT)


or

Code:
if(REG & (1<<BIT)){}


where BIT is a bit belonging to the register REG.

this use seems to differ from your examples of building a bit mask such as:

Code:
(0x01<<2)


which sets bit number 2 of an 8-bit mask.

Thanks
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 13, 2010 - 10:31 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62220
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

what does it mean when the left shift operation is used in statements such as this?

Have you actually READ this thread? It gives a total and unequivocal explanation of this - that's the WHOLE POINT of the tutorial (to save having to explain it to the 1 millionth newbie)

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Mar 13, 2010 - 10:34 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18520
Location: Lund, Sweden

Quote:

what does it mean when the left shift operation is used in statements such as this?

Code:
REG |= (1<<BIT)

Surprise: The answer to your question is on page 1 of this thread, more specifically in a post by "clawson" made on Jun 28, 2007.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
syberraith
PostPosted: Mar 18, 2010 - 02:49 PM
Wannabe


Joined: Mar 14, 2010
Posts: 60


danni wrote:
Another approach:

I like it to access bit variables like any other variables and then I can write:

if(i == 1)
if(i == 0)
i = 0;
i = 1;

which looks easy readable for me.

This can easy be done by casting a portbit as a member of a bit field.

On the attachment there is the definition of the macro SBIT.

Following an example code:


Code:

#include <io.h>
#include "sbit.h"


#define KEY0            SBIT( PINB, 0 )
#define KEY0_PULLUP     SBIT( PORTB, 0 )

#define LED0            SBIT( PORTB, 1 )
#define LED0_DDR        SBIT( DDRB, 1 )


int main( void )
{
  LED0_DDR = 1;         // output
  KEY0_PULLUP = 1;      // pull up on

  for(;;){

    if( KEY0 == 0 )     // if key pressed (low)
      LED0 = 0;         // LED on (low)
    else
      LED0 = 1;         // LED off (high)
  }
}


Naturally this macro can also be used for internal flag variables, not only for IO registers.


Peter


Hi Everybody,

I'm just getting started with micro-controllers and have pieced together a little learning project for myself from various tutorials to match what I have available to work with, namely VMLAB and WinAVR. I have found some interesting results using this:

Code:
R0 VDD RESET 4.7K
R1 N001 PB1 300
R2 N002 PB3 300
D1 VDD N001
D2 VDD N002
K1 VSS PB0
K2 VSS PB2 MONOSTABLE(30u)
Code:
#include <avr\sbit.h>

#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)

#define KEY1            SBIT( PINB, 0 )
#define KEY1_PRESET     SBIT( PORTB, 0 )

#define LED1            SBIT( PORTB, 1 )
#define LED1_DDR        SBIT( DDRB, 1 )

#define KEY2            SBIT( PINB, 2 )
#define KEY2_PRESET      SBIT( PORTB, 2 )

#define LED2            SBIT( PORTB, 3 )
#define LED2_DDR         SBIT( DDRB, 3 )


// ***********************************************************
// Main program
//

int main(void) {

   LED1_DDR = 1;          // output
     KEY1_PRESET = 1;       // high
     
     LED2_DDR = 1;          // output
     KEY2_PRESET = 1;       // high

     for(;;){

       if( KEY1 )         // if ( key == 1 ) (high)
         LED1 = 1;       // LED off (high)
       else
         LED1 = 0;       // LED on (low)
         
        if( KEY2 == 0 )   {
           if ( LED2 )
              LED2 = 0;
           else
              LED2 = 1;
        }
                    
     }

}


I dropped sbit.h into the WinAVR header folder. First thing I noticed is that VMLAB complains about accessing reserved memory the first time a write to DDRB is made.

As you can see I extended the example to include a toggled LED. This worked out less well than I thought. I started with a latched key, then found the toggle action was undependable, so I migrated to a monostable key. That helped, although only after I found a pulse width that worked well. I presume reliable toggling take some code for debouncing etc.

Lastly I found the "^= 0x01" technique fails to work for toggling bit field variables, so I had to do it the long way.

Fred
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Mar 18, 2010 - 05:03 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 13815
Location: Vancouver, BC

Why are you putting "#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)" in your code? Isn't it already defined in sbit.h? Also I noticed that the download link is SBIT.H, not sbit.h. Did you change the name of that file to lowercase?

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
syberraith
PostPosted: Mar 18, 2010 - 06:21 PM
Wannabe


Joined: Mar 14, 2010
Posts: 60


I had all the code in the c section first, the extraneous sbit define is remnant. I changed the case of the include statement. Under wine that seems to have worked. I changed it back.

It's been years since I did any coding. It's almost like beginning all over again. Smile

For some reason the stimulation starts up with LED2 on. From the scope it looks like the state test is made before the voltage at PB2 is pulled high, so the toggle is triggered without a key press. After it gets running it works as expected.

I wonder if that is just a simulator thing.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 18, 2010 - 06:23 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62220
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

I wonder if that is just a simulator thing.

No sh*t?

(trust simulators about as far as you can comfortably spit them)

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits