Go Down

Topic: Compile problem using macro (Read 8934 times) previous topic - next topic

april.steel

Code: [Select]
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRB = _BV(PB0);
    for(;;){
    PORTB = _BV(PB0);
        _delay_ms(1000);
    PORTB = 0;
        _delay_ms(1000);     
    }
    return 0;
}


I get the error that "PBO was not declared in this scope"  I thought that PB0 was defined automatically
Its Port B0 so does anyone know what I must include to compile this please?

PaulS

Quote
I thought that PB0 was defined automatically

Its value depends on which board you are using.

How are you compiling this code? There is no loop() or setup() function, so I know that you are not using the IDE.
The art of getting good answers lies in asking good questions.

april.steel

You said you would not respond again and I agreed.
However if you wish to consider this and give me honest answers I am happy to give you the details.

I am experimenting
This code compiles and uploads direct to my atmega328p through the Arduino IDE !
Code: [Select]
#include <avr/io.h>

#define F_CPU 20000000UL  // 1 MHz-20Meg
#include <util/delay.h>

int main() {
        DDRB |= 1; // Turns PB0on as output LED on PB0 Pin8?(8 for pin 11)
       
        while(1) {
                PORTB |= 1; // Turn LED on (8 for pin 11)
                _delay_ms(500);
                PORTB &= ~1; // Turn LED off
                _delay_ms(500);
        }

        return 1;
}


If I change PORTB and DDRB to 255 all of the Bports blink

However the code I have listed above will not compile and I am wanting to know why.
I am working through a tutorial to learn what is happening here

PeterH


However the code I have listed above will not compile and I am wanting to know why.


You have not included the header file which declares it.

Given that you are working way outside the conventional structure of a sketch and using advanced features such as direct port manipulation, I think you should be prepared to go find the declaration for yourself.

PaulS

Quote
I think you should be prepared to go find the declaration for yourself.

Where that declaration is depends on which board you have selected. Whether the declaration is relevant for your board, or not, depends on which board you have.

You haven't bothered saying which board you have.
The art of getting good answers lies in asking good questions.

april.steel

#5
Sep 23, 2012, 10:11 am Last Edit: Sep 23, 2012, 11:57 pm by april Reason: 1
Quote

You have not included the header file which declares it.I assumed that no declaration is needed for DDRB for instance and PORTB then I assumed that PB0 would be the same.

Given that you are working way outside the conventional structure of a sketch and using advanced features such as direct port manipulation, I think you should be prepared to go find the declaration for yourself.
See the problem with this forum I have found is that the trolls who patrol it cannot give a straight answer without including some sort of smart-arse comment. I thank you for the first part and you can stick what you think . It does not contribute to anyone's knowledge.


Quote
You haven't bothered saying which board you have.
Again is the hav'nt bothered bit necessary ? This is the denegration sneaking in again , you don't seem to be able to resist.
If you wanted to know you had but to ask! I use Duelminove board with a 328p
Please don't bother replying again

april.steel

#6
Sep 25, 2012, 10:45 pm Last Edit: Sep 25, 2012, 10:53 pm by april Reason: 1
I think both of these people are wrong anyway. PB0 is just one of the PORTB register's pin input/outlets
Here is a bit from Mellis's tute at http://hlt.media.mit.edu/wiki/pmwiki.php?n=Main.AVRProgrammingAdvanced
Quote
Most of the bytes in the microcontroller's memory are used to store numbers and other data, but a few have special meanings. Some of these special bytes are called registers and they control the behavior of the various components that are contained in the microcontroller. These registers are bytes, but we don't use them as numbers. Instead, each of their eight bits has an particular meaning. The program above used two registers: DDRB and PORTB. These registers control the behavior of the eight pins of port B (PB0 to PB7):

   DDRB is the data direction register for port B. It determines whether each pin is an input or an output.
   PORTB is the data register for port B. For output pins, this determines whether the pin is set high or low.

