www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Erste geh versuche mit AVR bitte mal anschauen


Autor: Hyronimus Herzberg (avr_by_ronny)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mich erst vor kurzem mit der Materie Programmierne und 
Mikrocontroller aus einander gesetzt.

ein paar kleine Programme wie drücke Taste1 und Led2 geht an habe ich 
natürlich auch gemacht.
Aber nun habe ich ein etwas sinvolleres programm geschrieben
und es scheint auch zufunktionieren.
Es ist eine digital Uhr für einen Attiny die man auch einstellen kann;-)
Habe an meinem Attiny zwar nur 3 74HC595 drann aber die zeigen das 
richtige an.

Meine Frage ist aber ob das totaler mist ist bzw wo man noch was 
verbessern kann.
Ach ich schreibe in Assembler. Mit C komme ich noch nicht klar.
Würde aber auch gern Programme für den Pc schreiben hauptsächlich um 
RS232 auszulesen.

Autor: hdd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du auch die .asm Datei anhängst, dann kann man dir sogar helfen :)

Autor: Hyronimus Herzberg (avr_by_ronny)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Oh wusste nicht, dass man die auch braucht
Hier ist sie

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>und es scheint auch zufunktionieren.

Da habe ich meine Zweifel.

Ich fang mal an:

>    ldi temp, 0b00100011  ;den zähl wert des timers für ein...
>    out OCR1AL, temp
>    ldi temp, 0b11110100
>    out OCR1AH, temp

Beim Schreiben von 16-Bit-Registern erst H-Teil, dann L-Teil. Beim Lesen 
umgedreht.

>ldi temp, 0b00100011

ist absolut unverständlich.

-> ldi temp, High($F423)
   ldi temp, Low($F423)

sieht gleich viel besser aus.
Da wir gerade beim Timer sind. Deine Interruptroutine:

>sec1:
>  push temp      ; temp sichern

Hier fehlt das Sichern von SREG

>  clr temp
>  out TCNT1H, temp  ; Timer1 zurücksetzen
>  out TCNT1L, temp
>  pop temp      ; temp wiederherstellen

Das kannst du dir sparen, wenn du CTC benutzt
  ....

Hierher käme das Zurückschreiben von SREG

>loop2:ret        ; Allgemeiner rücksprungbefehl

Eine Interruptroutine wird mit reti beendet.

So etwas:

>  ausgabe2:
>    cpi temp, 0
>    breq zif0
>    cpi temp, 1
>    breq zif1
    ....
>                    ;  Hier sieht man die LEDs der Segmentanzeige
>zif0:                  ;  und die dazugehörige Bit nummer
>    ldi temp, 0b01110111      ;###################################
>    rjmp back            ;#                   #

macht man über eine Tabelle:
    ; Ziffer in temp

    ldi ZL,Low(ziffern<<1)
    ldi ZH,High(ziffern<<1)  
    clr temp2
    add ZL,temp
    adc ZH,temp2
    lpm temp,Z      ; Muster nach temp
    ....
                    
ziffern:
    .db 0b01110111,0b00100100
    .db 0b01011101,0b01101101
    .db 0b00101110,0b01101011
    .db 0b01111011,0b00100101
    .db 0b01111111,0b01101111

Das ist noch nicht alles. Lass dich aber nicht entmutigen. Ich habe hier 
schon viel schlimmeres gesehen.

MfG Spess

