Hi,
ziel dieses Programmes ist es die Frequenz eines Rechtecksignals mit einem Duty cycle von 50% zu bestimmen und diese wieder an einem Ausgang auszugeben. Die Eingangsfrequenz ist in etwa 1kHz (viel kleiner als 16MHz)
Hardware: Arduino Duemilanove ATmega328P-PU
Problem:
Der Interrupt wird bei einer steigenden Flanke zwar aufgerufen, jedoch dannach nicht mehr, den dann hängt sich mein Programm auf.
Ich sehe dann keinen Flankenwechsel ledPin1 (Ausgang) mehr. Testweise habe ich einen Ausgang verwendet um zu sehen wie weit mein Programm kommt. Sobalt ein Interrupt mit (run1=LOW) fertig ist, rührt sich nichts mehr. Beim SerialMonitor hängt sich das Programm schon früher auf, nehme an, dass der Buffer nicht mehr vollständig zum PC gesendet wird.
Schaltung:
Als Ausgang dienenzurzeit LEDs die ich mir mit dem OSZI anschaue. Am Eingang habe ich einen Rechtecksignal mit einem 1kHz, bzw zum Testen simuliere ich nur eine steigende bzw fallende Flanke.
ledPin1 Ausgang des Signals
ledPin2 zum Testen
ledPin3 zum Testen
Error zum Testen
input digitaler Eingang 2
interrupt_pin2 Interrupt an eingang 2
SerialMonitor:
TIMER2_OVF_vect
Setup_geladen
TIMER1_COMPA_vect 65534 65534
TIMER1_COMPA_vect 65534 65534
TIMER1_COMPA_vect 65534 65534
TIMER1_COMPA_vect 65534 65534
TIMER1_COMPA_vect 65534 65534
TIMER1_COMPA_vect 65534 65534 //Steigende Flanke
1stateChange_
Code:
#define ledPin1 3
#define ledPin2 9
#define ledPin3 8
#define Error 13
#define input 2
#define interrupt_pin2 0
#define test digitalWrite(ledPin3, digitalRead(ledPin3) ^ 1);
volatile unsigned long var_timer2_anzahl=0;
volatile unsigned long var_timer2_buffer_anzahl=0;
volatile unsigned long var_timer2_buffer=0;
volatile int run1=LOW;
volatile int lesen=HIGH;
volatile unsigned long zwischen=65534;
void setup()
{
Serial.begin(9600);
noInterrupts(); // disable all interrupts
//config Input/Output
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(Error, OUTPUT);
pinMode(input, INPUT);
//config timer1 16-Bit Ausgang
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 65534; // compare match register Anfangswert auf ca. 1s bei 16MHz/256
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // prescaler 16MHz/256
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
//config timer2 8-Bit Eingang
TCCR2A = 0;
TCCR2B = 0;
TCNT2 = 0;
//OCR2A = 0; // compare match register 16MHz/256/2Hz
//TCCR2B |= (1 << WGM1); // CTC mode
//TCCR2B |= (1 << CS12); // prescaler bzw timer stoppen bzw starten
//TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
TIMSK2 = 0x01; //Timer2 INT Reg: Timer2 Overflow Interrupt Enable
//config Interrupts
attachInterrupt(interrupt_pin2, stateChange_rising,RISING); //Attach the interrupt to the input pin and monitor for RISING Change
interrupts(); // enable all interrupts
Serial.println("Setup_geladen");
}
void stateChange_rising()
{
//noInterrupts();
detachInterrupt(interrupt_pin2); //Interrupts an PortD2 anhalten
Serial.println("1stateChange_rising1");
digitalWrite(ledPin2, digitalRead(ledPin2) ^ 1);
//starten:
if(run1==LOW)
{
Serial.println("1starten1");
TCNT2 =0; //Timer2 auf Null setzten
var_timer2_anzahl=0; //Anzahl der Durchläufe auf Null setzen
TCCR2B |= ((1 << CS22)|(1 << CS21)); //Timer2 Starten
digitalWrite(ledPin2, digitalRead(ledPin2) ^ 1); // toggle LED pin
run1=HIGH;
}
else //stoppen:
{
Serial.println("2stoppen2");
TCCR2B =0; //Timer2 Eingang Stoppen
var_timer2_buffer_anzahl=var_timer2_anzahl; //
var_timer2_buffer=TCNT2;
digitalWrite(ledPin2, digitalRead(ledPin2) ^ 1); // toggle LED pin
lesen=LOW;
zwischen= var_timer2_buffer+var_timer2_buffer_anzahl*128; //Berechnung des Comare Wertes
lesen=HIGH;
run1=LOW;
}
attachInterrupt(interrupt_pin2, stateChange_rising,RISING); //Attach the interrupt to the input pin and monitor for ANY Change
//interrupts();
}
ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
if(lesen)
{
if((zwischen>65534)|(zwischen<10))
{
zwischen=65534;
}
OCR1A = zwischen;
}
digitalWrite(ledPin1, digitalRead(ledPin1) ^ 1); // toggle LED pin
Serial.print("TIMER1_COMPA_vect");
Serial.print("\t");
Serial.print(zwischen, DEC);
Serial.print("\t");
Serial.println(OCR1A, DEC);
}
void loop()
{
}
ISR(TIMER2_OVF_vect) {
var_timer2_anzahl++;
Serial.println("TIMER2_OVF_vect");
if(var_timer2_anzahl>=65500)
{
var_timer2_anzahl=0;
digitalWrite(Error, 1);
Serial.print("Error_timer2_overflow");
}
}
Ich glaub jetzt hab ich alle relevanten Informationen.
Wäre echt toll wenn jemand eine Idee hätte und bedanke ich mich natürlich schon im vorhinein.
Ist nähmlich das erste mal das ich einen ATmega verwende.
@Mario: du warst einfach zu schnell für mich