www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Assembler und Mega48


Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Prorammierer,

möchte mit AVR-Studio und STK500 Mega48 progen.

Hier bleib ich schon hängen
--------------------------
Reset:
       ldi temp, LOW(RAMEND)     ; LOW-Byte der obersten RAM-Adresse

     out SPL, temp
     ldi temp, HIGH(RAMEND)           ; HIGH-Byte der obersten
RAM-Adresse
     out SPH, temp

           ; Baudrate einstellen
     ldi temp, LOW(UBRRVAL)
     out UBRR0L, temp
     ldi temp, HIGH(UBRRVAL)
     out UBRR0H, temp              ; Frame-Format: 8 Bit
     ldi temp, (1<<URSEL)|(3<<UCSZ0)
     out UCSRC, temp
     sbi UCSRB,TXEN                   ; TX aktivieren
-------------------------------------------------------------------
bei Baudrate einstellen "out UBRR0L, temp"  kommt eine Fehlermeldung
"illegal Argument .."
In den Unterlagen von ATMEL steht es aber auch so drinnen [UBRRnL].
Wer sagt mit wo's fehlt?

Gruss Kurt

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man sieht ja leider nicht den Anfang aber hast Du die Datei
"m48def.inc" eingebunden?

MfG
Andi

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry habs übersehen.

hier der Anfang
-------------------

.include "m48def.inc"

.equ CLOCK = 1000000
.equ BAUD = 1200
.equ UBRRVAL = CLOCK/(BAUD*16)-1        ; Stackpointer initialisieren


.def  Temp = r16    ;
;

Kurt

Autor: mmerten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
beim Mega48 liegt der UART außerhalb des mit IN/OUT Befehlen
ansprechbaren Bereiches. Ist nur mit den entsprechenden Memory
Befehlen
LDS/STS usw. ansprechbar.

Autor: Christian Zietz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf UBRR0L und UBRR0H kann man beim Mega48 nicht über OUT zugreifen.
Diese I/O Register sind Bestandteil des "Extended-I/O-Bereiches" und
müssen mit STS (statt OUT) bzw. LDS (statt IN) benutzt werden.

Steht auch so im Datenblatt:
"For I/O Registers located in extended I/O map, “IN”, “OUT”, “SBIS”,
“SBIC”, “CBI”, and “SBI” instructions must be replaced with
instructions that allow access to extended I/O. Typically “LDS” and
“STS” combined with “SBRS”, “SBRC”, “SBR”, and “CBR”."

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Über diese Hürde bin ich drüber.
Danke.

nun steht er bei:

>     ldi temp, (1<<URSEL)|(3<<UCSZ0)
     out UCSRC, temp
     sbi UCSRB,TXEN                   ; TX aktivieren

hier kommt Undef. Var-referenz

Was bedeutet das "(1<<URSEL)|(3<<UCSZ0)
sollte hier eine Auswahl getroffen werden ?

Kurt

Autor: Christian Zietz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Kurt: Es scheint mir, dass Du den Code für einen falschen AVR verwendet
hast. So kommst Du nicht weiter. Keine der drei Zeilen aus Deinem
letzten Posting wird für den ATMega48 assembliert werden, geschweige
denn richtig laufen. Bitte lies doch den Abschnitt zur USART im
Datenblatt.

Autor: mmerten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider hat Atmel beim Mega48/88/168 die UART Beispiele aus dem "alten"
Mega8 übernommen. Man hofft wohl auf das der Anwender die
Kompatibilitäts-Macros aus der App-Note benutzt. Die andere Frage
dürfte wohl die ASM-Hilfe im AVR-Studio unter der Rubrik Expressions
hinreichend beantworten.

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so soweit läuft es ohne Errormeldung!! (Freude)

------------------------------------------------
Reset:

       ldi temp, LOW(RAMEND)            ; LOW-Byte der obersten
RAM-Adresse
     out SPL, temp
     ldi temp, HIGH(RAMEND)           ; HIGH-Byte der obersten
