WprowadzenieATmega.pdf

(216 KB) Pobierz
Microsoft Word - Wprowadzenie2w.doc
SławomirCięszczyk
Wprowadzenie do programowania mikrokontrolera ATMEGA32 w asemblerze
PodstawoweinformacjeomikrokontrolerzeATMEGA32:
32KBpamięciprogramutypuFLASH(ilośćcykliprogramowania10000)
1024BpamięciEEPROM(ilośćcykliprogramowania100000)
2KBwewnętrznejpamięciSRAM
dwa8bitoweTimerzpreskaleramiijednostkamiporównującymi
jeden16bitowyTimer
8kanałów10bitowegoprzetwornikaADC
ModułUSARTtransmisjiszeregowej
ModułTWI–transmisjatypuI 2 C
Komparatoranalogowy
4porty(32wpełniprogramowalneliniewejścia/wyjścia)
Mikrokontrolery AVR posiadają architekturę harwardzką. Została w nich rozdzielona
przestrzeń pamięci programu i pamięci danych. W przestrzeń pamięci danych pierwsze 32
bajtyzajmująrejestryrobocze,wszystkieonemogąbyćwykorzystywanetakjakakumulator
wprocesorachtypu8051.
Przestrzeńpamięcidanych
adresy
0x00 R0
0x01 R1
0x02 R2
4 4
0x1F R31
0x20 I/O
0x21 I/O
4 4
0x5F I/O
0x60 SRAM
0x61 SRAM
4 4
0x85F SRAM
I/O–przestrzeńwejściawyjścia(64adresy)
SRAM–pamięć(2048bajtów)
1. Porty
W mikrokontrolerach AVR porty oznaczamy odpowiednio PORTA, PORTB, PORTC,
PORTD.Poszczególnelinieportów:
PORTA0–liniazerowaPORTA,
PORTB7–liniasiódmaPORTB.
DoobsługikaŜdegoportu dedykowane są trzy rejestry PORTX, PINX, DDRX, gdzie X
oznaczanazwęportuA,B,CiD.Rejestryteznajdująsięwpodstawowejprzestrzeniwejścia
wyjścia.
JeŜeli port ma pracować jako wyjściowy to naleŜy ustawić odpowiednio rejestr DDRX.
Np. aby ustawić cały port A jako wyjściowy naleŜy wpisać do rejestru DDRA wartość
70378884.003.png 70378884.004.png 70378884.005.png
SławomirCięszczyk
0FF=0b11111111. Następnie stan poszczególnych linii wyjściowych ustalamy wpisując
odpowiedniewartościdorejestruPORTA.
Zmiana stanu rejestrów dotyczących portów moŜe być dokonana poprzez operacje na
całymporcielubnaposzczególnychbitach.Operacjebitowe:
sbi–ustawbitwrejestrzefunkcyjnym,
cbi–wyzerujbitwrejestrzefunkcyjnym,
sbiDDRA,DDA1–ustawiamtrybwyjściowyliniipierwszejportuA,
sbiPORTA,PORTA1–ustawiamliniepierwsząportuAnajedynkę,
cbiPORTA,PORTA1–zerujliniepierwsząportuA,
sbiDDRA,2–ustawliniedrugąportuAjakowyjściową,
cbiPORTA,2–zerujliniedrugąportuA(wcześniejustawionąjakowyjściową).
Operacje na całym porcie (bajcie). Najczęstszym sposobem modyfikacji rejestrów
funkcyjnych (podstawowa przestrzeń wejwyj) jest wykorzystanie rozkazu out, który
powoduje załadowanie do wybranego rejestru funkcyjnego zawartości określonego rejestru
roboczego.
outPORTA,R16
outDDRA,R16
Aby więc wpisać tym sposobem interesująca nas daną do rejestru funkcyjnego najpierw
musimy umieścić ja w rejestrze roboczym. Ładowanie rejestru roboczego stałą w sposób
bezpośredniwykonujemynastępująco:
ldiR16,0xFF–załadująwartością255rejestrR16.
Przy czym taką operację wykonać moŜemy jedynie na rejestrach górnych (zakres R16
R31). Ostatecznie aby ustawić wszystkie linie portu B jako wyjściowe potrzebna jest
następującasekwencja:
ldiR16,0xFF
outPORTB,R16
Program który zapala diodę podłączoną do linii 7 portu A, wykorzystujący bitowe
operacjelogicznewyglądałbędzienastępująco:
.INCLUDE”m32def.inc”
;pliknagłówkowydlaAtmega32
sbi
DDRA,7
sbi
PORTA,7
LOOP:
rjmp LOOP
Zwykorzystaniemoperacjibajtowych:
.INCLUDE”m32def.inc”
;pliknagłówkowydlaAtmega32
out
DDRA,R16
ldi
R16,0b10000000
out
PORTA,R16
LOOP:
rjmp LOOP
Abyzmienićstanjednejliniisensowniejszywydajesięsposóbbitowy.
W celu wykorzystania współpracy portów z klawiaturą i odczyt stanu klawisza
musimy przestawić linie portu odpowiedzialne za jego stan w tryb wejściowy. Nasza
klawiatura zbudowana jest w taki sposób, iŜ wciśnięcie klawisza powoduje zwarcie linii do
masy poprzez odpowiedni rezystor. JeŜeli klawisz nie jest naciśnięty to linia wejściowa mu
odpowiadająca nie jest podłączona do Ŝadnego potencjału. Teoretycznie w układach typu
TTLoznaczatodlaliniiwejściowejstan wysoki.MogątutajpojawićsięróŜnezakłóceniai
niepewne działanie. Dlatego teŜ linie wejściową połączoną do tego typu klawisza naleŜy
ldi
R16,0xFF
SławomirCięszczyk
podciągnąć rezystorem do napięcia zasilania. Mikrokontrolery AVR posiadają wewnętrzne
rezystory podciągające. Najpierw naleŜy przestawić daną linie na tryb wejściowy, np. cały
portB.
ldi
R16,0x00
;clr R16
out DDRB,R16
Po resecie mikrokontrolera linie portów są ustawione jako wejściowe, nie ma więc
konieczności ich modyfikacji. Samo podłączenie rezystorów podciągających następuje
poprzezzapisjedynkinawymaganelinieportuwrejestrzePORTX:
ldi
R16,0xFF
;ser R16
out PORTB,R16
Odczyt danej linii następuje poprzez odczytanie rejestru PINX. Stan portu odczytać
moŜnawykorzystującrozkazin:
in R16,PINA
JeŜeli działanie programu ma być uzaleŜnione od stanu jednej linii to uŜyć naleŜy
rozkazów testujących pewien warunek i jeśli jest on spełniony to następuje pominięcie
jednegorozkazu.Instrukcjamitakimidziałającymiwobszarzerejestrówfunkcyjnychsąsbic
orazsbis.
sbic–pomićinstrukcjęjeŜeliodpowiednibitjestwyzerowany,
sbis–pomińinstrukcjęjeŜeliodpowiednibitjestustawiony.
FragmentprogramuuzaleŜnionegoodwarunku:
sbic PINB,PINB2
rjmp Bit_ustawiony
Bit_wyzerowany:
...
Bit_ustawiony:
...
lubteŜodpowiednio:
sbis PINB,PINB2
rjmp Bit_wyzerowany
Bit_ustawiony:
...
Bit_wyzerowany:
ProgramzapalającyigaszącydiodęwzaleŜnościodstanuklawisza:
.INCLUDE ”m32def.inc”
ldi
R16,0xFF
out
DDRA,R16 ;trybwyjściowyportuA
out
PORTB,R16 ;podciąganiemłodszejczęściportuB
LOOP:
sbi
PORTA,PORTA1 ;ustawlinie
KLAWISZ1:
sbic PINB,PINB0
rjmp KLAWISZ1
cbi
KLAWISZ2:
sbic PINB,PINB1
ldi
R16,0x0F
SławomirCięszczyk
rjmp KLAWISZ2
rjmp LOOP
Kolejny program wykorzysta klawisze do przedstawienia zawartości tablicy na linijce diod
podłączonej do portu A. Niezbędna do tego jest deklaracja tablicy oraz odczyt pamięci
danych.Tablicędeklarujemynastępująco:
TABLICA:
.DB 1,3,10,14,20
Aby odczytać pamięć programu uŜyć musimy adresowania pośredniego z uŜyciem rejestru
indeksowegoZorazinstrukcjilpm.OdczytjestmoŜliwydowszystkichrejestrówroboczych
R0R31.PamiętaćnaleŜy,iŜmikrokontrolerjest8bitowyapamięćprogramuzawierasłowa
16 bitowe. Aby moŜliwe było odczytanie obydwu 8 bitowych części zarezerwowano
najmłodszy bit rejestru indeksowego Z do takich celów. Bit wyzerowany oznacza odczyt
młodszej części słowa a bit ustawiony starszej części. Wpływa to równieŜ na ograniczenie
adresów w pamięci moŜliwych do odczytania do 64kB (32ksłów). Sekwencja odczytu
pierwszejkomórkipamięci(młodszejczęścisłowa)TABLICYwyglądanastępująco:
ldi ZH,high(TABLICA<<1)
ldi ZL,low(TABLICA<<1) ;ustawiamadresrejestruindeksowego
lpm R16,Z+ ;młodszaczęśćpierwszegosłowatablicy
lpm R17,Z ;starszaczęśćsłowapierwszegotablicy
PoniewaŜ uŜycie dyrektywy DB powoduje umieszczenie 2 bajtów w jednym słowie w
kolejnościodnajmłodszegodonajstarszego.
Rejestr 16 bitowy Z składa się z dwu 8 bitowych rejestrów ZH=R31 i ZL=R30. Istnieją
jeszczedwarejestryindeksowe:
X,XH=R27iXL=R26
Y,YH=R28iTL=R29
Innym 16 bitowym rejestrem jest wskaźnik stosu SP składający się z dwu rejestrów SPH i
SPL.
AdresyprzerwańodposzczególnychźródełwAtmega32:
Addres Nazwa Opis
$000jmp RESET ;Reset Incicjalizacja
$002jmp EXT_INT0 ;IRQ0 Zewnętrzne
$004jmp EXT_INT1 ;IRQ1 Zewnętrzne
$006jmp EXT_INT2 ;IRQ2 Zewnętrzne
$008jmp TIM2_COMP ;Timer2 Porównanie
$00Ajmp TIM2_OVF ;Timer2 Przepełnienie
$00Cjmp TIM1_CAPT ;Timer1 Przechwycenie
$00Ejmp TIM1_COMPA ;Timer1 PorównanieA
$010jmp TIM1_COMPB ;Timer1 PorównanieB
$012jmp TIM1_OVF ;Timer1 Przepełnienie
$014jmp TIM0_COMP ;Timer0 Porównanie
$016jmp TIM0_OVF ;Timer0 Przepełnienie
$018jmp SPI_STC ;SPI Koniectransmisji
$01Ajmp USART_RXC ;USART Odebranybajt
$01Cjmp USART_UDRE ;UDR Koniectransmisjiwychodzącej
$01Ejmp USART_TXC ;USART Pustybufornadawczy
$020jmp ADC ;ADC Zakończonakonwersja
$022jmp EE_RDY ;EEPROM Gotowy
$024jmp ANA_COMP ;Analog ComparatorZmianastanuwyjscia
$026jmp TWI
;TWI Aktywnośćmodułu
$028jmp SPM_RDY
;FLASH
Konieczapisupamięci
Jak widać na obsługę przerwania zarezerwowano jedynie miejsce niezbędne do
wykonania skoku do innego miejsca w programie gdzie znajdzie się właściwa procedura
obsługi.
Przerwania są aktywne pod warunkiem włączonego ogólnego zezwolenia na przerwania
(flagaIwrejestrzestatusowymSREG)
SławomirCięszczyk
ListainstrukcjiATMega32
INSTRUKCJEARYTMETYCZNEILOGICZNE
ADDRd,Rr DodajdwarejestryRd←_Rd+Rr
ADCRd,Rr DodajdwarejestryzCARRYRd←_Rd+Rr+C
ADIWRdl,K DodajstałądosłowaRdh:Rdl←_Rdh:Rdl+K
SUBRd,Rr OdejmijrejestrodrejestruRd←_RdRr
SUBIRd,K OdejmijstałąodrejestruRd←_Rd–K
SBCRd,Rr OdejmijrejestrodrejestruzCARRYRd←_RdRrC
SBCIRd,K OdejmijstałąodrejestruzCARRYRd←_RdKC
SBIWRdl,K OdejmijstałąodsłowaRdh:Rdl←_Rdh:RdlK
ANDRd,Rr LogicznyAND,dwarejestryRd←_Rd__Rr
ANDIRd,K LogicznyAND,rejestristałaRd←_Rd__K
ORRd,Rr LogicznyOR,dwarejestryRd←_RdvRr
ORIRd,K LogicznyOR,rejestristałaRd←_RdvK
EORRd,Rr ExclusiveOR,dwarejestryRd←_Rd__Rr
COMRd Dopełnieniedo$FFRd←_$FF__Rd
NEGRd Dopełnieniedo$00Rd←_$00__Rd
SBRRd,K Ustawbit(y)wrejestrzeRd←_RdvK
CBRRd,K Wyczyśćbit(y)wrejestrzeRd←_Rd__($FFK)
INCRd IncrementujRd←_Rd+1
DECRd DekrementujRd←_Rd__1
TSTRd TestczyzerolubminusRd←_Rd__Rd
CLRRd WyczyśćrejestrRd←_Rd__Rd
SERRd UstawrejestrRd←_$FF
MULRd,Rr MnoŜenieunsignedR1:R0←RdxRr
MULSRd,Rr MnoŜeniesignedR1:R0←RdxRr
MULSURd,Rr MnoŜeniesignedandunsignedR1:R0←RdxRr
FMULRd,Rr MnoŜeniefractionalunsignedR1:R0←(RdxRr)<<1
FMULSRd,Rr MnoŜeniefractionalsignedR1:R0←(RdxRr)<<1
FMULSURd,Rr
MnoŜeniefractionalsignedandunsignedR1:R0←(RdxRr)<<1
INSTRUKCJEORGANIZUJĄCEROZGAŁĘZIENIA
RJMPk SkokwzględnyPC←_PC+k+1
IJMP Skokpośrednido(Z)PC←_Z
JMPk SkokbezpośredniPC←k
RCALLk SkokwzględnyześlademPC←_PC+k+1
ICALL SkokpośredniześlademPC←_Z
CALLk SkokbezpośredniPC←k
RET PowrótzproceduryPC←_STACK
RETI PowrótzobsługiprzerwaniaPC←_STACK
CPSERd,Rr Porównaj,pomińjeślirówneif(Rd=Rr)
CPRd,Rr PorównajRd__RrZ,N,V,C,H1
CPCRd,Rr PorównajzCARRYRd__Rr__C
CPIRd,K PorównajrejestrzestałąRd__K
SBRCRr,b Pomińjeślibitwrejestrzerówny0if(Rr(b)=0)PC←_PC+2or3
SBRSRr,b
Pomińjeślibitwrejestrzerówny1if(Rr(b)=1)PC←_PC+2or3
70378884.006.png 70378884.001.png 70378884.002.png
Zgłoś jeśli naruszono regulamin