Forum: Mikrocontroller und Digitale Elektronik LCD wird immer aktualisiert


von Sven M. (Gast)


Lesenswert?

Hallo Leute ich ahbe ewin problem aber finde den fehler nicht ich 
schreibe OK in mein LCD lege dann in r18 die zahl 20ab und vergleiche 
beim nächsten laden r18 und die zahl 20 wenn beides gleich ist soll er 
die funktion in der er das display neu beschreibt überspringen die 
lcd-routines.asm kommt hier ausem tut
1
;main.asm
2
.include "m8515def.inc" ; Definitionsdatei für den Prozessortyp einbinden
3
4
.def temp1 = r16 ; register bestimmen
5
.def temp2 = r17
6
.def temp3 = r18
7
8
ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
9
out SPL, temp1  
10
ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
11
out SPH, temp1
12
ldi temp1, 0xFF ; I/O's setzen
13
out DDRC, temp1 ; Port C als ausgang setzen
14
15
rcall lcd_init ; Display initialisieren
16
rcall lcd_clear ; Display löschen
17
rcall main
18
19
main:
20
rcall lcd_ok ; lcd Ausgabe OK aufrufen
21
22
.include "lcd-routines.asm" ; lcd Arbeitsbefehle laden
23
.include "lcd-ausgaben.asm" ; lcd ausgaben laden
1
;lcd-ausgaben.asm
2
3
lcd_ok:
4
  cpi r19, 20
5
  brne lcd_ok_1
6
  ldi r19, 20
7
  rjmp main
8
9
lcd_ok_1:
10
  ldi ZL, LOW(text_ok*2) ; Adresse des Strings in den
11
  ldi ZH, HIGH(text_ok*2) ; Z-Pointer laden
12
  rcall lcd_flash_string ; Unterprogramm gibt String aus der
13
14
text_ok:
15
.db "OK",0 ; Ausgabe bei keinen fehler

von holger (Gast)


Lesenswert?

rjmp main

Wie wärs mit einem einfachen RET?



  rcall lcd_flash_string ; Unterprogramm gibt String aus der

Und wohin springt das Programm ab hier?
Auch hier fehlt ein RET

von Hansi (Gast)


Lesenswert?

In der Routine lcd_ok springst du wieder zu Main und nicht, wie nötig, 
mit ret zurück.

von Sven M. (Gast)


Lesenswert?

rcall lcd_flash_string

ist eine lcd routine die den Text ans LCD weitergiebt

wohin soll ich zurückspringen?  und reintehortis ist es doch egal weil 
das r19 ja auf 20 gesetzt wurde und somit einfach beim nächsten 
durchlauf zur main zurückgesprungen wird.

wenn es geht könntet iht mir rin beispiel machen ich bin anfänger was 
asm angeht

von Sven M. (Gast)


Lesenswert?

sry... aber ich kann nunmal nix für mein unwissen

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Sven M. schrieb:
> wohin soll ich zurückspringen?
Für dich uninteressant.
Das ret springt schon an die richtige Stelle zurück.
1
lcd_ok:
2
  cpi r19, 20
3
  brne lcd_ok_1
4
  ldi r19, 20
5
  ret
6
7
lcd_ok_1:
8
  ldi ZL, LOW(text_ok*2) ; Adresse des Strings in den
9
  ldi ZH, HIGH(text_ok*2) ; Z-Pointer laden
10
  rcall lcd_flash_string ; Unterprogramm gibt String aus der
11
  ret
Aber es ist klar, dass da dauernd was geschrieben wird, denn danach:
1
main:
2
rcall lcd_ok ;  lcd Ausgabe OK aufrufen
Wird irgendwann wieder von vorn begonnen....

So wird in der Mainloop gewartet:
1
main:
2
rcall lcd_ok ;  lcd Ausgabe OK aufrufen
3
mainloop:
4
rjmp mainloop

> sry... aber ich kann nunmal nix für mein unwissen
Aber dagegen: Lernen.

von Sven M. (Gast)


