| Author |
Message |
|
|
Posted: Jan 08, 2009 - 03:36 PM |
|


Joined: Jul 18, 2005
Posts: 62220
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
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
Code:
# define Sensor0 PORTC &= 0xFC
# define Sensor1 PORTC &= 0xFC; PORTC |= (1<<PORTC0)
# define Sensor2 PORTC &= 0xFC; PORTC |= (1<<PORTC1)
# define Sensor3 PORTC &= 0xFC; PORTC |= ((1<<PORTC0) | (1<<PORTC1))
|
_________________
|
| |
|
|
|
|
|
Posted: Jan 08, 2009 - 04:04 PM |
|

Joined: Nov 29, 2007
Posts: 3219
|
|
|
Code:
PORTC &= ~((1<<PORTC0) | (1<<PORTC1)); // 00
PORTC = (PORTC & ~(1<<PORTC1)) | (1<<PORTC0); // 01
PORTC = (PORTC & ~(1<<PORTC0)) | (1<<PORTC1); // 10
PORTC |= (1<<PORTC0) | (1<<PORTC1); // 11
|
_________________ Stealing Proteus doesn't make you an engineer.
|
| |
|
|
|
|
|
Posted: Jan 08, 2009 - 04:32 PM |
|

Joined: Apr 01, 2006
Posts: 84
|
|
Ok, thats what i thought but didn't know how to do
Will the compiler produce the same code from both your examples?
Thanks!!  |
|
|
| |
|
|
|
|
|
Posted: Jan 08, 2009 - 04:37 PM |
|


Joined: Jul 18, 2005
Posts: 62220
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
| 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) |
_________________
|
| |
|
|
|
|
|
Posted: Jan 08, 2009 - 05:29 PM |
|

Joined: Nov 29, 2007
Posts: 3219
|
|
|
clawson wrote:
I think mine maybe makes it a little more obvious what's going on
Hey, I even added comments. What more can you ask for?  |
_________________ Stealing Proteus doesn't make you an engineer.
|
| |
|
|
|
|
|
Posted: Jan 08, 2009 - 06:05 PM |
|

Joined: Apr 01, 2006
Posts: 84
|
|
|
ArnoldB wrote:
Hey, I even added comments. What more can you ask for?
No fighting please, LOL
As speed is needed i will go with ArnoldB his version.
Points go to the both of you, |
|
|
| |
|
|
|
|
|
Posted: Jan 09, 2009 - 07:04 PM |
|

Joined: Dec 12, 2008
Posts: 9
|
|
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
Code:
//PORT INITIALITATION.(1)OUTPUT,(0) INPUT
DDRB = 0b00001100;//LEDS AS OUTPUT
PORTB = 0b11111111;//PULL-UP ACTIVE
DDRD = 0b11101011;//DDC112 COMUNICATION
PORTD = 0b11111111;//PULL-UP ACTIVE
// PORTD &= ~(1 << 6);//DCLK "LOW"->INITIALITATION
dclksemiperiod=0;
PORTB ^= (1 << 3); //Toggle the LED PB3
PORTD ^= (1 << 6); //Toggle PD6
if((PIND & (1<<PD6)) && (dclksemiperiod == 0) && (PIND & (1<<PD4)))
The problem is that when I uncomment the line
Code:
PORTD &= ~(1 << 6);
The condition in the if its not true, and I don't not why.
I suposse that, at the beggining PD6=1, after
Code:
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 |
|
|
| |
|
|
|
|
|
Posted: Jul 08, 2009 - 04:12 AM |
|

Joined: Jun 23, 2005
Posts: 3
|
|
|
tigrezno wrote:
those are my definitions, i find them more user-friendly, tell me what you think.
Code:
#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:
Code:
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.
Code:
#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
Code:
// ##############
// 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.
Just my 2 cents. Thank you. |
|
|
| |
|
|
|
|
|
Posted: Oct 09, 2009 - 11:53 PM |
|

Joined: Oct 09, 2009
Posts: 2
|
|
Hi 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 ? |
|
|
| |
|
|
|
|
|
Posted: Oct 10, 2009 - 12:13 AM |
|

