Witam .
Napisałem ( prawie) sobie na ww procesor program w asm i bascomie który ma robić za zamek otwierany kartą . W bascomie wszystko działa w 100 % według założenia jednak w asm mam taki problem że układ sam zmienia swoje taktowanie (ponad 2x) przez co wszystkie funkcje czasowe nie pracują jak powinny . Nie było by w tym nic niezwykłego ( ustawiony prescaler ) gdyby nie fakt że 1 raz po wgraniu programu bez odłączania zasilania wszystkie funkcje czasowe działają poprawnie ( zrobiłem sobie na początku kodu zaraz po starcie pętlę która ma zaświecać i gasić diodę co 3 sec ) . Jednak gdy zresetuję układ przez odłączenie zasilania , po ponownym uruchomieniu tego samego kodu !! wszystkie czynności wykonują się ponad 2 razy wolniej . P Odkreślam że w programie ani fusach nic nie zmieniałem w tym czasie .
próbowałem podczas startu zerować bajt prescalera , oraz kalibracji oscylatora ale dalej jest to samo . Nie mam pojęcia co może powodować takie spowolnienie pracy procesora skoro czas odliczany jest przy pomocy timera więc podstawa czasowa jest brana z oscylatora ( używam wewnętrzny oscylator 8 Mhz ) .
Wrzucam kawałek kodu w ASM :
i używane podfunkcje :
Fajnie było by gdyby ktoś mógł wskazać na co należy zwrócić uwagę .
Ustawienia fusów prezentują się tak :
LOW : 0xD2
HIGh : 0xD7
EXT : 0x01
Komentarze zawierają sporo błędów językowych ale przepuszczę je przez Worda gdy program będzie działał jak należy .
Kolejną intrygującą rzeczą jest to że po zapisaniu programu razem z pamięcią EEPROM program się zawiesza ( nie startuje ) , chociaż w żaden sposób nie odnosiłem się do tej pamięci , i nie były załączone żadne przerwania .
Wszystko zaczynało jednak działać gdy najpierw wgrałem EEprom , zresetowałem układ , a następnie wgrałem program . Wtedy wszystko ruszało tak jak powinno . Oczywiście przy ustawionym fusie EESAVE . Sprawdziłem jednak czy dane z eeprom się nie skasowały, i tak jak być powinno wszystkie były na swoim miejscu.
I to chyba tyle .
Byłbym wdzięczny gdyby ktoś potrafił wytłumaczyć mi te 2 zagadki .
Priorytetem jest pierwsza , druga można traktować w kategorii ciekawostki jako że nie przeszkadza ona przy pisaniu programu , jeśli czynności wykona się prawidłowo .
Ps. Gdy skończę kod w asm to podzielę się na elektrodzie całym kodem zarówno w bascomie jak i assamblerze z dokładnymi komentarzami , wykresami funkcji , schematami płytkami itd..
Pozdrawiam .
Napisałem ( prawie) sobie na ww procesor program w asm i bascomie który ma robić za zamek otwierany kartą . W bascomie wszystko działa w 100 % według założenia jednak w asm mam taki problem że układ sam zmienia swoje taktowanie (ponad 2x) przez co wszystkie funkcje czasowe nie pracują jak powinny . Nie było by w tym nic niezwykłego ( ustawiony prescaler ) gdyby nie fakt że 1 raz po wgraniu programu bez odłączania zasilania wszystkie funkcje czasowe działają poprawnie ( zrobiłem sobie na początku kodu zaraz po starcie pętlę która ma zaświecać i gasić diodę co 3 sec ) . Jednak gdy zresetuję układ przez odłączenie zasilania , po ponownym uruchomieniu tego samego kodu !! wszystkie czynności wykonują się ponad 2 razy wolniej . P Odkreślam że w programie ani fusach nic nie zmieniałem w tym czasie .
próbowałem podczas startu zerować bajt prescalera , oraz kalibracji oscylatora ale dalej jest to samo . Nie mam pojęcia co może powodować takie spowolnienie pracy procesora skoro czas odliczany jest przy pomocy timera więc podstawa czasowa jest brana z oscylatora ( używam wewnętrzny oscylator 8 Mhz ) .
Wrzucam kawałek kodu w ASM :
.include "m48def.inc" ; dane dla kompilatora AVRstudio
.def flagi = r2
.def wyswietlacz = r3
.def klawiatura = r4
.def sloty = r8
.def zro = r6 ; przechowujemy tutaj wartośc zero do porównania instrukcją CP
.def status = r7
.def liczbakart = r5
.def i = r16
.def o = r17
.def p = r18
.def slep = r19
.def daneeram = r20
.def adreseram = r21
.def dane = r22
.def u = r23
.def r = r24
.def zadanie = r25
.EQU IOKARTY = PC0 ; Linia danych karty
.EQU KLAPA = PC1 ; Krańcówka otwarcia klapy ( 1 - klapa zamknięta , 0 - klapa otwarta)
.EQU ZAMEK = PC2 ; Otwieranie zamka
.EQU RXD = PD0 ; Uart - dane odbierane ( Transmisja rs232 , do wykorzystania )
.EQU TXD = PD1 ; Uart - dane wysyłane ( Transmisja rs232 , do wykorzystania )
.EQU OK = PD2 ; Przycisk SET na klawiaturze .
.EQU STYKKARTY = PD3 ; Krańcówka obecności karty ( 0 - karta obecna , 1 - karta nieobecna )
.EQU WEJSCIE1 = PD5 ; Wejście logiczne do wykozystania
.EQU WEJSCIE2 = PD6 ; Wejście logiczne do wykozystania
.EQU DS = PD7 ; Linia danych wyświetlacza i klawiatury .
.EQU KIERUNEK = PB0 ; Kierunek transmisji ( 0 - transmisja do wyświetlacza (wyświetlacz świeci jeśli ustawiony) , 1 - wyświetlacz gaśnie , wybrano odczyt z klawiatury )
.EQU STCP = PB1 ; Linia potwierdzenia wyświetlacza i klawiatury
.EQU SHCP = PB2 ; Linia zegara wyświetlacza i klawiatury
.EQU WYJSCIE1 = PB3 ; Wyjście tranzystorowe ( max 0,5 A ) - do wykorzystania
.EQU WYJSCIE2 = PB4 ; Wyjście tranzystorowe ( max 0,5 A ) - do wykorzystania
.EQU WYJSCIE3 = PB5 ; Wyjście tranzystorowe ( max 0,5 A ) - do wykorzystania
.EQU RSTKARTY = PB6 ; Linia resetu karty
.EQU ZEGARKARTY = PB7 ; Linia zegara karty
; Dodatkowo zostały wyprowadzone 2 linie przetwornika analogowo-cyfrowego do wykorzystania
; Stałe adresów dostępu do pamięci 24c02 ( nogi E0 , E1 , E2 zwarte do masy )
.EQU adresW = 0xA0 ; Adres zapisu do pamięci
.EQU adresR = 0xA1 ; Adres odczytu z pamięci
.dseg
danekarty: .byte 16
zapisanekarty: .byte 128
.cseg
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ATmega 48 / 88 / 168 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;!! W wyżej wymienionych procesorach rejestry wejścia/wyjścia o adresach od 0x60 do 0xFF !!
;!! nie mogą być odczytywane i zapisywane przy pomocy instrukcji OUT oraz IN . Rejestry !!
;!! te obsługuje się jak zwykłą pamięć S-RAM czyli przy pomocy funkcji STS , ST , LD , LDS !!
;!! Najprostszym sposobem na sprawdzenie czy dany rejest należy do ww grópy jest zobaczenie!!
;!! czy w oknie we\wy ( po prawej stronie ) dla interesującego nas rejestru są podane oba !!
;!! adresy , jśli taknie jest to rejestr ma adres powyżęj 0x60 . Dla rejestrów które mają !!
;!! wyswietlone oba adresy TRZEBA użyć instrukcji IN , OUT ponieważ tylko one działają dla!!
;!! tej grópy rejestrów. Trzeba na to uważać ponieważ bardzo trudno jest znaleźć taki błąd !!
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
; program
.org 0x00 ; PC = 0 , przerwania reset lub podania zasialania i załączenia ukłądau
rjmp start ; przeskakujemy adresy przerwań (od 0x01 do 0x19) . Atmega48 ma 26 przerwań.
.org 0x02 ;adres przerwania INT1
; rjmp karta ;jeśli nastąpi przerwanie z INT1 to przeskakujemy do podfuncji karta
.org 0x10 ;adres pzerwania przepełnienia timer0
rjmp czas ;przeskakujemy do podfunkcji czas
.org 0x30
start:
; clr i
; sts clkpr , i
; ldi i , 160
; sts osccal , i
ldi i , high(ramend) ;wpisujemy do rejestru SP (wskaźnik stosu) adres ostatniej komórki pamięci SRAM
out sph , i ; funkcja high(x) oznacza odczytanie starszego bajtu adresu
ldi i , low(ramend) ; funkcja low(x) oznacza odczytanie młodszego bajtu adresu
out spl , i ; ramend jest to etykieta zawarta w paczce z informacjami o procesorze dla AVRStudio
; (patrz 1 linijka kodu) w której zapisany jest adres ostatniej komórki SRAM dla danego procesora
ldi i , 0B00110110 ; ustawianie portu c
out ddrc , i
ldi i , 0B00110101
out portc , i
ldi i , 0b10000000 ;ustawianie portu d
out ddrd , i
ldi i , 0b11101100
out portd , i
ldi i , 0B11111111 ;ustwaianie portu b
out ddrb , i
ldi i , 0b00000111
out portb , i
ldi i , 0b00000100 ;ustwiamy przerwanie INT1 na zmianę stanu
sts eicra, i
ldi i , 0b00000010 ;i odblokowujemy przerwania
out eimsk , i
; ustawiamy sprzetowy I2C
ldi i , 2 ; wpisujemy do rejestru TWBR wartość 2 , co powoduje ustawienie częstotliwości lini SCl na 400 kHz
sts twbr , i ; czyli takiej z jaką pracuje kontroler I2C w procesorze . Pamięć 24c02 od atmela może być taktowana do 1Mhz . Dokładny opis oraz wzór na str.216 noty katalogowej
ldi i , 1
sts timsk0 , i
; odblokowujemy przerwanie dla timer0 . Będziemy nim obliczać długie odstępy czasowe
; Timer0 to timer 8-bitowy czyli zlicza od 0 do 255 . My będziemy go używać wraz z prescalerem ( dzielnik częstotliwości)
; o wartości 1024 . Możemy obliczyć ilość przepełnień w ciągu 1 sec dzieląć częstotliwość taktowania procesora przez prescaler oraz maksymalną liczbę zliczeń
; 80000000 Hz \ 1024 \ 256 = 30,51 przepełnień timera w ciągu sec czyli jedno przepełnienie będzie trwało 1 \ 30,51 sec ~ 0,03 sec
clr i ;rejestr GPIOR0 używamy jako rejestru z flagami , jest to wolny rejestr z adresowaniem bitowym
out GPIOR0 , i ; Bit rejestru - wykorzystanie
; 0 - timer1 odliczył wskazany czas (1) , jeszcze nie odliczono (0)
; 1 - karta jest poprawna (1) , karta niepoprawna (0)
; 2 - wykryto wsadzenie karty, nalezy ja odczytać (1) , nie wykryto / odczytano kartę (0)
; 3 - dopisz kartę do pamięci (1) , NIE DOPISUJ (0)
; 4 - wyświetl kropkę na wyświetlaczu (1) , nie wyświetlaj (0)
; 5 - stan przycisku Set
; 6 - flaga odczytania zapisanych kart do SRAM , należy przepisać dane z ERAM do SRAM (0) , dane już odczytane (1)
; 7 - wybór pamięci EEPROM , pamięć wewnętrzna (0) , pamięć zewnętrzna 24c02 (1)
ldi i , 0b01011111 ; wyłączamy wszytkie nieuzywane moduły ( SPI , UART , ADC . nieużywane timery ) aby nie pobierały one prądu .
sts prr , i
;#########################################################################################################################
cbi gpior0 , 7 ;wybór pamięci EEPROM , pamięć wewnętrzna (0) , pamięć zewnętrzna 24c02 (1) ##
;#########################################################################################################################
sei ; załączamy globalne zezwolenie przerwań
;**************************************************** program własciwy **************************************************
s1:
ldi slep , 90 ; oczekujemy około 3 sec --> slep(90) * 0,0333 sec ( max czas jaki możemy odczekać to około 8,5 sec (slep = 255))
rcall odliczaj ; pzeskakujemy do funkcji odczekiwania czasu
sbic portb , 3 ; zmiana stanu wyjscia diody
rjmp u1
sbis portb , 3
sbi portb , 3
rjmp s1
u1: cbi portb , 3
rjmp s1
i używane podfunkcje :
;************************************* funkcja odliczaj - załączanie timer0 i czekanie na zakończenie odliczania ***********************
odliczaj:
cbi gpior0 , 0 ; zerujemy flagę odliczania
ldi i , 5
out tccr0b , i ; wpisujemy do tccr0b 5 co znaczy załączenie timera0 i ustawienie prescalera na 1024
nop
nop
od1:
nop
nop
nop
nop
sbis gpior0 ,0 ; sprawdzamy czy timer odliczył czas
rjmp od1 ; jesli nie to wracamy do od1
cbi gpior0 , 0 ; zerujemy flagę odliczenia
ret ; powracamy z funkcji
;**************************** Przerwanie Czas - zlicza czas do wartości ustalonej przez wzór t = (1\3) * slep [sec] gdzie t = czas po jakim funkcja ustawi flagę ***************************
czas:
dec slep
cp slep , zro
breq czas2
reti
czas2:
clr i
out tccr0b , i
sbi gpior0 , 0
retiFajnie było by gdyby ktoś mógł wskazać na co należy zwrócić uwagę .
Ustawienia fusów prezentują się tak :
LOW : 0xD2
HIGh : 0xD7
EXT : 0x01
Komentarze zawierają sporo błędów językowych ale przepuszczę je przez Worda gdy program będzie działał jak należy .
Kolejną intrygującą rzeczą jest to że po zapisaniu programu razem z pamięcią EEPROM program się zawiesza ( nie startuje ) , chociaż w żaden sposób nie odnosiłem się do tej pamięci , i nie były załączone żadne przerwania .
Wszystko zaczynało jednak działać gdy najpierw wgrałem EEprom , zresetowałem układ , a następnie wgrałem program . Wtedy wszystko ruszało tak jak powinno . Oczywiście przy ustawionym fusie EESAVE . Sprawdziłem jednak czy dane z eeprom się nie skasowały, i tak jak być powinno wszystkie były na swoim miejscu.
I to chyba tyle .
Byłbym wdzięczny gdyby ktoś potrafił wytłumaczyć mi te 2 zagadki .
Priorytetem jest pierwsza , druga można traktować w kategorii ciekawostki jako że nie przeszkadza ona przy pisaniu programu , jeśli czynności wykona się prawidłowo .
Ps. Gdy skończę kod w asm to podzielę się na elektrodzie całym kodem zarówno w bascomie jak i assamblerze z dokładnymi komentarzami , wykresami funkcji , schematami płytkami itd..
Pozdrawiam .
