Skocz do zawartości

Opoznienia programowe dla AVR (C)


Zuk

Pomocna odpowiedź

Witam.

Chciałbym przedstawić programik i jego zastosowanie do generacji opóźnień w mikrokontrolerach AVR.

Program na podstawie informacji o wymaganym przez nas opóźnieniu

podawanym w cyklach lub sekundach i częstotliwości kwarcu generuje kod

ASM pętli czekającej odpowiednią liczbę cykli.

Kodu tego, po drobnych modyfikacjach, można bez problemu użyć jako funkcji

np w AVRstudio.

W jednym pliku ASM możemy mieć wiele funkcji opóźnień, należy utworzyć plik .s oraz plik nagłówkowy .h, w którym podajemy nazwy funkcji.

Algorytm postępowania:

- generujemy kod (przykład:opóźnienie 25 cykli):

; ============================= 
;    delay loop generator 
;     25 cycles: 
; ----------------------------- 
; delaying 24 cycles: 
         ldi  R17, $08
WGLOOP0:  dec  R17
         brne WGLOOP0
; ----------------------------- 
; delaying 1 cycle: 
         nop
; ============================= 

-zmieniamy liczby w zapisie HEX do formatu gcc

czyli zamieniamy $ na 0x

ldi  R17, $08
na
ldi  R17, 0x08

- zamieniamy nic nie mówiącą nazwę pętli na unikalną

 WGLOOP0:  dec  R17
         brne WGLOOP0
na
Petla1:  dec  R17
         brne Petla1 

- przed funkcją zachowujemy wszystkie używane w niej rejestry na stosie,
w naszym przypadku tylko R17,
wstawiając na początku i na końcu instrukcje obsługi stosu:

 push R17
//ciało funkcji
pop R17 

- dodajemy nazwę funkcji, którą będziemy ją wywoływać z poziomu C

gotowy zmodyfikowany kod wygląda tak:

//naglowek pliku s z nzawami funkcji
.text
.global delay_29_cycles
// .global inne_opoznienie

//funkcje
delay_29_cycles: 
push R17
; ----------------------------- 
; delaying 24 cycles: 
         ldi  R17, 0x08
Petla1:  dec  R17
         brne Petla1
; ----------------------------- 
; delaying 1 cycle: 
         nop
pop R17
ret

// inne_opoznienie: 
// (...) 

- przygotowujemy plik nagłówkowy h

w którym podajemy nazwy funkcji w sposób następujący:

 extern void delay_29_cycles(void); 
//extern void inne_opoznienie(void); 

Stosuję tę metodę i u mnie zawsze działa, jeśliby nie działało

to dodanie słowa volatile w deklaracji powinno rozwiązać problem:

extern volatile viod delay_29_cycles(void);

Dlaczego wygenerowałem kod na 25 cykli a w nazwie użyłem 29...

Ponieważ dodałem instrukcje stosu, które zajmują też kilka cylki zegarowych.

Nie sprawdziłem czy jest generowane dokładnie 29 cykli opóźnienia, więc moze być generowane 30 lub 31.

Przypominam o dołączeniu obydwu plików do projektu i użycie #include.

W załączniku znajduje się opisywany przeze mnie program oraz przykładowa

(działająca) biblioteka opóźnień wykorzystywana przeze mnie do obsługi magistrali

1-wire.

Mam nadzieję, że się to komuś przyda.

W razie pytań odpowiem na nie w miarę możliwości.

delay.zip

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.