LCD

so, jetzt probiere ich mich mit komplizierterem, nämlich erst dem LCD - ich benutze keinen Timer für die warteschleife. Ich rechne es hier vor. Ich muss ja senden, 0x03, 0x03, 0x03, 0x30. Das dürfte ein geringeres Problem sein, auch als Nibble.

Dann muss ich erst am Anfang 15ms warten, dann 4,1 ms, dann 100 mikrosekunden

Ich mache das so. Ich mache einfach zunächst mal eine Warteschleife, das dürfte kein Problem sein. Einfach eine generelle Warteschleife.

ich mache einfach eine generelle Warteschleife und rechne, die anzahl der Takte zusammen. Ich nehme bewusst kein Interrupt. Ich nehme die Warteschleife von vorher

´
sleep:
push r16
push r17
ldi r16, 0x00
sleep_loop1:
ldi r17, 0x00
sleep_loop2:
inc r17
cpi r17, 0xff
brne sleep_loop2
inc r16
cpi r16, 0xff
brne sleep_loop1
pop r17
pop r16
ret

Fangen wir an:

rcall sleep ;;;;;;;3

 ...

sleep:
push r16 ;;;;;2
push r17 ;;;;;2
ldi r16, 0x00 ;;;;;1
sleep_loop1:
ldi r17, 0x00 ;;;;;1
sleep_loop2:
inc r17 ;;;;;1
cpi r17, 0xff ;;;;;1
brne sleep_loop2 ;;;;; bei nicht sprung 1, sonst 2, normal 2:
inc r16 ;;;;;1
cpi r16, 0xff ;;;;;1
brne sleep_loop1 ;;;;; bei nicht sprung 1, sonst 2, normal 2:
pop r17 ;;; 2
pop r16 ;;; 2
ret ;;; 4

Das sind zun"achst mal nicht wiederholung:

rcall sleep ;;;;;;;3

 ...

sleep:
push r16 ;;;;;2
push r17 ;;;;;2
ldi r16, 0x00 ;;;;;1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sleep_loop1:
ldi r17, 0x00 ;;;;;1
sleep_loop2:
inc r17 ;;;;;1
cpi r17, 0xff ;;;;;1
brne sleep_loop2 ;;;;; bei nicht sprung 1, sonst 2, normal 2:
inc r16 ;;;;;1
cpi r16, 0xff ;;;;;1
brne sleep_loop1 ;;;;; bei nicht sprung 1, sonst 2, normal 2:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pop r17 ;;; 2
pop r16 ;;; 2
ret ;;; 4
Das sind zunächst mal nicht wiederholung: 8+8 = 16

wenn die innere schleife n mal wiederholt wird:

(1+1+2)*n
dann mit der äusseren
((1+1+2)*n*+1)*m+(1+1+2)*m
So und jetzt kann man ausrechnen, ein Befehl ist 1/4.000.000 MHz. aber ich gucke genau nach
 3.686 MHz
Und jetzt, das sind
2,71296798698e-07s
und jetzt
((2,71296798698e-07+2,71296798698e-07+2*2,71296798698e-07)*n*+1*2,71296798698e-07)*m+(1*2,71296798698e-07+1*2,71296798698e-07+2*2,71296798698e-07)*m=4,1/0,0041
das probiere ich mal mit xmaxima irgendwie zu lösen oder so

Zum Beispiel

(%i3) ((2.71296798698e-07+2.71296798698e-07+2*2.71296798698e-07)*n*+1*2.71296798698e-07)*m+(1*2.71296798698e-07+1*2.71296798698e-07+2*2.71296798698e-07)*m=0.0041;
(%o3)    2.944078119351326E-13 m n + 1.085187194792E-6 m = 0.0041
(%i4)

Image Screenshot_20241029_044251 Da steht jetzt keine Lösung, das Ergebnis überrascht mich. Ich habe eine bessere Idee. Ich setze für m für das innere einfach mal 256 ein und dann rechne ich das neu aus.

Anstatt

2.71296798698e-07
zu schreiben, nehme ich
(float)1/(float)3686000

Und schreibe den Ausdruck in C hin

Entschuldigung nicht für m sondern n

das hat nicht funktioniert, aber ich mache es sauberer

//((((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))*n*+(float)((float)1/(float)3683000))*m+((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))*m;

#include <stdio.h>

#define n 255

int main (void) {

    printf ("%f\n", (float)((float)4.1/(float)1000)/((((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))*n*+(float)((float)1/(float)3683000))+((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))));
}
So, das sieht schon besser aus
//((((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))*n*+(float)((float)1/(float)3683000))*m+((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))*m;


