www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Anfängerfragen zu ATMEL Mega8


Autor: Bernd Kehr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

beschäftige mich heute zum ersten Mal mit dem ATMEL und hab mir die
AVR-Tools runter geladen.
Hab, bis jetzt (Ausbilding/Studium), immer mit Intel/Infineon Sachen zu
tun gehabt.

Würde gern ein paar alte Programme zum Laufen bekommen. Mußte aber
feststellen, dass das AVR-Programm keine C Dateien unterstütz..ist das
richtig?

Und für was ist das MAKEFILE?

Gruß Bernd.

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

das AVRStudio kann von Haus aus kein C. Dafür gibts z.B. WinAVR
(basiert auf gcc) oder auch andere kommerzielle Compiler. Ich
persönlich finde WinAVR aber ziemlich gut.

Das Makefile selber gibt an was denn zum bauen des Projekts notwendig
ist -- ich würde es als "Bauanleitung" bezeichnen. Ein ziemlich
mächtiges und für größere Sachen imo unverzichtbares Tool.

Autor: Bernd Kehr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay...vielen Dank!

Nun zu meiner nächsten "blöden" Frage...

Wollte einfach mal den Timer0 Zählen lassen. Hab mir folgende Zeilen
ausgedacht:

include "m8def.inc"
.device ATMEGA8


.def stunden=r1
.def minuten=r2
.def sekunden=r3
.def hunderst=r4
.def temp=r7

out TCCR0, 0b00000101 ; Vorteiler einstellen
......

okay. Soweit so gut.

Beim Umwandeln kommt die Fehlermeldung "error: Invalid Register"
Obwohl ich die inlcude-Datei richtig eingebunden ist.
Geb ich den Zahlenwert falsch an. In allen Beispielen die ich gefunden
habe geht das so. Benutze AVRStudio4.

Danke für Eure Hilfe.

Gruß Bernd.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
in bzw. out geht nicht direkt mit Operand, sondern nur über Register.

ldi r16, blabla
out TCCR0, r16

Autor: ...HanneS... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Out geht nur über Register.

 ldi r16,irgendeinbyte
 out tccr0,r16

Es gibt einen Unterschied zwischen unteren (r0...r15) und oberen
(r16...r31) Registern, die unteren können nicht mit Konstanten
arbeiten.

Vielleicht hilft dir das Datenblatt des AVRs und die Hilfe zum
Assembler (Instruction-set) weiter. Oder Beispiele hier im Forum und
auch das Tutorial.

...

Autor: Bernd Kehr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo...

..vielen Dank! Irgendwie ist das eine totale Umstellung vom Infineon
auf den Atmel. Danke schonmal.

Bernd.

Autor: Bernd Kehr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe endlich meinen ersten Timer + Interrupt auf einem ATMEL zum laufen
gebracht. Danke.

Nur eine kleine Frage.

Meine Programm sieht so aus:

----------------------

.include "m8def.inc"    ;Inlcude Datei für ATMEGA8
.device ATMEGA8      ;Angabe des Chips

.def temp=r17

.org 0x000
rjmp start

.org 0x123
start:        ;

ldi temp, 1<<TOIE1    ;Timer Interrupte freigeben
out TIMSK, temp
ldi temp, 0b11111111    ;Timer1H mit Startwert laden
out TCNT1H, temp
ldi temp, 0b11111110    ;Timer1L mit Startwert laden
out TCNT1L, temp

ldi temp, 0b0000000    ;Timer1 Vorteiler
out TCCR1B, temp

ldi temp, 0b0000001    ;Timer1 Vorteiler
out TCCR1B, temp

sei


warte: rjmp warte    ;Warte auf Interrupt

.org 0X008
inc sekunden
ldi temp, 1<<OCF1A    ;Timer1 Overflow Flag zurücksetzen
out TIFR, temp
reti

-------------------------------

Nun ist mir aufgefallen, daß beim Interrupt nicht das Overflow
Interrupt-Flag TOV1 sondern das Compare Register OCF1A gesetzt wird.
Damit der Rücksprung funktioniert setzte ich dieses auch am Ende der
IR-Routine zurück.

Was bring ich da durcheinander?

Danke.

Gruß Bernd.

Autor: ...HanneS... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi...

Du hast den Stackpointer nicht initialisiert.

