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

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.