Projektowanie
Jak już wcześniej wspomniałem, na listingu 2 pokazano kod zawierający błędy. Mam nadzieję, że nie są one zbyt oczywiste :). Najprostszą metodą ich wyszukania jest zastosowanie debuggcra PICkit 2, który umożliwia śledzenie wykonania programu. W założeniu program ten ma wyświetlać liczby z zakresu 0...99 na dwóch wyświetlaczach 7-scgmento-wych. Wyświetlacze są obsługiwane w sposób multipleksowa-ny za pomocą przerwania.
Po skompilowaniu kodu i załadowaniu go do mikrokontrolera nic się nie dzieje, układ milczy... W zasadzie pomyłki na płytce drukowanej lub uszkodzone elementy powinny zostać już wykluczone we wcześniejszych etapach pracy. Wyszukując błędy w oprogramowaniu, staram się postawić najpieiw diagnozę i potwierdzić ją lub obalić, przeprowadzając stosowny eksperyment (prawie jak dr House:)).
Pierwsza diagnoza brzmi: pętla opóźniająca wewnątrz pętli głównej wykonuje się koszmarnie długo, stąd układ nie reaguje. Sprawdzenie tego jest bardzo proste.
Wystarczy ustawić pułapkę na linii z instrukcją value++; aby się o tym przekonać. Jeżeli pętla for się wykona, to program Rys. 12 zatrzyma się na tej pułapce, jeżeli nic - będzie pracował cały czas i pułapka nie zostanie osiągnięta. Rezultat ustawienia pułapki widoczny jest na rysunku 10 (klikając na zmiennej i zatrzymując na niej kursor, można podejrzeć jej wartość). Teoria o zbyt długim wykonaniu pętli upadła. Potwierdza ją dodatkowo okienko Watch, którego zawartość sukcesywnie się zmienia - rysunek 11. Kolejnym pomysłem do sprawdze
nia jest określenie, czy wywoływane jest przerwanie. Być może procedura obsługi przerwania jest źle napisana? Pułapka została zatem zastawiona wewnątrz przerwania, aby upewnić się, czy jest ono wywoływane. Niestety okazu-
Rys. 11
B
L>
Rys. 10
//pętla główna while(1){
for (wait=0 valu
}
1
wait<0xFFFF ; wait++){;}
wait = 0x4270
Watch
Add SFR
jnjxj
|ADC0N0 Add Symbol
| Update |
Address |
Symbol Nawe |
Value |
Binary |
I- | |
l |
06B |
yalue |
Ox3Di |
11110 |
r~ | |
F82 |
PORTC |
0x00 |
OOOOOOOO |
▼ |
Watch 1 Watch 2 Watch 3 Watch 4
//pętla główna while(1){
for<wait=0 value++ /
wait<OxFFFF ; wait + 4-) { ; }
\
L)
,vk wyświetlacz - MPLAB IDE v8.33
File Edit View Project Debugger Programmer Joo!s Ccnfigure Window Help
D & B | £ *
D% D«s 0
m m m o
D: projekty\AVT\uruchamianie układów elekronicznych\program_l \main.c
E3 CU wyswietlaczjncp
& CU Source Ffes [=1 main.c
;.....CU Header Files
} -CU Object Files CU library Files LU Linker Script CU Other Files
| <S ^ m <P % f | [5ebuq 3 d0 1 B O | $
O II N> ?> O1 ® O : HWBP (TjUsed [TjOSWBP
IM)
No Support 3
goto InterruptHandlerHigh //jump to interru endasm
PICkit 2
pici8F4530
Rys. 13
wyświetlacz - MPLAB IDE v8.33 - Watch
}
// High priority interrupt routine #pragma codę
tfpragma interrupt InterruptHandlerHigh 0void InterruptHandlerHigh <){
//zmień wyświetlacz □| if(display==0){
display = 1 ;
PORTC = 0x00 ;
PORTD = 0x7F ;
PORTC = codę[<value%100)%10] ;
□ }else{
1 • * A
pc:0x54
W:0xff
n ov z dc c
I
bankO In27, Coli
File Edit View Project Debugger Prcgrammer Took Configure Window Help
je się, że me jest... Bardzo dokładna analiza noty katalogowej pozwoli stwierdzić, że nic został ustawiony jeszcze jeden bit odpowiedzialny za uruchomienie przerwań. Teraz dopiero udało uruchomić się przerwanie (rysunek 12). Pojawia się jednak nowy problem - na wyświetlaczu jest cały czas 00. Pętla główna pracowała poprawnie, przerwanie zostało włączone, więc co jest przyczyną? Nie zawsze udaje się
- postawić diagnozę, którą można
zweryfikować. Czasami trudno jest coś sensownego wymyślić i pozostaje niestety szukanie po omacku. Podobnie może być i w tym przypadku. Czasami o znalezieniu błędu decyduje również szczęście i zdolność do oceny tego, co udało się zauważyć. W tym przypadku uruchamiając i zatrzymując na zmianę program, można zauważyć pewną nieprawidłowość: program ZAWSZE zatrzymuje się wewnątrz przerwania. Przerwanie trwa ułamek sekundy w porównaniu z czasem wykonywania pętli głównej. Jaka jest zatem szansa, że uda się „wstrzelić” w przerwania w momencie zatrzymania programu? Niewątpliwie bardzo mała, a udaje się to za każdym razem. Czyżby program główny nic był wykonywany? To można łatwo sprawdzić, ustawiając pułapkę w jego obrębie. Wskaże ona jednoznacznie, że program w ogólne nie wykonuje pętli while. Jest tam zwiększana zmienna value, która odpowiada za to, co jest wyświetlane na wyświetlaczu. Czy gdyby zmienna ta ulegała zmianie, to program działałby prawidłowo? Po ustawieniu pułapki wewnątrz przerwania i dodaniu zmiennej value do narzędzia watch można zmienić jej wartość, klikając na niej dwukrotnie i wprowadzając nową liczbę (rysunek 13). Wskazanie wyświetlacza uległo zmianie. Zatem winę ponosi brak wykonania pętli głównej, gdyż program cały czas tkwi w przerwaniu. Pojawia się pytanie - dlaczego? Jest to pytanie, na które nie da się odpowiedzieć analizując kod. Jest to pewna pułapka, w
1INS WA
|Debug JcT D & @ O 0 3 “6V | l> HI £>[> i1) {?• Sf 1 HWBP £3] Used [7~jQSWBP
No Support
Add SFR | |ADCONO Add Symbol |_Jmp_0 _^| | |
Binary | |
□ 6B value j dMU |
ODO10010 OOOOOOOO |
Watch 4
3void InterruptHandlerHigh (){
//zmień wyświetlacz if (display ^=0){
display = 1 ;
PORTC = 0x00 ;
PORTD = 0x7F ;
PORTC = codę[(value%100)%10] }else{
D Files
Watch 1 Watch 2 Watch 3
Vet$ion Contiol Find in Files
PKWam0006: The local copy o Programming Target (2009-09-1
Dim«Fjr;ptnfr.«.nrł rDoł/fiv^
u.
©a
W
[PICkit 2
(PIC18F4580
pc:0x54
iW:0xff
n ov z dc c
bank 0
A
64 Luty2010 Elektronika dla Wszystkich