0

Should this code pulse the PB3 and PB4 pins (MOSI and MISO of an Arduino Uno) at 2ms interval ?

#include <avr/io.h>

int main(void) 
{

//  for (byte i = 0; i < 32; i++)
//    pinMode(i, INPUT);

  DDRB |= (1 << PB4);       
  DDRB |= (1 << PB3);       
//  pinMode(PB4, OUTPUT);
  while (1)
  {
    PORTB &= ~(1 << PB4);        
    PORTB &= ~(1 << PB3);        
  //  digitalWrite(PB4, LOW);
//      __asm__ __volatile__("nop");
//      __asm__ __volatile__("nop");
//      __asm__ __volatile__("nop");
//      __asm__ __volatile__("nop");
//      __asm__ __volatile__("nop");
//      __asm__ __volatile__("nop");
//      __asm__ __volatile__("nop");
//      __asm__ __volatile__("nop");
//    delayMicroseconds(10000);
    delay(1);
    PORTB |= (1 << PB4);        
    PORTB |= (1 << PB3);        
  //  digitalWrite(PB4, LOW);
//    delayMicroseconds(10000);
    delay(1);

  }
}

If used for SPI MOSI can do 1 MHz just fine - so my logic analyzer says. MISO would not behave when used by SPI. MISO works in other non-SPI scenario: I am able to use the Arduino for in-system programming other AVR boards.

But the code above pulses neither MISO nor MOSI, as pointed out by the same logic analyzer in the same setup. Should it?

update

There has been some issue with the board. Changed it and all works fine now, regardless of using int main() alone or also calling init() as per @Majenko 's answer

  • 2
    Code is looking ok. Are you sure that ports are not shorted by something, or driven from somewhere outside? – smajli Jan 10 at 12:11
  • @smajli that was probably it. Feel free to turn the comment into an answer – kellogs Jan 11 at 9:05
2

The code content works fine while compiled as an Arduino program - that is, using the proper setup() and loop() structure:

void setup() {
    DDRB |= (1 << PB4);       
    DDRB |= (1 << PB3);       
    while (1) {
        PORTB &= ~(1 << PB4);        
        PORTB &= ~(1 << PB3);        
        delay(1);
        PORTB |= (1 << PB4);        
        PORTB |= (1 << PB3);        
        delay(1);
    }
}

void loop() {
}

However the same code will not work when using it in main(). This is simply because delay() will never work. Normally main() calls init() which then configures TIMER0 to generate the millis() and micros() count used for the delay() functions.

So either use setup() and loop() instead of main(), or make your program call init() before anything else:

int main() {

    init();

    DDRB |= (1 << PB4);       
    DDRB |= (1 << PB3);       
    while (1) {
        PORTB &= ~(1 << PB4);        
        PORTB &= ~(1 << PB3);        
        delay(1);
        PORTB |= (1 << PB4);        
        PORTB |= (1 << PB3);        
        delay(1); 
    }
    return 0;
}
  • Makes sense. But, it didn't make a difference. Tried both calling init() and switching to setup(). As a sidenote, when I go lower with the delays, into tens / hundreds of microseconds, glithces start showing up on the MISO line. Going for even lower delays causes some (fewer) gltiches to also show up on MOSI . – kellogs Jan 10 at 14:59
  • 1
    Then your board is probably broken, or something, because that code does work. I tested it. It worked. – Majenko Jan 10 at 15:02
  • Yes... something like that. I wonder why the lines are doing fine when used as ISP at 19200 baudrate but not when pulsed at similar rates by hand. I am off to more investigations. – kellogs Jan 10 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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