#include <stdio.h>

int main (void) {
    float t = 4.1/(float)(1000);
    float n = (float)255;
    float x;

    printf ("%f\n", (float)((float)4.1/(float)1000)/((((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))*n*+(float)((float)1/(float)3683000))+((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))));

    x = ((1*t+1*t+2*t)*n*+1*t)+(1*t+1*t+2*t);
    printf ("%f\n", x);
}
Da kommt raus
david@work:~$ ./a.out
3774.813721
0.033546
david@work:~$
Das heisst, indem falle wurde m = 1 gesetzt und das bedeutet, alleine mit der inneren schleife, für m = 1, dauert es bei n=256 etwa, 0.034s

Das entspricht der erfahrung. Rechnen wir mal aus

0.034s*256 = 8s
wir können den Test machen, am Controller und die Zeit stoppen

das kann nicht stimmen, weil der macht ja jetzt schon weniger als eine s.

Ach gucken sie mal: ich habe t falsch gesetzt

float t = 4.1/(float)(1000);
Das stimmt natürlich nicht.

das kann auch nicht sein

david@work:~$ ./a.out
3774.813721
0.000001
david@work:~$
ich weiss, wo der Fehler war, syntaxfehler, da stand +*
//((((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))*n*+(float)((float)1/(float)3683000))*m+((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))*m;
C-Code
#include <stdio.h>

int main (void) {
    float t = (float)1.0/(float)3683000;
    float n = (float)255;
    float x;

    printf ("%f\n", (float)((float)4.1/(float)1000)/((((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))*n*+(float)((float)1/(float)3683000))+((float)((float)1/(float)3683000)+(float)((float)1/(float)3683000)+(float)((float)2/(float)3683000))));

    x = ((1.0*t+1.0*t+2.0*t)*n+1.0*t)+(1.0*t+1.0*t+2.0*t);
    printf ("%f\n", x);

      x = (((4.0*t)*n+5.0*t))*n;
    printf ("%f\n", x);
}
Also jetzt kommt raus
david@work:~$ ./a.out
3774.813721
0.000278
0.070968
david@work:~$
Das könnte gerade so sein. ich mache eine Schleife drum rum, um das bisher, mit dem 12 fachen. Das müsste, 1s ergeben, dann kann ich messen. Erster Versuch
.include "m8def.inc"

ldi r16, HIGH (RAMEND)
out SPH, r16
ldi r16, LOW (RAMEND)
out SPL, r16

ldi r16, 0xff
out DDRB, r16

rcall lcd_init

ldi r16, 'a'
rcall lcd_chout
ldi r16, 'b'
rcall lcd_chout
ldi r16, 'e'
rcall lcd_chout
ldi r16, 'r'
rcall lcd_chout
ldi r16, ' '
rcall lcd_chout
ldi r16, 'h'
rcall lcd_chout
ldi r16, 'a'
rcall lcd_chout
ldi r16, 'l'
rcall lcd_chout
ldi r16, 'l'
rcall lcd_chout
ldi r16, 'o'
rcall lcd_chout

end: rjmp end

lcd_chout:
push r17
push r16
mov r17, r16
swap r16
andi r16, 0b00001111
sbr r16, 1<<4 ; wichtig RS=0 befehl, rs=1, daten, ja, aber hier daten
out PORTB, r16
rcall lcd_enable
andi r17, 0b00001111
sbr r17, 1<<4
out PORTB, r17
rcall lcd_enable
pop r16
pop r17
ret


lcd_init:
push r16
rcall sleep_15ms
ldi r16, 0x03
out PORTB, r16
rcall lcd_enable
rcall sleep_4_1ms
ldi r16, 0x03
out PORTB, r16
rcall lcd_enable
rcall sleep_100mus
ldi r16, 0x03
out PORTB, r16
rcall lcd_enable
ldi r16, 0x02
out PORTB, r16
rcall lcd_enable
pop r16
ret

lcd_enable:
sbi PORTB, 5
nop
nop
nop
cbi PORTB, 5
ret


sleep_15ms:
push r16
push r17
ldi r16, 0x00
sleep_15ms_loop1:
ldi r17, 0x00
sleep_15ms_loop2:
inc r17
cpi r17, 90
brne sleep_15ms_loop2
inc r16
cpi r16, 0xC9
brne sleep_15ms_loop1
pop r17
pop r16
ret