Each of the eight bits of the register corresponds to one of the eight pins of the port. The 0'th (right-most) bit of the register corresponds to PB0. The 7'th (left-most) bit to PB7. If a bit of the DDRB register is set to 1, the corresponding pin is set as an output. If the bit is 0, the pin is an input. The pins default to being inputs (i.e. the bits of DDRB default to 0). If a bit of the PORTB register is set to 1, and the pin is set as an output, the microcontroller will hold the pin high - that is, set it to 5V (or whatever voltage is used to power the microcontroller). If a bit of PORTB is 0, and the pin is an output, the microcontroller will hold the pin low (0V).

Here's an example:
Pin   PB7   PB6   PB5   PB4   PB3   PB2   PB1   PB0
DDRB   0   0   1   0   0   0   0   1
PORTB   0   0   0   0   0   0   0   1

Here, pins PB0 and PB5 are set as outputs. PB5 is set low, PB0 high. That means that if you measured the voltage on PB5 leg of the microcontroller with a multimeter (with the other probe touching ground), you'd get 0V; if you measured PB0, you'd get 5V.


So PB0 compiles in the example given above in post 3 but will not compile using the macro in post 1.
Can anyone explain why the macro approach would give a different outcome?

retrolefty


I think both of these people are wrong anyway. PB0 is just one of the PORTB register's pin input/outlets
Here is a bit from Mellis's tute at http://hlt.media.mit.edu/wiki/pmwiki.php?n=Main.AVRProgrammingAdvanced
Quote
Most of the bytes in the microcontroller's memory are used to store numbers and other data, but a few have special meanings. Some of these special bytes are called registers and they control the behavior of the various components that are contained in the microcontroller. These registers are bytes, but we don't use them as numbers. Instead, each of their eight bits has an particular meaning. The program above used two registers: DDRB and PORTB. These registers control the behavior of the eight pins of port B (PB0 to PB7):

   DDRB is the data direction register for port B. It determines whether each pin is an input or an output.
   PORTB is the data register for port B. For output pins, this determines whether the pin is set high or low.

Each of the eight bits of the register corresponds to one of the eight pins of the port. The 0'th (right-most) bit of the register corresponds to PB0. The 7'th (left-most) bit to PB7. If a bit of the DDRB register is set to 1, the corresponding pin is set as an output. If the bit is 0, the pin is an input. The pins default to being inputs (i.e. the bits of DDRB default to 0). If a bit of the PORTB register is set to 1, and the pin is set as an output, the microcontroller will hold the pin high - that is, set it to 5V (or whatever voltage is used to power the microcontroller). If a bit of PORTB is 0, and the pin is an output, the microcontroller will hold the pin low (0V).

Here's an example:
Pin   PB7   PB6   PB5   PB4   PB3   PB2   PB1   PB0
DDRB   0   0   1   0   0   0   0   1
PORTB   0   0   0   0   0   0   0   1

Here, pins PB0 and PB5 are set as outputs. PB5 is set low, PB0 high. That means that if you measured the voltage on PB5 leg of the microcontroller with a multimeter (with the other probe touching ground), you'd get 0V; if you measured PB0, you'd get 5V.


So PB0 compiles in the example given above in post 3 but will not compile using the macro in post 1.
Can anyone explain why the macro would give a different outcome?


From your own posted reference you will see they don't have you use say PB0 to manipulate bit 0 of port B, but rather rely on a macro that specifies the bit value to use when using the port command. So a symbol like PB2 is just a shorthand way to write 'port B, bit 2, and not a argument to use in setting that bit. So I think you are getting program syntax mixed up with port/bit labels?

Quote
UNDERSTANDING THE PROGRAM

_BV()
In this program, we use a new syntax to set bits in the DDRB and PORTB registers: the _BV() macro. This macro accepts a number and turns it into the byte with that numbered bit set. For example _BV(0) gives a byte with the 0'th bit set: 00000001, _BV(1) is 00000010, _BV(2) is 00000100, etc. In the program, we use a notation that specifically refers to the pin we're using: PB0. This actually has the value 0, but using PA0 instead helps make it clear that we are doing something that affects that pin. So: DDRB = _BV(PB0) sets DDRB to 00000001, making PB0 an output and the other port B pins inputs.


