Forum: Mikrocontroller und Digitale Elektronik Pin Change Interrupt atmega168


von daslachendeknie (Gast)


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
}

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.