sleep_4_1ms:
push r16
push r17
ldi r16, 0x00
sleep_4_1ms_loop1:
ldi r17, 0x00
sleep_4_1ms_loop2:
inc r17
cpi r17,32
brne sleep_4_1ms_loop2
inc r16
cpi r16, 0xC9
brne sleep_4_1ms_loop1
pop r17
pop r16
ret

sleep_100mus:
push r16
ldi r17, 0
sleep_100mus_loop2:
inc r17
cpi r17, 67
brne sleep_100mus_loop2
pop r16
ret
Zweiter versuch
.include "m8def.inc"

ldi r16, HIGH (RAMEND)
out SPH, r16
ldi r16, LOW (RAMEND)
out SPL, r16

ldi r16, 0xff
out DDRB, r16

rcall lcd_init

ldi r16, 'a'
rcall lcd_chout
ldi r16, 'b'
rcall lcd_chout
ldi r16, 'e'
rcall lcd_chout
ldi r16, 'r'
rcall lcd_chout
ldi r16, ' '
rcall lcd_chout
ldi r16, 'h'
rcall lcd_chout
ldi r16, 'a'
rcall lcd_chout
ldi r16, 'l'
rcall lcd_chout
ldi r16, 'l'
rcall lcd_chout
ldi r16, 'o'
rcall lcd_chout

end: rjmp end

lcd_chout:
push r17
mov r17, r16
swap r16
andi r16, 0b00001111
sbr r16, 1<<4 ; wichtig RS=0 befehl, rs=1, daten, ja, aber hier daten
out PORTB, r16
rcall lcd_enable
andi r17, 0b00001111
sbr r17, 1<<4
out PORTB, r17
rcall lcd_enable
rcall sleep_50mus
pop r17
ret


lcd_cmdout:
push r17
mov r17, r16
swap r16
andi r16, 0b00001111
out PORTB, r16
rcall lcd_enable
andi r17, 0b00001111
out PORTB, r17
rcall lcd_enable
rcall sleep_50mus
pop r17
ret


lcd_init:
push r16
ldi r16, 50
powerupwait:
rcall sleep_4_1ms
dec r16
brne powerupwait
ldi r16, 0x03
out PORTB, r16
rcall lcd_enable
rcall sleep_4_1ms
ldi r16, 0x03
out PORTB, r16
rcall lcd_enable
rcall sleep_4_1ms
ldi r16, 0x03
out PORTB, r16
rcall lcd_enable
rcall sleep_4_1ms
ldi r16, 0x02
out PORTB, r16
rcall lcd_enable
rcall sleep_4_1ms

           ldi r16, 0b00101000
           rcall lcd_cmdout
           ldi r16, 0b00001100
           rcall lcd_cmdout
           ldi r16, 0b00000110
           rcall lcd_cmdout
pop r16
ret

lcd_enable:
sbi PORTB, 5
nop
nop
nop
cbi PORTB, 5
ret


sleep_50mus:
           ldi  r16, $42
sleep_100mus_loop1:dec   r16
           brne sleep_100mus_loop1
           ret
ret

sleep_4_1ms:
push r16
push r17
           ldi  r16, $21
WGLOOP0:   ldi  r17, $C9
WGLOOP1:   dec  r17
           brne WGLOOP1
           dec  r16
           brne WGLOOP0
           ret
pop r17
pop r16
ret

sleep_100mus:
push r16
ldi r17, 0
sleep_100mus_loop2:
inc r17
cpi r17, 67
brne sleep_100mus_loop2
pop r16
ret
Dritter Versuch
.include "m8def.inc"

ldi r16, HIGH (RAMEND)
out SPH, r16
ldi r16, LOW (RAMEND)
out SPL, r16

ldi r16, 0xff
out DDRD, r16

rcall lcd_init

ldi r16, 'a'
rcall lcd_chout
ldi r16, 'b'
rcall lcd_chout
ldi r16, 'e'
rcall lcd_chout
ldi r16, 'r'
rcall lcd_chout
ldi r16, ' '
rcall lcd_chout
ldi r16, 'h'
rcall lcd_chout
ldi r16, 'a'
rcall lcd_chout
ldi r16, 'l'
rcall lcd_chout
ldi r16, 'l'
rcall lcd_chout
ldi r16, 'o'
rcall lcd_chout

end: rjmp end