Autor: Hyronimus Herzberg (avr_by_ronny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Solche schreibweisen habe ich noch nie gesehen.

Ja und das mit den Einzelnden sprungbefehlen sieht wirklich nicht so gut 
aus.
Und zu der interrupt routine hatte ich aber ein kommentar geschrieben.
Ich frage das interrupt flag ab ob es gesetzt ist um zu erkennen, dass 
eine neue zeit zum ausgeben bereit steht.

Das hätte ich aber noch geändert.

Aber das mit dieser Tabelle kannst du mir ja erklären. Und sage ruhig 
was noch so schlimm ist. Ich lerne aus meinen fehlern.
Und leider kenne ich keinen der mir das näher beibringen könnte.
musste mir ja bis jetzt auch alles selber erarbeiten. (so wie viel denke 
ich mal)

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Solche schreibweisen habe ich noch nie gesehen.

Dann nimm dir mal die Zeit und sieh dir die Hilfe zu 
AVR-Assembler/AVR-Assembler2 in Ruhe an.

>Das hätte ich aber noch geändert.

Hellseherischen Fähigkeiten hat meine Frau. Allerdings keine Ahnung vom 
Programmieren.

>Aber das mit dieser Tabelle kannst du mir ja erklären.

ziffern:
   ....

Legt eine Tabelle im Programmspeicher an.

    ldi ZL,Low(ziffern<<1)
    ldi ZH,High(ziffern<<1)

'ziffer' ist eine Adresse im Programmspeicher. Dort repräsentiert eine 
Adresse aber einen 16-Bit-Wert (Word). 'lpm' verlangt aber eine Adresse 
für ein Byte (1/2 Word). 'ziffern<<1' entspricht ziffern*2.

    clr temp2           ; Null für Addition

    add ZL,temp         ; ZL+temp
    adc ZH,temp2        ; ZH+Übertrag (Carry-Flag)

Das ist die Addition eines Bytes zu einem Word

    lpm temp,Z      ; Muster nach temp

MfG Spess

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spess53 schrieb:

> ist absolut unverständlich.
>
> -> ldi temp, High($F423)
>    ldi temp, Low($F423)
>
> sieht gleich viel besser aus.

@Hyronimus.
Wobei hier noch nicht einmal die Notwendigkeit gegeben ist, das in 
Hex-Zahlen zu schreiben.
Wenn, wie dein Kommentar verrät, die Absicht ist, 62499 in das 
Registerpärchen zu schreiben
    ldi temp, 0b00100011  ;den zähl wert des timers für ein sec einstellen (16bit)(62499)
    out OCR1AL, temp
    ldi temp, 0b11110100
dann schreib das auch unmittelbar so, dass sich diese Absicht direkt im 
Code niederschlägt und nicht im Kommentar.
     ldi temp, High( 62499 )
     out OCR1AH, temp
     ldi temp, Low( 62499 )
     out OCR1AL, temp

Dem Assembler ist es wurscht, ob du eine Zahl angibst, indem du ihr 
Bitmuster hinschreibst, oder die entsprechende Hex-Zahl oder gleich 
dezimal. Es passiert sowieso immer das Gleiche: Das entsprechende 
Bitmuster wird in das Register geladen.
Nur für dich als menschlicher Programmierer macht es einen 
Riesenunterschied. Ganz abgesehen, dass du nicht selber mühsam die Bits 
bestimmen musst wobei es wieder 20 Möglichkeiten für Fehler gibt.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Und zu der interrupt routine hatte ich aber ein kommentar geschrieben.
>Ich frage das interrupt flag ab ob es gesetzt ist um zu erkennen, dass
>eine neue zeit zum ausgeben bereit steht.

Jetzt habe ich erst gesehen, was du da machst. Damit blockierst du bis 
zu 'reti' alle Interrupts. Dann könntest du die Ausgabe auch gleich in 
der Interruptroutine machen.

Wenn du ein Flag benutzen willst, dann bietet sich das T-Flag in SREG 
an. Das wird vom Controller nicht beeinflußt und steht zu deiner 
alleinigen Verwendung.

MfG Spess

Autor: Hyronimus Herzberg (avr_by_ronny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Vielen dank für die informationen!!

Also die schreibweiße eines word habe ich somit umgehend aufgenommen.
Hat mich auch immer genervt das im rechner erst zu dezimal umzurechnen.

Das ich die routine mit reti verlasse, werde ich noch ändern da die uhr 
in RGB mit PWM gebaut werden soll. (Dann aber ein Atmega8)

Die Tabelle verstehe ich noch nicht so recht vorallem was die carry 
addition beeinflusst.

Ich werde mir demnächst ein paar schöne bücher bestellen und auf 
göttliche erleuchtung hoffe ;-)

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Die Tabelle verstehe ich noch nicht so recht vorallem was die carry
>addition beeinflusst.

Das 'adc ZH,Null' berücksichtigt den Übertrag der Addition 'add 
ZL,temp'.

Beispiel:

  Z:    $00FF
  temp: $FF

  ZL + temp      = $FE  Übertrag: 1 (im Carryflag)
  ZH + Null + Cy = $01
  Ergebnis:   Z = $01FE

Ohne dieses 'adc' wäre $00FE herausgekommen, was offensichtlich falsch 
ist.

Ausführlich bei ATMEL:

http://www.atmel.com/dyn/resources/prod_documents/...
http://www.atmel.com/dyn/resources/prod_documents/avr202.zip

MfG Spess

Autor: Hyronimus Herzberg (avr_by_ronny)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So habe jetzt das ganze mal etwas überarbeitet

Die erklärungen treffen jetzt vllt nicht mehr 100% zu
aber dafür ist der quelcode nur noch 502byte groß

Dank einiger optiemierungen und der Tabelle die ich jetzt so halb
verstanden
habe.

Vielen dank an Spess für die offene kritik.
Weiter schreib verbesserungen nehme ich gerne entgegen

Bin noch fleißig am Lernen

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sieh dir deine Codeformatierung an.
Da liegt noch vieles im argen

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Sieh dir deine Codeformatierung an.
>Da liegt noch vieles im argen

Richtig. Schalte mal Edit->Show Whitespace. Dann wirst du das Chaos 
erkennen.
Tabulatoren haben im Quelltext nichts zu suchen.

MfG Spess

Autor: Spess53 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Vielen dank an Spess für die offene kritik.
>Weiter schreib verbesserungen nehme ich gerne entgegen

>.def sec01 = r17  ; Einerstelle der Sekunden (0-9)
>.def sec10 = r18  ; Zenerstelle der Sekunden (0-5)
>.def min01 = r19  ; Einerstelle der Minuten  (0-9)
>.def min10 = r20  ; Zenerstelle der Minuten  (0-5)
>.def std01 = r21  ; Einerstelle der Stunden  (0-9/4)
>.def std10 = r22  ; Zenerstelle der Stunden  (0-2)

Du benutzt für jede Ziffer ein Register. Ich persönlich würde nur mit 
Stunden, Minuten und Sekunden arbeiten. Die Zerlegung in Einer- und 
Zehnerstellen kann man bei der Ausgabe machen. Man braucht dafür auch 
keine Register, denn du hast auch noch RAM. Und wenn schon Register, 
dann die 'halbstarken' r0...r15.
Ich habe dir mal eine Datei mit Routinen angehängt, mit denen du sogar 
einen Wecker programmieren kannst, der dich schlafen lässt, wenn in 
deinem Bundesland Feiertag ist. Das Einzige, was noch fehlt ist die 
Sommer-/Winterzeitumstellung. Ist schon angefangen, aber irgendwie 
liegen geblieben.
Vielleicht hilft es dir. Die DateTime.mac (Makros) ist nur der 
Vollständigkeit halber dabei.

MfG Spess

Autor: Hyronimus Herzberg (avr_by_ronny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh man dein quelltext ist ja sehr umfangreich.
Mit dem sram habe ich noch nie gearbeitet.
Werde mich da gleich mal einlesen.

Und warum sollte man keine tabulatoren im quelltext verwenden??
Funktioniert doch oder was ist daran falsch.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hyronimus Herzberg schrieb:

> Und warum sollte man keine tabulatoren im quelltext verwenden??

Weil jeder eine andere Vorstellung davon hat, nach wievielen Schritten 
eine Tabulatorposition einzufügen ist.

> Funktioniert doch oder was ist daran falsch.
Sieh dir deinen Code weiter oben mal hier im Forum an!
Mach beide Versionen auf (ohne und mit automatischer Codeformatierung) 
und sieh dir mal an, wie da die Einrückungen sind. Sonderlich zuträglich 
zum Verständnis des Codes ist es gerade nicht, wenn sich alle 2 Seiten 
das Einrückschema verändert.


Dazu auch noch eine Beobachtung:
Interessanterweise sind es sehr oft die mit dem allgemein annerkannt 
grauslichstem Code, die die meisten Fehler in ihren Programmen haben. 
Und das beschränkt sich nicht nur auf Assembler, das ist in anderen 
Programmiersprachen genau gleich: Die mit dem Kraut und Rübencode haben 
meistens die dummen Fehler.

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Oh man dein quelltext ist ja sehr umfangreich.

Das kommt dir nur so vor.

>Mit dem sram habe ich noch nie gearbeitet.
>Werde mich da gleich mal einlesen.

Ist eigentlich relativ einfach:
    
       .dseg        ; Datensegment

aaa:   .byte 1      ; ein Byte reservieren

       .cseg        ; Codesegment

       ....

       ldi r16,$FF
       sts aaa,r16  ; $FF in aaa speichern

       lds r17,aaa  ; Inhalt von aaa nach r17

MfG Spess

Autor: Hyronimus Herzberg (avr_by_ronny)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe meine quelltext nochmal komplett überarbeitet und statt 
register nun mit dem sram gerechnet. also code ersparniss hatte ich 
jetzt nocht so viel aber etwas.

Habe erst mal die programmierung der uhr rausgeschmissen um das mit dem 
sram hin zubekommen aber meine uhr zeig nichts mehr an.
Da ich es nicht schaffe die werte des sram aufzuteilen

also wenn da gespeichert ist "23" brauche ich zuerst die 3 und dann die 
2 zum senden. aber ich kann das mathematisch nicht lösen das dass mit 
allen zahlen funktioniert.

Dies ist im "rcall ausgabe". Solche tricks kenne ich einfach noch nicht.

Autor: Hyronimus Herzberg (avr_by_ronny)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe ne lösung. Ich subtrahier immer 10 und für jedesmahl zähle ich 
ein anderes register hoch bis zum carry flag und dann einmal plus 10 und 
das andere wieder eins runter.

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Ich habe ne lösung. Ich subtrahier immer 10 und für jedesmahl zähle ich
>ein anderes register hoch bis zum carry flag und dann einmal plus 10 und
>das andere wieder eins runter.

Ich wollte dir gerade eine Routine dafür schicken. Aber wenn du selbst 
darauf gekommen bist, um so besser. Lange niemand hier erlebt, der sich 
so intelligent anstellt.

MfG Spess

Autor: Hyronimus Herzberg (avr_by_ronny)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Vielen dank.
Habe mir nen zettel genommen und die ein paar zahlen als binär und 
dezimal hingeschrieben und dann die ganze rol und und xor opperationen 
ausprobiert bis ich dann das subi genommen habe. hatte noch einen 
kleinen fehler hatte vergessen das temp4 zu löschen aber jetzt läuft die 
uhr wieder. könnte mit push und pop sogar temp4 sparen mal schauen ob 
ich das machen muss.

ist es so mit der formatierung halbwegs inordnung?

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>ist es so mit der formatierung halbwegs inordnung?

Sieh das nicht so eng. Ich persönlich bin es seit den 8-zigern des 
vorigen Jahrhunderts gewohnt, das Labels, Code und Kommentare jeweils in 
einer 'Spalte' stehen und eine Zeile Label, Code und Kommentar enthalten 
kann. Und dabei bleibe ich auch. Weitere Einrückungen, wie bei höheren 
Programmiersprachen machen, meiner Meinung nach, wenig Sinn. Nur sollte 
es einheitlich sein. Mit einer Einschränkung: wenn Labels und Code 
permanent am linken Rand kleben finde ich das extrem unübersichtlich.
Mach dir einen Reim daraus.

MfG Spess

Autor: Hyronimus Herzberg (avr_by_ronny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe mir dein Datetime mal angeschaut und das sieht wirklich besser aus.
Denke das ich mir das auch noch angewöhnen werde. Mit einem unterschied
Das Label bleibt eine Zeile drüber finde ich hübscher;-)

Ich möcht mich aber bei dir schon mal bedanken für die vielen tipps!

Werde jetzt noch die 8 kanal RGB PWM versuchen zu integrieren mittels 
SPI und wenn ich da nicht weiter komme melde ich mich noch.

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.