Pfad: Home => AVR-Überblick => Programmiertechniken => Projektplanung

Programmiertechnik für Anfänger in AVR Assemblersprache

Wie plane ich ein Projekt in Assembler?

Hier wird erklärt, wie man ein einfaches Projekt plant, das in Assembler programmiert werden soll. Weil die verwendeten Hardwarekomponenten eines Prozessors sehr vieles vorweg bestimmen, was und wie die Hard- und Software aufgebaut werden muss, zunächst die Überlegungen zur Hardware. Dann folgt ein Kapitel zur Entscheidung über den Einsatz von Interrupts und schließlich Einiges über Timing.

Überlegungen zur Hardware

In die Entscheidung, welchen AVR-Typ man verwendet, gehen eine Vielzahl an Anforderungen ein. Hier einige häufiger vorkommende Forderungen zur Auswahl:
  1. Welche festen Portanschlüsse werden gebraucht? Feste Portanschlüsse sind Ein- oder Ausgänge von internen Komponenten, die an ganz bestimmten Anschlüssen liegen müssen und nicht frei wählbar sind. Sie werden zuerst zugeordnet. Komponenten und Anschlüsse dieser Art sind:
    1. Soll der Prozessor in der Schaltung programmiert werden können (ISP-Interface), dann werden die Anschlüsse SCK, MOSI und MISO diesem Zweck fest zugeordnet. Bei entsprechender Hardwaregestaltung können diese als Eingänge (SCK, MOSI) oder als Ausgang doppelt verwendet werden (Entkopplung über Widerstände oder Multiplexer empfohlen).
    2. Wird eine serielle Schnittstelle benötigt, sind RXD und TXD dafür zu reservieren. Soll zusätzlich das RTS/CTS-Hardware-Protokoll implementiert werden, sind zusätzlich zwei weitere Portbits dafür zu reservieren, die aber frei platziert werden können.
    3. Soll der Analogkomparator verwendet werden, dann sind AIN0 und AIN1 dafür zu reservieren.
    4. Sollen externe Signale auf Flanken überwacht werden, dann sind INT0 bzw. INT1 dafür zu reservieren.
    5. Sollen AD-Wandler verwendet werden, müssen entsprechend der Anzahl benötigter Kanäle die Eingänge dafür vorgesehen werden. Verfügt der AD-Wandler über die externen Anschlüsse AVCC und AREF, sollten sie entsprechend extern beschaltet werden.
    6. Sollen externe Impulse gezählt werden, sind dafür die Timer-Input-Anschlüsse T0, T1 bzw. T2 zu reservieren. Soll die Dauer externer Impulse exakt gemessen werden, ist dafür der ICP-Eingang zu verwenden. Sollen Timer-Ausgangsimpulse mit definierter Pulsdauer ausgegeben werden, sind die entsprechenden OCx-Ausgänge dafür zu reservieren.
    7. Wird externer SRAM-Speicher benötigt, müssen alle nötigen Address- und Datenports sowie ALE, RD und WR dafür reserviert werden.
    8. Soll der Takt des Prozessors aus einem externen Oszillatorsignal bezogen werden, ist XTAL1 dafür zu reservieren. Soll ein externer Quarz den Takt bestimmen, sind die Anschlüsse XTAL1 und XTAL2 dafür zu verwenden.
  2. Welche zusammenhängenden Portanschlüsse werden gebraucht? Zusammenhängende Portanschlüsse sind solche, bei denen zwei oder mehr Bits in einer bestimmten Reihenfolge angeordnet sein sollten, um die Software zu vereinfachen.
    1. Erfordert die Ansteuerung eines externen Gerätes das Schreiben oder Lesen von mehr als einem Bit gleichzeitig, z.B. eine vier- oder achtbittige LCD-Anzeige, sollten die nötigen Portbits in dieser Reihenfolge platziert werden. Ist das z.B. bei achtbittigen Interfaces nicht möglich, können auch zwei vierbittige Interfaces vorgesehen werden. Die Software wird vereinfacht, wenn diese 4-Bit-Interfaces links- bzw. rechtsbündig im Port angeordnet sind.
    2. Werden zwei oder mehr ADC-Kanäle benötigt, sollten diese in einer direkten Abfolge (z.B. ADC2/ADC3/ADC4) platziert werden, um die Ansteuerungssoftware zu vereinfachen.
  3. Welche frei platzierbaren Portbits werden noch gebraucht? Jetzt wird alles zugeordnet, was keinen bestimmten Platz braucht.
    1. Wenn es jetzt wegen eines einzigen Portbits eng wird, kann der RESET-Pin bei einigen Typen als Eingang verwendet werden, indem die entsprechende Fuse gesetzt wird. Da der Chip anschließend nur noch über Hochvolt-Programmierung zugänglich ist, ist dies für fertig getestete Software akzeptabel. Für Prototypen in der Testphase ist für ISP ein Hochvolt-Programmier-Interface am umdefinierten RESET-Pin und eine Schutzschaltung aus Widerstand und Zenerdiode gegenüber der Signalquelle vonnöten (beim HV-Programmieren treten +12 Volt am RESET-Pin auf).
