[TUT] [C] Bit manipulation (AKA "Programming 101") Previous  1, 2, 3, 4, 5, 6, 7, 8 ... 10  Next All
Author Message
 gatoruss
 Posted: Jan 01, 2010 - 02:56 PM
 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

 JohanEkdahl
 Posted: Jan 01, 2010 - 08:28 PM
 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<

 gatoruss
 Posted: Jan 01, 2010 - 09:31 PM
 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. 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

 Internetwarrior
 Posted: Jan 29, 2010 - 05:26 PM
 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

 Koshchi
 Posted: Jan 29, 2010 - 08:33 PM
 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.

 Internetwarrior
 Posted: Jan 31, 2010 - 10:08 PM
 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.

 Koshchi
 Posted: Jan 31, 2010 - 10:18 PM
 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.

 Internetwarrior
 Posted: Jan 31, 2010 - 10:33 PM
 Joined: May 06, 2009 Posts: 12 Location: Stockholm, Sweden
 These were defined earlier in the thread: #define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1< (PORTA &= ~(1<<1)) Bad syntax or good syntax, I dunno, it works though...

 Koshchi
 Posted: Feb 01, 2010 - 01:58 AM
 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.

 Internetwarrior
 Posted: Feb 01, 2010 - 07:26 AM
 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.

 clawson
 Posted: Feb 01, 2010 - 09:32 AM
 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? ) 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). _________________

 JohanEkdahl
 Posted: Feb 01, 2010 - 11:33 AM
 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); }

 Koshchi
 Posted: Feb 01, 2010 - 07:25 PM
 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.

 Posted: Mar 13, 2010 - 10:25 PM
 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<

 clawson
 Posted: Mar 13, 2010 - 10:31 PM
 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) _________________

 JohanEkdahl
 Posted: Mar 13, 2010 - 10:34 PM
 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<

 syberraith
 Posted: Mar 18, 2010 - 02:49 PM
 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 #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 #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

 Koshchi
 Posted: Mar 18, 2010 - 05:03 PM
 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.

 syberraith
 Posted: Mar 18, 2010 - 06:21 PM
 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. 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.

 clawson
 Posted: Mar 18, 2010 - 06:23 PM
 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) _________________

 Display posts from previous:  All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First
 Jump to: Select a forum Forum index|--[AVR (8-bit) Technical Forums]|   |-- AVR forum|   |-- XMEGA forum|   |-- AVR Wireless forum|   |-- AVR GCC forum|   |-- AVR Studio 5 and Atmel Studio 6 forum|   |-- AVR studio 4 forum|   |-- AVRfreaks Academy forum|   |-- AVR Tutorials|--[AVR Software Framework]|   |-- AVR Software Framework|--[AVR32 (32-bit) Technical Forums]|   |-- AVR32 Linux Forum|   |-- AVR32 General (standalone)|   |-- AVR32 Software Tools|   |-- AVR32 Hardware|--[General Electronics Technical Forums]|   |-- General Electronics|   |-- Atmel Security Products|--[Non-technical forums]|   |-- AVRfreaks.net Housekeeping|--[Non-topical forums]|   |-- Off-topic forum|   |-- AVRfreaks Trading Post
All times are GMT + 1 Hour