Die Int-Vektoren nimmt man meist als Sprungtabelle, da braucht man sich
nicht um die verwendeten Adressen zu kümmern (org) und kann auch mit
mehreren INTs arbeiten.

Beispiel:

.cseg
.org 0              ;Reset- und Interrupt-Vektoren AT-Mega 8
 rjmp reset         ;Reset Handler
 reti; rjmp EXT_INT0      ;IRQ0 Handler
 reti; rjmp EXT_INT1      ;IRQ1 Handler
 reti; rjmp TIM2_COMP     ;Timer2 Compare Handler
 reti; rjmp TIM2_OVF      ;Timer2 Overflow Handler
 reti; rjmp TIM1_CAPT     ;Timer1 Capture Handler
 rjmp TIM1_COMPA      ;Timer1 CompareA Handler
 reti; rjmp TIM1_COMPB    ;Timer1 CompareB Handler
 reti; rjmp TIM1_OVF      ;Timer1 Overflow Handler
 reti; rjmp TIM0_OVF      ;Timer0 Overflow Handler
 reti; rjmp SPI_STC       ;SPI Transfer Complete Handler
 reti; rjmp USART_RXC     ;USART RX Complete Handler
 reti; rjmp USART_UDRE    ;UDR Empty Handler
 reti; rjmp USART_TXC     ;USART TX Complete Handler
 reti; rjmp ADC           ;ADC Conversion Complete Handler
 reti; rjmp EE_RDY        ;EEPROM Ready Handler
 reti; rjmp ANA_COMP      ;Analog Comparator Handler
 reti; rjmp TWSI          ;Two-wire Serial Interface Handler
 reti; rjmp SPM_RDY       ;Store Program Memory Ready Handler

.include"LCDprint.inc"   ;LCD-Ausgabefunktionen
.include"_LCD_4x27.inc"  ;LCD-Treiber-Routinen für LCDs mit 2
HD44780
.include"locate_4x27.inc";Ausgabepositionierung für LCD 4x27 Zeichen

reset:
 ldi wl,low(ramend)         ;Stackpointer initialisieren
 out SPL,wl
 ldi wl,high(ramend)
 out SPH,wl
 ;... weitere Initialisierungen...

In der Interrupt-Service-Routine sollte das SREG gesichert werden:

TIM1_COMPA:             ;ISR Timer1-Interrupt (alle 10ms)
 in srsk,sreg               ;SREG sichern (Exklusivregister)
 push xh                    ;benutzte Register
 push xl                    ;sichern
 in xl,ocr1al               ;Weckzeit
 in xh,ocr1ah               ;holen,
 subi xl,low(-tim1zu)       ;Intervall
 sbci xh,high(-tim1zu)      ;dazu,
 out ocr1ah,xh              ;und wieder
 out ocr1al,xl              ;in den Timer
 ;xl und xh können jetzt innerhalb der ISR frei benutzt werden

Tastenabfrage: ;Entprellroutine, geklaut bei Peter Dannegger...
 in zl,tap        ;Tastenport einlesen (gedrückt=L)
 com zl           ;invertieren (gedrückt=H)
 eor zl,tas       ;nur Änderungen werden H
 and tz0,zl       ;Prellzähler unveränderter Tasten löschen (Bit0)
 and tz1,zl       ;Prellzähler unveränderter Tasten löschen (Bit1)
 com tz0          ;L-Bit zählen 0,2,->1, 1,3,->0
 eor tz1,tz0      ;H-Bit zählen 0,2,->tz1 toggeln
 and zl,tz0       ;Änderungen nur dann erhalten, wenn im Prellzähler
 and zl,tz1       ;beide Bits gesetzt sind (Zählerstand 3)
 eor tas,zl       ;erhaltene Änderungen toggeln alten (gültigen)
                  ;Tastenstatus
 and zl,tas       ;nur (neu) gedrückte Tastenbits bleiben erhalten
 or tfl,zl        ;und zugehörige Bits setzen
                  ;(gelöscht wird nach Abarbeitung)
 ;in "tas" steht jetzt der gültige Tastenzustand,
 ;in "tfl" die Flags der neu gedrückten,
 ;aber noch nicht abgearbeiteten Tasten...
 ;zl ist jetzt wieder frei für weitere temporäre Zwecke in der ISR

 dec teiler                 ;Sekundenvorteiler runter
 brne nixvollsek            ;abgelaufen? nein...
 sbr flags,1<<neusek        ;ja, Flag setzen,
 ldi teiler,teilfaktor      ;und Teiler auf Startwert setzen