Lesenswert?

ja das tue ich ja durch eure beispiele :) ich lerne beim abtippen in dem 
ichmir die aufgaben der funktionen vor augen halte

aber... habe das gerade mal eingefügt und aufen avr geladen aber er 
aktualisiert noch immer dauerhaft i-was passt da nich

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Sven M. schrieb:
> aber... habe das gerade mal eingefügt und aufen avr geladen aber er
> aktualisiert noch immer dauerhaft i-was passt da nich
Watchdog aktiv?

von Sven M. (Gast)


Lesenswert?

sagst mir mal ebend den Fuse bit ambesten so wie er in PonyProg heißt

von Sven M. (Gast)


Lesenswert?

und ich kann nunmal nicht in einer extraschleife warten... weil nachher 
sollen dort abfragen gemacht werden und diese rufen nunmal bei jdem 
durchlauf lcd_ok auf

von Karl H. (kbuchegg)


Lesenswert?

Sven M. schrieb:
> ja das tue ich ja durch eure beispiele :) ich lerne beim abtippen

Das glaub ich ehrlich gesagt so nicht ganz

> in dem
> ichmir die aufgaben der funktionen vor augen halte

Du beachtest die Details viel zu wenig.
Irgendwo hast du den Befehl rcall gesehen und jetzt verwendest du ihn 
ohne zu wissen was er GENAU macht und wann man ihn einsetzt.

> aber... habe das gerade mal eingefügt und aufen avr geladen aber er
> aktualisiert noch immer dauerhaft i-was passt da nich

Wie sieht dein Programm jetzt aus?

Es gibt hunderte Möglichkeiten was du beim 'jetzt einsetzen' wieder 
falsch gemacht haben kannst. Und genau deswegen ist abtippen so 
problematisch. Viel besser wäre es, wenn Hinweise ausreichen würden, du 
darüber nachdenkst und dann selbst auf die Änderung kommst. Ein fertiges 
Ergebnis nachzuvollziehen ist zwar ein erster Schritt, aber es ist eben 
nur nachvollziehen und nicht selbst draufkommen. (Das ist die Sache mit 
dem Ei des Kolumbus. Sich eine Lösung präsentierten zu lassen ist 
einfach, auf eine Lösung zu kommen ist ungleich schwieriger)

von Sven M. (Gast)


Lesenswert?

Soo... habe den code jetzt mal komplett in die main geschreben und es 
geht

von Sven M. (Gast)


Lesenswert?

im übrigen auch ausgelagert läufts jetzt
1
.include "m8515def.inc" ; Definitionsdatei für den Prozessortyp einbinden
2
3
.def temp1 = r16 ; register bestimmen
4
.def temp2 = r17
5
.def temp3 = r18
6
7
ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
8
out SPL, temp1  
9
ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
10
out SPH, temp1
11
ldi temp1, 0xFF ; I/O's setzen
12
out DDRC, temp1 ; Port C als ausgang setzen
13
14
ldi r25, 10
15
16
rcall lcd_init ; Display initialisieren
17
rcall lcd_clear ; Display löschen
18
rcall main
19
20
main:
21
rcall lcd_ok
22
23
rjmp main
24
25
.include "lcd-routines.asm" ; lcd Arbeitsbefehle laden
26
.include "lcd-ausgaben.asm" ; lcd ausgaben laden
1
lcd_ok:
2
  cpi r25, 10
3
  breq lcd_ok_ja
4
  ldi r25, 11
5
  ret
6
7
lcd_ok_ja:
8
  ldi r25, 11
9
  ldi ZL, LOW(text_ok*2) ; Adresse des Strings in den
10
  ldi ZH, HIGH(text_ok*2) ; Z-Pointer laden
11
  rcall lcd_flash_string ; Unterprogramm gibt String aus der
12
  rjmp main
13
text_ok:
14
.db "OK",0 ; Ausgabe bei keinen fehler

von Karl H. (kbuchegg)


Lesenswert?