In die Entscheidung, welcher Prozessortyp für die Aufgabe geeignet ist, gehen ferner noch ein:
Zum Seitenanfang

Überlegungen zum Interrupt-Betrieb

Einfachste Projekte kommen ohne Interrupt aus. Wenn allerdings der Strombedarf minimiert werden soll, dann auch dann nicht. Es ist daher bei fast allen Projekten die Regel, dass eine Interruptsteuerung nötig ist. Und die will sorgfältig geplant sein.

Grundanforderungen des Interrupt-Betriebs

Falls es nicht mehr parat ist, hier ein paar Grundregeln:

Grundaufbau im Interrupt-Betrieb

Aus dem Dargestellten ergibt sich die folgende Grundstruktur eines Interrupt- getriebenen Programmes an einem Beispiel:

;
; Registerdefinitionen
;
.EQU rsreg = R15 ; Status-Sicherungs-Register bei Interrupts
.EQU rmp = R16 ; Temporäres Register auäerhalb von Interrupts
.EQU rimp = R17 ; Temporäres Register innerhalb von Interrupts
.EQU rflg = R18 ; Flaggenregister zur Kommunikation
.EQU bint0 = 0 ; Flaggenbit zur Signalisierung INT0-Service
.EQU btc0 = 1 ; Flaggenbit zur Signalisierung TC0-Overflow
; ...
; ISR-Tabelle
;
.CSEG
.ORG $0000
	rjmp main ; Reset-Vektor, wird beim Start ausgeführt
	rjmp isr_int0 ; INT0-Vektor, wird bei eine Pegeländerung am INT0-Eingang ausgefürt 
	reti ; nicht belegter Interrupt
	reti ; nicht belegter Interrupt
	rjmp isr_tc0_Overflow ; TC0-Overflow-Vektor, wird bei Überlauf TC0 ausgeführt
	reti ; nicht belegter Interrupt
	reti ; nicht belegter Interrupt
	; ... gegebenenfalls weitere ISR
;
; Interrupt-Service-Routinen
;
isr_int0: ; INT0-Service Routine
	in rsreg,SREG ; sichere Status
	in rimp,PINB ; lese Port B in Temp Register
	out PORTC,rimp ; schreibe Temp Register in Port C 
	; ... mache irgendwas weiteres
	sbr rflg,1<<bint0 ; signalisiere INT0 nach außerhalb
	out SREG,rsreg ; stelle Status wieder her
	reti ; Sprung zurück und Int wieder zulassen
isr_tc0_Overflow: ; TC0 Overflow Service Routine
	in rsreg,SREG ; sichere Status
	in rimp,PINB ; lese Port B in Temp Register
	out PORTC,rimp ; schreibe Temp Register in Port C 
	; ... mache irgendwas weiteres
	sbr rflg,1<<btc0 ; setze TC0-Weiterbehandlungs-Flagge
	out SREG,rsreg ; stelle Status wieder her
	reti ; Sprung zurück und Int wieder zulassen
;	
; Hauptprogramm-Start
;
main:
	ldi rmp,HIGH(RAMEND) ; setze Stapelregister
	out SPH,rmp
	ldi rmp,LOW(RAMEND)
	out SPL,rmp
	; ... weiteres
	; INT Enable bei TC0 Overflow
	ldi rmp,1<<TOIE0 ; Overflow Interrupt Enable Timer 0
	out TIMSK,rmp ; Interrupt-Maske der Timer setzen  
	ldi rmp,(1<<CS00)|(1<<CS02) ; Teiler durch 1024
	out TCCR0,rmp ; Timer starten
	; INT Enable beim INT0-Eingang
	ldi rmp,(1<<SE)|(1<<ISC00) ; SLEEP-Enable und INT0 bei allen Flanken
	out MCUCR,rmp ; an das Kontrollregister
	ldi rmp,1<<INT0 ; INT0 ermöglichen
	out GICR,rmp ; im Interrupt-Kontrollregister
	; Interrupt Status Flag setzen
	sei ; setze Interrupts an
