Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[Atmega8][ASM]Timer1 phase and frequency correct PWM

20 Paź 2010 20:25 2137 1
  • Poziom 2  
    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:
    Code:
    .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
  • Poziom 39  
    szimon napisał:
    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:

    To może być błąd symulatora. Niestety symulator AVR Studio nie lubi fikuśnych ustawień dla liczników i działa ignorując je. Najlepiej takie rzeczy sprawdzać na realnym sprzęcie, albo na innym mikrokontrolerze posiadającym JTAG w trybie emulacji ICE.