Immer noch falsch
1
lcd_ok_ja:
2
  ldi r25, 11
3
  ldi ZL, LOW(text_ok*2) ; Adresse des Strings in den
4
  ldi ZH, HIGH(text_ok*2) ; Z-Pointer laden
5
  rcall lcd_flash_string ; Unterprogramm gibt String aus der
6
  rjmp main

da gehört kein rjmp hin.

Du bist über einen rcall an diese Stelle gekommen. Dass du zwischendurch 
mal einen breq gemacht hast ist irrelevent. Der rcall von main wartet 
immer noch auf seine Auflösung durch einen ret. Machst du ihn nicht, 
geht dir irgendwann der Stack über.

Das ist doch nicht so schwer.

Mittels rcall springst du irgendwo hin. Dabei wird die Adresse des 
Befehls nach dem rcall auf den Stack abgelegt. Am Sprungziel kannst du 
dann machen was du willst, du musst nur:
* den Stack wieder in den gleichen Zustand bringen wie nachdem der rcall 
gesprungen ist. Sprich immer gleich viele Push wie Pop haben
* mittels einem RET wieder zurück zu der Stelle springen, von wo der 
rcall gekommen ist. Das geht deswegen, weil ja die Adresse vom rcall auf 
dem Stack abgelegt wurde.

Verletzt du eine der beiden Voraussetzungen, dann läuft dir unweigerlich 
irgendwann der Stack über und grausame Programmabstürze bzw. seltsames 
Programmverhalten sind die Folge.

von Sven M. (Gast)


Lesenswert?

oh... ja sry habe die stelle ganz übersehen klar muss da ein RET hin 
mich entschuldige für den bekloppten fehler

von Sven M. (Gast)


Lesenswert?

Hallo Leute,
sry muss euch noch ein mal nerfen undzwar geht es darum kann ich auch 
nur 1Pin von z.B. PortD als eingang benutzen und die restlichen als 
ausgang?, wenn ja wie mach ich das mit dem auslesen des pins und mit den 
ausgeben von signalen über die anderen Pins?

von spess53 (Gast)


Lesenswert?

Hi

>sry muss euch noch ein mal nerfen undzwar geht es darum kann ich auch
>nur 1Pin von z.B. PortD als eingang benutzen und die restlichen als
>ausgang?,

Ja.

> wenn ja wie mach ich das mit dem auslesen des pins und mit den
>ausgeben von signalen über die anderen Pins?

sbic
sbis
sbi
cbi
and(i)

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Sven M. schrieb:
> Hallo Leute,
> sry muss euch noch ein mal nerfen undzwar geht es darum kann ich auch
> nur 1Pin von z.B. PortD als eingang benutzen und die restlichen als
> ausgang?, wenn ja wie mach ich das mit dem auslesen des pins und mit den
> ausgeben von signalen über die anderen Pins?


AVR-Tutorial
gleich das erste Kapitel in dem das erste mal programmiert wird.

von Sven M. (Gast)


Lesenswert?

ehhmm ....

ich bin gerade dabei ein timer zu programmeren aber sobald ich
.org OVF1addr
rjmp power_on ; Timer Overflow Handler

 bestimme wo hin der overflow gehen soll wird meine LCD ausgabe nur noch 
swartz
1
main.asm!!
2
3
.include "m8515def.inc" ; Definitionsdatei für den Prozessortyp einbinden
4
5
.def temp1 = r16 ; register bestimmen
6
.def temp2 = r17
7
.def temp3 = r18
8
.def temp4 = r20
9
10
.org OVF1addr
11
rjmp power_on ; Timer Overflow Handler
12
13
ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
14
out SPL, temp1  
15
ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
16
out SPH, temp1
17
ldi temp1, 0xFF ; I/O's setzen
18
out DDRC, temp1 ; Port C als ausgang setzen
19
ldi temp1, 0xb00000011 ; I/O's setzen
20
out DDRA, temp1 ; PortA Pin A0 un A1 als ausgang setzen
21
22
ldi r25, 10
23
24
rcall lcd_init ; Display initialisieren
25
rcall lcd_clear ; Display löschen
26
rcall power
27
rcall main
28
29
main:
30
rcall lcd_ok
31
32
rjmp main
33
34
.include "lcd-routines.asm" ; lcd Arbeitsbefehle laden
35
.include "lcd-ausgaben.asm" ; lcd ausgaben laden
36
.include "power_supply.asm" ; 50hz ausgabe laden
37
38
39
40
lcd-ausgaben.asm!!!
41
42
43
44
lcd_ok:
45
  cpi r25, 10