RAM-Adresse
     out SPH, temp

           ; Baudrate einstellen
          ldi temp, LOW(UBRRVAL)
          sts UBRR0L, temp
          ldi temp, HIGH(UBRRVAL)
          sts UBRR0H, temp        ; Frame-Format: 8 Bit

            ; enable receiver und transmitter
       ldi temp, (1<<RXEN0) | (1<<TXEN0)
       sts UCSR0B, temp

            ; setze Framformat 8 dat 2 stop
       ldi temp , (1<<USBS0) | (3<<UCSZ00)
       sts UCSR0C, temp

-----------------------------------------------
Im Datenblatt werden die Var mit "out" weggeschrieben !

Was ich nicht verstehe ist "(1<<USBS0) | (3<<UCSZ00)"
das schaut nach "C"  aus.
Sind das ev. Schiebeoperationen in eine Byte-Var ?

Kurt

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"(1<<USBS0) | (3<<UCSZ00)"

ist eine IMHO umständliche Art und Weise, drei Bits an der richtigen
Stelle zu setzen.

Angenommen, USBS0 sei 2 und UCSZ00 sei 4 (das sind völlig aus der
Luft gegriffene Werte!), dann ist das Resultat

(1 << 2) | (3 << 4)
  0x04   |   0x30

also 0x34.

Das ganze rührt wohl daher, daß viele Leute das manuelle Zusammensetzen
von Bits für zu kompliziert und fehleranfällig halten.
Warum das dann noch zusätzlich "elegant" gemacht werden muss durch
Definition der Bit_nummer_ statt des Bitwertes hat sich mir noch nie
eröffnet.

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

Bewertung
0 lesenswert
nicht lesenswert
Das Verändern von Bits mit 'symbolischen Namen' hat schon seine
Vorteile. Man erkennt im Code, was man damit bezweckt. Es sagt
bedeutend mehr aus als das Arbeiten mit nichtssagenden Hexwerten oder
Binärwerten. Es macht den Code daher lesbarer. Man muss nicht mehr jede
Kleinigkeit im Datenblatt nachschlagen (welches Bit war das denn
nun???).

...

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

Bewertung
0 lesenswert
nicht lesenswert
Achso:

---->8----
Warum das dann noch zusätzlich "elegant" gemacht werden muss durch
Definition der Bit_nummer_ statt des Bitwertes hat sich mir noch nie
eröffnet.
----8<----
Nunja, die Bitnummer braucht man für sbi, cbi, sbic, sbis, sbrc, sbrs,
die Bitmaske (Bitwert) für cbr und sbr.

...

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
irgendetwas schaff ich nicht.
"USBS0 sei 2 und UCSZ00 sei 4 "

USBS0 = 00000010
UCSZ00= 00000100



-------------------------
(1 << 2) | (3 << 4)
  0x04   |   0x30

also 0x34.
--------------------------


Teil1:  (1 << 2)
          0x04

an die "erste" Stelle kommt eine Zwei   00000100
                                              *
                                     Zwei  0010

Teil2: | (3 << 4)
       |   0x30
an die "dritte" Stelle kommt eine Vier  00100000
                                            *
                                         0100
ergibt dann                             00100100   = 0x44

wo kommt das 0x34 her?

schaut mal

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

Bewertung
0 lesenswert
nicht lesenswert
Ich schiebe zwar meist nur EINSen durch, aber:
Wenn du eine 3 (DREI) durchschiebst (4 mal), dann bleiben schon die
beiden Einsen, aus denen die 3 besteht, erhalten.

Also

00000011 ist die 3, eine 1 in der Einer-Stelle, eine in der Zweier

00110000 ist 3<<4, nämlich 11 um 4 Stellen nach links geschubst

00000100 ist dann 1<<2,
00110100 wäre dann 1<<2 OR (|) 3<<4

Aber: Wenn ich das mache, um "sprechende Bitnamen" zu nutzen, dann
schiebe ich keine Dreien sondern nur Einsen...

...

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also:

(1 << 2) | (3 << 4)
  0x04   |   0x30

(1 << 2)   =  eine Eins     2 x nach links geschoben
(3 << 4)   =  zwei Bits (3) 4 x nach links geschoben

