Forum: Mikrocontroller und Digitale Elektronik Interrupt TIMER1_CAPT wird nicht ausgelöst


von X.P. (Gast)


Lesenswert?

Hallo zusammen,

Ich versuche gerade einen Wert an einem Potentiometer einzulesen und 
anhand des ADCs ihn in digital umzuwandeln. Den digitalen Wert gebe ich 
an den OCR0B und den Timer0 habe ich im Fast-PWM-Modus mit einer 
Frequenz von 1 kHz eingestellt. Anhand des Timer1 (bzw. 
Timer1-Capture-Interrupt) versuche ich den Duty Cycle in Prozent 
auszugeben. Alles scheint ok zu funktionieren bis auf das Auslösen des 
Interrupts. Der Interrupt wird gar nicht ausgelöst und die Variable 
result hat keinen (vernünftigen) Wert am Ende. Kann mir bitte jemand 
sagen, was ich hier falsch mache?


1
#define F_CPU 16000000UL
2
#define BAUDRATE 9600
3
#define BAUD_CONST (((F_CPU/(BAUDRATE*16UL)))-1)
4
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <util/delay.h>
8
#include <stdio.h>
9
10
volatile uint8_t ready = 0;
11
volatile uint16_t result;
12
13
// USART
14
void USART_Init() {
15
  UBRR0H = (BAUD_CONST >> 8);
16
  UBRR0L = BAUD_CONST;
17
  UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
18
}
19
20
void USART_Transmit(unsigned char data) {
21
  while(!(UCSR0A & (1<<UDRE0))) ;
22
  UDR0 = data;
23
}
24
25
// ADC
26
void ADC_Init() {
27
  ADCSRA |= (1<<ADEN);    // ADC on
28
  ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);    // set prescaler to 128
29
}
30
31
uint8_t ReadValue(uint8_t adc_value) {
32
  uint8_t d_value;
33
  
34
  ADMUX = adc_value;
35
  _delay_ms(5);
36
  
37
  ADCSRA |= (1<<ADSC);    // start first conversion
38
  
39
  while (ADCSRA & (1<<ADSC)) ;    // wait until the conversion is over
40
  
41
  d_value = ADC >> 2;
42
  
43
  return (d_value < 250) ? d_value : 0;
44
}
45
46
// Timer1
47
ISR(TIMER1_CAPT_vect) {
48
  static uint16_t value1, value2;
49
  
50
  if(TCCR1B & (1<<ICES1)) {
51
    value1 = ICR1;
52
    TCCR1B &= ~(1<<ICES1);    // now waiting for falling edge
53
  }
54
  else {
55
    value2 = ICR1;
56
    TCCR1B |= (1<<ICES1);    // now waiting for raising edge
57
    result = value2 - value1;
58
    ready = 1;    // ready to print the duty cycle
59
  }
60
}
61
62
63
int main(void)
64
{  
65
  const unsigned char DutyCycle[] = "Duty cycle in percentage: ";
66
  unsigned char IntToString[3];
67
  int percentage;
68
  
69
  DDRD |= (1<<DDD5);    // OC0B set as output (LED)
70
  
71
  USART_Init();
72
  ADC_Init();
73
  
74
  // Timer0
75
  TCCR0A |= (1<<COM0B1)|(1<<WGM01)|(1<<WGM00);    // clear OC0A and OC0B on compare match, Fast PWM
76
  TCCR0B |= (1<<WGM02)|(1<<CS01)|(1<<CS00);    // prescaler set to 64
77
  OCR0A = 249;    // frequency is now 1 kHz
78
  
79
  // Timer1
80
  TCCR1B |= (1<<ICES1)|(1<<CS11)|(1<<CS10);    // waiting for raising edge, prescaler set to 64, 250 kHz frequency
81
  TIMSK1 |= (1<<ICIE1);    // Capture-Interrupt on
82
  
83
  sei();
84
  
85
    while (1) 
86
    {
87
    OCR0B = ReadValue(0b01000000);
88
    
89
    if(ready) {
90
      cli();
91
      
92
      percentage = (result / 1000.0) * 100;
93
      sprintf((char*)IntToString, "%d", percentage);
94
      
95
      for(int i = 0; DutyCycle[i] != '\0'; i++)
96
        USART_Transmit(DutyCycle[i]);
97
        
98
      for(int i = 0; IntToString[i] != '\0'; i++)
99
        USART_Transmit(IntToString[i]);
100
        
101
      USART_Transmit('%');
102
      USART_Transmit('\r');
103
      USART_Transmit('\n');
104
      
105
      sei();
106
      
107
      ready = 0;
108
    }
109
    
110
    //_delay_ms(500);
111
  }
112
}

von TLDR (Gast)


Lesenswert?

Was ist unter dem Hinweis

"Wichtige Regeln - erst lesen, dann posten!
.............
 Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
............."

nicht zu verstehen?

von S. Landolt (Gast)


Lesenswert?

> Der Interrupt wird gar nicht ausgelöst und ...

? - ?
Es läuft doch alles!? Mal von einem ATmega328P ausgehend.
  Nur die Rechnerei sieht merkwürdig aus, Beispiel Ucc/2: dann ist der 
Tastgrad 0.5, bei 1 kHz werden also 500 us erzeugt, mit dem Timer1 bei 
250 kHz folglich 125 gemessen, was zur Ausgabe "Duty cycle in 
percentage: 12%" führt; bei Ucc*3/5 "Duty cycle in percentage: 15%".

von S. Landolt (Gast)


Lesenswert?

PS:
D5 und B0 sind natürlich verbunden.

von X.P. (Gast)


Lesenswert?

Danke für die Bemerkung. Hatte vergessen, den Wert von result nach dem 
Subtrahieren mit 4 zu multiplizieren, da bei 250 kHz ein Tick = 4 µs. 
Bei mir hat es gestern nicht funktioniert (duty cycle hat ständig 0 
ausgegeben), deswegen habe ich es gepostet (konnte es aber danach nicht 
testen, da das Gerät nicht im Labor der Uni liegt). Aber wenn du sagst, 
dass es funktioniert, dann sollte es. Vielen Dank nochmal :)

Beitrag #6913061 wurde von einem Moderator gelöscht.
von X.P. (Gast)


Lesenswert?

Hab's heute nochmal probiert und es hat funktioniert. Es hat 
höchstwahrscheinlich an die Verbindung der PINs gelegen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.