Hallo liebes Forum, ja ich weiß der Phasenanschnitt wurde hier schon oft besprochen, aber trotzdem würde ich euch einmal bitten mir den Fehler in meinem Programm zu erklären. Als erstes finde ich es sehr merkwürdig das bei einem Analogwert von 0V der Zündimpuls erst ~220us(vielleicht auch weniger) nach der steigenden Flanke kommt. Ohne Analogwertmessung liege ich bei einer Zündung bei 0 bei 50us. Zweites hatte ich mir vorgestellt das bei einem Analogwerte von 5V der Zündpunkt genau auf der fallenden Flanke sitzt. Doch in der jetzigen Version bin ich schon bei ~3.1V(vielleicht auch weniger) bei der fallenden Flanke. Wo liegt der Fehler? (Compiler ist MikroC von Mikroelektronika) Hauptprogramm
1 | unsigned char ucADCH; |
2 | unsigned char ucADCL; |
3 | unsigned char ucTempSensor = 0; |
4 | unsigned char ucTempSensorCopy = 0; |
5 | unsigned char ucTMR1Active = 0; |
6 | |
7 | #include <interrupt.h> |
8 | |
9 | void main() { |
10 | OPTION_REG = 0b01001000; //pull-up enabled, INTE rising, Prescaler WDT, 1:1 |
11 | WPUA = 0b00000000; //all pull-ups on PORTA disabled |
12 | WPUB = 0b00000000; //all pull-ups on PORTB disabled |
13 | ANSEL = 0b00000001; //analog Input on AN0 |
14 | ANSELH = 0b00000000; //no more Analog Inputs |
15 | CM1CON0 = 0x00; //all comparators disabled |
16 | CM2CON0 = 0x00; |
17 | |
18 | ADCON0 = 0b10000001; //result right justified, reference VDD, AN0, ADC enabled |
19 | ADCON1 = 0b01010000; //Fosc/2 250ns per TAD 0b00000000, Fosc/16 0b01010000 better, but 2us per TAD |
20 | |
21 | INTCON.PEIE = 1; |
22 | INTCON.INTE = 1; |
23 | INTCON.T0IE = 1; |
24 | PIE1.ADIE = 1; |
25 | TMR0 = 205; |
26 | |
27 | TRISA = 0b00000101; //RA0 and RA2 are inputs |
28 | TRISB = 0x00; |
29 | TRISC = 0x00; |
30 | |
31 | PORTA = 0b00000010; //RA1 set to high |
32 | PORTB = 0x00; |
33 | PORTC = 0x00; |
34 | |
35 | INTCON.GIE = 1; |
36 | ADCON0.GO_DONE = 1; |
37 | while(1) |
38 | {
|
39 | |
40 | }
|
41 | }
|
Interrupt
1 | void interrupt() |
2 | {
|
3 | if (INTCON.INTF) |
4 | {
|
5 | INTCON.INTF = 0; |
6 | OPTION_REG ^= 0x40; //toggle Interrupt on falling/rising edge of RA2/INT pin |
7 | ucTMR1Active = 1; //actived ingition of the Triac |
8 | ucTempSensorCopy = ucTempSensor; //transfer 10-bit resolution of the ADC to 8-Bit |
9 | INTCON.T0IF = 1; //set the interrupt of the timer0 |
10 | }
|
11 | |
12 | if (INTCON.T0IF) |
13 | {
|
14 | INTCON.T0IF = 0; |
15 | if (ucTMR1Active && !(--ucTempSensorCopy)) //decrements the value of usTempSensorCopy |
16 | { //true if usTempSensorCopy=0 and ucTMR1Active=1 |
17 | PORTB.RB4 = 1; //Ignition triac |
18 | ucTMR1Active = 0; //deactived ingition of the Triac |
19 | ADCON0.GO_DONE = 1; //read analog |
20 | }
|
21 | TMR0 = 205; |
22 | PORTB.RB4 = 0; |
23 | }
|
24 | |
25 | if (PIR1.ADIF) |
26 | {
|
27 | PIR1.ADIF = 0; |
28 | ucADCL = ADRESL; |
29 | ucADCH = ADRESH; |
30 | ucTempSensor = ((ucADCH << 6) | (ucADCL >> 2));//divided 1024Bit/4 |
31 | if (!ucTempSensor) |
32 | ucTempSensor = 1; //avoid decrement of 0 |
33 | }
|
34 | }
|
1 | Berechnungen: |
2 | Prozessortakt: 8MHz Zyklustakt: 2MHz Zykluszeit: 0,5µs |
3 | Frequenz: 50Hz Länge einer Halbwelle: 10ms |
4 | I.Sprung in Interrupt-Routine: 9 Cycles 4,5µs |
5 | II.Sprung aus Interrupt-Routine: 8 Cycles 4µs |
6 | III.INTF: 11 Cycles 5,5µs |
7 | IV.T0IF(ucTMR1Actvie=0 ODER usTempSensorCopy>0): 10 Cycles 5µs |
8 | V.T0IF: 16 Cycles 8µs |
9 | |
10 | 256 mögliche Zündpunkte in einer Halbwelle: |
11 | 256 * I + 256 * II + III + 255 *IV + V = 3,464ms |
12 | 10ms – 3,464ms = 6,536ms |
13 | 6,536ms/256 = 25,53µs |
14 | 25,53µs/0,5µs = 51,06 |
15 | 256 – 51 = 205 |
16 | TMR0 muss immer mit 221 beschrieben werden (kein Prescaler) |
Vielen Dank