Mittermayr Roman
AVR.RISC selbstentwickeln Software Embedded AufCD-ROM: . AVRStudio4.13undwinAVR
Roman Mittermayr
AV...
312 downloads
1887 Views
34MB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
Mittermayr Roman
AVR.RISC selbstentwickeln Software Embedded AufCD-ROM: . AVRStudio4.13undwinAVR
Roman Mittermayr
AVR.RISC Embedded Software selbstentwickeln zuneßtenMal Ganzgtelch,obSledasHbn Mikoconkoller s{hreiben oder Hiren,s€itelnlgrnhhrur Sofr$rare" "Enbedded lnbrmatikünteilchten:Dle6es BuchhllfrlhnenbelmE{enell dnel{ln€ umlteEenmd\tut'refun lhrc6wk6€nsSlebekommen die EinRihrung ir dieSFächeAss€mbler ündl€nenaußedem Filrden vrichtigs€n GrundlagEn derC-Pogrammlerung kennen. Prdkflkerwidpdgnanterldä4woraufe5belderSofrwatewirklichankonmt enü/vlcldung aufAvR-Poue6soren lhnen Die8-Bit-l,likroconrlolleFserie vonATlVlELerlaubt eine rasche VeNirklhhung wßthiedenster ldeen und unglaublich Die R|Sc'Architeldur, der einheitliche Aulbau der Pojekte. schnelle Prozessoftmilie undnichtzuletztdieattaktiven kompletten machen diesen Contmller zur Prcisantebote furHobbyentwhkler richtisenWahl. DerAutorhatsichdaEufkonzenfiietda5BuchveFtändlkh prakrisch ka zuSesialten. Dieses WerkwnddenA'beibtisch g verhssen. EinNachschlägewerk fürlhrehoj€kt€rHäufi
Tabellen, Routinen werden klarund undbeknnt€"Fallen" e [irt. unleßri:Et denbse'rnd Eine umbngreiche onlireplattform beantwodei Frdg€n,die überdenUmfantdes8u(hsh zah|?iche Pra-xisbeispjele undSchaltulten stehen darUber freizumDownload zurvefügun8.
r s B N9 7 8 I 7 7 2 3 4 1 0 7 6
||tililil tililil illtill tl
9t743772t341076t Eüo39,5 lDl
Be$rchon Sioun6im Inlongt wwwjranzls.d
Roman Mittermayr
AVR.RISC entwicketn Embedded Software selbst Mit 88 Abbildungen
BibliosrafischeInfor.|'äüod der Deutdren Bihlioüek DieDeulscheBibliolhekE@ichnet dise Publikation in ds DeutsdenNationalbibli@rafie: deraileneDaren sindm hternetübprhttr./dnbddb.de äbnilbär.
*ft,
xonto ltuBiahms
rcp'od@a(
Adddqrö8Esqql.hmö€frlb''dffiq6r€lhUidufuiEßhafunqw*. toEdem tid f€hrer drhr qe aq6d'!€€6 Ds \daq und der ado, *hei s d dr+ärb evfdereiEc6 ie dh db jük&h
nel|end6bdRdaktdlsdl|G€trüq Emb.geJdgleÖdgaml)dn|odä' fmmnqds|-i!Enh.bas'6q|id''
O 2004FränzirVerlägGnbH, 35535Poing Ale Rechte vorbeh.lren, äuchdie de. fotom{h.nischen wiedersabe undderspeicheruns in e ekt.onischen Mediei. DasEßlellenuid vedreitenwn Kopienaul Papie':auf Daten$&emoderim r^remet insbeenderea s PDI st nü mit ausdlüdlider Genehmigunq d6 Ve aq696taner undwid widigenfals malrechnichverfolqr D e meislei Pmduhbez€ichnunq€n rcn Had- und Softwär€seie Fnmnnamenund Fkmenoqoi, die n d esem Welk qenännlweden, iind in d€r R€q€lqlei.hailiq au.h €inq€taq€neWarcnei.h€nund soll€n ah solchebelra.hlel weden. DerV€ aqiolqt bejd€nPrcduhbeuidnunq€nimWen ichenden Schrcibwpn der H€ßteler sats: folosatzPfeifela2166GräIemng art & d6i9n: w.idehfthzde Dtuclc Bercke(47623Kdelaer
tsBN978-3-77234107-6
)
Vorwort crnz gleich,ob Siednswort Mikroantrolbr hette zum erstenMal höien oder seit Iiinf Iahren ,,EmbeddedSoftware"schreiben:DiesesBuch hilft Ihnen b€im Erler nen, Umsteigenund Vertiefen Ihres wissens zu diesemThema. Es wird prägnant erklärt, worauf es bei der Softlyareentwickiungmit AvR-Prozessorenwirklich Die 8 Bit Mikrocontroiler-Serie von ATMEL erlaubt Ihnen eine rascheVerwirkli chung verschiedensterldeen und Projekte. Die schnelle RISC Architektur, der einheitliche Aufbau der kompletten Prozessorfamilieund nicht zuletzt die attrak tiven Preisängebotefür Hobbyentwickler lassen diesen Controller die dchtige Wahl sein. lch hoffe, dassIhnen diesesBüch rücht nur wissen verschafft,sondernauch Freude bereitet.Um Sofha'arezu entwickeln,braucht man einen klaren Kopf Gönnen sie sich eire Pause,wenn Sie einmal nicht vorankommensollten. Ich wünschelhn€n eineVielzahl an erfolgreichenund spännendenProjektenund steheIhnen tur Fra gen zu diesemBuch gerneüber meine Webseitehttp://M.avrbu.h.de zü Vertu-
cuns Buchwetfenuntel: SietollteneinenBlickaufdieWebseitezum http://ww.avrbu> ( L ] 8 RF RO RE L ) ;
Als NächsteslegenSiedie Ube ragügseinstellungenfest.Das notwendigeRegister biertur heißt UCSRC.Mit diesemRegisterlegenSiez. B. fest,ob essichum enre s).nchrone oder eineaslnchroneUbertragunghandelnsoll.Dazuein Auszugaus dernDatenblattdesÄTmesaS:
A b b . 2 . 1 1U : CSRC-Register
Wichtig: Das Bit URSTI muss immer auf I gesetztsein.Ansonstenwird ein ganz programmiertorehr Detailsdazuim Datenblatt). anderes Register Die folgendenEinstellusen könncn daher (unter anderem)mit dem UCSRCRegisterkoDfiguriert werden: . . . .
USARTModl1s(asynchron,synchron) Parity (Disabled,Enabled/EvenPndty,Enabled/OddParity) StopBit (l-Bit,2-Bit) CharrcterSize(ZeicheDgröße 5 bit, 6 bit, 7 bit, 8 bit, 9 bit)
werten: Hier einekurze übersicht mit den eDtsprechenden USART-Modus: . Asynchron:UMS[I-=0 . Slarchron: UMSEL=1
2.5 DieserielleSchnittstee (USART/R5232')67 Paritla . Disabled/ No Parity:UPMI=0, UPM0=0 . Enabled/ EvenPärity:UPMl=r, UpM0=0 . Enabled/ Odd Paity: UPM1=1,UPM0=1 Stop Bit: . r Bir USBS=() .2-Bit:USBS=I Charact€rSize: . 5-bir UCSZ2=0,UCSZl=0,UCSZo=0
. 6 bir ucsz2=0, ucszr=0, ucSZO=1 . 7-bit:UCSZ2=0,UCSZl=1,UCSZ0=0 . 8 bir UCSZ2=0,UCSZl=l, UCSZ0=l . 9-bit UCSZ2=l,UCSZr=r,UCSZo=l In den meistenAnwendungenfinden SiefolgendeKonfiguration: . . . .
As).nchroneLßcrtragunC CharacterSizevon 8 Dit 1 StopBit No pariry
OhDenoch näher ins Detail gehenzu wollen, hier die direkten Anweisungenin C ftu drei häuig veMendeteEinstellungen: 1r 2: 3: 5l 6l 8:
Hiermit sind die Llbeüagungsparameterfestgelegt.Als NächstesmüssenSie sich entscheiden,ob die S€hnittstellenur senden,nur empfangen- oder beideskönnen sol].In den meistenF?illenv.ird eineKommunikation in beideRichtungenverlangt. Dasverintlvo liche Registerhiertur heißt UCSR3.Äbb. 2.12zeigt eineDarstelung ausdemDatenblatt.
68
2 Detlvlikrocontroller
ffi".""R.""m,8ffi Abb.2.12:UCSRB'Register Iklevant sind die Bits AXEN und ?XÄN, also Receiler Eflable lnd Trafls't1ifter ein Erdbld.EiDei in diesenBitsschältetdiejeweiliseKommunikationsrichtung in Cl Hier ein cinfaches Codebeispiel 't, / / E m p f ä n süenr dS e n d ee -rvi rt s\ lcr h i alt€u | PB- . P-\'
Unrer UmstäDdenwollen Siebeim EmpfangeinesBytesper Interupt b€nachrich' tigt werden.Daskönren Sicebenfallsin diesemRegisterfesdegcnDazuveMenden Siedie Bits RXCI' und T,{c'Il , alsoRuetueConpleteInterrupt EnablenI,.l nansflit Eine i in diesenBitsschaltetdie Interrupt-BenachrichtiInterntptEnable. CotnpLete gung ein. Hiermit habenSiealle relcvantenDinstellungcnfiir eineerfolgreicheVer erledigt. wenduDgderserielenSchnittstelle
. UBRRH/UBRRL züständig(16 Bit). ist filr die Baudrate . UCSRBdient zunl Einschaltenvon Scnderund/oder Empfüngerund der lnter . I Lsßc leg dr'ÜberrrdsLrrg\pd'Jmcrer le.r. Abschtießendnoch ein Beispielfür cire q?ische Initialisierung' wie man sie in den meisteDProgrammenveMendenkann: t. : 3:
loörin. a. ,o.r -,. qo.:.e rlPt B6DDAIL 10200 # d e f i f e U A R TS E T T I N G { ( T A K T / l 6 L / U A RBTA U D R A T IrI )
void setup_uart() 5: 6: { -F ö Bauodöö /t ( UART = ( c h a f ) S E T T I N>G> 8 ) ; 8: L-rBRRu U B R R=L ( c l r a r ) ( U A R T - S E T T I N G ) i 9: 10: a L,o;no" il: = B( r < < R X E N ) ( I < < T X E N ) i \2: l.lCSR 1l: 14: / / a s y n c h r o i ,8 N 1 15: U C S R=C ( 1 < < U R S E L () 3 < < U C S Z 0 ) ; 16: ]
(usART/Rs232)69 2.5 Dieseielleschnittstelle vonDaten 2.5.2 SendenundEmpfangen TrnnsDasSendenvon Datengestaltet sichsehreinfach.Esgibt eiDensogenannten m;t Buffer,in deDSieIhre Dntenschreibcn. Der Controllerholt dasZeichendort ab,versendet esund leert damit den Puffer.Sobaldder Putrs leerist, könnenSic ein neuesZeichenversendeD. SiebenötigendazufolgendcRcgister: . UCSR{ - enthält den StatusdesTransmit ßuffers . UDR USARTDatenregisterbzw Transmit-Buffer
Abb.2.13:Daßtellung desUCSRA-Registeß. DatäRegistcr Enply)-Bit überpd VordemSendenmüssenSiedar UDRE(USART fen.wenn derwert vonUDREI ist,kannder TransmitButrer(dasUDR-Register) diesesBir über wiederDatenaufrrehmen. Siemüssen.lsolorjedem Sendevorgnng prüfenund wnrten,biscsdenZustandI annimmt. Zeichenin dasUDR'Register. Der ConAnscbließend schreiben Siedassewünschte trollerversendet esund setztdnmchUDREwiederauf l. Hier eineC-FunktionzumVersenden e'nes7-€ichens: 1: 2: 3. 4: 5: i; 8:
v o i d u d r t p u t c h a r ( u r s j g ncehda rc ) I / / l l a r t e rb i s B u f f e rb e r e i t l h i l e ( l b i t i s s e t ( I C S R IAD, R E ) ) ; / / S e n d e.n. . = c; UDR
Ähnlich tunltioniert dcr EmpfangeinesZeichens.Sieprüfen, ob im Empfangspuf DäzubenötigenSie fer schonein Z€ichensteht.wenn ja, könnenSiees auslesen. wiederdasRegister UCSRA.Indiesem!i]l prüfenSiejedochdnsBit R{C (USÄRT ReceiveComplete).Hat dicscsBit den Wert l, befinden sich Daten im Empfangs puffer.DiesekönnenSieebensowiebeiln SendeD mit dernRegister UDRäuslesen. Es sibt diher auch zwci Möglichkeiten für den Empfang:Blo*irg Mode und No, so lnngc,blsein Zeirlociirg Mode.EntwederSiewater in der EmpfangsÄlnktioD (Blocking), chenenpfängenwuide oder Sieschauennur kurz in den Puffer, "ob dennschonein Zeichenda ist" (Non Blocking).Hier beideAnwcndungen:
2 DerMikrocontroller
70
BlockingMode: c h a r u a f t g e t c h a rv( o id ) ' . o r " n , o b s c h o ne i n B y t e j n E m p f a n q s b t i f r e r , , ,' ö - - " _ " e t / u c 5 P r .D \ !h ..b
Non Blocking-Mode: 1r 2: 3l
d )i int uart,getchar(vo 1. / / P r ü f e r , o b s c h o re i . B y t e i m E n p f a n g s b u f f e r r e t u r n 1 ; / / - 1 = K e i f l e i c h € nv o r l r a h d e n
5: 6: 8:
l
2.6 Timer/Counter Ein Timer bz-w ein Counter ist eine Einheit, die mit einer bestimmten Frequenz eine Zahl erhöhr. Ein 8-Bit Tnner/Counter z:ihlt daher den We ebereich0 bis 2s5 durch und erzeugtdann einen Überlauf besinnt also wieder von voln mit der Zahl0. In den meistenF:illenkonfiguriert man den Timer so, dassbei einem Uterlauf ein Interrrpt ausgelöstwird. Ie nach Zlihlfre,tuenz können Sie so eine peiodische Funktion ausiilren. Dies eignetsich z. B. zü GenerierungeinesTalts, einer Lrhr etc. zeit,einesSynchronimpulses Die Zäh[requenz (Clo.l) kann entlreder intern oder extem erz€ugtwerden.wird die Clock el1en erzeugt,spricht maD voD einem Corrtel, weil damit die Anzahl steigenderbzw faltenderllanken ,,gezzihlt"werdenkann. AußerdemhabenSie die Mögliclkeit, die inteme Clo& durch einensogenanntenPrescalerherunterzuteilen. Sokann auseinerVielzrlrl von FrequenzengewäNtwerden. Modus (CompareMode) kann man den Timer bis zu einem In einemspeziellen bestimmtenWe hochzählenlassen,un dann einen Interrupt äuszulöseDSomit müssnicht nnmer €in Überlauf (bei 256) statt6nden,um ein Sisnalzu erzeugen Wichtig: Die verschiedenenA\rR Contro er besitzenhier unterschiedlicheKonfigurationen.Ein Blick in dnsDatenblati ist daherunvelmeidlich ,{le folgendenBei-
,r
.
'
.,:..,. ,:;::2i:6,;4tf6iltöi.idt: , 77
spiele und Erkläungen beziehensich auf den ATmegaS.Er besitzt zlyei 8- und einer 16-Bit Timer/Counter. Hier eine kulze Lbersi€ht der einzelnenTimer/Counbr: 8-Bit-Timer/Counte . . . . . .
10-BitPrescaler Frequenzgenerator PWM Modus Unt€rstütztdasZählenvon Taktflanten CTC Modus (ClearTimer on CompareMatch) EinfacherTimer, tur simpleAufgabengedacht
16-Bit-Timer/Counterl . . . . .
BesitztdieselbenEigenschaften wie Timer/Counter0 (0 Z.üNtim l6-Bir Bereich bis65.s3s) VerfiiCtüber ein zusätzliches, (CornparcRegiste4 unabhängiges Vergleichsregister BeherrschtPwM mit r"riabler Periode Input CaptureUnit (Zählenetelner Ereignisse)
8-Bit-Timer/Counter2 . BesitztdieselbenEig€nschäften wie Timer/Countero,außerdasZählenvon Takt tunken . Erlaubt ,,as).n€hronenModus", also die Verwendungeines 32-kHz Uhrenquarz als Taktquelle(ist damit unabhängigvom Systemtaktund kann so äuch längere Zeitabst?inde messen) Zur ReferenzeineTabelle:
Abb.2.14:Ubersicht derTimer
2 DetMikrocontrollel
72
0 2.6.1 8-Bit-Timer/Counter vor: Um diesenTimer/Counter zu verwenden,gehenSiefolgendermaJien (Clock) I . Einsteilen derZäNfrequenz Interrupts 2. Konfigurierendes des,,Startwertes" 3. Einstellen 4. AIe Interrupts,,erlaüben" 5. StartendesTime DerVorgangSchitt für Schritt: Die Clock wird mit dem Register?CCROeingestelt:
Abb.2.15:TCCRO Register DieseTabelleäusdem Datenblatterklärt die vorhändenenMöglichkeitenl cs02 csol 000 001 010 011 100 101 '1 11
KeinClock Timergestoppi.
clk = Pro2essortakt/ 64 clk = P.ozessorlakl / 256
10
clk = Proze$orraK/ 1024 anT0 pin{FalrinS EdSe) clk - Exl cl@ksisnal clk= Exl cl@ksiqialanT0 pinlRisinsEdse)
desTirners Abb.2.16:Taktquelle Siealsodie Quelleder Clock(intern/ Anhandder BitsCS02,CS0l und CS00legen Teiler fest.tseieinem 16 MHz-Quaü und einen Tei extern) und deDgewüDschten ler von 8 würde dcl Tim€r/Counter mit einer Frequenzvon 2 MHz zählen. TabelleGieheoben).Fürden wichtig: Fürden 16-BitTimer/Counterlgilt dieselbe (siehe jedoch gibt Konfigurationstabelle es eine eigene 8-Bit Timer/Counter2 Datenblau).
Als Nächsteswird ein Interrupt konfrguiert. wenn der Timer überläuft (also 256mat getickt hä0, stoppt der Prozessordie Austuhrung des akudlen PrograDms und springl an einebestimmteAdresse.IederArt von Interupt (Timer, RS232,etc.) ist eine bestimmte Speicheradrcsse zugeordnet.Diese nennt man auch ,,Internpt Für dasAktivieren desTimer 0 - Ovetflo14Interrupts veNenden Sie das Register flMSK (Timer/Counter Intenupt Mask Register).Dassieht so aus:
Abb.2.17:TIMSK-Register
Hier interessiertvorerst nur der Zustand des Bits ?OIE0 (Timer/Counter0 overflow Interrupt Enable).Diesesmuss den Wert I enthalten,um den Interupt zu .ldvieren. ln C könnte dasetwaso aussehen;
bei welchemStartwertder Timer zu zäNenbegirnt. Siekönnen nun noch fesdegeD, Ein 8-Bit-Timer/Counter zählt nomaleMeise von 0 bis 255 dur€h und erzeust dann einenÜbedaüf bzw.ein€n Interrupt. Siekönnen den Timer ab€r auch späterstarten lassen,also nicht et{a von 0 weg, sondern z. B. von 200. Dies ist sinnvol, denn bei einer Zählfrequenzvon I MHz würde erstnach256 Schrittenein iJberlauf stattfinden.Daswäre eineFrequenzvon etwa3.907Hz, alsoalle256ps. SetzenSie den Startwert auf 246, benötigl der Timer noch 10 Schritt€ bis zum Uberlauf.Mit einer Z?illfiequenzvon 1 MHz wäredasein 100-kHz Tald. regisDiesenStärtwert setztman, irdem dasRegisterICNTO alssogenanütes "Zäl jedem Zähldurchgangum eine Einleit ter" dient. Dieseswird vom Timer mit erhöht. Bei 2s6 fiihit dies dann zu einem itberlauf (Äufrufen desInterrupts, Neusta bei 0). Sie solten dasRegisterdahervor dem eigendichenStarcn desTimers Wichtig: Sie dürfen in der Interrupt-Rorltine nicht vergessen,das Z?ihlregist€r immer wieder auf den g€\,rünschten Startwertzu setzen.Nach dem Ubedaüf wi.id€ der Timer sonstwieder bei 0 beginnen.Meh{ dazuir ein€mspäts angetuhrtenBeisprelprogramm.
2 Det llikrocontrcllel
74
ßevor es nun endlichlosgeht,müssenSi€dem Controllernoch den Aufruf aler Interrupts ,,erläuben".Normalerweisehat der Controller in der StandardeinsteluDs dä esbesonders zeitkitischeProgrammnicht die Erlaubnis, Interruptszuzulnssen, teile gebenkönnte, die Sie auf gar keinen fal durch eineDInterrupt unterbrechen desControllers.Mit deln C Befell lassenwollen.Das ist die StandardeinstelluDg dnli seio könnenSieihm nitteilen,dasser abjetztaIe lntermpt zulassen Unter Umständenwollen Siedie Unterbrechungdurch lnterrupts in minchen ProDannempfiehltsichderBefclldi0. srammteilenabcrnicht zulassen. seio - Erlaubenal1erInterrupt Aufrufe ab diesemZeitpunkt cli0 Verbietenaller Interrupt-Aufrufc ab diesemZeitpunkt Beispiel. MehrdazusehenSiein einen nächfolgcnden In dem Nun könnten Sie den Timer startcn,doch das ist bereitsseschehen. Moment, in dcm Sied€m Timer eine Cloci zuweisen,beginnt er bereitszu laufen. Wenn Sie den Timer wieder stoppenwolen, weisenSie einfachden Bits CS02, TCCÄ0)je eine0 zu und derTimerpausiert. CSol,CS00(zu findenim Register bei einem8 MHzHier ein Beispiclzur Generierung eines625 Hz-Rechtecksignäls, aimrz. . p".. .t. . t: ".. q." , t...6 3; 4: 5l 6t 7: 8
#include #include / * 3 I 2 5 A l z Z ä h l t a k t q e t € i l t d u r c h ? 5 ' 1 , 2 5 At u * / / * A b e f : l P e r i o d e = z u s t ä n d eH i s h + L o v lD a l r e r6 2 5 N z * / d o e i n e D . o L l' a | |
' P T ' ' 1 - R00V r _ / " . .
r0: ll: t?. 13: 15r o:
I
/ * z u s t a n da n P 0 R T iBn v e r t i e r e n* / P O R T=B - P 0 R T B j /' * N e u l a d e n , n i c h t b € i 0 b e s i n i e r l * / N-0
18: 19r 1r ro 20: { ? 23. 2al
.oid) '\'0-
o
DPrra
lr'
/ * C l o c kl e t e i l t d u r c h 2 5 6 = 3 1 2 5 0H 2 T a k t + / \0 i . o0-'
2.6 Tiner/Counter 75 26: 2/-, 28: 29: 30: 31r 321 33:
/ * 1 r t € r r u p t E n a b l e ,f ü f 0 v e r f l o w T I M S (= ( 1 < < T 0 I E 0 ) ; / * A l l e l f t e r f u p t s e r l a u b e n* / / * E n d ' l o s s c h l e i *f e/ !hile {1) i
35. 36: ]
In Zcilc 4 bindcn Sie das notwendigeHexderfilefür Intettupt-Handling ein. Diese DateibenötigenSieeigentlichimmer,wenDIhr Programmrnit Interruptszn trul In Zeile i0 beginnt die InterrupGRor.ltine(nach neuer Schreibweise).Der Inhalt dieserRoutinebestehtim Wesendichen auszweiAktionen: l. nö Invertierer de' Porl/rburdivunPurlB 2. Den Z?i}llerwieder neu laden, drmit er nicht bei 0 beginnt (und somit 256 Durchläufebis zum überlaufbenötigenwürde).Hier startetder Zählerbei,,2s6 Durchläufe".Inuserem Fällalso231.Ab hierwerden Anzahlder gewinrschten nür noch 25 Durchläufebenötigt, um dieseRoutine dasnächsteMal zu starten. Bei einerZähfrequenzvon 31.2s0Hz (= 8 MHz geteiltdurch 2s6) entspricht dasenrer,,Uberlaulfiequenz"von 1.2s0Hz. Im Hauptprogrammfindcn Siedie Initiatisierung desTimers.Anschließendbegibt (und zähltnattirliclr;m Hintelsrundden sichder Controllerin eineEndlosschleife Tinerue hoch). Achrung: Die wohl wichtigsteAnweisungdesgaüzenBeispielsfindet sic]l in Zeile jetzt alle 30, nännich sdia).Mit dieserÄnweisungteilen Siedem Prozessormit: "Äb Dinse: Interruptserlauben!". Eshandeltsichhierwnklich urr zrei verschiedene l. SiemüsseD nn Register TIMSKdeDInterruptfiir dengewünschten Timer/Coünter einschalten.Diesbeziehtsich dahernur auf den Timer selbst. rnitteilen: Ab 2. AußerdemmüssenSiegenerel in Ihrem Programm dem Pro?.essor jetd sindallelnterlupts,,erlaubt'.Dasgeschieht mit derArweisungseiQ. Hier werdeDanr häufigsteD Fehlergemacht.DenkenSie alsodnrän,wenn etwäs nicht so funktioniert, wie essollte.
76
2 Der ll4i ktocontroller
2.6.2Output-compare-Mode Der Timer/CounterbesitztJedochnochetwasnehr Powera1sdasreine,,Hochzählen" einesRcgisters. Sie könnendem Zählerz. D. sagen,bis zl1welchemWert er hochzählen soll. Siemüssenalsonicht mehr auf einenÜberlaufnach 256 (bzw warten,soDdernkönnenschonfrühereinenInterruptauslö 65.536)Durchgängen Der Timer zählt in diesemModus dasZählregisterwie üblich hoch und vergleicht den wert ständigmit einer ,,Obergrenze".Ist dieseGrenzeerrei.ht, wird ein Iuter' wiederbei 0. Durch dnsstänrupt ausgelöst uDd der Timer beginntanschließend nennt sich dieserModus däner auch dige "Compare-Mode". "Vergleichen" Wichtig: Beim ATmegaSvertugt der Timer/Countero über keinen CompareMode (beim ATmegal6jedochschon).Timer/Counterl(16 bit) und Timer/Counter2 (8 bit) haben einen Compare-Mode.wir verwendenftir die Lrkltuung daher den Ttuer/Counter2. Um den CompareMode eirzustellen,folgen SiediesenSchritten (die UDters.hiede sindfett geschrieben)l zur normalenTimerkonfiguration lclo"l) I. Fin'relien dcr/ählfrequenz 2. Konfigurieren des Comp.re-Match-lnt€ruprs 3. Einstellendes,,Startwerts" 4. Output-Compare-Regisrersetz€n(OCR2) 5. Alle Intenupts,,erlauben" 6. StaitendesTimers Die Schitte 1, 3, 5 und 6 sind nus dem vorigen Beispielbereitsbekannt. Folgend gehtesum die neuenEinstelungen. mit dem desZählregisters Bei einemCompde-March,alsodem Übereinstimrnen Sie das Regis ausgelöst lterden. Dazlr benötigen ein Interrupt ,,Vergleichsregister", ler TIMSK, dasIhDennun schonbekannt ist:
ffi,."" abb.2.18:T I\lSKRegist€r
2.6 Timer/Countet
77
Hier intcrcssiert uns das Bit OC.IE2 (Output Comparc Match Interupt Enable). wie üblich bewirkt hicr eine 1, dass der Interrupt aktiviert ist. Das würde in C so
1:
| '1. - \
'
Nun nüssen Sie eigentlich nur noch festlegen,bei welchem Vergleich$lert der Inteüupt ausgelöstwird. Dizu verwendetnan däs RegisterOCR2.Danit wird der gewünschte,,Triggerwert'gesetzt. Sehenwir uns ein ganzesBeispieldazu anl 1: 2:
# i n c l u d e< a v r l i o , l ' r > # i n c l u d e< a v r / in t € r r l p t . h >
4: 5: 6t 7: 8: 9. r0: l: 12i :
t S R ( I I r , 1 E RC2o [ P v e c t ) I n v e r t i e f e n* / / + Z u s t a n da n P O R Ti B P O R T=B- P 0 R T B j C IT' I TlZl i e d e r z u r ü c k s e t z e n* / / + U N B E D I T ,TI G T1-\ -0: l nt noinr'o d) I a t c h \ i e n nT C N T 2 = 0 x 0* /4 / * 0 L r t p u tC o m p a f e 0 C R 2= 0 x 0 A ;
15. 16: 17r 18r 19: 2A: ?1. 2t: 241 ?51 26: ?7. 28: 29-. 30: )l:
/ i C r o c kl e t e i l t d f c l r 2 5 6 = 3 1 2 5 0r z T ä k t * / T C C R=2 ( 1 < < C S 0 2 ) ; / * I f t e f r u p t E n a b l e ,f ü r 0 u t p u t c o m p a r l€l a t c h* / -, Ojt?j / * A l l e I n t e r r u p t s e r l a u b e n* / s e iI l ; / * E n d l o s s c h l e i f*e/ llhile (1) | return 0j )
Achrug: Sie düfen nicht vergessen,am lnde des hterrupts (siehe Zejle 10) das Register TCN?2 auf NuI zurückzusetzen. Das passiert nicht autonatisch. Anderer seits würde der Tiner/Counter dann bis zum Üterlauf weiterzählen
2.6.3 Output-Compare-Mode fürWaveform Generation Siekönnen mithilfe desOutput-Compare-Modesnoch weitausmehr erledigen.Der Controller unt€rstützt z. B. das automatischeSetzenoder lnschen einese)'ternen Pins bei einem ,,CompareMatch". DiesesFeature€ignet sich hervorragendfur die einfacheGenederung eines Rechtecksignalsoder auch eines sogenänntenPWM (Pulsweiten-ModuliertesSignal).cmfisch würde dasso alrssehen: G6fik l:TCNi2ähk von0 biszuOCR2hoch(Compare Match)
Glafik2:Zunandsändeiung a!feinenextern€n Pinbeijedem Compare Match Abb.2.19rPd'rzipd€sWaveform Genention Modes Es gibt vier Möglichleiten, ein Rechtecl$ignalzu eüeugen: L Normal-Mode (siehevorigesBeispiel) 2. CTC Mode (ClearTimer on CompareModus) 3. Iast-PwM-Mode (SchnellePulsweiten-Moddierung) 4. Phasenkorrekt€rPWM-Mode (langsameralsFast-PWM-Mode)
. . 2.:6.rincilcöintel. 79 2.6,4 Rechteckignat mit CTC-Mode Beginnenwir mit der Generierung eines einfachen Rechtecksignals mithilfe des CTC-Modus. Dieser ist sehr praktisch: Der Timer zählt so lange hoch, bis es zu einem Compare-Matchkommt (TCNT2 entspri€ht OCR2). Dann fithrt der Contioller eine definiert€ Zustandsändenngam OC2-Pin aus (b€i ÄTmega8,Port B, Pin 3) tllld setzt den Zibl€r automatischwieder auf 0 zurück (TCNT2=0). Somit z?ihltdieserTimer immer rür bis zum Compare-W€rtund ftihft dann eineÄktion Mit dem wert in OCR2 und der Z?ihlgeschwindigkeit(Betriebstaktdurch Teiler) wird also die Länge einer halben P€riode des R€cht€cksfestgelegt(siehe crafik Dazu müssenwi€der einigeBits im RegisterTCCR2gesetztwerden:
Abb.2.20:Waveform Gene€-
Die Bits WGM21 und WGM20 legen den Wav€form-cenemtion-Modefest. Wir veffendenhierModus2, alsoCTCMod€(wcM21-1, wcM20=0). Außerdemmussdem Controller noch erklärt werden,was er bei einem CompareMatch zu tun hät - also eine steigendeoder ein€ faltendeFlankeelrzeügen.Dafür werdendie Bits COM2 I und COM20 benötigt. Theoretischist esja meist egal,ob man mit einer steig€ndenoder einer fll€nden Flank€beginnt. Aus diesemGrund ist es auch am besten,wenn der Contoller in unserem Fall eiDfach ,,toggelt", also den Zustand mit jedem Compare-Mätch umdreht (von 0 auf I und umgekehrt).Dazu ein kuzer Blick auf die entsprechenden Bits:
Nomal pon opealion, oc2 di$onn6cl6d.
Toqoleoc2 on conparc March Cl€arOC2on comparc Malch Sel OCz on Compaß Match
Abb. 2.21:Zustandvon OC2beieinemComDarc-Match
2 DerMikrocontroller
80
Wir setzeD alsoCOM2I=0 und COM20=r. In einemProgrammwürde dasGanzeso aussehen: Pb
J: 4: 5: 6. /: 8: 9t t{]r 11: I2: L1: Lr|
ö."
q.o
'/ rin l,de ., r/io.' # i n c l u d e< a v r / in t e r r u p t .h >
F I r
r !4odo
int maif(void) / * ! i c l r t i g . 0 1 2 P i n a u f A u s g a n sqc h a l t e f l * / D D D B ,0 E E . /'
- . D 2- v a r f o - . d .i o : L l oe . o . r ' ö r q . ! vodö (o o lton Puv) 'ro
18: 19. 2A: 22: 23: ?4, 25: ?6: 27t 8: )
4 o!i
:
. o r0 q , 6 v a r .
l' I
*/ T C C R= Z ( 1 < < l , l c l 4 z l )I ( l < < C 0 M 2 0 ) ( 1 < < C S Z I ) ; -0.pu''o'p."'!4o 0 C R 2= O x A A i
hrpi
C\ l-0 dÄ'
/ + [ n d l o s s c h l e i f e* / while (r) ; retum 0;
mit Fast-PWM-Mode 2.6.5 Rechtecksignal Der Fast PWM Mode wird tur die Er,€ugungeinespulsweiteDmodulieftenSignnls benötigt,rlso ein SignalInit untersctriedli.hlangenPulscn(Zuständen).Ein PWMSignalsieht z. B. so auswie in Äbb. 2.22dargestellt. ln der funktionsweise ist diesdenvorherigen Beispielen sehrähnlich.SieleseDfest wie lange der Tiner zur ersten Flrilen;inderung zählen muss (älso TCNT2=OCR2) und ob dic llankc hicr cinc steigcndeoder eine fallende lorm lm Gegensatzzum CTC Modus läuft der Timer bei einem Compare Match (TCNT2=OCR2)weiter bis zum tiberlauf (also kein Zunlcksetzennuf 0 bei TCNT2=OCR2). BeimLlterlauf änderter die Flankewieder und zwargenauin die andereRi.htung.Die Längeeincr ginzen Peiodc wiid alsoaleine durch die
2.6 Tiner/Counter 81
TT !t I
{
rl
!1
12
tl
ll
}1
12
){
Ll
= OCR2 1.Flankenwechsel:TCNT2 = 255(Überlauf 2.FlankenwechselTCNTz )
Abb.2.22rPwfi,l.Signal Clock(und denentsprechendeD Teiler)bestimmt.Wo innerhalbdieserPeriodeder ersle llankenwechselstattfindet, wird mittels desWerts in OCR2,ä]so dem Compare Match Wert, festgelegt.Die FlaDlGwechseltdasa{'eite Mal dänn automatisch beim Uberlau{ Zu den Bitkonfi guration€nl Als Erst€smussman wieder den waveform-Generntion-Modesetzen.Däzu wieder ein kurzer Blick auf die Bits WGM2 I und WGM20 im RegisterTCCR2:
Abb. 2.23:Waveform-Gene-
Därausergibtsich:WGM21=r, WGM20=1. wie üblich werdennun die Birs COM21 und COM20 gesetzt.Hier ist jedoch Achttrng geboten:Für den Fast PWM Mode gilt eiDeandereKonfigurationstabelleals vorher(sieheAbb.2.24). Esgibt nur die Möglichkeiten,mit einer steigendenoder mit einer fallendenFlanke zu starten.Wir wollen mit einer steigendenFlankestarten,daher wäh1enwir die werte: CoM2r=1, CoM20=r.
82
2 DetMikrocontrcller
Normal pod ope 6lion, OC2 dlscon n€cled.
clearoc2 on compareMatch,sel oc2 at BoTToM, SelOc2 on compar€Mal.h,clearoc2at BoTToNl
lvlatch Zusiand vonOC2beiUberlaufund Compare Abb.2.24: wenn TCNT2=0 dann befiDdet sich der Zustand 0 auf Pin OC2, we'rn TCNT2=OCR2dannderZustandI aufPin OC2. Ein lauffahigesProgramm dazuist:
i:,
I
d,q"or'\!orar
n'lroq
P!woop
l, ;i; ::::.ll li;! ,", 9, '" '" "" ' :, '|
,?,,
t::
t,,
Lc(io:o. =0 DDoB ;
Dnd.'Aued,e.-"
el,
P9"B-ooo,
i,,i:i""1:;"::i;:r:""' [.. -:ll3;"0'?01?-,
i?' ,,,liil,.,,1,,--,,",, .\.0,.r2,. 1 i01!0rl I/.c.'
l:"
f:,
;, iZ:
vät /' ourp.' onpare
o ra 2 a ,. a . .
;l ;:';" """" r e t u r on ;
re
;
rrN =0, 0
2.7 Analog-/Digitalkonverter83
2.7 Anatog-/Digitalkonverter Der ATmega8vcrfügt über einen l0-Bit-ADC, der mit einem analogen8-Kanal Eingangsmultiplexerverbundenist. Somit kann der ADC eine der acht verschiede nenEnrgangsspaDnungen messenund die Spannung in eineml0-Bit-WertdarstelÄusdiesemGrundwürdeDdannz. ß. s V am Eingangdem 10 ßit wert (Dezimal) V am Eingangwürde in den digitalenWert 0 konvertiert ,,1.023"eDtsprechen.0 werden.wem dasein zu großerWenebereichist, der kann den A-iD Konverter auf eine 8 Bit Auflösungumstellen(wasin den meisteDFällenau.h komplett äusreicho. Dcr Abhuf einerlD-Konvertierung siehtfolgendermaßenaus: 1. Konfigurieren derADc'Regisier 2. Konvertierung starten 3. FertigeWerte ausdenRegistern ADCH undADCL auslesen
2.7.1 Konfigurieren derADC-Register zweiverschiedenen Betdebsmodi wählen: SieköDnenzwischen . FreeRunningMode . SinCle-Conversion Mode Beim lree-Running Mode liefert der ADC st?indigneueWerte. Er stoppt nach der Konvertierungeineswerts nicht, sondernfilllt die Rcsultatrcgisterständigmit den aktuellen,konvertiertenSpannungswerten. Im Single-ConversionMode hingegenwnd nur enreeinzigeA/D wandlung vorge nommen.NachdieserwxndlungpaüsiertderADC, bis Sieihm wiedcrdcn nächsgeben. len Befehlzur Konvertierung Beghnen wir mit der Auswabl des gewünschtenEingangskanals.Der ATrnega8 wir dasRegister ADMLD(: unterstütd8 Kanäle.Dazr beDtjtigeD
Abb.2.25:AD[,lUX-Register
84 Die Bits 0 bis 3 sind fü die Auswähl desgewünschtenEirgangskanalszüständig. Hier die entsprechenden Wertedazu:
Abb. 2.26:AuswahldesADC-Kanals
Es existierenjedoch noch drei weitereKonfigurationsbitsim ADMUX RegisterDie Bits REFSIund ÄEIS0 erlaubendie Konflgurntion der ,,Referenzsp.nnung". le nach Iinstellung können Sie mit REFSI u:rd REFSobestimmen,mit welcher Referenzverglichenwerdensoll. spannungdie Eingangsspannung z. B. 3 V entspricht eine Eingangsspannung von etwa 3 V lst die Referenzspannung schondem Marimum, also einem l0-Bit-Wert von 1.023(bzw.255 im 8 Bit Modut. Es stehenlhnen datur drei Mögli€hkeitenzur Auswahl:
AREi lnl€nal V,€rllrned olf
AVcc wilhexternalcapacitor al AFEFpii Voliag€Fel€rcncevrjlhoxlehalmpaclorat AFEFpin Internal2,56V
Abb.2.27:Auswahl der Refercnzspa nnuns ünd REFS0=1(Veqleich mit der Im Normalfall wählenSiehier die wefte -RAFSI=O Versorgungssprnnung, alsomeistens 5 V). Das letzte Konfigurationsbit trägr den Namen ,,ADLAR",was ausgeschrieben ÄDC Left Adjust Registetbedeutet.Die Funktion diesesBits besteht darin, das 10-BitErgebnisentwederlinks oder rechtsin den RegisternADCH und ADCL auszurich ten. Darunter kmn man sich kaum etwasvorstellen.Abhilfe schaft dieseGrafik in Abb.2.28.
85
Abb. 2.28:ADLAR-Register
Wenn SiealsoADLAR=r seten, frnden Siefast daskomplette Resultatim Register ADCH. Die erstenbeiden Bits werden im RegisterADCL gespeichert,verändem das Ergebnisaber lediglich um ma-ximaldrei Einheiten (Binär 11=3). Viele Ent wiclder entscheidensich daler tur ADLAR=I und lesen nach der Konvertieruns nur den Wert im RegisterADCH aus. Der W€rt in ADCL würde ohnehin kaum zu einer wesendichentuderung des Ergebnisses tuhren. Man nennt diesenBeüieb auch ,,8 Bit Modus", weil man sich nur um die höherenI Bit desResultatskümmert. Nun widmen wir üs dem letzten Konfigurationslegister{iir den ADC, dem Register,4rCSRÄ (ADC Contlol and Status Register).Mn diesem Registerlegen Sie noch ein paär letzteEinstellungenfest und können außerdemdie Steuerung(Start, Stopp)derADc-Einheitübernehmen. SosiehtdasRegister nus:
Read//vhle nilialvarue
AOEN
ADSC I
ADFR
Rry 0
R4/1] 0
R/l/V
ADIF
ADIE
I ADPS2
ADPS'
AO
0
Abb.2.29:ADCSRA-Register Beginnenwir ganz rechts.Die erstendr€i Bits, ADPS0,ADPSI und ÄDPS2,legen den Vo eiler fest.Sie können damit bestimmen,mit welcher Geschwindisleit die A/D-Konveitierungen stattfinden sollen. Sie gehendabei vom Systemtaktaus,der durch einen bestimmtenVorteiler h€runtergeteiltwhd. Abb.2.30 zeigt eineTnbele mit den entsprechenden We en. Hier würdendieWerteADPS2=o. ADpSI=0.ADPS0=0einenVo(eilervon 2 fesd€ gen,alsobei einem Sysremtaktvon 8 MHz ehe Konvertierungmit 4 MHz Taktver-
85
2 DerMikrocontroller
Abb. 2.30:ADC-Verteiler
DasnachsteBit in der Reiheist dasBitÄD/E (ADC InterruptEnable).Wie auchbei vielen anderenEreignissenftLhft enle abgeschlossene A./D-Konvertierungzu eiren Interrupt, wenn das gewünschtwird. Um den Interrupt zu aktivieren, müssenSie diesesBit nuf i setzen(und generclldie AusfiihruDgvon Interrupts erlauben). Am Bit 4,ADF (ADC Intcrupt Fläg),erkennenSieeineabgesc}lossene Kon\.crtierung. DiesesBit trägt den Wert 1, wenn eine Umwandlungerledigt ist. Sie müssen däherfiir diesesBit zru KonfigurationkeinenWertsetzen(alsoauf0lassen). Bit s, AD-FR(ADC FreeRünningSelect),bestimmtnun den Betiiebsmodus des ADC. Bei einemaktiviertenFree-Running-Modus liefert der ADC ständigneue Resultate. SolltenSiedaswünschen, set,€nSiediesesBit einfachauf L Bit 6, ADSC (ADC Start Conve$ion), liefert dasStatuignal fiir den ADC. Wenn Sie i.n diesesBit eine I schreiben,beginnt der ADC die Konvertierung.Haben Sie den Iree RunningModusgewäh]t,reichtdaseinmaligeSetzendiesesBitt. Im Si,rgle Conversion-ModushingegenmüssenSie nir jede KonvertierungdiesesBit erneut \{it Bn 7, AD,N (ÄDC Enable),sind wir beim letzten und wichtigsten Bit ange ]ängt.DiesesBit schiltetdeDADC ein (l) oder aus(0). Nicht zu vemechselnmit demßit 6 (ADSC) denn wenn ÄDEN nicht denWert i enthält,passiertgar nichts. DasBit ADSCstartetlediglichdieKonvenierung an sich. Um die graue Theorie ein wenig abzurunden,hier wieder ein kurzes Beispieltur denFree-Running-Modus: 1: ..
#include dir I
,:
5r
lL[.
{
Jdo
iD
,ö |
2.7Anolog-/Digitolkonvefter87
6: / / A D CR e s u l t a te i n l e s e nu n d a l s O e m o n s t r a t i o n l. / / | l i € d e r a L r fP o r t B a | s g e b e n. . . 8'00D8-60.t1; l0: ''|
':'' 13:
i
L |d'
(.o
d
/ / A l l e I n t e f r u p t se r ' l d u b e n
1 rI 6: 18: 19: 201 21: 22: 23: 24: ?^: 261 271 8: ?9. J
.rp,,uDl i] ,"" o,n..o'4od" 1i tD 8 B P" " e z p. a: / / / T a k t : S y s t e m t d k t/ ? { 4 r l H z b e l 8 l , l h z0 u a r z ) A D l l U=l ( L < < R E F S o )( l < < A D L A R ) i A D C S R=A ( I < < A D E N ) ( 1 < < A 0 F RI) ( 1 < < A 0 1 E ) ; / / A D Cs t a r t e n ! A D C S Rl = A (r i r t n a in ( v o id ) i c h a r l e d s t a t u s= 0 x 0 0 ; c h a r r o t a t i o n s q e s c hnwdj i9 k e tj i f t g e h e i n c o d-e 3 4 5 6 i l o n s s c h l u e s s e=l r 2 3 4 5 6 4 3 4 5 ; retürn 0l
Arßerdem hnt si.h durch dieseAnderung äuch die LängedesProgmmmswesentlich verküzt. Itichtig interessantwerdenVariablennatürlich erst dann, wenn Siemit den AusgabeportsinVerbindunggebrachtwerden: 1: 2: 3: 4: 5: 6: 7: 8: 9r
# i n c lu d e < d v f / i o . h > i n t m d ni (v o id ) { charled status= 0xFF; = l]rFFi DDRB P O R T=B I e d _ s t a t u s ; I e d _ s t a t u s= 0 x 0 0 ; P 0 R T=B l e d - s t a t u s ; returf 0;
r0r ]
An1 bestcncrklärt sich das Beispiel wicder Zcite ftir Zcile: In Zeile 4 wird einc Variablemit der Bezeichnungled srarasvom T1a c/rarerstellt und erh:ilt den Wert 0xIF (alsohexadezimäl FF).Bintuwürdedasder Zähl,,11r r I r 11" entsprechen. Zcilc s ist bcreits rus dcnl Eintuhrungsbeispielbekännt. Hier wird lediglich die Datenrichtungvon POIITB auf ÄUSGÄNGgeschaltet. In Zeile 6 wird auf POIUB der Inhalt der Variablenled starasgeschrieben,in unse rem Fall also oaFÄ Das wiederum bedeutet, dass alle Pins von PORTB auf i geschalietwerden. ln einer 8 reiligen LID-Reihe würde jetzt kein Licht leuchten (beiPull Up SchaltuDg, änsonsten natürlichschon). Ir Zeile7 wird der Inhalt derVariableled sransauf 0x00(Binär:00000000) geän dert.An der Schaltung der LEDSpassierthier no.h gar nichts.wir habenlediglich den neuen Inhalt der Variable led sraaa festgelegt.Darum ryird in Zeile 8 dieser neue Weft den PORTB zugewiesen,was bei einer LED Reihe a]le ncht Li.hter
776
in C 4 EineEinfuhrung
Gehen nir einen Schriu weiterl 1, 2r 3: 4, 5r 6r 7: 8: 9: 10: 11r 12: 13:
#lnclLrd< e a v f / lo . h > ift nair(void) { c h a nl e d s t a t u s = 0 1 0 0 ; D D R -A r l r F F r/ / P O R A T a l i f A u s q a n sg. h a l t e n D D R =B l l r F F j / * P o R TB a u f A u s q a n sgc h a l t e n* / P 0 R T =A O X A A ; P o R T -B 0 N 0 0 ; D D R =A 0 1 0 0 ; l € d _ 5 t a t u 5= P I l 1 A i P o R T =E l e d s t d t u s i r€turf 0; ]
verscliedeDe zlrr KomDreD Siesehenim angeführteD Beispiel?-wei MöglichkeiteD (//) tierungvon Quelltext.Zum Einenden doppcltcnSchrägstdch und zumAnderen denSchrägstrich mit enremStart (/.) und einemStoppz-ejchen {t/). li ist ganz Ihnenüberlnssen, für welchcArt dcl Kommcnricrung Sicsichcdschcidcn. // bcdcutct,dassfür dcn Rcsldcr aktuclcnZcilc nü nlchr Kon]menrarfolgt.Bei von /* uDd*/ definierenSie,illl Gegensatz derverwendung zur // KommentieruDg, s€lbst,wo Ihr Komnentnrbeginntund wo er endet.Siekönnenhiermit ruch übcr (weitereBeispiele nchrcrc Zcilcnhinwegkommentieren. dazufindenSiein eini gender nochfolgendenQuelltexte.) In deDZeileDs und 6 wcrdendie PortsA und B je$'eilsauf A S.rflggeschältct. In den darautrolgendenzwei Zeilen wnd dabei auf Port A der u/ert Hcrj AA und auf RlrtB derWertHe{i oalausgegebenAnschließend wird die Datenrichtung von Port Ä zuni.k iuf tingd'rggcsctzt. Bcsondcrcs intcrcssanr $,irdcsin Zcilc 10.SieerkennenbereitsdieVerwendung derVariableled status.In diesemfall wnd ihr der Etn ga'gswertvon PortA zuge$'icsen. Würden SieanstattPINA die BezeichnungPORTAveNenden, weiß der Mikocontroler nicht,dassSieeinenwen enrlesen wollenund er liestlediglichdenAasgaüe l,"rfsrvon PORTA,ohncdrzu äuf dic PinsdcsMil(]ocontrollcrs sclbstzuzügrcifen. WennSiegeradedenSimulatorauflhrem Rechnerlaufenhaben,werfenSieeimal einenulick auf das Feßter I/O Viet^/(Achtung:Nur sichtbanwenn Sie sich im Debugmodus befinden).Öfiren Sie.lort deDEiDtragI/o ?oftA und Siewerder erkennen,dassder Simulator tatsächlichz-'fischenData Rcgittetnn,J.Input Pins unterscheidet. BeachtcD Sic dah€rbitte:W€nDSiedcn ZustaDdeiDesPortswisscr WollenSieden 7-ustand wollen,müssenSiennmer PIN,A,PINB usw.veLvenden. eineslorts änden,verwenden SicPORIA,PORTB,usw.
4.3 Variablen 777 Zurü& zu Zeile 10.wir lesendso den wert von Port A (an den Pint e;n und schreiben diesen Zustard in die Variable bd status.Am Ende des Beispiels,in Zeile I l, wird der eben in def Variablc led_strtusgespeichertewert nun auf Port B geschricben.DiesenVorgangkönnen Sieebenfallsim Simulatorverfolgen. In derfolgenden TabelekönnenSiedieAnderungen derZusthde senaumitverfolgen: Zeile Wert Dalendchtung PORTA/(PINA) PORTA
wert PORTB(PINB)
Drtenri€hrung PORTB
4??? 5?Ausgang!! 6?Al1sgang?Ausgang 7 He* AA Ausgang AusgaDg 8 Herl:ÄA 9 He{: AA Eingang Eingang 11 Her AA
? He* 00 Hex: 00 Her AA
Ausgäng Ausgang Ausgang Ausgang
der Achtung:DiesesBeispieleignetsichhäuptsäcllichnir die Verinschautichung wertezuweismgenbei Varhblen und Ports mittels Simulator.In einem hardware basiertenTestist nicht sichergestellt,dassder wert von Port A ab Zelle 7 am Port selbstgespeichertwird. So könDte beim EinlesendesZustandsir Zeile 10 bereits ein gänzlich unterschiedlicler wert am Port A anliegen.wundern Sie sich also nicht, wenn daherauf Port B am Endeni.ht Her ,{-4 anliegt. Ein weiteresBeispielzur aithmetischen Verwendungvon Vnriableni ': l:
'ir!
u a €. o . i o . r ' nd .o d)
4t 5: 6:
N o . r e a e l l e . e D " r o n ._ d ( r o n v o n e i n e n K o m m € n t adra, s s ü b e r e i n i 9 € Z e i l € n h i n w e qv e n l ä u f t . * /
8:
.'
t0: ltr 1?: 13: 14:
000:
".,.,
o 0 oa - l e d ' d ,
:
l e d , s t a t L r s= l e d _ s t a t u r + l ; = led_statusl PoRTA 'öc_(rar | | _ i
.:
18:
P O DA = t p o
..or J.;
118 t9: ZA, 21. 22: 23: ]
4 EineEinftihrungin C
= led,status i P0RTA
Hier seheDSie drei verschiedeneMöglichkeiten, um den Wert einer Variable zu erhühenb^{ eineAdditiondur.hzuführen.Zeile13 erhöhtdeDWert voDled r.a t s auf ficri 0.1.Die Funktionsweisedabei ist relativ einfach zu verstehen:,,Neuer Wert = Alter Wert + Zahl." Zeile 16 bietetschoüeinewesentlichkrmfortablere Möglichlcit,denWert von ldd_statrJum die Zahl 1 zu erhöhen.Zeile 13 erlaubt dasErhoherum belieb;ge Werte.Zeile 16bedeutetjedoch:,,ErhöhedenWertvon led-Jtdtrr um gennucinc Einhcit': Mehrerc,,+" änden dann nichts-Da nber sehr häufig die Addition von .l benötigt wird, wurde diese++ Anweisungeingeführt. Zeile19 zeigtschließlich die dritte MöSlichkeitz-urAddition.Es handeltsichdabei in1 wesentlichennur um eine,,kürzcreSchreibweise" \'on Zeile 13. Sie können daberauchhier beliebigeWerteaddiereD. Der Wert i-Ier0,4befindetsichnuD auf PortA am EndedesBeispiels. Siesind bei C natürlichnicht nur auf dasAddierenbeschränkt, sonden kömen allegängigen Grundrechenarten durchfiihren. Hier einigeBeispiele: e d _ s t a t ! s= l e d _ s t a t u s+ 1 ;
ed status= 10 I ed_status; ed status= led status* 2;
DieserÄuszugist schon etwasanspruchsvoler.Äm Ende enthä]t die Variableled srdhlideDWert Her 08.
4.3.1Schtüsselwörterund Einschränkungen Sic könncn bci dcr Dcklaricrmg Ihrcr Variablen alle nöglichen Konbinationcn von wörtern und Zahlenverwenden, esgibt dabeijedochein paxr Einschränkun gen: . DcI Namcdcr Variablcdärf nicht mit einerZähl beginnen,jedochmit eiier oder nrehrererZahlen ender. (Nicht erlaubr int l2rariableie(1a'rbtint l,atiable12)
4.4 Anweisungenund Funktionen
719
. Die VnriableDdürfen kehe aiitlnetischen oder C spezifischenOperatorenent halten,wie etwal, /, \, +, -, #, usw Erlaübt sind Zeichenvon a-2,A Z, 0 9 uDd der Unterstrich ( ). UDrlauteund Satzzeichen sind nicht erlaubt. . Die Längeder Bezeichnung Ihrer Variablensolltenicht ausmehrals32 Zeichen bestehen,denn C unterscheidetVariablennur anhanddieserersten32 Zeichen. . Achruig: C unterscheidetz.wischenGroß und KleinschreibunglDie Variablen int testlnd i t Testsjna zweikomplett verschiedeDe Instanzen. . Esgibt eine lteihe von Schlüsselwörtern,die fiir die Progrämmierungin C reserviert sindund dähernicht alsVariablenbezeichnuns vemendetwerdenkönnen:
Abb.4.2: SchLüsse lwörter in c
4.4 Anweisungen undFunktionen sie hnben anhand der bisherisenBeispielebereits ejnige AnweisuDgeDkennengelernt. ln diesem Abschnitt widmen $.ir uns dcn sogenannten F,irlfiores. Beispiel:
P O R T=B 0 x 0 0 i
5r 6:
)
8:
,o'd eoo r\
0: 11: l
DODB-O
:
l 3 : i r t n d in {v o id ) l,t: { 15: D D R =B O x F F i/ , / P o r t Ba u f A l r s g a n q 16: Il I ledonoi
720
4 EineEinführungin C
18: L9: 2It
J
wird, wennSie EincF?./rkrto, ist eine,,Programmenrheit", die erstdaDnausgetuhrt (iln Befehl gebeD. kinnten Sie z. B. einc Reihe von funkdazu So Quellcode)den Diese tionen 1ür die Konmuniletion mit der seriellenSchnittstelle schreibeD. ProjektenwiederveNendcn. tunktioren könnenSiedanr in nrehreren DerAulbaucincrlunklion siehtimmer gleichaus: ( 0PTloliAL: FllN(Tl0NSllAl,1E PARAüETER 0AIEflTYp DtSRUC(GASELIERTS ) i I . ] T ] A LD T E RF U N ( T I 1 ] ] . ]
] ID Zeile3 b€ginDtbcreitsdic crstcFunktionmit denlNamenledor.Äußerdemken nen Sie den nückgabewert dieserFunktion,ror'd.Da sich zwis.henden beiden KlamDlenin Zeile3 ]€in Inhaltbelindct,eneartetdieseFunltion keineLrbergabe pann1ctcr(mehrdazuetwasspater).Der Inhalt der fuDktioD,Port B auf 0x00zü schalten, ist denkbareinfach. EineFunktionkönntcz. B. einekomplereBerechnung enthalten. [ine Berechnung Dieses ist sogenaDnE Rn./.gdler?rt liefert bekanndichauch ein ,,llrgebnis". der welcher einer Furkti.'r. wie überallin C nüsscn Sie sich nüch hiff überlegen, Datenrypsichfür diesenltückgabewert am besteneignet. AngenomDreD, Ihre lunktion licfcrt rür 0 odü I zuftick.$ielcherDxtenq.puürde dso .idr Dcr sichdnfür anbieten? Natürlichder mit dem kleinstenwertebereicli, danDetrvaso aussehen: F-unktiooskopfvürde t:
c h a rw a h f 0 d e r F a l s c h o
Wasb€deutetabernun der DateDtp /otd,wie er sichim Eingangsbcispiel findet? Daswort 'otd ddckt so vi.j auswic ,,Lccre"oder,,nichts".Und genaudaswoilen wir dort ja rüch: kcinenRückgabewert. UnsereFunkion ausdem Beispielschaltet aus, lediglichden Pon B aufeinenneueDZustand.wir RihrenkeincBcrechnungen und wenn wir dicscFunktionaufrufen,erwartenwir auchkein llrgebnis(abgese henvon der 7.üstandsänderuDs). wlchtig: Wcnn Ihre Furktion also gar keinen Rlickgabeivertliefert, Düssen Sie trotzderndieBezeichrurgro;d angebcn.
undFunktionen 727 4.4 Anweisungen Z-urrickzum Beispiel Dort folgt mit tudojf0 eine weitere,sehr ähnliche Funktion Richtig zur Sachegeht cs dann im Hauptprogramm Dort fiDden Sie den eigeDt lichen ,,Auäuf' von den beideDzuvor definierten Funktionen. Un1 eine lunktiotl vorl zu starten,gehenSieDachfolgendemSchema IUNKTJONSNAME( OPTIONAL:PARAMETER )i DenAufrufeinerFunktionnenntman aucheineAtrwen"rg Siefindenzweidieser den Funltionenhier keine in den Zeilen17 und 18.wir übergeben ArweisunseD Parametcrund erwarten au.h keinen Rücksabewert.Das folgendeBeispielveran schaulichtDun die VcrwendungeinesRü.kgäbewertes: i .h > : L : # i n c l u d e< a v r / o 2: 3 . c h d rq e t P o f t B Vuael() O D R=Bo x 0 0 ;/ / P o r t I a r s E i n q a r sg c h a l t e n
5:
o'NB; o: "'. 7: ) 8: v o i d s e t P o r t B V a l u e ( c hnaer v v a l u e ) 9: 10r { D D R E : 0 x F F /i / P o f t B a l s A u s g a n sgc h a l t e n 11: '
!r,o
P0P|B
Le,
13r ] 16: { ll: 18:
charled stdtus=0; - 0 rl I oo' B d. DDoB
.J.ga a
0: l:
9 " - o o . t B \ ou e I "a_. o u u : "d ö D o ". _ B V ,oö " 4 d or .,r;
a:
"L
0i
DiesesBeispielist schon etwas anspru.hsvoler' Z€rlegenwir €s in seine BestandEs gibt ä\'ei Funktionen: geQartBvalue) Iiefefi Ihnen den aktuelen Zustand an Port B als Rü&gabewert zurrick. Die Funktion serPorfBvalr€a) erlaubt es Ihnen, Poft B einen neuen wert zuzuweisen. Drei wichtige Grundlagensind: L Die Definition von FunktioDen, die Parmeter erwarten ünd einen Rückgabewert liefern.
722
inc 4 Eine Einfuhrung
2. DasZ'rischenspeicherndesRr.ickgabewertes in eineHilfsvadable. 3. Der Aufrufvon lunktionen (nit ParaDeterübergabe und Rückgabewert). ln Zeile 3 beginnt die Funkriol' getPortBv ue) lnd sie erkennensofort Es wird nicht roid alsRückgabewe(ve|wendet,sonderDc/ral.Dasbedeutet,die !'unktion mrss titsäc}lichcincnWcrt zurüclgeben. Diespassiertdirekth Zeile6. Dazuver wendenwir die Anweisung/et /fl. Nach dem ScNüssehvortretrff könncn Sic auf verschiedene WeiseeinenWert zurückgebeD. Daskönntez. B. soaussehen:
3: 4r 5:
f e t u r n( 1 + 1 + 2 + 3 ) ; r e t u r n1 2 8i r e t u r i r e d _ s t a t u s/ ;/ l ' . J e lnend _ s t a t ues i n €c h a rV a f i a b l €i s t
ls gibt alsoeinigeMöglichkeiten, um auseinerFunktioneinenWert zurückzulie jedoch fern. Hierbei ist es wichtig, einigewesentlichePunktezu beächten: 1. NachdemSie die Aiweisung /etul, \erwenden,wird kenr weiterer Code in der Funktionmehl ausgetuhrtund die lunklion sofortbecndct.Sic l(önncnsomit enreFunktionauch abbrechen. "vorzeitig" 2. Der in Zeile 6 ( dcn vers.hiedenen rct,|, Beispielenoberhalb)aDgefiihrte parameterlose Aufruf wird nur in Funktioncnakzeptiert, die keinenRückgabcyoid (also wert ablieferDmüssen Funktionensind).Dieswnd in solchenFunk tionen xussctrließlichals ,orzeingerAbbntch vctwcndet ünd nacht nur Sinn in VerbinduDsmit KoDtrollabäagen wie z. B. der Ii/!ZST Abfrage.Mehr dazu 3. Der Datentypder Daten,dieSiexlsParaneterfü dieAnweisungretur, verwenden,mussdemRückgabewert Datentp entsprechen. Siekönnenalsoz. B. nicht eineZahlwie ,,123456532" bei einemRückgabc-Datcntp clrr übergeben. Zurück 7xm Beispiel.In Zeile 20 6nden Sie den Aufruf der Funldon getPorrt ydlr.O. Diesmal findet sich atcr dic Vaiablc led_staflr noch vor .lem lu*tionsnamen.Um nr enrerVariablenejnenneuenWert zu speichern, müssenSiediesen Wert,,zurveisen". Dis funktioniertfolgenderrnäßen: VARIÄBLENNAME= NEUERWERT j Wobei der ,,neueWert" natürlich selbsteine Variableoder Sar enrekoDplexe Berechnung seinkann.Der Compilersetztdannautomatisch denberechneten Wert oderdenInhaltder angegebenenVariable als,,neuen wert" ein.Außerdemkannder Wert" auchdasResultateiner Funktion sein.Und genaudieseÄrt der Zuwei"neue sungver\eenden wir bcim Aufmf in Zeile20.Der Compilerliihrt zuerstdie lunk
4.4 Anweisungenund Funktionen
123
tlon getportBvalue) ars ünd setzt ansc ießend das Ergebnis dieser Funltion (Rückgäbewert) als neuenWert ein. Dieserneuewert wild in unseremBeispiel wird iD Zeile2I der danndirektin derVarjableled Jtatri gespcichert.Anscbließend Wert von led ifatus um eineEhheit erhöht. wieder iDteressantwird esin Zeile 22. Hier sehenSie den Aufrlrf der Funktion setjedocherwanet die PorrBvdl"ea).ln diesemFall erwartenwir keinenRückgabewert, DateDtp .rar Dieser Parameter muss voDr Iunktion enren Ubergabeparameter. (Zeile (siehe 9) wurdeim Klammer sein Zeile9). In der DefiDitioDder Funktion ausdruckdie Variäble.idl ,1€r,,val. definiert. DieseVariablestehtder lunktion zur Ve#ügrurgund cnthält den urert, der beim Au&uf übergebenwurdc. Hi€r einige Beispielel 1: ?r 3: 4,
s e t P o r t B Vu ae r(t 0 ) | s e t P o r t B Vu ae l{0 x F F ) ; s e t P o . t B V a l1ü9e+( 2) 9 ; / sl )e;d s t a t u si s t e i i r eV a r i a b r e s € t P o f t B V a l u e ( r e d - s t a t/ u
Auch wenn die aufgerdcne Furktion keine Parametererwartet, müssenSie auf jedenFaI immerdiebeidenKlamrnenr,,("uDd,,)"anseben: 1:
i r q e r d enie F u n kotni () i
enthält einen bestimmtenWert (Ein Die Vrriable bd sfatrr irn Ausgangsbeispiel gangswertvon Port B un einc Einheit erhöho. Dieserwird dc lunktiolr übergeben.Der Compilerspringtdann auf Zeile9 urd setztdiescnfßergabewertin die lokaleVariableaerwafur ein. Im weiterenVerläufdieserlunktion (Zeile 12) kann dieselokäleVariablc(nur ,,sichtbar" ncrhalbder Funktion)verwendetiverden.In unsercmBeispielwird derwert derVariableauf denPortB geschricbcn. wichtig: Sie benötigen in dieser Funition kein rctur4 da die FuDktion keinen e rartet.Die Funktion,,1äuftenrfachaus" ünd spingt dann Rückgabeparimeter Juromdri',ih dn denUr\prungl./erle221/ur-c' nusbei einerÜbergabe von mehrerenParamet€m wie würdedasBeispielszeDado sehen? l: 2: 3: 5:
# i f c l u d e < a v f / io . h > i n t a d d i e r e { i n ta , 1 n t b ) return a+b;
4 EineEinführung in C
724
9.
r0:
= DDRB P O R T=B
l1: 12. l3:
ln Zeile 3 finden Sie den entscheidendenSchritt da?x. Im Funltionskopf werden mehrereVariablen einfach mit einem ßeisüich voneinandergetrennt. Sie können hier eine ganzeReihevon Vaiablen überseben.Achten Siejedoch darauf Für jede Variable.die von der Funlrtion €rwartet wird, müssenSie beim Aufruf äuch einen wert übergeben(sieheZeile I t ). Im oben angeführtenDeispielwird schlussendlich der Wert Dezr20 auf Port B ausgegeben.
.her |
additionl.h;. .
., .har.ir) 2 . ' . ..
I 3
inr I,'
laan llcidl
.
Y - additioal5,:ii)
I
I
Abb.4.3:Ubersabe vonFunktionspa-
4.5 Abfragen undSchleifen in diesemKäpitel lernen Siezwei wichtige Technikender Programmierungkennenl Entscheidungenund Scl eifen. Diesewerden Ihnen €ine Fülle von Möglichkeiten eröfüen und einen weiteren großen Vo eil von C gegenüberAssemblerdeudich
4.5.1 lf-Abfrage Um einen Äusdruck auszuwertenund je nach ErgebnisweitereSchitte zu setzen, verwendetman in C die Anweisung4 Grundsätzlichist dieseAnweisungrehliv beschränkt,denn Sie erlaubt nur die Unterscheidung,ob ein Ausdiuck '/a,?r oder
4.5 Abfrogen undSchleifen 725 Erstesßeispiel: l:
# i n c l u d e< a v r / io . h >
3r
int maiYr{void)
5: 6:
D O R=B 0 x 0 0 i / / P o f t B a u f E i n q d n ss c h a l t e n = O X F F /i / P o r t A a u f A u s g a n sqc h a l t e n D0RA
8r
i f ( P I N B= = 0 x F F )
10: 11r 121 13:
]
= oxAA; PoRTA .eturf 0;
Port B wird auf Eingang geschaltet,Port A aufAusgang. Anschließendwnd über pdft, 01, der aktuelle Wert aD Port B der Zill Heri II entspricht. Trifft dies zu, wird artf Port A dcr Wert Ha* 1,4 xusgegeben, ansonsten nicht. In Zeile 8 finden Sie unsereErweiterung.Es handelt sich um eine sogennnnteIfAbfrage. ln der darauf folsenderl Klammer (in Zcile 8) sehen Sie den zu überprüfenden Ausdruck. aftr oder /.4lsrfi ist. Genau Die i/-Ärfrdg? kann nur überprlifen, ob eh Ausdn& gerade der Wert orF passiert lier. Die Abfragc überprüft, ob an PIN3 das auch anliegt.Entscheidendhier ist das doppelte Gleichheitszeichen(==). Es signalisiert keine Zuweisuns(wie das normäle Gleichheitszeiclenin C, =), sondern eine Uber pdfung: ,,Ist der erste Ausdruck gleich dem Zweiten?" Solte dieser Ausdruck wjhr sein,wird der PrograDmblock darunter ausgefühn.DieserB1o& reicht von Zeile 9 bis Zeile 11 und ist durch die geschwungenen Kammern und,,}" gekennzeich"{" Block üb€rsprungen. net. ht der Äusdruck nicht wahr, wjrd dieser Somir haben Sie einen bestimDten Progränmteil, der,,auf Bedingungen"reagiert.Würde an Port B eine Taste odcl ein Knopf geschaitet sein, könnte man danit nun äuf ehe ZustandsänderungreagiereD.Ist die Tastegeddckt, wird ein spczieler Programmblock aüsgefiihrt, ist die Taste nichi gedrückt, wird dieser Abschnitt übersprungen. Auch dar Gegenteil der Gleichheitsptnfungisr rll,öglich, die PrLifung auf U"gl€tchret. 1r l,
# i n c l u d e< a v r / io . h > rt
.d r (vo d)
5: 6l
= 0 x 0 0 ; / / P o f t B a u f E i n s a n 9s c h a l t € n DoRB = D x F F ,/ / P a . t A a u f A u s g a n sgc h a l t € n DoRA
8: 9:
i f ( P I N Bl = o x F F ) {
4 EineEinfiihrung in c
726
= OxAAi P0RTA
lO: tl: 14: l':
p0Pta 0,00: ]
I : t8:
" -
0:
In diesemProsrammsehenSiezum einendie angeknndigte UngleichheitEtüfung (Zeile 8) tllld zum anderen eine neue Anweisuns, nämlich die elseADweisung (Zeile 12). ln Zeile 8 wnd nun also überprüft, ob der aktucle wert an Port B nicht HercIF entspricht.Das kann bei allen Werten von ,xt0 bis 0rFf der }.all sein.Die else-Anweisungerlaubt es Ihnen, eiren speziellenProgrämmblockzu definielen, der nur dann ausgetuhrtwnd, wenn die l/'Abfrage nicht ,,wahr" oder,,nicht elfildlt" ist. In unseremFall würde däsbedeuten:Ist der Wert aDPort B nicht oirFÄwird der Programmblock von Zeile 13 bis Zeile 15 ausgefühn, nicht jedochder Blockvon Zeile 9 bis Zeile 11. Würde, im ümgekehrtenFall, an Port B der Wert orFI anliegen, würde der ersteProgrammblockausgefühn(weil der Ausdruck ist), de1^leite "aftr iedochübersprunseD. Wir könDendieseTechniknoch um eine letzteMöglichkeit erweitern: 1r
* i n c l u d e < a v r l lo . h >
1:
1.
, or o /
5: 6:
D D R =B 0 x 0 0 ; / / P o f t B a u f E i n g a n gs c h a l t e n D D R =A 0 x F F t/ / P o f t A a u f A u s g a n sgc h a l t e n
8:
i
\D.\B - O,DOD-I 0,--:
L0: l2:
e l s e i f ( P I N B= = 0 x 0 0 )
d.
D o D0 - 0 . 0 0 .
'61 1: .8:
?,.: ,a' l': l
el.e t
| ( P I N B- ' 0 ^ 0 5 ) D 0 0 - .- 0 / r 0 .
D o oÄ : o . t ; .e '' n o;
undschleifen 727 4.5 Abfrogen In diesemBeispiclbcfindcl sich eine Els.-{-Anweisung in Zeile 12.Siekönnen auf dieseWeisemehrereAusdrückeüberpdfen, dabei kann jedoch nur ein eitlziger 1valrrsein.Altennti\-dazu könnten Sic natürlich au.h cinzclneIf-Abfragenvenrendcn. Dicswürdejedochunter UmständenmehrereLösungenergebenund somit mehrereProgrammblocke austuhren. Im oben angeftlhrtenBeispielbekomDt Port A ehen bestimmtenweit zugewiesen, je nnchdemwel.hd wcrt an Poi B geradeanliegt.Trifft keineder Bedingungel zu, in Zeile22,alsodeDrelseBlock,ausseftihrt. wnd der Programmcode NatürlichkaDnin einem4Programnblock auch eine weiterellAbfrage liegen. Daskönntedannso ausschenl r:
1.\ts--'
==0x50) lf (PIND
3: 5, 6: 7:
/
j
P 0 R T=B0 x 0 0 i
)
In diesem FaI reürde Zeile 5 nur dann erreicht werden, wenn an Port B und Port D je eils den Wert H€'Ij 50 anliest.
4.5.2 switch-Abfrage Die {-Abfrage ist ein brauchbaresHjlfsmittel bei der f,Dtwickluns nr@raktiver ApplikatioDen. Ein kleiner NachteildieserAbfingemncht sich dann bemerkbär, wenneincchzigcVarhbleauf verschiedene werte gepdft werdensoll. Nchmer {'ir an, sie verwendenin Ihrer AnwendungeinenDrehschalte6der 20 ver wert än Port schiedene Zus6ndeerlaubt.Ie nachZustaDdliegrein entsprechender B an. Die Ablinge dieserZuständewürde ein unübcrsichtlichesIf-tlse-Konstrukt bcnöligen. Art \-onAl,/rase, nämlichderrurch-Abhage DieslässrsichabermiteiDerahnlicheD 1i 2: 3:
# i n c l u d e< a v r l io - h > int main(void)
5: 6:
D D R =B 0 1 0 0 r/ / P o f t B a u f t i n g a i g s c h a l t e n D D R =A A t l l j / / P o r l A a u f A u s g a f Ss c h a l t e n
8:
sritch (PINB)
724
4 EineEinführungin C
I l0: 11: 12, 13: 141 1 5| 16: 17: 18r t9: 20. 21. 22:
c a s e0 x 0 0 : P O R T=A 0 x F Fi breaki c a s e0 x 0 i : = OXAA; P0RTA b r e ak ; c a s e0 x 0 2 : P O R T=A 0 1 5 5 ; c a s e0 x 0 3 . P O R T=A 0 x 8 8 i D r e d( ;
?5: 261 271 2Al 29: 30: 31r ]
= 0x00; P0RTA break; )
Vor dlen1fit State-Machines istdieses'dtc, Abl;agesehrhilfiei.h.Stnte-Machines Art wobei die Softwarevon beschreiben eine besondere der Progrämmierung, j€der ZustaDdeineeigene einemZustandin cinenanderenZustandwechseltund Aufgabeäusführt. In Zeile 8 befindet sich der Start der Anweisung.In den runden Klalnmern, die nach dem Schlüsselworti'rit /r folgen, findet sich immer die zu überyrüfende Variablc(bzw.ein Port).Wn wo en denaktuellenZustandvon PortB näherunterMöglichkeiten(eng.:cases), die auf den suchen.Fernergibt es dann verschiedene Zustxndvon Port B zutreffen. In ursereDFa pdfen wir Port B auf die Werter0, l, 2 und 3. Soilte an Port B der Wert 0x02 anliegen, springt die srvr'rclr-Abfragcdirekt zi1 Zeile 18. Dort wird l,reat ist Das anschließende anscbließe'dder wert 0x5s auf Port A geschrieben. hier bcsondcrswichtig. Brealbedeutet,,Abbruch", und genaudaswollenwir hier auch.Wn habenunseren wert gefundenund wollel, dassder Controller die i]berprüfung abbricht. Würde Dan dasr'eak nicht verwenden,würde d€r ganzeCode,der diesemcaseDochfolgt, tpischen Eigenheiten der nutomatisch ausgetuhrt. Diesist einederwenigen,jedoch Sprache C.
4.5 Abftugen undSchleifen 729 Daher: Das Schlüsselwort,/eaft bricht an der aktuellen SteIe die weitereAusfti}lrung der Ab&agenb und kehn rurn Pfogamm zudck. wird dieses,rea& nicht am Ende einesjeden cdseverw€ndet,werden bei einer Ubereinstimmungmit einem Ab&agewertauch alle anderenAbfragen als erkannt und der komplette, "richtig" noch folgendeCodeausgeftihrt. Würde in unseremB€ispieloben kein €inzigesü/eaftvorhandensein und an Port B dei Wert 0x00anliegen, würdennacheinarder die Zeilen11,15,19,23und 27 ausgetuhn werden. Das ist sicherlich nicht erwünscht,daher soilte lnan niemals das In Zeite26 findet sich mit der& lf nbernoch ein weiteresS.hlüsselwort.NehmeDwir an,Port B trüge denWert 0x20.DanDwürde keine der oben mgefühfien .dre-Möglichkeiten zutieffen. Genau darum kümDert sich das Schlitsselwortlelaah Es bedeutelin ersterLinie: wenn wirklich keineder Möglichkeitenzutrifll, mach "Nur ro[endes ..." Sobaldeine Möslichkeit isl wird dasdelarlr auch schonver"wahr" worfen. Wäre der Wert im Beispielan Port B also 0x20,würden wir än Polt A den Wert 0x00ausgeben. Diesetut der Abftagesiehtbei einer Reihevon Anwendungendoch etwasübersicht licher aus als e:-l]ereil.e lf-Abfrage.Es sei jedoch angemerkt,dassman eigendich immer äucheinenormale4/tbe Abftagestatteinerslrtfc, Abfrageverwendenkann. Siehabenzu diesemZeitpunkt bereitsdie wichtigstenMethoden der Softwareent wicklung in C kennengelernt.Das Einzige,was lhnen zur erfolgreichenBntwicklung noch fehlt, sind Scl eifen.
4.5.3white-Schteife Eine Schleifeist, w;e der Name schon erahnenlasst, etreäs,wäs sich ,,im Kreis" bewegt.Gennu diese Eigenschaftwird Ihnen bei Ihren Programmeneine große Hiife sein.Was,denkenSie,passiert,nachdemIhr Programm zrr Ende ist, also die Ielutc ZeUe\on nah) eueicht mrde? Darauf gibt es wahrschen ich keine hun dertprozentigrichrigeAntwort. Denn je nach Compiler und Einste ungenwird Ihr Programm sich anschließendentweder aufhängen,neu starten oder vellücke, .nl'".ri--r"
ni"."
i"-
Der Programmcod€wird im Flash des Mikrocontrollers gespeicheit.wenn näch IhremProgranmcode nochZeichenim Speicher liegen(all€saußer0x00),wird der Controler dies als Maschinencodezu interyretielen versuchen.Das kann zu uer wünschtenResultatenführen. Normalerweisehangt sich der Controler aber auf und benötigt anscNießendeinenReset.
in C 4 EineEinführung
130
Die säDgigste Anwendungeiner Sc7'b,t beginnt bereir' hier. DasProsramm könnte sich z. B. immer wiederholen.Es sibt hierbei zwei Möglichleiten, wie Sielhre Soft wareentwickelnkönnen: -
sequentielleAusführ!ng
L,ry:Evc l l> f "".,p,"hb.tr" r t_.
Abb.4.4:Programmablauf
2:
{ 5: 6:
D D R =B 0 x F F i llhile (l)
{ 8: 9l l0: 11: ),2:
= 0x00i PORTB = 0xFF; PORTB
Die neueFunktion trägl den Namenü/lil€, as so viel bedeutetwie ,während". Urn genauerzu sein:,,während der Ausdruckin der Klämmer wahr ist, führe den untergeordnetenProgrammblockaus". ln C (und generellin warum habenwir dann eine I in die Ioammer geschrieben? der Softwäreentwicklung)cntsprechen0 und ale negativenZahlen alrtomatisch den Zustand,,nicht wahr",oder,,falsch". Zahlenwie die I und darüberentsprechen dann dem Zustand,,wahr".In unseremFrll würde dnsbedeuten,dassdie Klammer bedhgung nnmer,,wahr" ist (weil sich die i dori nicht mehr verändert).Dasmacht durchausSinn, denn das ist genauunser Anliegenrbedingungslosewiederholung Der Controller wird desProgranmblocks.Man nennt dies auch eine-El,dlosscÄld/e. - zumhdestsolange in diesemBeispielausder Schleife nicht nehr herauskommen nicht, bis Sieihm einen Rcsetgenebmigen.
4,5 Abfrcgen undschleifen 737 Un sicherzugehen, dasssich lhr Progranmnach der Ausführungnicht in einen unbestimmtenZustandbegibt, empfieblt essich auch,diese,n,llosr.l,lefe am Ende jedes Programmszu verwenden.Vor allem natürlich bei solchen,die nur einen bei dener der DurcNauf pro Resetbe,rötigen(Beispiel:Einschaltmechanismen, eingeschaltetwird und dann eine Mikocontroller mit enrerSpannüngsversorgung kurzeRoutincausführt,um anscliießend ,,nichttmehr"zu tun). Auch bcim TestenIhrer Soliware wird sich diesc ScHeifenmethodikals hillieich erweisen.SieköDnendasGanzeauch in eher Hdrg llp AnweisuDs(in dieserZeite bleibt der Controler sicherbis zum Resethängen)zusaamcnfässenl : 3
,Lde a1'
"
o.h
1 1 1 o : n r .o d '
5: 6r
D D R A- O x F F i / / D D R B= 0 x F F ; / /
8: 9r 0: 11: lzt
DOPB-000: = 0rA3; // P0RTA bOD-B 0 : Rhile(1); //
): \4:
r e t u r n0 ;
P o r t A d u f A u s s a f gs c h a l t e n P o r t I a u f A L r s q a i qs c h a l t e n
B e i s p i e l . E i n s c h a l t c o d es c h i c k e n
Endlosschleife: Hang-rp
Erreichtder Mikrccontroller Zeile 12,wird er sich dort bis zum nächstenResetf€sthängen.Ailes darunter(nr unseremFallnur /etulfl 0)wird niemalsausgetuhrt. Die ttrile-Schleife ist aber eigentii.h fiir höhere AufgabenbestimDrt.Das könnte
1;
2: )
e
!
udö
o.'
o.L
r 'a.' ,oidl
5: 6:
D D R =A 0 x 0 0 ; / / P o f t a ( = T a s t e )a u f E i n q a n !s c h a l t e n D D R =B 0 x F F i/ / P o r t B a u f A u s g a n sqc h a l t e r
8.
rh t" /pl!d:
t0. 1t: t2r 13: 14:
D O P - .B 0 1 Ä d ,
0.00) j
while(1)i // tirdlosschlejfeH r a n su p r" u
0i
732
4 EineEinführung in C
Die Magie passierthier in Zeile 8. Im WesentlicheD bedeutetdieseAnweisung an Port A nicht der Wert He* 00 anliegt, warte in einer Schleifeund ,,Solange machenichts': Nehmen wir an, es liegt plötzlich der Wert He,. 00 an Port A an (Beispiel; ist sonlit eineTaste,die alle8 Bit äuf.] schiltet).Die Schleifenbedingrüg nicht mehr erfü]lt und der Controller springl weiter zul nnchstenAnweisungin jn dieEndlosschleife Z,eile10.DasPrograDmläuft schlussendlich ab Zeile12. Das ware bereits ein gutes Beispiel ft Interaktuität, basiereld auf extemen Zustandsänderunsen. cehenreir einenschrittweirer: 1:
# i i c l u d e < a vn / i o . l r >
3: 5: 6:
c l d r a - 0 1 / / Z ä h l v a r i a b l ea n i t 0 l n i t i a l i s i e r e n D D R =A 0 x r l 0 i/ / P 0 r t A ( = T a s t e )i r u f E i n g a n !s c h a l t e n = 0 x F F t / / P o r t B a u f A u s g a n gs c h d t e n DDRB ! h i l e { P I N A! = 0 x 0 0 )
t0: 11. 12. l3: t5: 16: Ll: 18:
P o R T =B a ; ] l , \ j h i l e ( 1i )/ / E n d l o s s c h l e i f el rl a n g - u p
Der Ken diesesBeispiels findet sich in den Zejten9 bis 13.wir veNcndcncine Variablea vom Typ crar (wertebereichr 0 bis 25s,8 Bit). Die wrtle-Schleife hat als Bednrgung, dassder ZustandaD Port A nicht Her ,0 anDimmt(wir gehen,lso davonaus,dassdcr Zustandzu BeginnHe* -FI ist).ln der Scileifeselbstwird der wert von d immer um eineEinheiterhoht und anschließend der neue\{ert auf Port B geschriebeD. $ienn wir davon ausgehen,dässan Pofl A eine Tasteoder ein Schalterliegt, dcr zu Beginn den Zustand Her,i:FF besitzt, würde bis zu einem ]ästendruck (also einer ArderungvonPortA) ständigeineZahlenreihe an Port B ausgegeben werden. im Simulatorverfolgen. Waswird passieren, SiekönnendiesesBeispielanschaulich wenn die Vadablea den wert 255crreicht?Siewird bei dcr nächstcnErhöhungwieder bei 0 beginnen.lvlannennt dieseinen Somitwürdeam Port eine "Uberlauf: Zahlenreihe, ähDlichdieserausgegebeü werdeD: 2, 3, 4, 5 ...253,2s4,255,0, 1,2, ,,r, 3,4......"
undschleifen 4.5 Abfragen
733
4.5.4 for-Schleife während die ltle-Schleifeeherals Es gibt noch eineweitereArt von SchleifeD. gedacht gilt ist, dicfor-schleife mehralseine,,2ählschleife': ,,Bedingurgsschleife" Die w,tle SchleifesolltenSieveNenden,weDnSieauf einebestimmteBcdingung wartenund nicht gcnar \rissen,,wann" daspxssieren wird, bzw.nachwie v;elen oft Dur.hläufcndieSclleifeendet.ßei der/or Schleife wissenSie(Dreist)seDau,wie die Schleifedurchlaufenwnd. Sieverwendene en Zähler,und wenn diesersein Zieleircichthat,wird dieSchleife beendet. Ein Bejspielzur/o/ Schleifel 1: 2:
+ i ' ' r c l u d<ea v f / io .h >
3:
int nain(void)
5: 6.
c h a r i = 0 ; / / Z ä l r l v a r i a b l ie m i t 0 i n i t i a l i s i e r e n D D R =B A \ F F , / / P a r t B a u f A u s q a n sqc l r a L t e n
8: 9. 10: 11: T2: 1:l:
f o f ( i = 0 ;i < 5 0i j + + ) { P O R T=B i ; J
15: 16r i
w h i l e ( 1 ) r / / t i d l o s s c l r l e i f e .H a r s - u p r e t uf n 0 i
l)i€ Anweisungh Zeile 8 sieht schon ein rvenigkomplcxü nus.Der Autuau einer forschlcifc: for (StdrtanNehxt1g;Belli gul1g;SchleifenatNe^ung) Sie erkennen die dieserAnw*uDs. Sie bestehtalso cigentlich aus "Dreifaltigkeit" dreieinzelnenBelehlen.Um gcnauzusein: zwei Befehlenund einerßedingung.Die Statta weisungw]ld nv ein einzigesMal ausgetuhrt,und mar äm Anfäng.In unscrem Beispiel wäre das i=0. Die Zähhaiable i wird initialisiert. Beim späteren Durchlaufdcr Sc}leifewird dieseArweisung nicht mehr berticksichtigt. Die ,Bed;,g,rs prüft Dit jedem Durchlatrf, ob dic Schleife noch rveiterlaufen dari In oben ingcführtcn Beispiellautet die Bedingung:,,Laufe,solangedie Zählvadable ; kleiner xls 50 ist". wenn die Variablet nuD also deDwert 50 annimmt, wird die SchleifeautomatischbeeDdet. kümmert sich im Beispiel um dic Dic letzte lnweisung, die Schleifenanweisung, Lrhohurg der Zählvariablcn.Dicsc A reisung wird mit jedem Schleifendurchlauf erneut aufgerufen.Mit der AnweisNrg t++ wird die Variablet also in jcdcr Runde run genau eine Einheit crhöht.
734
in C 4 EineEinführun?
jedochLiestder sroßeVorteildarin,dassdiese Dasklingt nun allesetwaskoDrplex, Art der Schleifeeigcntlich inmcr glcich ausschcnwird. wenn Sie einnul den Auf bau (wie oben)kennen,konren sie die schleifeimmer genauso verwerdenund Prognmnlblockund die SchleifenbedingunändernledislichdeDunterseordneten gen.DasErgebnisunscrcsBcispicls wärcdieAusgabe derZahlen0 bis49 auf Port a. D;.eLtkret ütanweisutlg lrird ersr nach dem ersten Durc|lauf ausgeführr.Somit trägtdie Variablei bein erstenDurchlaufnoch denwert 0. Auf Port B liegtnach der Schleife.ter wcrt.19an,jcdochrräg1dicVariablci denwert 50. Dn diej{,r-Schlcifc auchanderePtrrameter alsi++ akzeptiert, könnenSiez. B. auch prolrammieren. Dies könDteso aussehen: eineAbt\tärtsschbife 1:
f o f ( i = 1 0 0i j > = 0i i - ' ) P O R T-B i i
3:
hr dieseD Beispielbeginit die Variible i mit cincm wert \.on 100 und zäblt mit jcdcm Durc|lauf auf 0 herunter. 0 deshalb,rveil die Abfrageja lauter ,,ht i größer ak oder gleich 0?"
vonSchleifen 4.5.5 break- Abbrechen Die Anwcisungürrdt ermöglichtdensofortigen AbbruchdesaktuellenProgramm blocks.Ein solcherProgramnblockktinrte aucheineschleifesein.Hier zweiBcispielczum Abbruchvon Schleifen: 1: 3r 4: 5: 6:
7: 8: 9: 10:
f o f ( i = 0 . j < 2 5 5i j + + ) if (i==50) bredkl P O R T= B i: ] r , / h i l e( P I N B l = 0 t 0 0 )
I
j f ( P I N B = = 5bIr)e) a k ; P O R T= B0 x 5 5 ;
]
Diese beideü Beispieleerklärensi.h von selbst.Sie könncn also nach einer bcstinmten ^bfrage entscheiden,ob Sie die Schleifeschon abbrechen "r-orzeitig" wollen. (zwischenden Klxmmern wichrig: Eswnd ledigli.h der aktuelc Progrnmmblock ,,{" und,,}") libenprungen,nicht derkompletteCode.
4,6 Arroys 135
4.5 Arrays NehmenSieeiDmalän,Siewollenmit Ihrcl AnwendrngeineReihevon Messdaten cinlcscn.Siebenötigendailr s0 Messwerte, die auchwährenddesBetriebeszwi schengespeichert werdeDrnrissen.Eine Möglichkeitwtue es nun, 50 einzclnc Variablenzu deklirieren.Daswäreschrmühsäm.AusdiescmGrundbietetunsdie Programmiersprxche C einhervorrageo desKonzeptmit derBezeichDuDgAr/aF. Ein Array umfassteine,,Reihevon Variablen".SiekitDneDbestinmen,wie groß dieseReih€ist ünd von welchemDatcntypdie werte sind.AußerdemkönnenSie und lesenund auf einzelneEinträgein dieserReihezugreiGn,derenurert setzeD komplette A//a]' durchlnufen. Dazu ein Beispiel: auchdas # i n c lu d e < d ! r / i o . h > 2: 3: 5:
chaf wertel50l;
8: 9: l0| 11: 12: i3:
!ertel0l = 50i r e r t e l l l = 5 5i |ieftel2l = 0; c = tert€I0l + reftelll i !eftel2l = c;
l5:
In Zeilcs lindcn Siedie DeklarationeinersolchenReihe.Siedefinierenalsogarz gebenSic DateDq?und eiDeBezeichnung. Anschtießend normaldengewünschten iD eckigenKlammemdieÄnzabldcr ElemenleIhrer Reihean.ln unserem!'a11sind das50 Elemente. Zu BeginndesProgrammsenthaltendieseElementeDü unsinnige,alsoirgendwelche zu*illigenwerte.ErwärtenSicalsonic, dnsslhre Elemente denwcrl 0 häbcn- außerSiehabendassoveranlasst. wichtig: Dcr crstc Wcrt dieserReinebeflndet sich an der Stelle ,ertel0j und der letzrewert an der Stellewertelagl.SiewerdeDalsokein Glückhaben,den s0.wert mit rsrrI50l zu errei.hcn.DassoltenSiebeachten. Die Zä]rlunglreginntbei 0. Siehabenesbereitscrkannt: In urrrrcl2l findet sich natürlich der Wert i05.
736 4.6.1 Strings(Zeichenketten) Die wohl häufigsteAnwendungvon Ä//a/s ist die Zeichenkettebzw St/ir& Es gibt in C keinen eigenenD.tentp tur wörter, Tene, etc.",lediglich d€n Daten"Sätze, t}?.iar, der nur ein eiDzelnesZeichenfassenkann. Äus diesemGrund bildet man ein kftay lon charvaiablen, um einen ganzenSatz darzustellen.Um dasEndeeiner Zeichenlctte zu mükieren, gibr €s die sogenannte sting-Terninierung. Das Konzept ist eigentlich einfach: Der Controller hat keine Ahnuns, wie lang dnsAnal wirklich ist. wenn Sie es durchlaufen,müssenSie als Programmiererwissen,wann dasletzteElementerreicht ist. hher hät mln sich entschieden,das Endeeiner Zeichenk€ttemit einem "Nullzeichen" zu kennzeichnen.Das ist nichts anderesä]s ein Byre mit dem wert 0x00. Somit würde ein Strilg im Sp€icherimmer so aussehen: asctl
hallo
@@@@@@ 012345 Abb.4.5: AufbaueinerZeichenkelte
Es ist daher üblich, beim Duchlaufen einer Zeichenlctte iDmer auf dasNulz€icheDzu waiten, um dann die Sclieife abzubrechen.Und genauhier passiertoft der F€hleadasNuilzeichenzu vergessen. Somit läuft Ihre Schleifeweiter ünd weitel bis irgendwannendlich ein Nulzeichen im Speicherdaherkommt. Das kliDgt nach einer Lappatie,wurde Jedochzum großen V€rhängnistur viele Untemehmen und Privatanwender,als die Virusprogrammierer ulrd Hacker herausfanden,wie man dieseschwachstellefiir kdminelle zweckenutzen kann. so glei€hganzeMaschinencodeskopiert, \4.urdenin ve$chiedensteTexteingnbefelder die natürlich die Größe des empfangendenÄ/.4.14überschritten. Somit war der ,,bösartigeCode" im SpeicherdesAnwenders(oder deswebservers). einer Funldon überschrieben Mit dieser Technik wurde die Rücksprungadresse urd die CPU fillrte beim scheinbarnormalen Rücksprungins Hauptprogramm plötzlich den bösartigenProgrammcodeäus.Auch die SpracheC ist nicht perfekt. Selbsteinemguten Programmiererkönnen dies€Fehlerimmer wieder passiereD. Züü.k zu den Strhgs. Nehmenwh an,wir habenein€ Funktion 1s232-lfltre3t fe, die ein Zeichenauf die serielleSchnittstelieausgibt.Dann könnte di€ V€rwendung einer Zeichenkettez. B. so aussehen:
4.6 Atroys 137
1: ?. 3l
char satz|2561i
s a t z l 0 l= satzlll s a t z t 2 l= s a t z t 3 l= s a t z t 4 l=
5: 8:
'H' 'a' I' 'l' 'o'
sat2I5l:0x00; 10: 11: 12. t3:
for {i:0' satzijl r- 0; i++) { R S 2 3 2l , l f jt e B r t € ( s a t zl i I ) i ]
Siehabenesbereitserraten:Auf demTerminalwürdedaswort,,Hal1o"erschenren. wenn Sie die abschließendeNu in Zeile 9 nicht setzenwürden, würde Ihr Pro ngendwann im Speicher gümn sichentwcderaufhlingen oderdannstoppeD,wenn AlrchweDnmnndiesleichtvcrmutenmag:Der Controllerweiß eineNull erscheint. bei einerfehiendenNull nicht, dassbei satz[s]Schlussbt. Ebensoweiß er nicht, dasser spätestens bei satz[255]aufllörensollte.Er $'eißgrr nichts.Somitläuft er s,trzl2s7], satz[258]usw aus. weiterund gibt deDInhaltvon sätz[2s61, Da lhr Aral irgendwoim Speicherliegt,liestder Compilerbei satz[2s6]einfäch das,wis ils Nächstcs im Speicher steht.ReinesChaos. fest,Nanngcnauder string zu Ende LcgenSiedaherentwederschonin derSchleife ist (in unseremFallnnch5 Zeichen)- oderachtenSieimmer auf die abschließende Null. wüfde män nun zum Iormulieren eines ganzen Satzesfür jedes Zeichcn eine dnssehrünständlichund würdekeinenSinnmacheD. eigeneZeilebenötigeD,Näre Als Abhlfe gibt es hier die StringFunktjone . Um dieselunktioDen benützenzu können,müssenSie die Bibliotheksrri'Tl einbinden.Damit erleichtertsich die Behandlungvon Zeichenketten erheblich: i .r .d. . o,'
t.
,
: t:
'4r.dö
a: 6: -:
8. 6:
'_'ci
:o.h.
ri'9h \.oa h. hd'
,rzt25_ i ii
-.'e. 'qr'.
rello I'o lo'\:
138
4 rineFinführung in C
Ltr
ro_ i 0: ,ar' i
13: la:
l
b: 17:
:- 0: a
Rs232_l,iri teByte(satzli I ); "r .
0j
]
Die tunktion trcp), kopiert eineZeichenkettein unserArr4,. DasNullzeichenw;d däbeiautomätischnDgehängt.Hier eine ldeineAuflisrung der wichtigstenFunktionendersfirg.h Bibliothekmit denentsprechenden ParameterDl Funktionsname
ErH?üung
strcpy(dest,sour€e)
Kopiert eiDeZeichenketteGource)über eine andere(dest)
strot(dest,sour€€)
(source)an enreandere HängteineZeichenkette (dest)an. Zeichenkette
strlen(souce)
DiescFunldionhät eilen Rücksabewert. cibtdie LängeeinerZeicherlette(source)zurü& (ADzahlderZeichenbiszum Nullzeichen).
strncpy(dest,source,count)
Kopiert einebestimrnteAnzahl von Zeichen (count)von enrerZeichenkette (source)in eine ander€(dest)
strncat(dest,source,count)
Hüngt einebestimmteAnzahlvon Zeichen (coun, von einer Zeichenkette(source)än eine aDdereZeichenkette(desi) an.
Abschließend ein Beispielderverschiedenen Funktionen: .:
t: r: .:
d.n
.aF
n. lain\
t.
9.
\
o aJ
{
6: 7;
c h a r s a t zl t 2 55 I i charrontll40l
8: 9: 10:
.harwort2l4ol c h a rw o r t 3 l 4 o l c h ar j j
l1: t2.
s h c p y( r o n t 1 , " S o " ) l l
.p. Lo.
_ru Ltra
a'-
"1,
739
4.7 Bit-Operationen Im folgendenUnte*apitel lernen Siedie wahrscheinlichwichtigstn Methodender hardwarenahenSoftwareentwicHungkennen,die soge']^al:nten Bit-Operotionefi. Mit Bit-Operationen könnm Sie, wie das Wort sdrcn erklärt, im ,,Bit-Bereich" arbeiten. Der Datentp.rrr ist der kleinstezur V€rfijg!ng ,rehendeDarenty?und 8 Bit 8roß. Ein Port hat auch eineAalressierungsbreite \ion 8 Bit. \{ie abersollenSiez. B. den 3. Pin auf Port B schalt€n,wenn Sie nur 8-Bit-wert€ schr€ibenkonnen?Genaudazu benötigenSiedie Bit-Operationen.
4.7.1Altgemeines Di€-Grundr€chenart€n der Bh-Operationen_ sind: . . . .
ÄND-V€rknüptung (Opemtor: &) OR-verlnüptun8toperator ll XoR-Verknüpfung(Operator: ^) NoT-Operation(Op€rator:-)
Bei alen VerknüptungenhabenSiezwei Opemnd€nzurVe iigung und b€komm€n ansd ießendejn E Sebris. Di€ AND-V€rknüpturg arbeitet nach folgendem Satzr w€nn beide Bits den "Nur Wert I haben,ist dasErgebnisl, sonst0':
140 Die oR-Verknüpfung arbeitet so: ,,wenn einesder beiden Bits oder beide Bits den Wert I havhaben,so lautet dai ErgebnisI': Die xoR-Verhüpfung funltioniert so: wenn einesder beidenBits d€n We l "Nur trägt, dasandereaberden Wert 0 besitzt,ist dasErgebnisl, sonst0': Achtung: Die NoT-Operation benötigt nur ehen Operanden.Sie kehrt lediglich denWert selbstum, wandelt alsoale .l in 0 und umgekehrt. Beispielel 1&0=0 0&0=0 110-1 0 0=0 l^0=1 0^0=0 -1=0
letzt k€nn€nSiedie Grundtunlcionsweiseder Bit Operationen,wissenabel immer noch nicht, wie Sie,n der ddtten Pin von Port B heranlommen. Düer n:ih€m wir uns d€n Bit-Operationenim 8 Bit Bereichl Beispiele: . . . . . . . . .
= 00000001 0000111 I & 00000001 = 00000000 11110000 &00001111 = 00000000 11110000 &00000000 = rrr10000 0000000011110000 1 1 1 1 0 0 0000 0 0 1 1 1 11=1 1 1 1 1 1 1 1 1 1 1 0 0^0 0 0 0 0 1 1 = 1 1l l l l l l l l ^ 11110000 = 00000000 11110000 ,'11110000 = 00001111 = l0l0r0r0 "01010101
Das isr ein beträchdicherBit-Block. Nehmen Si€ sich die Zeit und überlegenSie, wie die Ergebnissein den Beispielenzustandegekommensindledes Bit wird mit einen Bit an derselbenStelle des anderenwertes gemäßBitOperation verknüpft. Um däs richtige Ergebnis zu bekommen, müssenSie also
4.7Bit-operotionen 747 ledigtich dic oben angetuhrten Bit OperationeDiir diese8-Bit-Wefie Bit tur Uit durchführen. Darnit ist noch immcr nicht geklärt,wie sich Pin 3, Port B verändemlässt.wir sind wir die obenangefiihrtenBeispiele, der Lösungaberschonsehrnahe.Analysieren lassensicb folsendeAussagentreffen: nm bcsten.Nur bei Bit zu setzen, eignetsichdie OR-Operatid, Un ein bestimmtes dieserOperationbleibenalle anderenBits unverändertund ejne 7xsätzlicheI bervirktdnsSetzeneinesßits.Hier die praltischeErklärung: . 0 0 0 0 1 1 l l0 0 1 0 0 0 = 0 00 0 1 0 1 1 1 1 Bezeichncn wir den erstenWert (00001I I l) ah Vaiableund dcn zweitenWert als Modifikator. Der Modifikator ist Ihr eigcntlichesWerkzeug.Mit diesemWert kdnnen Sie einzelneBits der Variablebeliebig ver:indern.in diesen Fall, bei Verwendungdcr OR-Verhüptung,könnenSiedie Bitssetzen. Um ein einzelncsBit zu löschen,bietet sich die ÄND Verlnüptung an. Außerdem wird hier noch die NOT Operationbenötigt.Dicscwird abernur auf denModifi Daswürde (nehmenwir an, wir wolleDdasdritte Bit löschen) kator angewandt. etwaso aussehenl anhandeinesBcispiels . . . . .
Wert:000011l1 (Wtuwolienßit 3löschen) Modilikator:00000100 -Modijikator: 1111101l I WeI1& (-Modi6kator)r 0000111 1 & I 111101 I = 0000101 Also:Bit 3 wurdegelöscht!
in C 4.7.2 Bit-Operationen h der Prl\is eirÜbung,um dieseßit OperationeD ns bedarfnatürlichgewisser fach und schnellanwendenzu könneD.Glücklicheiweisegibt cs i]l C hierfür eine praktische,,Äbkürzung": 1: 2: 3,
/ * H € t f e f m a k r o s* * * + + * * * * * * + + * + + * * + + / # d e f i n €s e t b i t ( P , B l T ) ( ( P ) = ( 1 < < ( B I T ) ) ) # d e f i n ec r e a r b i t l P , B t T )( ( P ) & = - ( 1 < < ( B I T ) ) )
5: 6:
s e t b i t ( P o R T B1,) i c l e a f b i t ( P 0 R T D4 ,) |
In Iiüheren Vcrsionen von AVLGCC gab es die Funktionen rüi und rrt, w.s so viel wie Ser lir und Cleal B;f bedeutet. Diese wurden aber vor kuuer Zeit nus der Bibliothek cntfcrnt. Damit Sie diesepraktischeDlunktionen dcnnoch verwenden
742
in C 4 EineEinführung
können, müssenSie dazu zwei kleine Makos definieren.Diesefinden Sie oben in deDZeilen2 und 3. SieköDnendiesebeidenZeilenin jedemIhrer Prosramnewiedcrvcrwenden.KopierenSiedie Zeilendazu direkt unter die #i,i.hdd-Anweisungen. Die Zeilen 5 und 6 demonstrierendie Anwendung.Der ersteParameterist der zu ver:inderndewert, der zweite Parameterist das 7.uveränderndeBit (begiDnend mit 0).
4.8 ISR:Interrupt-Service-Routine In dem nun folgendenAbschnitt flnden Sie Hinweise zur Programmierungvon sogenanntenInterrupt ServiceRoutinen. Diese Funldonen werden automatisch vom ProzessoräügeNfen, wenn die Interruptbenachichtigling eingeschrltetist und ein bestimmterInterrupt ausgelöst wird (BeispielEmpfangeinesZeichens überdie serielleSchnittstelle). SolcheineInterupt-Funktion kann in C etwäso aussehen: ' 3t r'
r l c r \ t ar
rFoo 0v
,p
1
/ / Z u s t a i d s ä n d e r u ' ragu f P o r t D ( e n t r e d e l D o DD : 00DDi0.
Sie merken: Diese Funldon sieht etwas ungewöhnlich aus. Es gil,t hier keinen Rückgabewert- auchkein ,oiA. Außerdemsind keinePärämetermöglich-Däs "Skelett" einer ISRsieht so aus: 'lL\Ä
_ \ T - o Dj P r \ I t
T0D
Dabei ändert sich lediglich die BezcichnungINTERRUPIyEKTOR, je nachdem, welchenlnterruptSieabfangen wollen.Auf Seite137sehenSieeineübersichtder wichtigsten Interrlrpts. Eine umf.ngreichere Liste finden Sie unter http://w.nongnu.org/avrlibctusermänud/group-nvr-interrupts.htnrl. (1. Spalte)velwenden.Diesewurde Siesolten auf alleFäIe die neueBezeichnung erstvor kur?€m(Seir avr libc 1.4.0)eingeftih(und wnd hngliistig die auslaufen den Bezeichnungenersctzen.Ein croßteil dcl im Internet vcrbreitcten Softwäre veruendetaberroch diealteBeT.eichnunsdahertuhrt dieseListebeideVariarten.
4.8 ISR:lnterrupt-SeNice'Routine
Vektor
Alte Bezeichnung
ADC_vcct SIG ADC ANA COMP vect SIG COMPARATOR ANALOG COMP_vcct SIG COMPARATOR INTo ve.l SIG INTIIRRUITo INTI vect SI(I_INTERRUITI INT2_rct SIG INTERRUPI2 INT3 vect SIG_INTERRUPT3 SIG SPI SPI,STC-vcct TMERo COMP vect SIG OUTPUT COMPAREo TIMER0 O\.F vect SIG_OVERFIOWo TIMER1-CAPT_Ve.I SIG INPUT CAITURI1 TIMERT OI.F vect SIG OVERFLOWI TIMER2 COMP-vect SIG OUTPUT COIIPÄRE2 TIMER2 OV! vect SIG O\rlREIOw2 SIG 2 \VIRE SERL{L T\\.1 vect SIG UÄRI RICV UART R{ vecr UART TX vect Src-UARI TRdNS SIG UAJTTDATA UART UDR!_vcci USAIT RX ved SIG USARI,RECU SlGUART-RECV SIG USÄI{T RDCV,SIG USART_RXCled UART-RE(]V SIG USART TtcANS,SIG USART-TXC vcct UART TRANS
143
Bescheibung ADcconvcßion Cohplete ^nalogComparator Aulog Conrparator lxtcmal hterrtrpt 0 lxtehal InterruptRequest l latenrallntcrrupt Requcst2 Externallnterrupt Request3 SerialTransfd ComPlete f imetclöunteroconp.reMatch Timetcounte Ove.flow T,m.r/Comrer CaptureEvent Tlmetcounterl Overilow Match Timer/CouDter2 Conrparc Tincr/Counter2 O\erflow 2 wire Süial Intcrfacc U R! Rx Cönplete UAm, Tr Comllete UARTData RegntcrEmp$, USART,td Complete USART,Rx Complcte USART,Ta ComPl.'tc
Achtüng: Nicht alle der oben angefr:ihrten Bezeichnungen geltcn für Jeden Control 1er.Diese Auswahl ist zwar aüf dcn mcisten -ATmegx8ähnlichen Varianten verfiig Datasheetbzw.der Dokumcnbar, cenauercstudcn Siejedoch im entsprechenden trtion Ihres C-Compilers. Die ,,neue Schreibweise" fiir eine Interrupt-lunktion und sieht nun so aus:
hat sich ebenfalh geäDde
] S R { I I i T [ R R U P T V E K )T O R { ] Es hat sich also lediglich das Wofi SIGNAI in die Bezeichnung IS.i'tgewaDdelt. Sie kennenhiermit nun beideVarianteDund werdenin der Praxisauchnoch eineWeile
744
in C.r"r' , '| :. r 4 Einib'Einfrihtüi|
.
.
', :- :r':
-.
Als letzten Schweryunl( möcht€ ich Ihnen noch einen wichtigen, wenn auch unvolständigen Einblick in di€,,Tiefen" der C-Prognmmierung geben.Siewerden die hier vorgestelten Methoden wahrscheinlich relativ oft in der praktischen Aawendungfinden, vor allem, wenn Sie sich den QuellcodeandererEntwickler z. B.im Inte et- ansehen.
4.9 Pointer(Zeiger) Die deutscheÜbersetzungfii| den Poirter tifft es eigendichsehr klar: Es handelt sich um €inen Zeiger,alsoetwas,wasuns auf einen anderenOrt hinweist. Angebot an Datent)?en. Sie Die Programmi€rspracheC bietet ein überschaubares können normsle ZaNen, Buchstabenund Fließkommawertespeichern. Bei einer Vadablehndelt essich dabei um einen reserviertenBereichim Speicher. le na€h DatengrößeIhrer Variablebenötiger Sie eine gewisseAnzahl an Speicherplätzen (gemessenh B)'te). Demnach bekommt also auch jede Variable eine bestimmte Speichem&esse, an der sie dre Daten im SRAÄ.{abspeichert.Hier eine graischeVeranschaulichung: SRAI\{
f
ü,t-''''-lT.r;;-lF--''''-l
t .n";lFr.I
Abb.4.6:Väriablen in SRAIVI Nun existiertabernoch eine weitereArt von Variable,näniich die bereitsangekündigte ZeigeNariabl€(eng.rPointer). Der Sinn dieserVariablenbestehtin der Spei cherungvon Adressen.sie merkt sich also,wo andereVadablenim Speicherplatziert sind. Siemerkt sich äuch,welcherDatentt? sich an eirer bestimmtenAdresse be6ndet.Sobenötigt €in crdr etwänur I B)'te im Speicher,w:iiretrd ein tuf schon2 Bltes belegt.Aus diesemcrund hat man sich fü eine einfacheund doch logische Bezeichnungentschied€n: . char*ptl; . inr* b! . double.d; Der Sternbedeutetimmer Zerger.Von welchemT]" dieserZeiger ist (bZw.,,...welchen Datent,? die Variableb€sitzt,auf die di€serZ€iger deutet"), sehenSie direkt davor.Sozeigl z. B. ein€ chdrt Variableauf einen I B)4ectar-wert.
(zeiger) 745 4.9 Pointet DäsfolgendeBeispielbrin$ Ihncn die t\nktionsweise von Pointernetwasnütrer: l: 2:
#i nclüde
I
5: 6: 8: 10. 1l: T2: 131 t5: 16: 17: 18: l9:
i = 5i p = 10; j - o; *k = 15;
Nun lautet die vermeintliche Fangfragenätürlich: ,,welchen wert enthalten die Variableni ünd j am EDdedesProgramms?" Löse,rwb dasProblemnrch altbekanntemSchema,alsoZeile tur Zeile:In den Zei len s bis 8 6nden sie die Deklaration von je zweiVariablenuüd zwei Zeigen eines passendenTyps.Mit Zeile 10 bekommt die Variablei den erstenWert zugewiesen' naimlich5. ln Zeile 11 gebenlvir der Z€igervariableP den Wert l0 Zu diesemZeitpuDtt ,,?-eisl"die Variablenün auf den Speicherplarzan der AdresseI 0. Es1\ird auf ein Bite gezeigt.Eshandelt sich urn einenZeigerdesTypstfial, alsonü ein ßlte. In wnklichkeitsastunsdieseAktion 'renig,wn wissenJanicht,wäsan dieseroninöscnSpeicherst.:lle10zu finden ist. lnteressanterwird esin der folgendenZeile.In Zeile 12 wird der ZeigervariableP nun die Adr€sseder Väriablet zugewiescn.wenn Sievor einer VadäblendasÄnpursd,ld {ein kautuännisches,,Und'.,also &) anftihren,setd der Compilernicht den Inhalt der Variablean dieseSrelle'sonden die Dasist entscheidend. Adresse. an dersichdieVariable p zeigtnun alsoan die Speichentele, UnsereZeigervariable (Terminal,et ) zur Vertugüg t befindet.Würden wir eine Ausgabemöglichkeit derVariable,aüsgeben Speicherort haben,köDntemandengenauen Nochmehl passiertin Zeile13.Hier findenSiedenSternvor der ZeiseNariablen Dns ist nun die ümgekehrtelunktion dessen,waswk ebengesehcnhaben Es wird an dieserAdresse. sondcmder eingeset4, hier alsonichtdieAdresse "Wert"
746 Um rn aber an den Zidort zu g€langen,also an die Stelle,an die dies€Adresse z€igt,benötigenwir den Stem-Operator Hier ein einfacherVergleichl SehenSiesich den C,oileill Zeile I I und Zeile 13an. Ir beidenzeilen weis€nwt d€r Zeigervariablep einenwert zu. Der wesendicheUnt€rcchiedbest€htdarin, das, vrü in Zeile l1 die Ädresse,auf die 2 z€igt,verändern und in Zeile 13 an dieseAdresse gehenund denwert, der sich dort befindet,?indem.Hier eineGrafik: SRAM
f.h";lfö"i'l
Abb.4.7:Funktion €in€sPointers Die resdichenZ€ilen sollten nun ein Klnderspiel sern.Die richtige Antwort lautet also:t=8 ünd j= 15.was in p und & steht,wissenwir nichg eshandelt sich dabeija lediglich um ngendwelcheAdressenim Speicher
747
5 Anwendungen 5.1 SerielleKommunikation Zu den häufigstenAnwendungenbei der Entwicklung am Mikrocontroler zählt die serielleKommunikation. EDtwedermit einem PC oder lnit einem nnderenMikro stellt daherein typischesSzenariodär: controller.DasersteAnwendungsbeispiel Der PC wird mit den1Mikrocontroller verbunden.Auf dem PC wird mithilfe eines trninals die seriele Kommunikation mit dem Mikocontm er hergestelt Anschließendkann der Anwender dem Mikrocontroiler einige Befehleschicken ünd bekonmt darauf jeweilseineentsplechendeAntwort. Di€seseinfncheBeispielbietet Ihnen einen gutenAusgangspunktfür neueProjekte, denn die serielleSchnittstelewerdenSiezumiDdestwälrcnd der EntwickluDsöltcr
siesollteneinenBli.kalfdiewebseitezumBuchwedenuster: und http://www.wrbu.h.de-Dortfinden5'e letzteAnderungen aktuelleUpdateszude.EeispielenindiesemBuch.
Matelial 5.1.1 Benötigtes . ATmegaS, ATmega32,... te nach gew;ihltemMikrocontroller müssen -ATmegar6, Sieeventuelldie Pin-Zuweisungenbz.vi'.die Schaltungetwasab:indern. . 3,868-MHz-Quarz (Standard beiSTK500und myAVR) . MAiC32 (wenn Siekein Entwicklungsboardverwenden) . SerieesKabel . PC mit zwei seriellenSchnittstellen(bei Verwendungvon STK500) . Terminalprosranm ÄVR ft/''ti,ral (auf beiselegteiCD)
748
5 Anwendungen
der Hardware 5.1.2 Instandsetzung Der ersteSchrittist, die Hardwarefunktionstüchtigzu machen.Hier passieren die häufigstenFehler,daher finden Sie auf der beigelegtenCD-ROM bereitseine vorkompilierteHEX-Datei,die Sienur mehr in Ihren Controllerflashenmüssen.Sollte dieAnwendungnichtfunktionieren,liegt der Fehlervermutlichim Hardwareaufbau. Wir eehenhier der Einfachheithalbervom STK500aus.SolltenSie ein STK500komfatiblesBoardbesitzen,solltendie meistenSchritteidentischsein.Wenn Sie Ihren eigenenAufbau verwenden,solltenSie bei diesemBeispieleigentlichauf keinegröberenProblemestoßen. Bei einem fliegendenAutbau dürfen Sie den MAX232 nicht vergessen, hier die Schaltune:
ATmegaS-P PC6(/RESET) AGND AREF avcc
PCo(AOCo) PCl(ADCI) PC2(ADC2) PC3(ADC3) Pca(A0c4/sDA) PC5(AOC5/SCL)
c1. c2+ tc3 C2. T1N T2 N
PDO(RXD) PBT(XTAL2/TOSC2) PO1[rXD) P02(Nro) P03(Nr1) PO4CXCK./ro) PD5tfl) vcc PD6(A|N0) PO7(ArN1)
GNO
GND TIOUT T2OUT
R2OUT R2IN
PBO(|CP) PB1(OC1A) PB2(SS/OC1B) PB3(MOS|/OC2) P34(MrSO) PB5(SOO
Abb.5.1: RS232-Grundschaltung
Abb.5.2zeigtdenschematischen AufbaudiesesBeispiels. DasSTK500besitztzweiserielleSchnittstellen mit denBezeichnungen RS232CTRI und RS232SPÄRE.Ersteredient der Kommunikation zwischendem AVR-Studio und dem STK500,die andereder eigendichen Verbindungzwischendem Milrocontrollerund demTerminalprogramm. Auf der beigelegtenCD finden Sie ein einfachesTerminalprogrammmit dem NamenÄI& Terminal,Das Prosramm muss nicht installiertwerden und läuft
5TK500 Aufbau des Prcjekts Abb.5.2: dnekt r-on der CD. Eine aktue e Version finden Sie äußerdem immer unter \li\tr.avrbuch.de. Das TerminalprogranD befindet sich auf der CD unter \Softwa re\AVRTerminal\AvrTerminal.exe. Zurück zum Beispiel.Der Quellcodedatur ist ebenfals auf beigelegterCD unter zu 6nden.DasHEx-FilebefiDdetsichin \Dei \Beisp;ele\SerielleKommuniktion\ jkation.heL spiele\SerieleKonmünikation\default\SerieleKommun Achtung: sollten sie keinen ATmega8veffenden, denken sie bitte daran, den Quellcodedirekt im AVR'Studiozu öffnen, um ihn dort neu tur Ihr Chipmodel zu kompilieren. Sie Anden außerdemeine stark vereinfachteVersion dieserAnweniellMinimdl\. dungi- VcrzcLhni''Bei'pi(le\\er StartenSie nun dasAVR Studio und flasheDSie die HEX-Datei in den Milcocon troller. AnschließendstartenSiedasTerminalprogrammund stellenesauf den entdassdasAVlt Studiobereits CoM'Port ein. Dabeiist zu beachten, sprecheDden dem STK500 verwendet.Siemüssen einen COM-Port tur die Kommunilation mit einstellen aul nochdie Kommunikntionsparameter im Term'nalprogramm Baudrate: 9.600 Datenbits: 8 Parity: Keine/NoDe Stoppbits:r Flusskontrole: Keine/None am STK500z11 wenn dasalleserledigt ist, brauchenSienur noch die RESET-Taste drückenund sollten unmittelbär darauf schoneinewilkommensnachiiclt im Ter minalfenstersehen.wenn nicht, solhenSieFolg€ndesüberpdfen:
150
5 Anwendungen
Verfügt däsSTK5O0über Strom und leuchtet die STATUSLED gdrl? Es sollten eine rote und zwei grüne LEDSleuchten.wenn nicht, besteht€in Problem mit der Stronversorgung. Die STK500Firmwarekönnteauchbeschädigt sein (das ist oft der FaI,wcnndic LEDSeineändereInrbe zeigenoderblinkeD). HabenSiedie COM Portsrichtig eingestelt? COM1 z. B. für dasAVR-Studio und CoM2 in1Terminalprogümm? HabenSiedie RxD/TxD-Lcitungen am sTK500ichtig mit den entsprechenden MikrocontrollerPins verbunden? Dazu 6nden Sie zwei Pins mit der Bezeich nung Rs232 sPÄRt im unteren Ende des Boards (bei den Tästen),die beim ATmesas(alsBeispiel)überejn Kabelmit denPinsPortD.0(RXD) und PoriD.l (I(D) v€rbü1denwerdenmüssen. Sind ale tunper in der Standxrdeinstellung? Vor allcm dcr tumper OSCSEI (aho,,rechts" solltePin 2 und Pnr3 verbinden gestecktsein). Sowird derOszilla tordesSTK500verwendet(Takl:3,68MHz). FuDktioniertllrre serielleSchnittstelle? TestenSiedaseventuelmir einemNuImodeml