| Author |
Message |
|
|
Posted: Mar 11, 2010 - 07:04 PM |
|

Joined: Apr 06, 2009
Posts: 150
|
|
I have a simple piece of code that should be working but is is not. I want to read portB, pin 1 to detect the presence of an sd card.
Code:
//Manage AVR Ports
DDRB = 0b00000000; //set Port B (SD Memory) pins to Input
PORTB = 0b00001111; //enable internal pull-up resistors for Port B, pins 1-4
//check for SD card errors
//sd_detected = bit_is_set(PINB, 0);
sd_detected = bit_is_set(PINB, 1);
//sd_detected = bit_is_set(PINB, 2);
//sd_detected = bit_is_set(PINB, 3);
if(sd_detected==1){
error_code=1;
}
error();
I have tried each of the above bit_is_set() lines and then manually shorted the appropriate avr pin to ground. If check it on pin 0, errors are reported correctly. If I comment out the pin 0 line and try any of the others, the pin is not read. Again, I am sure that the circuit is not an issue because I am shorting pins to ground manually.
Thanks |
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2010 - 07:19 PM |
|

Joined: May 24, 2004
Posts: 4228
Location: Tampere, Finland
|
|
The code is working properly, you just don't know how to use the result given to you by the macro.
Code:
// from some header
#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
So, for PINB1, the result is either 2 or 0, never 1.
Normally people just compare if result is zero or not.
Few ways to fix:
Code:
if(sd_detected) // result is non-zero
if(!sd_detected==0) // result is not zero
if(sd_detected!=0) // result is not zero
|
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2010 - 07:20 PM |
|


Joined: Feb 19, 2001
Posts: 18830
Location: Wisconsin USA
|
|
|
Quote:
sd_detected = bit_is_set(PINB, 1);
What value does bit_is_set() return? Is it 1 and 0? Or 0 and non-zero? |
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2010 - 07:34 PM |
|

Joined: Apr 06, 2009
Posts: 150
|
|
| Perfect, thanks for the help |
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2010 - 08:12 PM |
|

Joined: Nov 17, 2004
Posts: 9102
Location: Vancouver, BC
|
|
It seems to me like a bad macro name. With a name like that, it should return 0 or 1.
Quote:
Few ways to fix:
A better way to fix it is to change the macro to do what it promises:
Code:
#define bit_is_set(sfr, bit) ((_SFR_BYTE(sfr) & _BV(bit)) != 0)
|
_________________ Regards,
Steve A.
The Board helps those that help themselves.
wylfwt?
|
| |
|
|
|
|
|
Posted: Mar 11, 2010 - 10:35 PM |
|

Joined: May 24, 2004
Posts: 4228
Location: Tampere, Finland
|
|
It returns true and false, false being 0 and true being anything else. That should be enough.
Besides it sounds more like English when used:
"if bit is set then do this", and not:
"if bit is set equals something then do that" |
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2010 - 11:23 PM |
|

Joined: Nov 17, 2004
Posts: 9102
Location: Vancouver, BC
|
|
|
Quote:
It returns true and false, false being 0 and true being anything else.
Wrong. True is 1, and anything evaluating as true will be given the value of 1. Yes, in certain circumstances, anything other that 0 will be interpreted as true, but that does not mean that is equivalent to true. From K&R:
Quote:
By definition, the numeric value of a relational or logical expression is 1 if the expression is true, and 0 if the relation is false.
If the macro were actually evaluating as true (as my variation does), then the OPs original code would have worked.
If you do this:
Code:
if (x == true)
(with true being defined as it is in std_bool.h), you will get the correct answer only if x is 1. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
wylfwt?
|
| |
|
|
|
|
|
Posted: Mar 12, 2010 - 08:06 AM |
|

Joined: May 24, 2004
Posts: 4228
Location: Tampere, Finland
|
|
But I don't get it, C originally did not have any boolean concept prior to C99 standard. std_bool.h is C++ header already, although it can be used in C too.
Quote:
By definition, the numeric value of a relational or logical expression is 1 if the expression is true, and 0 if the relation is false.
Yes I think I get what you were after, but I would like to point out that the macro is neither relational (>,<,...) nor logical expression (&&,!=,...). It is a bitwise and, so it can't return true or false per se, but either zero or non-zero.
You are absolutely correct that the zero/nonzero value can be converted to 0/1 with these expressions like you demonstrated. I think even ! would do it, since it is a boolean not operator.
So basically, to be formal, an if statement should only be fed with something that evaluates to 0 and 1.
I guess I have been using too much these zero/non-zero evaluations for boolean, but I guess I am not that formal person after all. |
|
|
| |
|
|
|
|
|
Posted: Mar 12, 2010 - 07:59 PM |
|

Joined: Nov 17, 2004
Posts: 9102
Location: Vancouver, BC
|
|
|
Quote:
But I don't get it, C originally did not have any boolean concept prior to C99 standard.
It did not have a boolean data type, but it did have the concept of true or false with relational operators.
Quote:
but I would like to point out that the macro is neither relational (>,<,...) nor logical expression (&&,!=,...).
Which is precisely why it is a badly written macro. My version does have a relational operator. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
wylfwt?
|
| |
|
|
|
|
|