lcd_chout:
push r17
mov r17, r16
swap r16
andi r16, 0b00001111
sbr r16, 1<<4 ; wichtig RS=0 befehl, rs=1, daten, ja, aber hier daten
out PORTD, r16
rcall lcd_enable
andi r17, 0b00001111
sbr r17, 1<<4
out PORTD, r17
rcall lcd_enable
rcall sleep_50mus
pop r17
ret


lcd_cmdout:
push r17
mov r17, r16
swap r16
andi r16, 0b00001111
out PORTD, r16
rcall lcd_enable
andi r17, 0b00001111
out PORTD, r17
rcall lcd_enable
rcall sleep_50mus
pop r17
ret


lcd_init:
push r16
ldi r16, 50
powerupwait:
rcall sleep_4_1ms
dec r16
brne powerupwait
ldi r16, 0x03
out PORTD, r16
rcall lcd_enable
rcall sleep_4_1ms
ldi r16, 0x03
out PORTD, r16
rcall lcd_enable
rcall sleep_4_1ms
ldi r16, 0x03
out PORTD, r16
rcall lcd_enable
rcall sleep_4_1ms
ldi r16, 0x02
out PORTD, r16
rcall lcd_enable
rcall sleep_4_1ms

           ldi r16, 0b00101000
           rcall lcd_cmdout
           ldi r16, 0b00001100
           rcall lcd_cmdout
           ldi r16, 0b00000110
           rcall lcd_cmdout
pop r16
ret

lcd_enable:
sbi PORTD, 5
nop
nop
nop
cbi PORTD, 5
ret


sleep_50mus:
           ldi  r16, $42
sleep_100mus_loop1:dec   r16
           brne sleep_100mus_loop1
           ret
ret

sleep_4_1ms:
push r16
push r17
           ldi  r16, $21
WGLOOP0:   ldi  r17, $C9
WGLOOP1:   dec  r17
           brne WGLOOP1
           dec  r16
           brne WGLOOP0
pop r17
pop r16
ret

sleep_100mus:
push r16
ldi r17, 0
sleep_100mus_loop2:
inc r17
cpi r17, 67
brne sleep_100mus_loop2
pop r16
ret

jetzt müssten wir die Formel noch mal machen

das stimmt nicht

      x = (((((4.0*t)*n+5.0*t))*n)+5.0*t)*5.0;
    printf ("%f\n", x);

david@work:~$ ./a.out
3774.813721
0.000278
0.354847
david@work:~$

das sind mindest 1.5s

https://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD

gut, laut dem artikel liege ich schon mal richtig, sie rechnen, aber takt für die verzweigung, ich 3

Der Code benötigt eine Warteschleife, die mindestens 50 µs dauert. Die beiden Befehle innerhalb der Schleife benötigen 3 Takte: 1 Takt für den dec und der brne benötigt 2 Takte, wenn die Bedingung zutrifft, der Branch also genommen wird. Bei 4 MHz werden also

4000000 / 3 * 50 / 1000000 ~= 67

Die Formel die sie so rum angeben, finde ich besser. Ich mache die Rechnung noch mal und versuche auf 1s zu kommen.

4.000.000 => 1s

ich brauche als 4.000.000 Befehle

Die innere schleife

4 Takte

Also ((4*255)+5)*255+1
s

Das 5 bei der äusseren kommt zustande, durch das ldi, was vor der inneren steht

also, gut ich möchte ja jetzt die übung machen, ich nehme für die Warteschleife deren werte, für die Wiederholungen.

OK, jetzt mache ich das so - ich nehme die Warteschleife, ich brauche 3. Die entsprechenden schleifewerte führe ich nachher ein, also durchläufe und mache den Rest.

da war auch ein fehler in dem für das Display - i2c - hat nichts geholfen, ein falsches bit

jetzt mit deren sleep tut es was nur die zeichen stimmen noch nicht.

ha, ha, ha, ha, ich habe den fehler gefunden, er war ganz dumm Ich habe dann ja angefangen die zählschleifen zu übernehmen, weil das nicht so toll war was ich gemacht hatte damit und dabei habe ich die Register gesichert auf dem Stack und hab dann das Return ausgeführt. Da war's bei mir auch. Allerdings hab ich ja den Teil vom Code einfach übernommen mit der Zählschleife, damit es stimmt und dabei ist es Return beim Kopieren Wieder mit reingekommen und dahinter war Push und Pop und damit war da einfach ein Fehler auf dem Stapel, weil weil da eben das nicht mitgenommen wurde. Ich zeige jetzt alle Codes, die ich habe.

Image IMG_4279

Image IMG_4280