Going from Arduino to pure C

I'm trying to run code rewritten from Arduino to AVR C (using AVR Studio 4).
It simply turns on LED which has:

  • anode connected to digital pin 2
  • cathode+resistor connected to digital pin 3

What I wrote in Arduino IDE works perfectly:

void setup(){
  pinMode(2, OUTPUT);//digital pin 2  - OUTPUT  
  pinMode(3, OUTPUT);//digital pin 3  - OUTPUT
  
  digitalWrite(2, HIGH);//digital pin 2  - HIGH (5V)
  digitalWrite(3, LOW);//digital pin 3  - LOW (GND)
  
}

void loop(){
  delay(1);
}

But what I wrote in AVR Studio using C does not turn on the LED:

#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
 
int main(void){ 

DDRD = (1<<PD2);
DDRD = (1<<PD3);

PORTD = (1<<PD2);
PORTD = (0<<PD3);

while(1){
  _delay_ms(1);
}


return 1;
}

Why is that and how to fix it?

But what I wrote in AVR Studio using C does not turn on the LED:

Because you haven't initialized the hardware. init() does that.

hmm, where do I have to put it? I haven't yet seen code with such function.

I haven't yet seen code with such function.

The IDE creates a main() for you, including a call to init(), then setup(), then a while loop to call loop(). Call init() in main() first.

Well, this is what I get:

I already used that tutorial and code to blink Arduino's built-in LED works great, but this does not.

DDRD = (1<<PD2);
DDRD = (1<<PD3);

PORTD = (1<<PD2);
PORTD = (0<<PD3);

should be

DDRD |= (1<<PD2);
DDRD |= (1<<PD3);

PORTD |= (1<<PD2);
PORTD &= ~(1<<PD3);

Now this seems to work, thanks!
Can you please explain those commands? As currently those additional symbols make no sense to me. :confused:

| is a bitwise inclusive OR
& is a bitwise and

http://playground.arduino.cc/Code/BitMath

Each time you write to PORTx, you need to set the status of all 8 bits. When you do this:

PORTD = (1 << PD2);
PORTD = (0 << PD2);

... what you're actually doing is this:

Set pin D2 on, and all other pins on PORTD off;
Set pin D2 off, and all other pins on PORTD off;

There are several things wrong with this:

First, setting PORTD with an equal sign sets the state of all 8 pins at once. However, your code is only explicitly setting / clearing one bit. The point you're missing is that changes are absolute, not cumulative, so you can't set PORTD with one pin's value without implicitly setting the state of the other 7 pins to LOW.

This is why you need to use bitwise operators, to make changes to a single bit while preserving the status of all the others:

PORTD = (1 << PD2);  // This means set PORTD to 0000 0100
PORTD = (0 << PD2);  // This means set PORTD to 0000 0000

// This means set PORTD to PORTD's existing value, combined with 0000 0100
// In other words, turn on bit 2
PORTD |= (1 << PD2);

// This means set PORTD to PORTD's existing value, with a mask of 1111 1011
// In other words, clear bit 2
PORTD &= ~(1 << PD2);

You need to look up bitwise operators and logic truth tables to really understand what this does, but to sum up:

0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

~0 = 1
~1 = 0

(1 << PD2)  = 0000 0100
(0 << PD2)  = 0000 0000
~(1 << PD2) = 1111 1011
~(0 << PD2) = 1111 1111

Therefore:

0000 0000  |  0000 0100  =  0000 0100  // PORTD |= (1 << PD2)
0000 0100  &  1111 1011  =  0000 0000  // PORTD &= ~(1 << PD2)

Now, your code did in fact light up PD2... but only for one instruction cycle, before all bits were turned off in the next instruction. So essentially, you will never see D2 light up.

Now this seems to work, thanks!
Can you please explain those commands? As currently those additional symbols make no sense to me. :confused:

Here's a tip. If you want to give up the perfectly good Arduino language and use AVR C instead, perhaps you should learn C.

Sidebar style question. Kind of a nit but wondering what folks' preferences are. I've been using the bit names from the datasheet, e.g.

DDRD |= ( 1 << DDD2 );
PORTD |= ( 1 << PORTD2 );
PIND |= ( 1 << PIND2 );

but since DDD2, PORTD2, PIND2 and PD2 all have the same value (2), they're interchangeable and it might be easier to code

DDRD |= ( 1 << PD2 );
PORTD |= ( 1 << PD2 );
PIND |= ( 1 << PD2 );

I'm thinking the latter might be just as easy to read, maybe easier.

Absolutely not. Use the definition for the value that corresponds to what you're trying to do, not some other arbitrary definition that happens to have the same value. If you don't use the correct definition then your code may work in this environment today, but it will not be portable.

The other problem is the "short" names (e.g. PD2) are a mistake. They don't exist for some processors and, apparently, were never intended to exist. In other words, the short names are not always portable to other AVR processors.

Thanks guys, I'll keep with my initial approach then!