Pin Change Interrupt atmega168

Gast #2261166
Lesenswert?
• ▲
▼
Hallo an Alle!

Da dies mein erster Beitrag hier im Forum ist, möchte ich mich erstmal 
für die tolle Arbeit hier bedanken! Hat mir schon oft aus der Patsche 
geholfen.. ;)

Nun aber zum Problem:
Ich habe an meinem atmega168 insgesammt vier PWM-Eingänge angeschlossen. 
Diese möchte ich nun auswerten um die PWM-Dauer festzustellen. Dazu sei 
gesagt, dass sich jeweils zwei der Pins (4,6 / 13,14) in den 
Pin-Change-Bereichen 0 und 1 befinden.

Mein Code funktioniert bisher aber leider nur für den 
Pin-Change-Interrupt-0 (PCINT0). Der PCINT1 wird irgendwie nicht 
ausgelöst! :( Die Signale liegen aber an - habs mit dem OSZI 
nachgemessen.

PCICR und PCIFR sollten korrekt sein und auch die PCMSK0/1 sollten mit 
den Pins überein stimmen (habs auch schon mit PCMSK1 = 0x7F) probiert.

Weis noch jemand einen Rat?

Grüße, Sascha

Code:
1
/*****************************************************
2
This program was produced by the
3
CodeWizardAVR V2.05.2 Evaluation
4
Automatic Program Generator
5
© Copyright 1998-2011 Pavel Haiduc, HP InfoTech s.r.l.
6
http://www.hpinfotech.com
7

8
Project : RC-Panzer
9
Version : 1
10
Date    : 07.07.2011
11
Author  : Sascha Albrecht
12
Company : Modellfreunde Thüringen
13
Comments: 
14

15

16
Chip type               : ATmega168
17
Program type            : Application
18
AVR Core Clock frequency: 16,001000 MHz
19
Memory model            : Small
20
External RAM size       : 0
21
Data Stack size         : 256
22
*****************************************************/
23

24
#include <mega168.h>
25

26
//Achtung: PWM-Signal ist invertiert! - damit liegt Fall vor Rise
27
unsigned int pwm1rise;  //steigende Flanke
28
unsigned int pwm1fall;  //fallende Flanke
29
unsigned int pwm1time;  //berechneter Zeitwert des PWM-(High)-Signals 
30
unsigned int pwm1last = 1;  //merkt sich den letzten Zustand des Pins (um zu prüfen, ob er geändert wurde)
31
unsigned int pwm1flag = 0;
32
unsigned int pwm2rise;
33
unsigned int pwm2fall;
34
unsigned int pwm2time;
35
unsigned int pwm2last = 1;
36
unsigned int pwm2flag = 0;
37
unsigned int pwm3rise;
38
unsigned int pwm3fall;
39
unsigned int pwm3time;
40
unsigned int pwm3last = 1;
41
unsigned int pwm3flag = 0;
42
unsigned int pwm4rise;
43
unsigned int pwm4fall;
44
unsigned int pwm4time;
45
unsigned int pwm4last = 1;
46
unsigned int pwm4flag = 0;
47

48

49

50
// Pin change 0-7 interrupt service routine
51
interrupt [PC_INT0] void pin_change_isr0(void)
52
{  
53
    int time_h, time_l;
54
    time_l = TCNT1L;
55
    time_h = TCNT1H;    
56
  
57
    if(PIND.2 != pwm1last)
58
    { 
59
        if(pwm1last == 1)
60
        {
61
            pwm1fall = ((int)time_h << 8) + time_l;
62
            pwm1last = 0;
63
        }
64
        else
65
        {
66
            pwm1rise = ((int)time_h << 8) + time_l;
67
            pwm1last = 1;
68
            pwm1flag = 1;            
69
        }            
70
    }
71
    
72
    if(PIND.4 != pwm2last)
73
    { 
74
        if(pwm2last == 1)
75
        {
76
            pwm2fall = ((int)time_h << 8) + time_l;        //Achtung: Signal ist invertiert -> Fall kommt vor Rise!
77
            pwm2last = 0;
78
        }
79
        else
80
        {
81
            pwm2rise = ((int)time_h << 8) + time_l;
82
            pwm2last = 1;
83
            pwm2flag = 1;
84
        }            
85
    }            
86
}
87

88
// Pin change 8-14 interrupt service routine
89
interrupt [PC_INT1] void pin_change_isr1(void)
90
{
91
    int time_h, time_l;
92
    time_l = TCNT1L;
93
    time_h = TCNT1H;    
94
  
95
    if(PIND.7 != pwm3last)
96
    { 
97
        if(pwm3last == 1)
98
        {
99
            pwm3fall = ((int)time_h << 8) + time_l;
100
            pwm3last = 0;
101
        }
102
        else
103
        {
104
            pwm3rise = ((int)time_h << 8) + time_l;
105
            pwm3last = 1;
106
            pwm3flag = 1;            
107
        }            
108
    }
109
    
110
    if(PINB.0 != pwm4last)
111
    { 
112
        if(pwm4last == 1)
113
        {
114
            pwm4fall = ((int)time_h << 8) + time_l;        //Achtung: Signal ist invertiert -> Fall kommt vor Rise!
115
            pwm4last = 0;
116
        }
117
        else
118
        {
119
            pwm4rise = ((int)time_h << 8) + time_l;
120
            pwm4last = 1;
121
            pwm4flag = 1;
122
        }            
123
    } 
124
    
125
  //Dient nur zur Überprüfung, ob die ISR ausgeführt wird, oder nicht
126
    //if(PINC.5)
127
    //    PORTC.5 = 0;
128
    //else
129
    PORTC.5 = 1;        //Der Ausgang sollte jett HI sein, sobald die ISR einmal ausgeführt wurde
130
}
131

132
// Standard Input/Output functions
133
#include <stdio.h>
134

135
// Declare your global variables here
136

137
void main(void)
138
{
139
// Declare your local variables here
140

141
// Crystal Oscillator division factor: 1
142
#pragma optsize-
143
CLKPR=0x80;
144
CLKPR=0x00;
145
#ifdef _OPTIMIZE_SIZE_
146
#pragma optsize+
147
#endif
148

149
// Input/Output Ports initialization
150
// Port B initialization
151
// Func7=Out Func6=In Func5=In Func4=Out Func3=Out Func2=Out Func1=Out Func0=In 
152
// State7=0 State6=T State5=T State4=0 State3=0 State2=0 State1=0 State0=P 
153
PORTB=0x01;
154
DDRB=0x9E;
155

156
// Port C initialization
157
// Func6=In Func5=Out Func4=In Func3=In Func2=Out Func1=Out Func0=Out 
158
// State6=T State5=0 State4=T State3=T State2=0 State1=0 State0=0 
159
PORTC=0x00;
160
DDRC=0x27;
161

162
// Port D initialization
163
// Func7=In Func6=Out Func5=Out Func4=In Func3=Out Func2=In Func1=Out Func0=In 
164
// State7=P State6=0 State5=0 State4=P State3=0 State2=P State1=0 State0=T 
165
PORTD=0x94;
166
DDRD=0x6A;
167

168
// Timer/Counter 0 initialization
169
// Clock source: System Clock
170
// Clock value: 16001,000 kHz
171
// Mode: Fast PWM top=0xFF
172
// OC0A output: Non-Inverted PWM
173
// OC0B output: Non-Inverted PWM
174
TCCR0A=0xA3;
175
TCCR0B=0x01;
176
TCNT0=0x00;
177
OCR0A=0x30;
178
OCR0B=0xA0;
179

180
// Timer/Counter 1 initialization
181
// Clock source: System Clock
182
// Clock value: 2000,125 kHz
183
// Mode: Fast PWM top=ICR1
184
// OC1A output: Non-Inv.
185
// OC1B output: Non-Inv.
186
// Noise Canceler: Off
187
// Input Capture on Falling Edge
188
// Timer1 Overflow Interrupt: Off
189
// Input Capture Interrupt: Off
190
// Compare A Match Interrupt: Off
191
// Compare B Match Interrupt: Off
192
TCCR1A=0xA2;
193
TCCR1B=0x1A;
194
TCNT1H=0x00;
195
TCNT1L=0x00;
196
//ICR1H=0x9C;                           //20ms Periode
197
//ICR1L=0x40;
198
ICR1H=0xAB;                             //22ms Periode
199
ICR1L=0xE0;
200
OCR1AH=0x0B;
201
OCR1AL=0xB8;
202
OCR1BH=0x0F;
203
OCR1BL=0xA0;
204

205
// Timer/Counter 2 initialization
206
// Clock source: System Clock
207
// Clock value: 16001,000 kHz
208
// Mode: Fast PWM top=0xFF
209
// OC2A output: Non-Inverted PWM
210
// OC2B output: Non-Inverted PWM
211
ASSR=0x00;
212
TCCR2A=0xA3;
213
TCCR2B=0x01;
214
TCNT2=0x00;
215
OCR2A=0x30;
216
OCR2B=0xA0;
217

218
// External Interrupt(s) initialization
219
// INT0: Off
220
// INT1: Off
221
// Interrupt on any change on pins PCINT0-7: On
222
// Interrupt on any change on pins PCINT8-14: On
223
// Interrupt on any change on pins PCINT16-23: Off
224
EICRA=0x00;
225
EIMSK=0x00;
226
PCICR=0x03;
227
PCMSK0=0x28;
228
PCMSK1=0x60;
229
PCIFR=0x03;
230

231
// Timer/Counter 0 Interrupt(s) initialization
232
TIMSK0=0x00;
233

234
// Timer/Counter 1 Interrupt(s) initialization
235
TIMSK1=0x00;
236

237
// Timer/Counter 2 Interrupt(s) initialization
238
TIMSK2=0x00;
239

240
// USART initialization
241
// Communication Parameters: 8 Data, 1 Stop, No Parity
242
// USART Receiver: On
243
// USART Transmitter: On
244
// USART0 Mode: Asynchronous
245
// USART Baud Rate: 19200
246
UCSR0A=0x00;
247
UCSR0B=0x18;
248
UCSR0C=0x06;
249
UBRR0H=0x00;
250
UBRR0L=0x33;
251

252
// Analog Comparator initialization
253
// Analog Comparator: Off
254
// Analog Comparator Input Capture by Timer/Counter 1: Off
255
ACSR=0x80;
256
ADCSRB=0x00;
257
DIDR1=0x00;
258

259
// ADC initialization
260
// ADC disabled
261
ADCSRA=0x00;
262

263
// SPI initialization
264
// SPI disabled
265
SPCR=0x00;
266

267
// TWI initialization
268
// TWI disabled
269
TWCR=0x00;
270

271
// Global enable interrupts
272
#asm("sei")
273

274
while (1)
275
    {            
276
        if(pwm1flag == 1)
277
        {   
278
            //if(pwm1fall > pwm1rise)          //für den Fall, dass zwischen pwmXfall und pwmXrise ein TimerOverflow stattgefunden hat
279
            //    pwm1time = ((int)(((int)ICR1H << 8) + ICR1L)) - pwm1fall + pwm1rise;
280
            //else
281
                pwm1time = pwm1rise - pwm1fall;             //Zeit berechnen
282
            
283
            if(pwm1time >= 1800 && pwm1time <= 4200)            //nur Werte zwischen 900us und 2100us sind gültig!
284
            {              
285
                #asm("cli") 
286
        //OCR1AH = pwm1time >> 8;            //setze den PWM-Ausgang mit der eingelesenen Zeit
287
        //OCR1AL = pwm1time & 0xFF;            //-"-      --> nur zum Test!
288
                #asm("sei")
289
            }   
290
            pwm1flag = 0;
291
        }  
292
  
293
        if(pwm2flag == 1)
294
        {   
295
            pwm2time = pwm2rise - pwm2fall;                     //Zeit berechnen           
296
            if(pwm2time >= 1800 && pwm2time <= 4200)            //nur Werte zwischen 900us und 2100us sind gültig!
297
            {    
298
                #asm("cli")           
299
                //OCR1BH = pwm2time >> 8;            //setze den PWM-Ausgang mit der eingelesenen Zeit
300
                //OCR1BL = pwm2time & 0xFF;            //-"-      --> nur zum Test!
301
                #asm("sei")
302
            }   
303
            pwm2flag = 0;
304
        }   
305
        
306
        if(pwm3flag == 1)
307
        {   
308
            pwm3time = pwm3rise - pwm3fall;                     //Zeit berechnen           
309
            if(pwm3time >= 1800 && pwm3time <= 4200)            //nur Werte zwischen 900us und 2100us sind gültig!
310
            {    
311
                #asm("cli")           
312
        OCR1AH = pwm3time >> 8;              //setze den PWM-Ausgang mit der eingelesenen Zeit
313
        OCR1AL = pwm3time & 0xFF;            //-"-      --> nur zum Test!
314
                #asm("sei")
315
            }   
316
            pwm3flag = 0;
317
        }
318
        
319
        if(pwm4flag == 1)
320
        {   
321
            pwm4time = pwm4rise - pwm4fall;                     //Zeit berechnen           
322
            if(pwm4time >= 1800 && pwm4time <= 4200)            //nur Werte zwischen 900us und 2100us sind gültig!
323
            {    
324
                #asm("cli")           
325
        OCR1BH = pwm4time >> 8;              //setze den PWM-Ausgang mit der eingelesenen Zeit
326
        OCR1BL = pwm4time & 0xFF;            //-"-      --> nur zum Test!
327
                #asm("sei")
328
            }   
329
            pwm4flag = 0;
330
        }                     
331
    }
332
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren