That depends on what register and what AVR you are talking about. For the newer AVRs and port registers you simply write a 1 to the proper bit in the PINx register. But I think you are a bit confused. No one uses shifting to toggle a bit. You use the shifting to create the proper bit mask that will be used for toggling (or setting or clearing) a bit. In that case an expression like:
1<<PB4
takes no clock cycles at all since the shifting is done by the compiler, not the AVR.
Hello
I feel stupid, because I read this and some more forums several times about bit set, clear, compare, etc. But, I still don't understand how to do sometihngs.
I'm working with a atmega32 in WinAVR.
For example:
PORTD = (PORTD ^ 0b00000001);
This code flipp bit0 of PORTD
PORTD = (PORTD & 0b11111110);
This code switch off PIND.0
PORTD = (PORTD | 0b00000001);
And this shoudl switch on PIND.0
This is an example to compare.
I use PIND.0 as input, and when PIND.0 is "H" the program show a "0" in the LCD, because I do salida+1, and salida-1, so salida keep "0".
But when I put ground in PIND.0 (externaly), the program shoudl increase de value of salida, but "0" continues in the LCD screen, why?.
#include //main program
int salida =0;
char y=0;
//MAIN PROGRAM
int main (void)
{
//Configure Pins / Ports as input- (0) or output (1)
// Port D (Interupts)
DDRD = 0b11111110; //La entrada es INT0 Y DATAOUT
//activate Pull Ups (1)
PORTD = 0b11111111;
// Port B (LED's)
DDRB = 0b00001100;
PORTB = 0b11110011;
lcd_clrscr();
lcd_init(LCD_DISP_ON);
lcd_gotoxy(0,0);
lcd_puts("NUMBER");
while(1)//bucle principal, pone en pantalla y espera interrupciones
{
salida++;
if(PIND0 & 0b11111111)//I KNOW THIS LINE IS WRONG
{
salida--;
}
lcd_gotoxy(0,1);
itoa (salida,&y,10);
lcd_puts(&y);//I put salida as an string in the LCD
// PIN3 PORTB set -> LED off
PORTB |= (1<<PINB2);//to see program its running
delay(2000);//to decrease the speed
}
}
Well, I want to do:
Compare de value of the input in PIND.0, and make something to know when is 0 or 1.
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. So it's
TARGET ^= (1<<bit_pos); // flip the bit
TARGET |= (1<<bit_pos); // set the bit
TARGET &= ~(1<<bit_pos); // clear the bit
if (TARGET & (1<<bit_pos)) // test if the bit is set
Posted by JohanEkdahl: Mon. Dec 22, 2008 - 01:54 PM
1
2
3
4
5
Total votes: 0
Quote:
Code:
if (PIND & ~(1<<PD0))
This code test if bit is not set?
No, it tests if any other bit is set. Take it step by step:
1:
1<<PD0
make a bitmask 00000001.
2:
~(1<<PD0)
negates every bit in that mask so you get 11111110
3:
A bitwise and of that and PIND thus will produce a 1 in any position where the bitmask has a 1 and PIND has a 1. Or in other words, it will produce a non-zero value if any of bits 7 of PIND to 1 is non-zero.
What you want is
if ( !(PIND & (1<<PD0)))
Work through that, in a similar manner as I did above, step by step, to see why this is diferent and will do what you ask for. (Please note that the logical NOT operator (!) is used.)
An alternative way would be to
if (~(PIND) & (1<<PD0))
as BenG has pointed out in the first page of this thread.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
If you want to both clear some bits and then set some bits you need to do TWO read/modify/write operations. One to clear the bits and then another to set any bits that need setting. Something like
Unlikely - I think Arnold's may be more efficient though personally I think mine maybe makes it a little more obvious what's going on at the cost of a bit of inefficiency (I'm a great fan of "obvious" code for the person who comes back to read this in 3 months)
Hello again
First of all thanks very much, because of all of you I can continue working in my project.
I think I understand your explanations. But I'm still confuse with one point.
Here it is my code
The condition in the if its not true, and I don't not why.
I suposse that, at the beggining PD6=1, after
PORTD ^= (1 << 6);
PD6 shoud be 0, but its not. Why?
(I know the problem is PD6, because I allready checked all the other things and are ok, of course PD4 its allways on by hardware)
THANKS
those are my definitions, i find them more user-friendly, tell me what you think.
#define LOW 0
#define HIGH 1
#define INPUT(port,pin) DDR ## port &= ~(1<<pin)
#define OUTPUT(port,pin) DDR ## port |= (1<<pin)
#define CLEAR(port,pin) PORT ## port &= ~(1<<pin)
#define SET(port,pin) PORT ## port |= (1<<pin)
#define TOGGLE(port,pin) PORT ## port ^= (1<<pin)
#define READ(port,pin) (PIN ## port & (1<<pin))
usage:
OUTPUT(D, 3); // port D, pin 3 as output
SET(D, 3); // set port D pin 3 to HIGH
CLEAR(D, 3); // set it to LOW
INPUT(B, 5);
if (READ(B, 5) == HIGH)
...
feel free to add them to the tutorial :)
[updated]
Hello All, I have extended this code one more step. I wanted to keep all the pin definition in one place or one file.
#define LED A, 0
#define SWITCH B, 1
SET(LED) // turn on
if(READ(SWITCH)== 0){ // switch active
}
The sequence of pre-processor substitution was causing compile problems. I found solution for this as variable arguments macro. http://en.wikipedia.org/wiki/Variadic_macro
The extended version is as follows
// ##############
// GPIO.h file
#define G_INPUT(port,pin) DDR ## port &= ~(1<<pin)
#define G_OUTPUT(port,pin) DDR ## port |= (1<<pin)
#define G_CLEAR(port,pin) PORT ## port &= ~(1<<pin)
#define G_SET(port,pin) PORT ## port |= (1<<pin)
#define G_TOGGLE(port,pin) PORT ## port ^= (1<<pin)
//#define G_READ(port,pin) (PIN ## port & (1<<pin))
#define G_READ(port,pin) ((PIN ## port & (1<<pin)) >> pin)
#define GPIO_INPUT(...) G_INPUT(__VA_ARGS__)
#define GPIO_OUTPUT(...) G_OUTPUT(__VA_ARGS__)
#define GPIO_CLEAR(...) G_CLEAR(__VA_ARGS__)
#define GPIO_SET(...) G_SET(__VA_ARGS__)
#define GPIO_TOGGLE(...) G_TOGGLE(__VA_ARGS__)
#define GPIO_READ(...) G_READ(__VA_ARGS__)
#define GPIO_READ_N(...) G_READ_N(__VA_ARGS__)
// ########
// project.h file : keep all the definitions here
#define LED A, 0
#define SWITCH B, 1
// ###########
// Project.c file
// This can be used as follows
#include "include/GPIO.h"
#include "include/project.h"
GPIO_SET(LED) // Turn on the LED
if ( GPIO_READ(SWITCH)==0){ // Switch on
}
Please note my version of READ is different. I prefer return values as either 1 or 0.
Bit Manipulation is clear for me, until it gets to negative values.
I have a function which returns an int16 value with following values:
-1 // OK
-2 // Failure
-3 // something
...
-75 // do something special
-128 // special detail
And of course some combinations with the special detail (-128)
-129 // OK and special detail
-130 // Not OK and special detail
But no combnination with the -75
And I don't have to use the special detail.
I have a working solution on how to check this, but in my opinion it is not a nice solution.
if (ret == -75){ // do something
SendEvent(DO_SOMETHING);
}
else if (~(ret) & 128) //special detail
{
ret +=128; //we don't need to check the special detail
SendEvent(ret);
}
else
Send_Event(ret);
So, how can I easily handle negative return values?
I don't wholly see the relevance of your question to this tutorial but to try and drag it slowly back on topic how about using negative binary return codes:
In a 16 bit signed int you could hold 15 such conditions with multiple error conditions combined with & and individual conditions tested on the return with bit testing instructions.
OK, maybe you're right. It's not really bit manipulation what I need.
I cannot change the return value, because the function is in a Lib. I have to live with the strange return values, but I'm searching for a nice solution to handle this life :-)
Edit:
Ok. Found an easy solution:
ret *= -1; // and now I have nice positive values
...
else if (ret & 0x80) // 128 special detail
{
ret = ret & ~0x80; //we don't need to check the special detail
SendEvent(ret);
}
else
Send_Event(ret);
Then I changed the events to positive values. And after that delete the magic numbers by #defines
i.e. #define SPECIAL_DETAIL 0x80
I have gone through this tutorial with the view of putting all the "good stuff" in one document. The aim was to pick out the eyes out of it to keep it on track. Ie. Programming 101 - Bit manipulation, Is anyone interested in doing a proof read. Please PM me.
Lee
Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?
Unfortunately it's not a free article. However, the "Programming 101" post at the top of this thread is free. The magazine article is essentially the same information (but with grammar/spelling corrections).
I am busy learning C, and busy writing my first GCC program, and I read in the GCC FAQ:
Quote:
Why does the compiler compile an 8-bit operation that uses bitwise operators into a 16-bit operation in assembly?
Bitwise operations in Standard C will automatically promote their operands to an int, which is (by default) 16 bits in avr-gcc.
To work around this use typecasts on the operands, including literals, to declare that the values are to be 8 bit operands.
This may be especially important when clearing a bit:
var &= ~mask; /* wrong way! */
The bitwise "not" operator (~) will also promote the value in mask to an int. To keep it an 8-bit value, typecast before the "not" operator:
var &= (unsigned char)~mask;
This made me cringe!! As all my variables are 1 byte, and I figured my code is probably 4x as long as it needs to be because of this casting to 2 bytes (since AVR is an 8-bit processor). So I added (unsigned char) in front of all my operations. Re-compiled and my code was the exact same size??
.... "Program: 1138 bytes (13.9% Full)"
I see this topic has been posted multiple times, in the forum the general consensus is you just accept it, in the FAQ it says use casting?
Just a noob in this crazy world trying to get some electrons to obey me.
Just to note that a common culprit for "bloated" code is if any of the math library function is used (this can even be */-+) and the code is not set to link against libm.a but links with inferior code in libgcc.a instead. This can "cost" up to about 3K. Another culprit is over-sized versions of printf.a being used.
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:
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
"The good thing about science is that it's true whether or not you believe in it."- Neil deGrasse Tyson
Posted by JohanEkdahl: Fri. Jan 1, 2010 - 08:28 PM
1
2
3
4
5
Total votes: 0
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
((1<<WGM01) | (1<<WGM00))
which says a lot more about what you are doing than eg
0b00011000
Add to this that the "0b" notation is not standard C and the argument in favour of the shift-notation becomes rather strong.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
:oops: 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
"The good thing about science is that it's true whether or not you believe in it."- Neil deGrasse Tyson
Posted by Internetwarrior: Sun. Jan 31, 2010 - 10:08 PM
1
2
3
4
5
Total votes: 0
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.
Posted by Internetwarrior: Sun. Jan 31, 2010 - 10:33 PM
1
2
3
4
5
Total votes: 0
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...
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.
Posted by Internetwarrior: Mon. Feb 1, 2010 - 07:26 AM
1
2
3
4
5
Total votes: 0
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.
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).
Posted by JohanEkdahl: Mon. Feb 1, 2010 - 11:33 AM
1
2
3
4
5
Total votes: 0
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
C_CLEARBIT(PORTx, n)
you would write a thin hardware abstraction layer, eg
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)
inline void LED_ON() { PORTB &= ~(1<<5); }
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
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)
Posted by JohanEkdahl: Sat. Mar 13, 2010 - 10:34 PM
1
2
3
4
5
Total votes: 0
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.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Posted by syberraith: Thu. Mar 18, 2010 - 02:49 PM
1
2
3
4
5
Total votes: 0
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:
#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:
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.
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?
Posted by syberraith: Thu. Mar 18, 2010 - 06:21 PM
1
2
3
4
5
Total votes: 0
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.
Hi, I'm trying to build a 16-bit word made up from three integer variables; address, control (both in range 0x00-0x03), and data (0x00-0xFF).
The most significant four bits of the word are irrelevant, the next two hold the address, the next two the control information, and the final 8 hold the data.
Will something like this allow me to contruct the word from these variables?
I haven't done bit twiddling in a long time but I thought that instead of shifting a one X positions, you just used an XOR to toggle a specific bit.
JWColby
AVRNubee
www.ColbyConsulting.com
- Log in or register to post comments
TopThat depends on what register and what AVR you are talking about. For the newer AVRs and port registers you simply write a 1 to the proper bit in the PINx register. But I think you are a bit confused. No one uses shifting to toggle a bit. You use the shifting to create the proper bit mask that will be used for toggling (or setting or clearing) a bit. In that case an expression like:
takes no clock cycles at all since the shifting is done by the compiler, not the AVR.
Regards,
Steve A.
The Board helps those that help themselves.
- Log in or register to post comments
TopOh, shift on then. :)
JWColby
AVRNubee
www.ColbyConsulting.com
- Log in or register to post comments
TopHello
I feel stupid, because I read this and some more forums several times about bit set, clear, compare, etc. But, I still don't understand how to do sometihngs.
I'm working with a atmega32 in WinAVR.
For example:
This code flipp bit0 of PORTD
This code switch off PIND.0
And this shoudl switch on PIND.0
This is an example to compare.
I use PIND.0 as input, and when PIND.0 is "H" the program show a "0" in the LCD, because I do salida+1, and salida-1, so salida keep "0".
But when I put ground in PIND.0 (externaly), the program shoudl increase de value of salida, but "0" continues in the LCD screen, why?.
Well, I want to do:
Compare de value of the input in PIND.0, and make something to know when is 0 or 1.
Thanks so much
- Log in or register to post comments
Toptry:
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. So it's
- Log in or register to post comments
TopThanks very much, I writte this and works ok:
My last question about this is:
This code test if bit is not set?
Thanks very much.
- Log in or register to post comments
TopNo, it tests if any other bit is set. Take it step by step:
1:
make a bitmask 00000001.
2:
negates every bit in that mask so you get 11111110
3:
A bitwise and of that and PIND thus will produce a 1 in any position where the bitmask has a 1 and PIND has a 1. Or in other words, it will produce a non-zero value if any of bits 7 of PIND to 1 is non-zero.
What you want is
Work through that, in a similar manner as I did above, step by step, to see why this is diferent and will do what you ask for. (Please note that the logical NOT operator (!) is used.)
An alternative way would be to
as BenG has pointed out in the first page of this thread.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopOk. Now I think I've got it.
Thanks very much
- Log in or register to post comments
TopAt this time i'm working on a little project and i just can't get my head around the following
Hardware: hef4052 multiplexer with a0 and a1 tied to PC0 and PC1 of Atmega168
I'm trying to find a nice way to define the four (0/1/2/3) states of those 2 bits and what i can come up with is:
# define Sensor0 PORTC &= ~((1<<PORTC0) & (1<<PORTC1))
# define Sensor1 PORTC &= ~((1<<PORTC0)
# define Sensor2 PORTC |= (1<<PORTC0)
# define Sensor3 PORTC |= (1<<PORTC0) | (1<<PORTC1)
Is it possible to combine an & and an | operation in a define?, and what is the best way to do it?
- Log in or register to post comments
TopIf you want to both clear some bits and then set some bits you need to do TWO read/modify/write operations. One to clear the bits and then another to set any bits that need setting. Something like
- Log in or register to post comments
TopStealing Proteus doesn't make you an engineer.
- Log in or register to post comments
TopOk, thats what i thought but didn't know how to do :-)
Will the compiler produce the same code from both your examples?
Thanks!! :D
- Log in or register to post comments
TopUnlikely - I think Arnold's may be more efficient though personally I think mine maybe makes it a little more obvious what's going on at the cost of a bit of inefficiency (I'm a great fan of "obvious" code for the person who comes back to read this in 3 months)
- Log in or register to post comments
TopStealing Proteus doesn't make you an engineer.
- Log in or register to post comments
TopNo fighting please, LOL
As speed is needed i will go with ArnoldB his version.
Points go to the both of you,
- Log in or register to post comments
TopHello again
First of all thanks very much, because of all of you I can continue working in my project.
I think I understand your explanations. But I'm still confuse with one point.
Here it is my code
The problem is that when I uncomment the line
The condition in the if its not true, and I don't not why.
I suposse that, at the beggining PD6=1, after
PD6 shoud be 0, but its not. Why?
(I know the problem is PD6, because I allready checked all the other things and are ok, of course PD4 its allways on by hardware)
THANKS
- Log in or register to post comments
TopHello All, I have extended this code one more step. I wanted to keep all the pin definition in one place or one file.
The sequence of pre-processor substitution was causing compile problems. I found solution for this as variable arguments macro. http://en.wikipedia.org/wiki/Variadic_macro
The extended version is as follows
Please note my version of READ is different. I prefer return values as either 1 or 0.
Just my 2 cents. Thank you.
- Log in or register to post comments
TopHi all,
I have one question about the bit's names definitions of AVR registers, as they are done in avrlib.
In avrlib are these defined like this :
#define PA0 0
#define PA1 1
#define PA2 2
and so on.
Is there any good reason why to not have them defined directly like this :
#define PA0 1
#define PA1 2
#define PA2 4
#define PA3 8
So You do not need to shift or use any _BV() macro everytime.
Who and when needs bits defined by their number, and not directly by their mask ?
- Log in or register to post comments
TopThis is the way that Atmel defined them in assembler. Avrlibc (not avrlib, that is a separate product) gets the definitions from Atmel's definitions.
Assembler uses them directly in opcodes such a SBI, CBI, SBIC, SBIS.
You can always define your own versions of them that are bit masks instead of bit numbers.
Regards,
Steve A.
The Board helps those that help themselves.
- Log in or register to post comments
TopThanks for reply.
Now it is clear.
Of course I was talking about avr-libc, sorry for that.
- Log in or register to post comments
TopBit Manipulation is clear for me, until it gets to negative values.
I have a function which returns an int16 value with following values:
-1 // OK
-2 // Failure
-3 // something
...
-75 // do something special
-128 // special detail
And of course some combinations with the special detail (-128)
-129 // OK and special detail
-130 // Not OK and special detail
But no combnination with the -75
And I don't have to use the special detail.
I have a working solution on how to check this, but in my opinion it is not a nice solution.
So, how can I easily handle negative return values?
http://xkcd.com/221/
- Log in or register to post comments
TopI don't wholly see the relevance of your question to this tutorial but to try and drag it slowly back on topic how about using negative binary return codes:
In a 16 bit signed int you could hold 15 such conditions with multiple error conditions combined with & and individual conditions tested on the return with bit testing instructions.
- Log in or register to post comments
TopOK, maybe you're right. It's not really bit manipulation what I need.
I cannot change the return value, because the function is in a Lib. I have to live with the strange return values, but I'm searching for a nice solution to handle this life :-)
Edit:
Ok. Found an easy solution:
Then I changed the events to positive values. And after that delete the magic numbers by #defines
i.e. #define SPECIAL_DETAIL 0x80
Now I'm happy :-)
http://xkcd.com/221/
- Log in or register to post comments
TopI have gone through this tutorial with the view of putting all the "good stuff" in one document. The aim was to pick out the eyes out of it to keep it on track. Ie. Programming 101 - Bit manipulation, Is anyone interested in doing a proof read. Please PM me.
Lee
Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?
- Log in or register to post comments
TopThis was already put into one document: an article in Circuit Cellar magazine, July 2005 issue:
Bit Flipping Tutorial
An Uncomplicated Guide to Controlling MCU Functional
Eric Weddington
http://www.circuitcellar.com/mag...
Unfortunately it's not a free article. However, the "Programming 101" post at the top of this thread is free. The magazine article is essentially the same information (but with grammar/spelling corrections).
Eric Weddington
www.linkedin.com/in/ericweddington/
- Log in or register to post comments
TopI am busy learning C, and busy writing my first GCC program, and I read in the GCC FAQ:
This made me cringe!! As all my variables are 1 byte, and I figured my code is probably 4x as long as it needs to be because of this casting to 2 bytes (since AVR is an 8-bit processor). So I added (unsigned char) in front of all my operations. Re-compiled and my code was the exact same size??
.... "Program: 1138 bytes (13.9% Full)"
I see this topic has been posted multiple times, in the forum the general consensus is you just accept it, in the FAQ it says use casting?
Just a noob in this crazy world trying to get some electrons to obey me.
- Log in or register to post comments
TopIn many cases the explicite cast is unnecessary. Before using casts, I would look at the assembly output to see if it is really needed.
Why 4 times? Surely the casting only occurs occasionally, not for every single operation.
Regards,
Steve A.
The Board helps those that help themselves.
- Log in or register to post comments
TopJust to note that a common culprit for "bloated" code is if any of the math library function is used (this can even be */-+) and the code is not set to link against libm.a but links with inferior code in libgcc.a instead. This can "cost" up to about 3K. Another culprit is over-sized versions of printf.a being used.
- Log in or register to post comments
Top- Log in or register to post comments
TopFirst 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.
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:
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
"The good thing about science is that it's true whether or not you believe in it." - Neil deGrasse Tyson
- Log in or register to post comments
TopNo, as that would clear the whole byte.
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
which says a lot more about what you are doing than eg
Add to this that the "0b" notation is not standard C and the argument in favour of the shift-notation becomes rather strong.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
Top:oops: 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
"The good thing about science is that it's true whether or not you believe in it." - Neil deGrasse Tyson
- Log in or register to post comments
TopJust 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
- Log in or register to post comments
TopYou 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.
- Log in or register to post comments
TopI'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.
- Log in or register to post comments
TopIn 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.
- Log in or register to post comments
TopThese 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...
- Log in or register to post comments
TopI 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.
- Log in or register to post comments
TopSure, 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.
- Log in or register to post comments
TopI still don't get your argument. How is:
any clearer than:
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).
- Log in or register to post comments
TopIt 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
you would write a thin hardware abstraction layer, eg
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)
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopNot only is the method that Johan showed more readable, it is far more safe. With the macros you could easily do this:
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.
- Log in or register to post comments
Topwhat does it mean when the left shift operation is used in statements such as this?
or
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:
which sets bit number 2 of an 8-bit mask.
Thanks
- Log in or register to post comments
TopHave 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)
- Log in or register to post comments
TopSurprise: The answer to your question is on page 1 of this thread, more specifically in a post by "clawson" made on Jun 28, 2007.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopHi 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:
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
- Log in or register to post comments
TopWhy 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.
- Log in or register to post comments
TopI 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.
- Log in or register to post comments
TopNo sh*t?
(trust simulators about as far as you can comfortably spit them)
- Log in or register to post comments
TopHi, I'm trying to build a 16-bit word made up from three integer variables; address, control (both in range 0x00-0x03), and data (0x00-0xFF).
The most significant four bits of the word are irrelevant, the next two hold the address, the next two the control information, and the final 8 hold the data.
Will something like this allow me to contruct the word from these variables?
- Log in or register to post comments
TopPages