Joined: Nov 17, 2004
Posts: 13815
Location: Vancouver, BC
|
|
|
Quote:
Is there any good reason why to not have them defined directly like this :
This is the way that Atmel defined them in assembler. Avrlibc (not avrlib, that is a separate product) gets the definitions from Atmel's definitions.
Quote:
Who and when needs bits defined by their number, and not directly by their mask ?
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.
|
| |
|
|
|
|
|
Posted: Oct 10, 2009 - 04:04 PM |
|

Joined: Oct 09, 2009
Posts: 2
|
|
Thanks for reply.
Now it is clear.
Of course I was talking about avr-libc, sorry for that. |
|
|
| |
|
|
|
|
|
Posted: Oct 13, 2009 - 08:47 AM |
|


Joined: Jul 10, 2008
Posts: 174
Location: Ruhrpott, Germany
|
|
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.
Code:
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? |
_________________ http://xkcd.com/221/
|
| |
|
|
|
|
|
Posted: Oct 13, 2009 - 09:31 AM |
|


Joined: Jul 18, 2005
Posts: 62220
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
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:
Code:
#define ERROR_CONDITION_1 -1
#define ERROR_CONDITION_2 -2
#define ERROR_CONDITION_3 -4
#define ERROR_CONDITION_4 -8
...
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. |
_________________
|
| |
|
|
|
|
|
Posted: Oct 13, 2009 - 09:50 AM |
|


Joined: Jul 10, 2008
Posts: 174
Location: Ruhrpott, Germany
|
|
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:
Code:
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
Now I'm happy  |
_________________ http://xkcd.com/221/
|
| |
|
|
|
|
|
Posted: Oct 18, 2009 - 04:39 AM |
|


Joined: May 04, 2007
Posts: 3529
Location: Geelong Australia, Home of the "Cats"
|
|
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 -.-
(If you haven't already done so, edit your PostNuke profile and let let us know where you are, what you do & what your interests are.)
|
| |
|
|
|
|
|
Posted: Oct 20, 2009 - 02:16 AM |
|


Joined: Mar 01, 2001
Posts: 4952
Location: Rocky Mountains
|
|
This 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/magazine/180toc.htm
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). |
|
|
| |
|
|
|
|
|
Posted: Oct 25, 2009 - 05:35 PM |
|

Joined: Jan 15, 2009
Posts: 165
Location: South Africa
|
|
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:
Code:
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:
Code:
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.
|
| |
|
|
|
|
|
Posted: Oct 25, 2009 - 06:57 PM |
|

Joined: Nov 17, 2004
Posts: 13815
Location: Vancouver, BC
|
|
In many cases the explicite cast is unnecessary. Before using casts, I would look at the assembly output to see if it is really needed.
Quote:
and I figured my code is probably 4x as long as it needs to be
Why 4 times? Surely the casting only occurs occasionally, not for every single operation. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Oct 26, 2009 - 09:02 AM |
|


Joined: Jul 18, 2005
Posts: 62220
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
| 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. |
_________________
|
| |
|
|
|
|
|
Posted: Dec 07, 2009 - 10:37 AM |
|

Joined: May 06, 2009
Posts: 12
Location: Stockholm, Sweden
|
|
|
abcminiuser wrote:
A recent thread had a very nice solution which extends on the basic bit-manipulation macros. IIRC it went something along the lines of:
Defines:
Code:
#ifndef _AVR035_H_
#define _AVR035_H_
// from AVR035: Efficient C Coding for AVR
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define SETBITMASK(x,y) (x |= (y))
#define CLEARBITMASK(x,y) (x &= (~y))
#define FLIPBITMASK(x,y) (x ^= (y))
#define CHECKBITMASK(x,y) (x & (y))
#define VARFROMCOMB(x, y) x
#define BITFROMCOMB(x, y) y
#define C_SETBIT(comb) SETBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))
#define C_CLEARBIT(comb) CLEARBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))
#define C_FLIPBIT(comb) FLIPBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))
#define C_CHECKBIT(comb) CHECKBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))
#endif
Use:
Code:
#define Status_LED PORTA, 3
C_SETBIT(Status_LED);
C_CLEARBIT(Status_LED);
- Dean
|
|
|
| |
|
|
|
|
|