0

I recently decided to learn direct port manipulation instead of builtin arduino routines.

First I tried this piece of code

void setup() {
pinMode(13, OUTPUT);
Serial.begin(9600);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("on");
delay(500);                  
digitalWrite(LED_BUILTIN, LOW);   
Serial.println("off");
delay(500);                       
} 

This program on running instantly established connection with the serial monitor on my arduino IDE.

But when I try this code

int main(void)
{
Serial.begin(9600);
DDRB = B11111111;
while(1)
{
PORTB = PORTB | 0x20;
Serial.println("off");
_delay_ms(500);
PORTB = PORTB & 0xDF;
Serial.println("on");
_delay_ms(500);
}
}

But this program is taking some time, about 5-10 seconds to establish serial connection. Also delay() is not working too. When I use delay() instead of _delay_ms(), the entire arduino board freezes like a computer and stops blinking the LED instead LED is fully ON.

I tried is on several programs, while "setup-loop" program connects instantly, AVR C programs does not.

why does it happen?

3
  • 2
    Because normally main() initializes all the appropriate hardware and timers. You're circumventing that with your own main() so nothing Ardunioy works.
    – Majenko
    Commented Aug 9, 2020 at 15:33
  • I should be most grateful if you could elaborate that in an answer.
    – User
    Commented Aug 9, 2020 at 15:50
  • please indent your code correctly .... beginners that might be browsing the quetions should be exposed to correctly formatted code no matter how simple the code listing is
    – jsotola
    Commented Aug 9, 2020 at 15:58

1 Answer 1

2

By defining your own main() you are circumventing the Arduino startup procedures.

Normally with Arduino code main() first runs an init() function before setup() and (repeatedly) loop(). This init() function will configure, amongst other things, the timer for millis() and delay().

This is the normal main() for a basic AVR-based board:

int main(void)
{
    init();

    initVariant();

#if defined(USBCON)
    USBDevice.attach();
#endif
    
    setup();
    
    for (;;) {
        loop();
        if (serialEventRun) serialEventRun();
    }   
     
    return 0;
}

It first initializes common functions, then board-specific ones (normally nothing), and if applicable, the USB interface (for ATMega32U4 based boards, like the Leonardo).

Only then does it go on to run your sketch.

If you want to use both your own main() and Arduino functions like delay() then you will have to call those initialization routines before running the rest of your code.

7
  • Could you explain the significance of "serialEventRun"?
    – User
    Commented Aug 9, 2020 at 16:45
  • If you haven't defined a serialEvent() function then it has no significance at all. If you have defined one then it runs it.
    – Majenko
    Commented Aug 9, 2020 at 16:53
  • What is the purpose of initVariant()?
    – User
    Commented Aug 9, 2020 at 16:55
  • 1
    That is the bit where I say then board-specific ones (normally nothing)
    – Majenko
    Commented Aug 9, 2020 at 17:03
  • I just rewrote my code to include just init() and nothing else, the serial communication, both read and write, is now working. So my question, is USBDevice.attach() necessary?
    – User
    Commented Aug 9, 2020 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.