MCUdude / MightyCore

Arduino hardware package for ATmega1284, ATmega644, ATmega324, ATmega324PB, ATmega164, ATmega32, ATmega16 and ATmega8535
Other
650 stars 183 forks source link

millis() with 11.0592 X-tal #249

Closed aikopras closed 2 years ago

aikopras commented 2 years ago

Hi

It seems millis() is not working well with my board (ATMega 16 / F_CPU=11.0592). I had problems in one of my projects, and therefore I checked timing using my Hantek DSO together with Pulseview. It turned out that each call to millis() takes (roughly) 1,5ms, thus 50% too long. Micros() is working well, however.

I can reproduce this with the following testcode:

#include <Arduino.h>

// test Points
#define INI_TP0  DDRC |=  (1<<0)    // PC0
#define SET_TP0 PORTC |=  (1<<0)
#define CLR_TP0 PORTC &= ~(1<<0)
#define INI_TP2  DDRC |=  (1<<2)    // PC2
#define SET_TP2 PORTC |=  (1<<2)
#define CLR_TP2 PORTC &= ~(1<<2)

unsigned long time_us;
unsigned long time_ms;

void setup() {
  INI_TP0;
  INI_TP2;
}

void loop() {
  if ((micros() - time_us) >= 1000) {
    time_us = micros();
    SET_TP0;
    CLR_TP0;  
    }

  if ((millis() - time_ms) >= 1) {
    time_ms = millis();
    SET_TP2;
    CLR_TP2;
    }
}

Any clue?? Bye, Aiko

aikopras commented 2 years ago

Hi I think I understand what causes my problem: I'm using millis() to check if one millisecond has passed. From inspecting the wiring.c code I understand that millis() uses Timer0, with a 64 prescaler and overflow after 256 ticks. With a 11.0592Mhz XTal this gives an overflow every 1.481 ms. Therefore I can't use millis() to check if precisely 1ms has passed; I should use micros() for that.

Sorry for bothering Aiko