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


von Hyronimus H. (avr_by_ronny)


Angehängte Dateien:

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.

von hdd (Gast)


Lesenswert?

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

von Hyronimus H. (avr_by_ronny)


Angehängte Dateien:

Lesenswert?

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

von Spess53 (Gast)


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:
1
    ; Ziffer in temp
2
3
    ldi ZL,Low(ziffern<<1)
4
    ldi ZH,High(ziffern<<1)  
5
    clr temp2
6
    add ZL,temp
7
    adc ZH,temp2
8
    lpm temp,Z      ; Muster nach temp
9
    ....
10
                    
11
ziffern:
12
    .db 0b01110111,0b00100100
13
    .db 0b01011101,0b01101101
14
    .db 0b00101110,0b01101011
15
    .db 0b01111011,0b00100101
16
    .db 0b01111111,0b01101111

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

MfG Spess

von Hyronimus H. (avr_by_ronny)


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)

von Spess53 (Gast)


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

von Karl H. (kbuchegg)


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
1
    ldi temp, 0b00100011  ;den zähl wert des timers für ein sec einstellen (16bit)(62499)
2
    out OCR1AL, temp
3
    ldi temp, 0b11110100
dann schreib das auch unmittelbar so, dass sich diese Absicht direkt im 
Code niederschlägt und nicht im Kommentar.
1
     ldi temp, High( 62499 )
2
     out OCR1AH, temp
3
     ldi temp, Low( 62499 )
4
     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.

von spess53 (Gast)


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

von Hyronimus H. (avr_by_ronny)


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 ;-)

von Spess53 (Gast)


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/doc0937.pdf
http://www.atmel.com/dyn/resources/prod_documents/avr202.zip

MfG Spess

von Hyronimus H. (avr_by_ronny)


Angehängte Dateien:

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

von Karl H. (kbuchegg)


Lesenswert?

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

von Spess53 (Gast)


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

von Spess53 (Gast)


Angehängte Dateien:

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

von Hyronimus H. (avr_by_ronny)


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.

von Karl H. (kbuchegg)


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.

von Spess53 (Gast)


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:
1
    
2
       .dseg        ; Datensegment
3
4
aaa:   .byte 1      ; ein Byte reservieren
5
6
       .cseg        ; Codesegment
7
8
       ....
9
10
       ldi r16,$FF
11
       sts aaa,r16  ; $FF in aaa speichern
12
13
       lds r17,aaa  ; Inhalt von aaa nach r17

MfG Spess

von Hyronimus H. (avr_by_ronny)


Angehängte Dateien:

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.

von Hyronimus H. (avr_by_ronny)


Angehängte Dateien:

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.

von Spess53 (Gast)


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

von Hyronimus H. (avr_by_ronny)


Angehängte Dateien:

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?

von Spess53 (Gast)


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

von Hyronimus H. (avr_by_ronny)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.