Jetzt habe ich in der Version mit häufig gesperrten Interrupts mal eine Korrektur eingebaut.
Und zwar sehe ich normalerweise (freie Interrupts) das das TCNT1 Register in der
Interruptroutine schon wieder 1 oder 2 enthält. Ok der Zähler rennt ja weiter.
Habe ich die FAST-Led laufen kommen auch schon mal höhere Werte vor.
Diese Werte >2 summiere ich auf und immer wenn ich mehr als 24 gesammelt habe (das ist
der Comparewert für 0.1 Millisekunden) korrigiere ich meinen 1/10 Millisekundenzähler.
Das klappt wunderbar un der korrigierte Zähler läuft nach Stunden synchron mit dem "millis" counter.
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Arduino.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include <WS2812.h>
#define I2C_ADDRESS 0x27
LiquidCrystal_I2C lcd(I2C_ADDRESS, 2, 1, 0, 4, 5, 6, 7,3,POSITIVE); // Neuer Adapter
// LiquidCrystal_I2C lcd(I2C_ADDRESS, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);
volatile uint32_t intCnt1 = 0;
volatile uint32_t intCnt2 = 0;
volatile uint32_t intCntB = 0;
uint32_t oldTime1 = 0;
#define NUM_LEDS 5
#define NUM_COLORS 7
struct cRGB Cols[NUM_COLORS] =
{
{0x00,0x00,0x10},
{0x00,0x10,0x00},
{0x10,0x00,0x00},
{0x10,0x10,0x00},
{0x10,0x00,0x10},
{0x00,0x10,0x10},
{0x10,0x10,0x10},
};
WS2812 LED(NUM_LEDS);
cRGB rgb;
void setup()
{
Serial.begin(9600);
lcd.begin(16,2);
lcd.print("TTEST 1");
pinMode(7,OUTPUT);
digitalWrite(7,LOW);
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
LED.setOutput(8); // Digital Pin 7
cli();
TCCR2A = 0; // RESET TIMER 2
TCCR2B = 0;
TCCR2A = bit (WGM21) ; // CTC mode
OCR2A = 24;
OCR2B = 12;
TCCR2B = bit(CS22); // Prescaler 64
// TCCR2B = bit(CS21) | bit(CS20); // Prescaler 32
// TCCR2B = bit(CS21); // Prescaler 8
// TCCR2B = bit (CS20) | bit (CS22) ; // prescaler of 128
// Overflow Interrupt erlauben
// TIMSK2= bit(TOIE2);
// Timer 2 - interrupt on match (ie. every 1 ms)
TIMSK2 = bit (OCIE2A); // | bit(OCIE2B); // enable Timer2 Interrupt
TCNT2 = 0; // In diesem Modus von null aufwärtz !
// TCNT2 = 231; // Fuer Prescaler 64
// TCNT2 = 206; // Fuer Prescaler 32
// TCNT2 = 56;
// Nochmal für Timer 1
TCCR1A = 0; // RESET TIMER 1
TCCR1B = 0;
// TCCR1A = bit (WGM11);
TCCR1B = bit(WGM12) | bit(CS11) | bit(CS10); // Prescaler 64
// TCCR2B = bit(CS21) | bit(CS20); // Prescaler 32
// TCCR2B = bit(CS21); // Prescaler 8
TCNT1 = 0;
OCR1A = 24;
OCR1B = 24;
// Overflow Interrupt erlauben
// TIMSK1= bit(TOIE1);
TIMSK1 |= bit (OCIE1A) | bit(OCIE1B);
// TCNT1 = 0; // Fuer Prescaler 64
// TCNT2 = 206; // Fuer Prescaler 32
// TCNT2 = 56;
sei();
oldTime1 = millis();
}
ISR (TIMER2_COMPA_vect) // Jetz den COMPARE Vector !!
{
intCnt2++;
}
uint8_t val_t;
volatile uint16_t ovCnt;
ISR (TIMER1_COMPB_vect) // Jetz den COMPARE Vector !!
{
intCntB++;
}
//------------------------------------------------------------------
ISR(TIMER1_COMPA_vect)
{
val_t = TCNT1;
if (val_t > 2)
{
ovCnt += (val_t - 2) ;
}
while (ovCnt >= 24)
{
intCnt1++;
ovCnt = ovCnt - 24;
}
intCnt1++;
}
uint32_t secs0 = 0;
uint32_t oldSecs0 = 0;
uint32_t secs1 = 0;
uint32_t oldSecs1 = 0;
uint32_t secs2 = 0;
uint32_t oldSecs2 = 0;
uint8_t Buffer[16];
uint32_t oldCnt1 = 0;
uint32_t oldCnt2 = 0;
uint32_t oldCntB = 0;
uint32_t var;
uint32_t ledTime = 0;
uint8_t col = 0;
uint8_t run;
void loop()
{
if ((millis() - oldTime1) >= 1000)
{
oldTime1 = oldTime1 + 1000;
secs0++;
}
if (secs0 != oldSecs0)
{
digitalWrite( 7,!digitalRead( 7));
oldSecs0 = secs0;
lcd.setCursor(8,0);
sprintf((char *) Buffer,"T1:%04ld",secs0);
lcd.print((char *) Buffer);
}
if (secs2 != oldSecs2)
{
oldSecs2 = secs2;
lcd.setCursor(0,1);
sprintf((char *) Buffer,"T2:%04ld",secs2);
lcd.print((char *) Buffer);
}
if (secs1 != oldSecs1)
{
oldSecs1 = secs1;
lcd.setCursor(8,1);
sprintf((char *) Buffer,"T3:%04ld",secs1);
lcd.print((char *) Buffer);
}
ATOMIC_BLOCK (ATOMIC_RESTORESTATE) { // cli()+sei() mit SREG Sicherung
var = intCnt2;
}
if ((var - oldCnt2) >= 10000)
{
secs2++;
oldCnt2 = oldCnt2 + 10000;
}
ATOMIC_BLOCK (ATOMIC_RESTORESTATE) { // cli()+sei() mit SREG Sicherung
var = intCnt1;
}
if ((var - oldCnt1) >= 10000)
{
secs1++;
oldCnt1 = oldCnt1 + 10000;
}
ATOMIC_BLOCK (ATOMIC_RESTORESTATE) { // cli()+sei() mit SREG Sicherung
var = intCntB;
}
if ((var - oldCntB) >= 10000)
{
oldCntB = oldCntB + 10000;
lcd.setCursor(0,0);
sprintf((char *) Buffer,"TB:%04ld",var / 10000);
lcd.print((char *) Buffer);
}
// Hier mal ein wenig LED Gezappel mit gesperrten INTs
if ((millis() - ledTime) >= 600)
{
ledTime = ledTime + 600;
for (run = 0 ; run < NUM_LEDS ; run++)
{
LED.set_crgb_at(run,Cols[col]);
}
LED.sync();
if (col == 6) col = 0; else col++;
}
}
Ok das klappt.
Ich verstehe nur nicht warum.
TCNT1 hat einen höheren Wert wenn der Interrupt "zu spät" kommt.
Interrupts gehen ja wohl nicht verloren sondern werden ich denke in einem FlipFlop
gespeichert und kommen dann wenn sie wieder frei sind.
Der Zähler tickt aber doch unbeirrt weiter. D.h. der nächste "freie" Interrupt kommt doch
wieder "pünklich". Warum muss ich überhaupt korrigieren, respektive warum klappt das
mit meiner Korrektur überhaupt ?
Ich hoffe das war verständlich. Der Korrektur-Code steht im ISR(TIMER1_COMPA_vect).
Ulli