Piszę program w AVRStudio 4.13SP2. Działanie programu jest (a właściwie powinno być) następujące:
Mikrokontroler generuje sygnał PWM o częstotliwości 50Hz i czasie trwania od 0,5ms do 2,5ms. Sygnał wysyłany jest na wyprowadzenie OC1A. Przy wyzerowaniu licznika podczas zliczania w dół wywoływane jest przerwanie włączające przetwarzanie A/C. Wewnątrz przerwania od przetwornika A/C ustalana jest szerokość impulsów PWM, a wynik dodatkowo wyrzucany do diody na port D.
Przetwornik działa dobrze, ale z Timerem męczę się już jakiś czas, a niestety do szafy tego schować i zapomnieć nie mogę. Problem jest taki:
Zgodnie z trybem pracy ustalonym bitami WGM1 3:0 = 8 licznik powinien zliczać w górę aż do osiągnięcia wartości rejestru ICR1, następnie zacząć zliczać w dół, aż do osiągnięcia poziomu zerowego, co uruchamia przerwanie. W międzyczasie osiąga wartość zapisaną w rejestrze OCR1A, co powoduje zmianę stanu na wyjściu. Przeglądam program któryś raz z kolei i nie mogę dojść dlaczego licznik po osiągnięciu wartości TOP (ICR1) nie przestaje zliczać w górę. Liczy dalej, dochodzi do wartości 0xFFFF, zeruje się i generuje przerwanie. Próbowałem jeszcze trybu Phase correct PWM (WGM1 3:0=9).
Być może ktoś miał podobny przypadek? Niewykluczone, że gdzieś się rypnąłem w pojedynczym bicie i od ciągłego szukania błędu przestałem cokolwiek zauważać. Poniżej kod programu:
Mikrokontroler generuje sygnał PWM o częstotliwości 50Hz i czasie trwania od 0,5ms do 2,5ms. Sygnał wysyłany jest na wyprowadzenie OC1A. Przy wyzerowaniu licznika podczas zliczania w dół wywoływane jest przerwanie włączające przetwarzanie A/C. Wewnątrz przerwania od przetwornika A/C ustalana jest szerokość impulsów PWM, a wynik dodatkowo wyrzucany do diody na port D.
Przetwornik działa dobrze, ale z Timerem męczę się już jakiś czas, a niestety do szafy tego schować i zapomnieć nie mogę. Problem jest taki:
Zgodnie z trybem pracy ustalonym bitami WGM1 3:0 = 8 licznik powinien zliczać w górę aż do osiągnięcia wartości rejestru ICR1, następnie zacząć zliczać w dół, aż do osiągnięcia poziomu zerowego, co uruchamia przerwanie. W międzyczasie osiąga wartość zapisaną w rejestrze OCR1A, co powoduje zmianę stanu na wyjściu. Przeglądam program któryś raz z kolei i nie mogę dojść dlaczego licznik po osiągnięciu wartości TOP (ICR1) nie przestaje zliczać w górę. Liczy dalej, dochodzi do wartości 0xFFFF, zeruje się i generuje przerwanie. Próbowałem jeszcze trybu Phase correct PWM (WGM1 3:0=9).
Być może ktoś miał podobny przypadek? Niewykluczone, że gdzieś się rypnąłem w pojedynczym bicie i od ciągłego szukania błędu przestałem cokolwiek zauważać. Poniżej kod programu:
.include "m8def.inc"
.cseg
;******** DEFINICJA WEKTORA PRZERWAŃ ************
.org 0x00 rjmp Reset ; RESET
.org 0x08 rjmp T1ovf ; T1 OVERFLOW
.org 0x0E rjmp ADconv ; ADC CONVERSION COMPLETE
;************************************************
Reset:
ldi r20, 0x0F
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, low(RAMEND)
out SPL, r16
ldi r16, 0xFF
out DDRD, r16
ldi r16, 0xFF
out PORTD, r16
ldi r16, 0xFF
out DDRB, r16
ldi r16, 0x00
out PORTB, r16
;********* PRZETWORNIK A/C ***************
ldi r16, 0x00
ori r16, (1<<REFS0 | 1<<ADLAR)
out ADMUX, r16
ldi r16, 0x00
ori r16, (1<<ADEN | 1<<ADIE | 1<<ADPS1 | 1<<ADPS0)
out ADCSRA, r16
;*****************************************
;********* TIMER1 ************
ldi r16, 0x00
out TCNT1H, r16
out TCNT1L, r16
ldi r17, 0x01
ldi r16, 0xF4
out OCR1AH, r17
out OCR1AL, r16
ldi r17, 0x27
ldi r16, 0x10
out ICR1H, r17
out ICR1L, r16
ldi r16, 0x00
ori r16, (1<<TOIE1) ;T1 ovf enable
out TIMSK, r16
ldi r16, 0x00
ori r16, (1<<COM1A1) ;kanal OC1A, non-inv PWM
out TCCR1A, r16
ldi r16, 0x00
ori r16, (1<<WGM13 | 1<<CS11) ;PWM phase & freq correct
out TCCR1B, r16
;*****************************
sei
Main:
rjmp Main
;********** PROCEDURY OBSŁUGI PRZERWAŃ **********
; Czytaj wynik przetwarzania i wyrzuć na port D
ADconv:
in r16, ADCH
ldi r17, 240
cp r17, r16
brcs ADCgreater
ldi r17, 60
cp r17, r16
brcc ADClower
out PORTD, r16
rjmp ADCustaw
ADCgreater:
ldi r16, 240
out PORTD, r16
rjmp ADCustaw
ADClower:
ldi r16, 60
out PORTD, r16
ADCustaw:
ldi r17, 10
mul r16, r17
out OCR1AH, r1
out OCR1AL, r0
reti
T1ovf:
sbi ADCSRA, ADSC
reti