(16>>4      = Bit4(00010000)   4 x nach rechts geschoben = 00000001


(1 << 2)  =  00000100
(3 << 4)  =  00110000
----------------------
             00110100    = 0x34

also sind das Schiebeinformationen  (Zahl sooft  Nach  geschoben)

Was passiert mit einem Überlauf:  z.B.  (4>>6)

Stimmt das so?

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

Bewertung
0 lesenswert
nicht lesenswert
Stimmt erstmal so.

Bei Überlauf kommt es drauf an, was du mit der übergelaufenen Zahl
anstellst. Weist du sie einem Register zu (ldi, cbr, sbr, andi, ori,
cpi, subi) bzw. veränderst ein Register damit, dann wird der obere Teil
abgeschnitten, bzw. geht ins Leere. Probiere es doch einfach mal aus,
wozu gibt es denn im AVR-Studio den Simulator?

...

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK gut so,
         ; setze Framformat 8 dat 2 stop
   ldi temp , (1<<USBS0) | (3<<UCSZ00)
   sts UCSR0C, temp

Dieses Zeichen dazwischen (|) muss also eine ODER-Verknüpfung
darstellen !

Was mich noch verwirrt sind die Angaben (1<<USBS0) | (3<<UCSZ00)
Es wird hier also beschrieben wie oft geschoben werden muss.
(3<<UCSZ00) heisst also dass 2 Bit's um UCSZ00 x geschoben werden
muss
Falls ich euch auf die Nerven gehe ...
Dann hat die Angabe UCSZ00 nichts mit realen Werten zu tun sondern es
sind nur Typbezogene Angaben.

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

Bewertung
0 lesenswert
nicht lesenswert
@Kurt:

Du arbeitest doch sicher mit AVR-Studio.
Das hat oben eine Menüleiste.
Ganz rechts gibt es den Menüpunkt "Help".
Wenn man den anklickt, bekommt man unter Tools, AVR-Assembler (oder so
ähnlich) komplette Auflistungen der Direktiven, Operatoren und Befehle
uns was sonst alles noch so wissenswert ist.
Im Gegensatz zur allgemeinen Windows-Hilfe (die absoluter Schrott ist,)
ist die Hilfe vom AVR-Studio sehr ergiebig. Du kannst also alles
nachlesen und brauchst nicht zu spekulieren.

Gruß...
...HanneS...

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
Danke für eure Hilfe.
Das mit derHilfefunktion schaut ja sehr gut aus.

Zeichen kann ich schon rausschicken.
Aber mit der Pufferkontrolle klappt es nicht

Ausgabe:      ; Zeichen raussenden

#   sbis UCSR0A, UDRE0
  RJMP Ausgabe
  out UDR0,  temp
    ret

Hier kommt eine Fehlermeldung.

   "sbis UCSR0A, UDRE0" ist aus Anleitung.

so nun schalt ich ab.

Grüsse an Alle  Kurt

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo bin wieder QRV

so nun mal Vergleichen.

32 Universalregister : (sind nahe an der CPU)
64 I/O Register      :  (hier ist die Verbindung zur Hardware)
160 erweiterte I/O Register :
512 Byte RAM

Die 160 erw. I/O's liegen im Ram und sind daher nicht mit den
"üblichen"  I/O Befehlen erreichbar.?

Darauf hin habe ich versucht diese Register (UCSR0A)  "direkt" zu
erreichen.  Ging nicht"

Wie es scheint sind "Berechnungen" wie Bit-nachschauen usw. nur in
den Universalregistern möglich.

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

; -----------------------------------------------------
Ausgabe:      ; Zeichen ausgeben

    lds temp2, UCSR0A    ; Zustandsregister (aus REM) in
Universalregister bringen
    sbrs temp2,UDRE0      ; schauen ob Bit gesetzt ist
    rjmp Ausgabe    ; zurück wenn noch nicht fertig
    sts UDR0,  temp        ; Zeichen in Ausgabe-Register bringen
  ret
-------------------------------------------------------------

Damit werden Zeichn "gesittet" ausgegeben.

Lieg ich soweit richtig?

Gruss Kurt

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Helfer,

dank Euerer Hinweise komm ich nun zurecht.
Im Simulator wurden die entsprechenden Register (SMCR + PRR)
bei Änderung nicht bearbeitet.
In den Unterlagen von Atmel sind die Adressen ja angegeben.
Aber erst die Verwendung der in klammerstehenden Werte führten zum
Erfolg.
Ich möchte mich nochmal bei Allen bedanken die mitgewirkt haben.

Kurt

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

Bewertung
0 lesenswert
nicht lesenswert
@Kurt,
schau dir bei solchen Problemen auch mal die dementsprechende
Include-Datei an. Ich habe da irgendwo auch schon einen Unterschied
zwischen der Bezeichnung im Datenblatt und in einer Include-Datei
gesehen. Leider weiß ich jetzt nicht mehr, wo (bei welchem AVR) das
war.

...

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ,
darf ich noch weitere Fragen stellen ?

Kurt

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

Bewertung
0 lesenswert
nicht lesenswert
@Kurt...

Mein Hinweis auf die Hilfe zum AVR-Studio heißt doch nicht, dass du
keine Fragen stellen darfst. Ich wollte dir damit nur mitteilen, dass
du wichtige Informationen bereits in deinem Rechner verfügbar hast und
sich dadurch manche Frage erübrigt.

Sicher kannst du weitere Fragen stellen. Schlimmstenfalls verweist man
auf das Datenblatt oder die AVR-Studio-Hilfe.

...HanneS...

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK gut,

Dann die nächste "Aktion"

Mega 48 (der von Oben)
32768 Hz Quarz

Interrupt alle Sekunden (also Teiler durch 32768)

Welchen Timer/Counter soll ich nehmen?

Kurt

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei einem Sekunden-Takt ist das eigentlich egal!

Timer 0:
 8Bit-Counter, max. bis 256
 Möglicher Prescaler z. B.1024
 Möglicher Counter dann 32768 / 1024 = 32 (256 - 32 = 224 wegen
Aufwärts-Counter).

Genauso mit Timer 2.

Timer 1 halte ich dann für verschwendung da 16 Bit und nicht nötig.
Nim am beste Timer0. Wenn Du Sleep mit Power-Down machen willst, dann
den Quarz an Timer2 (zusätzlich) anklemmen.
Sollen die 32768KHz etwa der Haupttakt werden?

MfG
Andi

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Sollen die 32768KHz etwa der Haupttakt werden?"


Bei dieser Anwendung  Ja.

Möchte aber auch mit höheren Frequenzen gleiches machen können.
( mit USART-Betrieb)

Kurt

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du eine genaue Sekunde mit 32768Hz benötigst mach das dann doch am
besten mit dem Quarz an T2 und nicht am System-Takt.
Den AVR kannst Du dann mit dem internen Oscilator Rechnen lassen und
wenn erforderlich kannst Du den per Software mit OSCCAL=0 bremsen.
Timer2 wird von T2 mit 32768Hz getaktet.
Wenn natürlich der AVR mit einer 3V-Batterie Wochenlang auskommen soll
ist das natürlich was anderes.

MfG
Andi

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja /

es geht primär um den Stromverbrauch

Dachte mir so:

Der 32k macht die "Zeit"    (Arbeitszyklen alle paar Sekunden)

Und in der Arbeit der Interne RC  die Taktung.
Jedoch muss man den RC dann auf "Kurs" bringen,
da sonst die Genauigkeit für USART nicht reicht.

Kurt

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der interne RC läuft allerdings immer.
Weiß nicht, ob der im Power-Down ruhig gestellt ist und ob der per
Fuses auf weniger als 1MHz mit Kalibyte in OSCCAL einstellbar ist.
Jedenfalls mußt Du da ein bißchen mit dem OSCCAL experimentieren, einen
Takt an einem Pin erzeugen und messen wie schnell der dann läuft.

Probier mal folgendes:

 ldi r16,0       ;oder andere Werte für den OSCCAL.
 out OSCCAL,r16

 sbi DDRB,0      ;PortB.0 als Ausgang.
 in r16,PortB    ;Port-Status einlesen.
 ldi r17,0b1     ;Bit 0 zum switchen.
loop:
 eor r16,r17     ;PortB.0 umschalten.
 out PortB,r16   ;Und Ausgeben.
 rjmp loop

Macht eine einfache Takterzeugung an PortB.0.
An PinB.0 mißt Du die Frequenz und multiplizierst sie mit 4 (4 Takte je
Schleife).

Gruß
Andi

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.