46
  breq lcd_ok_ja
47
  ldi r25, 11
48
  ret
49
50
lcd_ok_ja:
51
  ldi r25, 11
52
  ldi ZL, LOW(text_ok*2) ; Adresse des Strings in den
53
  ldi ZH, HIGH(text_ok*2) ; Z-Pointer laden
54
  rcall lcd_flash_string ; Unterprogramm gibt String aus der
55
  ret
56
text_ok:
57
.db "OK",0 ; Ausgabe bei keinen fehler
58
59
60
61
power_supply.asm!!!
62
63
64
65
power:
66
ldi temp4, 0xB1
67
out TCNT1L, temp4         ; set preset in
68
ldi temp4, 0xE0
69
out TCNT1H, temp4         ; set preset in
70
ldi temp4, 0b00000001 ; CS00 setzen: Teiler 1
71
out TCCR1B, temp4
72
ldi temp4, 0b00000100 ; TOIE1: Interrupt bei Timer Overflow
73
out TIMSK, temp4
74
sei
75
ldi temp4, 0b00000001
76
ret
77
78
power_on:
79
cpi temp4, 0b00000001
80
breq power_low
81
ldi temp4, 0b00000001
82
out PORTA, temp4
83
ret
84
85
power_low:
86
ldi temp4, 0b00000010
87
out PORTA, temp4
88
ret

und eigendlich habe ich kein fehler gemacht :/ oder seht ihr einen?

von Spess53 (Gast)


Lesenswert?

Hi

>und eigendlich habe ich kein fehler gemacht :/ oder seht ihr einen?

Einen?

An den Anfang des Programms (Adresse $0000) gehört ein Sprung zum 
eigentlichen Programmanfang.

Interrupts werden mit 'reti' abgeschlossen.

Was soll der Mist mit 'rcall main'?

MfG Spess

von Sven M. (Gast)


Lesenswert?

Spess53 schrieb:
> An den Anfang des Programms (Adresse $0000) gehört ein Sprung zum
> eigentlichen Programmanfang.


kannst du mir das mal erklären?

von agentur (Gast)


Lesenswert?

zBsp.
1
 
2
3
.include "2313def.inc"
4
;.device AT90S2313
5
6
.def  T1    =r1
7
.def  T2    =r2
8
9
10
.equ  PreScal  =3  ;timer prescale by 64
11
.equ  C  =119  ;time 
12
13
;********************************************************
14
.eseg
15
.org 0              
16
    .db 89,6,79,2,71,4  
17
    .db 79,4,63,4,71,4  
18
    .db 79,2,94,2,89,4
19
    
20
21
;*******************************************************
22
.cseg
23
.org $0000                    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
24
25
  rjmp RESET   ; Reset Handler
26
  reti     ;rjmp EXT_INT0 ; IRQ0 Handler
27
  reti     ;rjmp EXT_INT1 ; IRQ1 Handler
28
  reti     ;rjmp TIM_CAPT1 ; Timer1 Capture Handler
29
  reti     ;rjmp TIM_COMP1 ; Timer1 Compare Handler
30
  reti     ;rjmp TIM_OVF1 ; Timer1 Overflow Handler
31
  rjmp TIMER  ;    TIM_OVF0 ; Timer0 Overflow Handler
32
  reti     ;rjmp UART_RXC ; UART RX Complete Handler
33
  reti     ;rjmp UART_DRE ; UDR Empty Handler
