2017-09-03 6 views
0

Ich versuche, einen Interrupt und einen Zähler/Timer einzurichten. Der Interrupt ist extern und liest eine niedrige Logik vom Pin. Timer sollte alle 100 us erhöhen und bis zu count Variable hinzufügen. Ich habe den Interrupt eingerichtet, der funktioniert aber nach dem Einrichten eines Timers funktioniert weder Interrupt noch Timer. Der Code ist so:atmega 328p Interrupt und Timer Setup [C/C++]

volatile boolean allowCount = false, timerFlag = false; 
volatile unsigned int counter; 
boolean pulseLow = false; 


void setup(){ 

Serial.begin(9600); 

// initialize external pin interrupt. 
PCICR = 0b00000010; // 1. PCIE1: Pin Change Interrupt Enable 1 
EICRA |= bit (ISC10); // set wanted flags (low logic level causes interrupt) 
PCMSK1 = 0b00010000; // Enable Pin Change Interrupt for A4 


// TODO Interrupt settings not working together 


// initialize Timer1 
cli();   // disable global interrupts 
TCCR1A = 0;  // set entire TCCR1A register to 0 
TCCR1B = 0;  // same for TCCR1B 

// set compare match register to desired timer count: 
OCR1A = 0x18; 
// turn on CTC mode: 
TCCR1B |= (1 << WGM12); 
// Set CS10 and CS12 bits for 64 prescaler: 
TCCR1B |= (1 << CS10); 
TCCR1B |= (1 << CS11); 
// enable timer compare interrupt: 
TIMSK1 |= (1 << OCIE1A); 


} 

void loop(){ 
    if (allowCount == true) 
    { timer100_uS(); 

     if (counter > 50 && pulseLow == false){ 
      DDRC |= (1 << DDC3); // sets bit DDC3 to 1 within register DDRC   
      //set pin 3(A3) ouput as sourcing Vcc(HIGH) 
      PORTC |= (1 << PORTC3); 
      timerReset(); 
      pulseLow = true; 
     } 
     if (pulseLow == true){ 
      timer100_uS(); 
      if (counter >= 500){ 
       //set pin3 of port C to LOW (A3); 
       PORTC &= ~(1 << PORTC3); 
       pulseLow = false 
       timerReset(); 
     } 

    } 
// external pin interrupt 
ISR(PCINT1_vect){ 
    if (allowCount == false) 
    allowCount = true; 
} 
// timer/counter interrupt 
ISR (TIMER1_COMPA_vect) 
{ 
    if (timerFlag == true){ 
     counter++; 
    } 
} 

void timer_100uS(void){ 
    timerFlag = true; 
    cli(); 
} 

void timerReset(void){ 
    sei(); 
    timerFlag = false; 
    counter = 0; 
} 

Wert von OCR0A berechnet 24 (0x18), um mit Vorteiler 64 und 16-MHz-Prozessor auf der Grundlage dieser Formel:

OCRn = [ (clock_speed/Prescaler_value) * Desired_time_in_Seconds ] - 1 

Wie verschiedene Interrupts so einrichten, dass sie überlappen sich nicht? Oder noch besser, ist es möglich, den Timer so einzustellen, dass er keinen Interrupt verwendet? Danke fürs Lesen!

+0

gerade gesetzt nicht die Interrupt-Freigabe in den Timer registrieren steuern ja ? und dann die Statusregister abfragen, um zu sehen, ob der Timer alles getan hat, worauf Sie gewartet haben. –

+0

können Sie sie separat nur das eine oder das andere verwenden, aber nicht beide, funktioniert der Interrupt für jede Situation? Was ist die Quelle Ihres externen Interrupts (eine Taste oder ein Signal von einem anderen Gerät)? Wenn Sie einen Knopf haben, wie geht es Ihnen mit Bounce? –

+0

@old_timer Wie würde der Lese-Timer/Zähler-Wert aus dem Status-Register aussehen? Gegenwert = SREG? Externer Interrupt liest Nulldurchgang Analogsignal, es funktioniert jedes Mal. – flowian

Antwort

0

Vielen Dank für Antworten @old_timer, @klasyc. ziemlich spät, aber ich löste es durch Timer0 statt timer1 mit folgenden Einstellungen im Setup mit:

// initialize external pin interrupt. 
PCICR = 0b00000010; // 1. PCIE1: Pin Change Interrupt Enable 1 
EICRA |= bit (ISC10); // set wanted flags (falling edge causes interrupt) 
PCMSK1 = 0b00001000; // Enable Pin Change Interrupt for A3 

TCCR0B = 0; 
TCCR0A = 0; 
//set CTC mode 
TCCR0A = (1 << WGM01); 

// set OCR0A value for 1 us counter (OCRxn = (freq/prescaler)*desired_value)-1 
OCR0A = 15; 

// set compare match counter 
TIMSK0 |= (1 << OCIE0A); 


//set prescaler 
TCCR0B |= (1 << CS00); 

und außerhalb der Schleife:

ISR(TIMER0_COMPA_vect){ 
    counter++; 
} 
0

Wie ich sehen kann, verwenden Sie ATMega328 mit Arduino-Bibliotheken. Ihr Problem ist, dass die Arduino-Bibliothek intern Timer 1 für ihre internen Zwecke verwendet. Wenn Sie daher Ihren eigenen Interrupt-Handler für Timer 1 hinzufügen, überschreiben Sie den Interrupt-Handler von Arduino für Timer 1, der die Bibliothek unterbricht.

Wenn Sie mit Arduino Bibliothek bleiben wollen, verwenden Sie die Bibliothek auch den Timer zu steuern: Arduino Timer1

+0

* Aus irgendeinem Grund funktioniert die Formatierung nicht wie beabsichtigt, Sie können diese Antwort also nur lesen. Ja, ich bin mit Arduino pro mini 16 MHz Ich glaube nicht, ist es möglich, 10 uS zu mit Timer 0 und Timer 2, weil sie 8-Bit-Timer sind die Vorteiler bis 256 erlaubt Also, Timer 1 scheint nur Option zu sein. Wie überprüft man alle Register? Wenn es zu kompliziert ist, würde ich lieber Code direkt in Avr auf dem Arduino-Chip programmieren. – flowian

+0

Nach dem Überprüfen von Arduino [Quellcode] (https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring.c#L241) scheint es, Arduino Bibliothek versucht zu konfigurieren und zu verwenden Alle Timer und der einzige "offizielle" Weg ist die Verwendung ihrer Bibliotheksfunktionen. Deshalb habe ich meine Antwort entsprechend geändert. Zu Ihrer Frage aus dem Kommentar: Um ein Prozessorregister zu überprüfen, schreiben Sie einfach seinen Inhalt wie normale Variable auf seriell :) – klasyc