którą najpewniej wpadną wszyscy Czytelnicy piszący oprogramowanie dla mikrokontrolerów AVR.
Odpowiedź w zasadzie można znaleźć tylko na dwa sposoby - zagłębiając się w dokumentację procesora lub analizując przykłady obsługi przerwania dostarczone przez producenta. Wtedy jasne stanie się. że programista musi SAMODZIELNIE skasować flagę przerwania! (sic!). Jeżeli nic, będzie ono zgłaszane raz po raz...
Po dodaniu stosownej instrukcji w obsłudze przerwania program wreszcie zaczyna działać.
Po tej długiej przeprawie z oprogramowaniem Czytelnik z przyjemnością zacznie obserwować, jak zmieniają się cyferki na wyświetlaczu, aby w pełni napawać się osiągniętym sukcesem. Po około dwóch minutach radość się skończy, gdyż na wyświetlaczu pokażą się dziwaczne znaki zamiast cyfr. Można przypuszczać, że „bzdury’' pokazywane przez wyświetlacz wynikają z błędnych kodów zapisywanych do portu C sterującego pracą poszczególnych segmentów. Trudno będzie jednak określić, co jest podstawiane jako adres tablicy codę w przerwaniu. W związku z tym kod przerwania zostanie trochę zmieniony - listing 3. Dzięki temu pojawia się nowa zmienna temp, której wartość można obserwować w narzędziu watch. Kod powinien zostać ponownie skompilowany i uruchomiony, aby przekonać się, -
czy działa tak samo (czy funkcje testujące same w sobie nie stanowią problemu). Okazuje się, że zachowanie jest takie samo. jak poprzednio. Pozostaje zatem wykonywać program krok po kroku lub lepiej wstrzymać go w momencie, gdy wyświetlacz pokazuje niewłaściwe znaki (przycisk pause). Prawdopodobnie zamiast wartości
void InterruptHandlerHigh (){ char temp = 0 ;
//zmień wyświetlacz if(display== ){ display = ;
PORTD = 0x7F ; temp = (value% )% ;
PORTC = codę[temp] ; }else{
display = 0 ;
PORTC =
PORTD =
temp = (value% )/ ;
PORTC = codę[temp] ;
}
//kasuj przerwanie PIRlbits. TMR2IF =
Listing 3
}
while( ){
//wlaćz diodę LED PORTD|=
} Listing 5
//ustaw port DDRC&= ;//wejście PORTC|= ;//puli-up
//naciśnięto przycisk ? if(PINC& ){ value = i 00 ;
} Listing 6
#include <pl8f4580.h>
//tablice kodow
char code[10] = {0xF6, 0x50, 7, 0xD3, 0x71, 0xB3, 0xB7, 0xD0, 0xF7, 0xF3);
char display = ; //wybór wyświetlacza
unsigned char value = ; //zmienna zawierajaca wskazanie wyświetlacza
// High priority interrupt vector #pragma codę InterruptVectorHigh = 0x08 void InterruptHandlerHigh(); //prototyp void InterruptVectorHigh (void){
_asm
goto InterruptHandlerHigh //jump to interrupt routine endasm
}
// High priority interrupt routine #pragma codę
#pragma interrupt InterruptHandlerHigh void InterruptHandlerHigh () {
//zmień wyświetlacz if(display== ){ display = ;
PORTC = 0x00 ;
PORTD = 0x7F ;
}else{
PORTC = 0x00 ;
PORTD = 'X3F ;
}
//kasuj przerwanie PIRlbits.TMR2IF =
}
//---------------------------
void main(){
int wait = ; //zmienna pomocnicza
//konfiguracja portow
TRISC &= 0 ; //porty segmentów jako wyjścia
TRISD &= 0F ; //porty tranzystorów wysw. jako wyjścia
PORTD |= 0xF0 ;
PORTC = 0x00 ;
//konfiguruj licznik i przerwanie T2CON =0x78 ; //ustaw preskalery T2CONbits.TMR20N = ; //wlacz licznik
PIElbits.TMR2IE = ; //wlacz przerwanie
INTCONbits.GIE = ; //przerwanie globalne
INTCONbits.PEIE = ; //przerwanie globalne
//pętla główna while(1){
for(wait= ; wait< y.FFFF ; wait++){;} value++ ;
}
zmiennej temp widoczny będzie napis out of scope, który oznacza, że wartość ta jest niedostępna. Program po naciśnięciu pause zatrzyma się najpewniej wewnątrz pętli głównej, w której nie ma takiej zmiennej, stąd ten komunikat. Nie jest to jednak żaden problem, gdyż rwania i uruchomić program. Po chwili przy-wystarczy ustawić pułapkę wewnątrz prze- czyna problemu widoczna jest jak na dłoni - rysunek 14. Zmienna temp ma
}
Listing 4
Rys. 14
wartość ujemną!!! Zakres adresowy tablicy codę jest zawarty w zakresie 0...9, a program odwołuje się do adresu -2! Winę za ten stan rzeczy ponosi przeoczenie przy deklaracji zmiennej value, powinna mieć ona wartości nicujcmne (bez znaku), czyli powinna być typu unsigned char, a nie char. Po zmianie na właściwy typ wszystko pracuje, jak należy. Ostateczny program można zobaczyć na listingu 4.
Ciąg dalszy w kolejnym numerze.
Jakub Borzdvński