34
  reti     ;rjmp UART_TXC ; UART TX Complete Handler
35
  reti     ;rjmp ANA_COMP ; Analog Comparator Handler
36
37
RESET:  
38
    ldi r16,low(RAMEND); Main program start
39
    out SPL,r16      ; !!!!! Set Stack pointer

an der Adresse $0000 beginnen die Sprungvektoren
der erste an adr.0 zeigt auf die adr. wo der Proz. nach einem Reset 
seine Programausführung startet.

Ich hab mir grad mal das tut angesehen und musste leider feststellen das
darauf nicht eingegangen wird . In dem guten glauben das der Proz seinen
Speicher linear abgrast und schon das macht was er machen soll wenn er 
an der entsprechenden Stelle ankommt, was ja leider auch zu 90% klappt.
Aber ein sauberer Programmierstil ist es nicht , und führt halt dazu das
wenn Programmteile abgeschrieben und verändert werden die funktionalität 
nicht mehr gewährleistet ist.

mfg

von Spess53 (Gast)


Angehängte Dateien:

Lesenswert?

HI

>kannst du mir das mal erklären?

Ja. Der Controller fängt nach einem Reset An der Adresse $0000 an das 
Programm abzuarbeiten. Ab Adresse, je nach Controller, $0001 oder $0002 
beginnt die Interruptvektortabelle. Um diese zu 'überspringen' setzt man 
an auf $0000 einen Sprung zum eigentlichen Programmanfang.

Bei mir sieht der Rumpf eines Programms wie im Anhang aus.

Nachtrag:

In Interrupts muss man SREG sichern.

>ja das tue ich ja durch eure beispiele :) ich lerne beim abtippen in dem
>ichmir die aufgaben der funktionen vor augen halte
>aber... habe das gerade mal eingefügt und aufen avr geladen aber er
>aktualisiert noch immer dauerhaft i-was passt da nich

Irgendwie klappt das nicht so richtig. Deine Programmiererei sieht 
Sch... aus.

MfG Spess

von Henrik (Gast)


Lesenswert?

Niemand hat hier übrigens etwas gegen Punkt oder Kommasetzung. Vllt 
gehts nur mir so, aber deine Texte sind schwierig zu lesen...

von Spess53 (Gast)


Lesenswert?

Hi

Henrik schrieb:
> Niemand hat hier übrigens etwas gegen Punkt oder Kommasetzung. Vllt
> gehts nur mir so, aber deine Texte sind schwierig zu lesen...

Rate mal, weshalb das Programm so konfus ist.

MfG Spess

von Sven M. (Gast)


Lesenswert?

okay soweit habe ich jetzt verstanden wie ihr das meint :)

danke schonmal nur jetzt meine letzte frage is Timer 1 so richtig 
initalisiert?
1
ldi temp4, 0xB1
2
out TCNT1L, temp4         ; set preset in
3
ldi temp4, 0xE0
4
out TCNT1H, temp4         ; set preset in
5
ldi temp4, 0b00000001 ; CS00 setzen: Teiler 1
6
out TCCR1B, temp4
7
ldi temp4, 0b00000100 ; TOIE1: Interrupt bei Timer Overflow
8
out TIMSK, temp4

also der timer soll alle 20sek einen Overflow erzeugen bei einer frquenz 
von 1Mhz

ichweiß halt nich ob das mit dem vorladen richtig ist also der Wert 
45536 sollte vorgeladen werden.

Stimmt das alles so?

von Sven M. (Gast)


Lesenswert?

Sven M. schrieb:
> timer soll alle 20sek einen Overflow

sry alle 20ms meinte ich :)

von Karl H. (kbuchegg)


Lesenswert?

Sven M. schrieb:

>
1
> ldi temp4, 0xB1
2
> out TCNT1L, temp4         ; set preset in
3
> ldi temp4, 0xE0
4
> out TCNT1H, temp4         ; set preset in
5
> ldi temp4, 0b00000001 ; CS00 setzen: Teiler 1
6
> out TCCR1B, temp4
7
> ldi temp4, 0b00000100 ; TOIE1: Interrupt bei Timer Overflow
8
> out TIMSK, temp4
9
>