Lefty

Coding Badly


"PORTB0" is the correct macro for bit 0 / PORTB.  By mistake, "PB0" (and its ilk) is supported for some processors.

april.steel

#9
Sep 26, 2012, 10:33 am Last Edit: Sep 26, 2012, 10:44 am by april Reason: 1
Thank you kind Sirs  (curtsey)
All of the examples I was working with now compile .
Here is another that used that same notation
Code: [Select]

#include <avr/io.h>

int main(void)
{
    DDRB |= (1 << PORTB0);//was PB0
    PORTC |= (1 << PORTC0);//Was PC0
    for(;;) {
    if (PINC & (1 << PORTC0)) {
            PORTB &= ~(1 << PORTB0 );
        } else {
            PORTB |= (1 << PORTB0);
        }
    }
    return 0;
}

spcomputing

I am still curious about when you flipped on all the bits on PORTB and DDRB registers and the response.  It just does not seem appropriate for the application.  Fun exploration maybe, but flippant (pardon the pun) never the less.

april.steel

#11
Sep 30, 2012, 07:39 am Last Edit: Sep 30, 2012, 07:48 am by april Reason: 1
Well if you set PORTB and DDRB=255 all the pins of Port B are made outputs and all are turned on. (See the link to Mellis's page explaining this above)  Each port can be run through an LED with resistor and I only tried it one at a time but I guess they could all operate together.

Now I went looking anyway for the definition of these ports and found in " avr/io.h" the header "avr/portpins.h" is included.
An extract from that headershows:-
Code: [Select]

/* PORT B */

#if defined(PB0) && !defined(PORTB0)
#  define PORTB0 PB0
#elif defined(PORTB0) && !defined(PB0)
#  define PB0 PORTB0
#endif
#if defined(PB1) && !defined(PORTB1)
#  define PORTB1 PB1
#elif defined(PORTB1) && !defined(PB1)
#  define PB1 PORTB1
#endif
#if defined(PB2) && !defined(PORTB2)
#  define PORTB2 PB2
#elif defined(PORTB2) && !defined(PB2)
#  define PB2 PORTB2
#endif
#if defined(PB3) && !defined(PORTB3)
#  define PORTB3 PB3
#elif defined(PORTB3) && !defined(PB3)
#  define PB3 PORTB3
#endif
#if defined(PB4) && !defined(PORTB4)
#  define PORTB4 PB4
#elif defined(PORTB4) && !defined(PB4)
#  define PB4 PORTB4
#endif
#if defined(PB5) && !defined(PORTB5)
#  define PORTB5 PB5
#elif defined(PORTB5) && !defined(PB5)
#  define PB5 PORTB5
#endif
#if defined(PB6) && !defined(PORTB6)
#  define PORTB6 PB6
#elif defined(PORTB6) && !defined(PB6)
#  define PB6 PORTB6
#endif
#if defined(PB7) && !defined(PORTB7)
#  define PORTB7 PB7
#elif defined(PORTB7) && !defined(PB7)
#  define PB7 PORTB7
#endif


So it seems PB0 and PORTB0 are each defined if the other is not so I am still a little confused why I had the initial problem . Or maybe there is another definition somewhere in the hardware file or in the macro definition. It may be my reading of this though as "codingbadly" said it should be PORTB.

april.steel

I am curious where the macros are defined - Does anyone know?

spcomputing

I was just under the naive impression that the DDRB ("B" port or any other register port) was limited to declaring IO direction.

SurferTim


I am curious where the macros are defined - Does anyone know?

/arduino-101/hardware/tools/avr/avr/include/avr/
As I remember, the exact file in that directory will depend on the device selected for compile.


Go Up