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 ;;; 4Das sind zunächst mal nicht wiederholung: 8+8 = 16
wenn die innere schleife n mal wiederholt wird:
(1+1+2)*ndann mit der äusseren
((1+1+2)*n*+1)*m+(1+1+2)*mSo und jetzt kann man ausrechnen, ein Befehl ist 1/4.000.000 MHz. aber ich gucke genau nach
3.686 MHzUnd jetzt, das sind
2,71296798698e-07sund 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,0041das 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)
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-07zu 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 = 8swir 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 retZweiter 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+1s
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.