Tu das nicht. (Schön langsam werde ich es leid immer wieder dasselbe 
predigen zu müssen).

So muss jeder im Datenblatt nachsehen, ob zb 0b00000100 wirklich das 
TOIE1 Bit in TIMSK ist.

Schreibst du es so
1
     ldi  temp4, (1<<TOIE1)
2
     out TIMSK, temp4
braucht zumindest dieses Detail niemand nachschlagen.


Wenn du den Timer mit 45536 vorladen willst, dann ist das dümmste was du 
tun kannst, dir selber diese Zahl in Hex umzuwandeln und dann die Bytes 
zuzuweisen
1
  ldi temp4, Low(45536)
2
  out TCNT1L, temp4         ; set preset in
3
  ldi temp4, High(45536)
4
  out TCNT1H, temp4         ; set preset in

Kannst du sehen, warum diese Schreibweise sehr viel besser ist als 
deine?

Das Tutorial ist voll mit derartigen Kleinigkeiten, die man nicht alle 
im Text beschrieben wiederfindet. Nur muss man den Code auch aufmerksam 
studieren! Nicht auf jeden Pfurz wird man extra hinbgewiesen, vieles 
muss man sich selbst erarbeiten, indem man sich fremde Programme 
ansieht. Und zwar genau ansehen! Nicht einfach drüberlesen und 'Aha' 
sagen, sondern studieren! Wie hat der Autor bestimmte Dinge gelöst? Was 
ist die Idee hinter einer SChreibweise? Welchen Vorteil hat sie? Was 
bringt sie mir als Programmierer? Welchen Fehler kann ich dadurch 
vermeiden? Welches Fehlerpotential gibt es überhaupt an dieser Stelle, 
so dass man eine bestimmte Schreibweise bevorzugt um ihn nicht zu 
machen? etc. etc. Vielleicht hat der Autor auch geschlampt und genau 
etwas gemacht, was man so nicht macht.
Das ist 'Studieren eines Codes' und nicht einfach nur 'abschreiben'. 
Durch 'studieren' lernst du. Durch 'abschreiben' lernst du nichts.


Und arbeite an deinem Codestil. Alles an den linken Rand zu quetschen 
ist kein Codestil!

In einem gewissen Sinne hat Spess weiter oben nämlich schon recht. Die 
Programmierer mit dem grauslichsten, unübersichtlichsten Code sind 
meistens auch diejenigen, die die meisten (dummen) Fehler machen.

Ein dummer Fehler ist es zb. erst das Low-Register und erst dann das 
High Register zu beschreiben. Ob das jetzt das Count Register vom Timer 
oder der Stackpointer ist, spielt keine Rolle. Oder findest du im 
Tutorial ein Beispiel dafür wo der Stackpointer genau anders herum (wie 
bei dir)  initialisiert wird?

von Spess53 (Gast)


Lesenswert?

Hi

>Stimmt das alles so?

Nein.

>ldi temp4, 0xB1
>out TCNT1L, temp4         ; set preset in
>ldi temp4, 0xE0
>out TCNT1H, temp4         ; set preset in

Beim Schreiben von 16-Bit_Registern erst H-Teil. dann L-Teil. Beim Lesen 
umgedreht.

Dem Timer ist es ziemlich egal, wo er anfängt. Der nächste Durchlauf 
fängt dann wieder bei Null an. Preload ist Müll. Dafür gibt es CTC.

Tu bitte dir, und uns einen Gefallen und lies dir das Datenblatt von 
deinem Controller durch und arbeite dich durch das Tutorial. Oder wie 
lange meinst du, will hier irgend jemand ständig den Müll, den du durch 
deine vermeidbare Unkenntnis produzierst, korrigieren. Fang erst mal mit 
kleineren Brötchen an.

MfG Spess

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.