nixvollsek:
 cpi teiler,teilfaktor/2    ;Halbe Sekunde?
 brne nixhalbsek            ;nein...
 sbr flags,1<<neuhalb       ;ja, Flag setzen
nixhalbsek:
 pop xl                     ;benutzte Register
 pop xh                     ;wiederherstellen
 out sreg,srsk              ;SREG wiederherstellen
 reti                       ;fertig...

Die Flags in TIFR werden durch den Aufruf der ISR automatisch zurück
gesetzt. Damit hat der Programmierer nix zu tun. Es werden natürlich
auch die Flags (in TIFR) gesetzt, deren INTs man nicht aktiviert hat
(TIMSK), diese sind aber wirkungslos und brauchen nicht beachtet
werden.

Ich hoffe, ein paar "Stolpersteine" beseitigt zu haben.

...

Autor: ...HanneS... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und schon ist mir ein Flüchtigkeitsfehler in der ISR aufgefallen:

Die Tastenentprellung muss natürlich das Register xl nutzen und nicht
zl. Es wundert mich nur, dass das Programm trotzdem funktioniert hat.

...

Autor: Bernd Kehr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo...

danke schonmal.

Das heißt ich brauch das hier:

-----------------------

.cseg
.org 0              ;Reset- und Interrupt-Vektoren AT-Mega 8
 rjmp reset         ;Reset Handler
 reti; rjmp EXT_INT0      ;IRQ0 Handler
 reti; rjmp EXT_INT1      ;IRQ1 Handler
 reti; rjmp TIM2_COMP     ;Timer2 Compare Handler
 reti; rjmp TIM2_OVF      ;Timer2 Overflow Handler
 reti; rjmp TIM1_CAPT     ;Timer1 Capture Handler
 rjmp TIM1_COMPA      ;Timer1 CompareA Handler
 reti; rjmp TIM1_COMPB    ;Timer1 CompareB Handler
 reti; rjmp TIM1_OVF      ;Timer1 Overflow Handler
 reti; rjmp TIM0_OVF      ;Timer0 Overflow Handler
 reti; rjmp SPI_STC       ;SPI Transfer Complete Handler
 reti; rjmp USART_RXC     ;USART RX Complete Handler
 reti; rjmp USART_UDRE    ;UDR Empty Handler
 reti; rjmp USART_TXC     ;USART TX Complete Handler
 reti; rjmp ADC           ;ADC Conversion Complete Handler
 reti; rjmp EE_RDY        ;EEPROM Ready Handler
 reti; rjmp ANA_COMP      ;Analog Comparator Handler
 reti; rjmp TWSI          ;Two-wire Serial Interface Handler
 reti; rjmp SPM_RDY       ;Store Program Memory Ready Handler

--------------------------------

und in der IR-Routine das hier:

--------------------------------
in srsk,sreg               ;SREG sichern (Exklusivregister)
---------------------------------

Verstehe irgendwie nicht was das soll..aber ich machs mal..

Gruß Bernd.

Autor: Bernd Kehr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit der Tabelle hab ich schon verstanden und mit dem Stack auch.
Aber wenn ich das Flag nicht lösche springt er mir 2 mal in die
IR-Routine.

Autor: ...HanneS... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du nur einen Int nutzt, geht das auch auf deine Weise. Ich finde
die Sprungtabelle aber übersichtlicher.

Das IN SRSK,SREG sichert das Statusregister (die Bedingungsflags) im
Register SRSK. Am Ende der ISR muss dieses dann wiederhergestellt
werden: OUT SREG,SRSK Damit wird erreicht, dass die ISR dem
Hauptprogramm nicht die Flags unterm Hintern verstellt.

Was aber bedeutend wichtiger ist: Du musst den Stackpointer
initialisieren, sonst klappt kein Rücksprung aus ISR oder UP (RETI,
RET).

...

Autor: ...HanneS... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Flags in TIFR brauchen definitiv nicht per Programm gelöscht
werden. Das geschieht automatisch.

...

Autor: Bernd Kehr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Jetzt weiß ich wo mein Fehler lag!!

Da ich den Stackpointer nicht initialisiert hatte ist mein Programm aus
der IR-Routine wieder auf 0x000 gesprungen!

Okay. Vielen Dank!!!

Gruß Bernd.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.