;
; Hauptprogramm-Loop
;
loop:
	sleep ; schlafen legen
	nop ; Dummy nach dem Aufwachen
	sbrc rflg,bint0 ; keine INT0-Anforderung
	rcall mache_int0 ; behandle INT0-Ergebnis
	sbrc rflg,btc0 ; keine TC0-Overflow-Behandlung
	rcall mache_tc0 ; behandle TC0-Overflow
	rjmp loop ; lege dich wieder schlafen
;
; Behandlung der Anforderungen
;
mache_int0: ; Behandle INT0-Ergebnis
	cbr rflg,1<<bint0 ; Setze INT0-Flagge zurück
	; ... mache weiteres
	ret ; fertig, zurück zum Loop
mache_tc0: ; Behandle TC0-Overflow
	cbr rflg,1<<btc0 ; Setze TC0-Flage wieder zurück
	; ... mache weiteres
	ret ; fertig, zurück zum Loop

Zum Seitenanfang

Überlegungen zum Timing

Geht ein Projekt darüber hinaus, ein Portbit abzufragen und daraus abgeleitet irgendwas anderes zu veranlassen, dann sind Überlegungen zum Timing des Projektes zwingend. Timing

Wahl der Taktfrequenz des Prozessors

Die oberste Grundfrage ist die nach der nötigen Präzision des Taktgebers.

Reicht es in der Anwendung, wenn die Zeiten im Prozentbereich ungenau sind, dann ist der interne RC-Oszillator in vielen AVR-Typen völlig ausreichend. Bei den neueren ATtiny und ATmega hat sich die selbsttätige Oszillator-Kalibration eingebürgert, so dass die Abweichungen vom Nominalwert des RC-Oszillators nicht mehr so arg ins Gewicht fallen. Wenn allerdings die Betriebsspannung stark schwankt, kann der Fehler zu groß sein.

Wem der interne RC-Takt zu langsam oder zu schnell ist, kann bei einigen neueren Typen (z.B. dem ATtiny13) einen Vorteiler bemühen. Der Vorteiler geht beim Anlegen der Betriebsspannung auf einen voreingestellten Wert (z.B. auf 8) und teilt den internen RC-Oszillator entsprechend vor. Entweder per Fuse-Einstellung oder auch per Software-Einstellung kann der Vorteiler auf niedrigere Teilerverhältnisse (höhere Taktfrequenz) oder auf einen höheren Wert umgestellt werden (z.B. 128), um durch niedrigere Taktfrequenz z.B. verstärkt Strom zu sparen. Obacht bei V-Typen! Wer dem Prozessor einen zu hohen Takt zumutet, hat es nicht anders verdient als dass der Prozessor nicht tut, was er soll.

Wem der interne RC-Oszillator zu ungenau ist, kann per Fuse eine externe RC-Kombination, einen externen Oszillator, einen Quarz oder einen Keramikschwinger auswählen. Gegen falsch gesetzte Fuses ist kein Kraut gewachsen, es muss dann schon ein Board mit eigenem Oszillator sein, um doch noch was zu retten.

Die Höhe der Taktfrequenz sollte der Aufgabe angemessen sein. Dazu kann grob die Wiederholfrequenz der Tätigkeiten dienen. Wenn eine Taste z.B. alle 2 ms abgefragt werden soll und nach 20 Mal als entprellt ausgeführt werden soll, dann ist bei einer Taktfrequenz von 1 MHz für 2000 Takte zwischen zwei Abfragen Platz, 20.000 Takte für die wiederholte Ausführung des Tastenbefehls. Weit ausreichend für eine gemütliche Abfrage und Ausführung.

Eng wird es, wenn eine Pulsweitenmodulation mit hoher Auflösung und hoher PWM-Taktfrequenz erreicht werden soll. Bei einer PWM-Taktfrequenz von 10 kHz und 8 Bit Auflösung sind 2,56 MHz schon zu langsam für eine software-gesteuerte Lösung. Wenn das ein Timer mit Interrupt-Steuerung übernimmt, um so besser.

Was ist wann und wie zu tun?

Mit welchen Methoden lässt sich das machen?

Zum Seitenanfang


©2006 by http://www.avr-asm-tutorial.net