Guten Tag,
ich möchte euch hier ein Scheduler zeigen. Vielleicht kann das für
jemand behilflich werden.
Grundidee stammt von einem Blogger mit Pseudonym DI HALT.
Vorteil so einer Lösung, wenn auf den ersten Blick auch etwas
abschreckend aussieht: man kann Projekt leichter pflegen und erweitern.
Hier ist eine Probe, mit einer Platine mit AtMega128A von Olimex.
Scheduler selbst, das sind rtos.c und rtos.h. Alles andere ist nur zum
Verständnis, wie alles funktioniert. Tastenabfrage ist nach Herrn
Dannegger. lcd.c und lcd.h - Grundideen aus diesem Forum, dazu noch
Modus mit Puffer in RAM (um nicht nach jedem Zeichen 50 us nutzlos
warten zu müssen).
Außer Init gibt es vier Funktionen:
SetTask speichert eine Aufgabe in Puffer.
SetTimerTask speichert eine Aufgabe in Timmerpuffer, für Verzögerung.
TaskManager arbeitet in der Hauptschleife ( while(1) ) und führt die
Aufgaben aus.
TimerService wird in Timerinterrupt jede 1 ms (oder so ähnlich)
durchgeführt: Die Programmtimer werden decrementiert und nach der Zeit
wird die Aufgabe mit SetTask in Puffer gesetzt.
Aufgabenpuffer ist als Ring gemacht, Timerpuffer nicht als Ring.
Zusätzlich gibt es die Möglichkeit, für jede Aufgabe bis 3 Variablen zu
speichern, die auch in Puffern bleiben. Diese Funktionalität ist zwar
nicht zwingend notwendig und kostet RAM und Zeit, erleichtert aber das
Programmieren.
Für eure Kritik werde ich dankbar.
Viele Grüße,
Maxim.
Säbelzahn schrieb:> die Programme und die Ideen von> Anderen.
Sollte ich Fahrrad selbst erfinden?
Selbst in Datenblatt stehen Programmbeispiele. Nicht benutzen?
Autoren von Ideen habe ich genannt, noch eigene Ideen dazu gebracht...
Hoffentlich etwas brauchbares bekommen. Ich habe schon mit Scheduler
(aber die Variante ohne Variablen) ein Ding gemacht.
Selbst J.S.Bach, mein Kollege aus Leipzig, hat die Tonleiter nicht
selber erfunden.
OT: Es ist mir immernoch schleierhaft, warum man auf einem 8bit
Prozessor einen Scheduler braucht? Kriegt man es nicht hin so ein paar
Prozesse ohne Wartezyklen parallel laufen zu lassen?
Albert schrieb:> warum man auf einem 8bit> Prozessor einen Scheduler braucht?
Um schneller viele gute Dinge machen zu können. Ohne die Zeit für
Gerippe zu verlieren.
Aber Scheduler kann genau so gut auch mit STM32 arbeiten. Das ist ja C.
>Kriegt man es nicht hin so ein paar Prozesse ohne Wartezyklen parallel laufen zu
lassen?
Ein Scheduler ist praktisch wenn man zyklisch mehrere Aufgaben
quasi-parallel erledigen will ... was ja der Sinn eines Controllers ist
(zyklisch Eingaben abfragen, Daten holen/ablegen, .. )
Nicht nur einfach zyklisch. Man kann aus einer Aufgabe eine andere mit
Verzögerung rufen und somit komplizierte Abhängigkeiten schaffen.
Hauptidee: die Zeit für delay nicht verschwenden.
Im Vergleich mit Flag-Automat ist Scheduler weniger problematisch, wenn
eine oder andere Aufgabe zufällig mehr Zeit braucht, als zwischen
Timer-Interrupts bleibt.
Maxim B. schrieb:> Nicht nur einfach zyklisch. Man kann aus einer Aufgabe eine andere mit> Verzögerung rufen und somit komplizierte Abhängigkeiten schaffen.
Genau das ist es - die Leute denken zu kompliziert. Dann braucht man
auch keinen Scheduler.
... scheduler habe ich verschiedene auf avr/pic/stm zu laufen und finde
es auch oft sinnig, aber richtig "böse" finde ich immer noch
1. viele triviale kommentare ohne informationsgehalt, anstatt
vielsagende bezeichner zu verwenden!
2. immer und immer wieder klammern zu setzen, auch wenn da keine sein
müssen - ein unding!
3. die redundante programmierung, sprich copy&paste oder basteln!
eins von vielen beispielen; lcd.c function
//original
void lcd_string_P( PGM_P data ) {
u8 tmp;
tmp=pgm_read_byte(data);
while( tmp != '\0' ) {
lcd_data( tmp );
data++;
tmp = pgm_read_byte(data);
}
}
//mein zweizeiler aus der pistole in 3sec
void lcd_puts_p(PGM_P sp) {
uint8_t s;
while (s=pgm_read_byte(sp++), s)
lcd_data(s);
}
mt
p.s. der hier gezeigte "scheduler" verdient den namen NICHT!
Albert schrieb:> OT: Es ist mir immernoch schleierhaft, warum man auf einem 8bit> Prozessor einen Scheduler braucht?
Seit wann ist es verboten, sich auch auf 8-Bittern die Arbeit zu
erleichtern?
Ich benutze einen Scheduler in fast allen Projekten, sobald etwas
verzögert ausgeführt werden muß. Das erspart einem, jedesmal extra
Zählschleifen hinschreiben zu müssen.
Hier mal meine Version. Die Idee mit der sortierten Liste ist aber nicht
von mir.
Beitrag "Wartezeiten effektiv (Scheduler)"
Danke Peter,
dass Du dein Projekt hier noch mal verlinks.
Ich verwende deinen Scheduler (peda) auch meinen Projekten und kann ihn
mit der Tastenentprellung (peda) nur empfehlen.
Apollo M. schrieb:> 2. immer und immer wieder klammern zu setzen, auch wenn da keine sein> müssen - ein unding!
Ich bin anderer Meinung. Die Klammer kosten nichts. Aber unter
bestimmten Umständen können sie viel Ärger sparen.
Apollo M. schrieb:> 1. viele triviale kommentare ohne informationsgehalt, anstatt> vielsagende bezeichner zu verwenden!
Lieber zu viel als zu wenig. Sonst vergesse ich bald selber, was und
warum so und nicht anders. Zeitverschwendung, ohne Kommentare zu
schreiben.
Wer aber besser ohne Kommentare lebt, der darf sie natürlich löschen.
So oder so, das Ding funktioniert. Man kann das natürlich auch besser
machen...
1
//original
2
voidlcd_string_P(PGM_Pdata){
3
u8tmp;
4
5
tmp=pgm_read_byte(data);
6
while(tmp!='\0'){
7
lcd_data(tmp);
8
data++;
9
tmp=pgm_read_byte(data);
10
}
11
}
12
13
//mein zweizeiler aus der pistole in 3sec
14
voidlcd_puts_p(PGM_Psp){
15
uint8_ts;
16
while(s=pgm_read_byte(sp++),s)
17
lcd_data(s);
18
}
Kannst du bitte erklären, welche Vorteile deine Schreibweise hat?
Du hast ein paar Zeilen weniger. Was hast du gespart? Papier? Geld? CO2?
Apollo M. schrieb:> 3. die redundante programmierung, sprich copy&paste oder basteln!
Für mich hat Verständlichkeit höchsten Wert. Wenn das ein paar Zeilen
mehr bedeutet, so muß das sein.
Apollo M. schrieb:> p.s. der hier gezeigte "scheduler" verdient den namen NICHT!
Egal wie das heißt. Hauptsache, das Ding arbeitet wie soll.
Albert schrieb:> Genau das ist es - die Leute denken zu kompliziert. Dann braucht man> auch keinen Scheduler.
Ja, früher habe ich das auch ohne gemacht. Für LED blinken je LED ein
Programmtimer. Für Tastenabfrage je Taste ein Programmtimer :) Ja, so
kann das auch funktionieren. Das Problem kommt erst wenn man nach einem
Jahr etwas zu ändern hat.
Einmal wollte ich genau sehen, was per MIDI übertragen wird. Es kam
immer wieder zu Verschlucken von MIDI-Code. Na ja, habe ich gedacht: AVR
sei sicher zu langsam :)
In Wirklichkeit war Problem natürlich nicht in AVR...
Maxim B. schrieb:> Kannst du bitte erklären, welche Vorteile deine Schreibweise hat?> Du hast ein paar Zeilen weniger. Was hast du gespart? Papier? Geld? CO2?
... ich bin zwar nicht der Author des Zweizeilers, aaaaber: deine
Version produziert zweimal Code für den Zugriff auf das Flash, der
Zweizeiler nur einmal (der Zweizeiler gefällt mir aber dennoch nicht so
sehr).
"Deine" Schleife wäre besser in einer do .. while Schleife aufgehoben
(um eben nur einmal Code für Flashzugriff zu generieren...
Ralph S. schrieb:> deine> Version produziert zweimal Code für den Zugriff auf das Flash, der> Zweizeiler nur einmal (der Zweizeiler gefällt mir aber dennoch nicht so> sehr).
Du wirst sicher lachen:
ich habe jetzt ausprobiert, das Programm mit meiner Variante 2 bytes
kleiner, als von Apollo M ...
Compiler optimiert alles, man sollte oft einfach ausprobieren... Also,
meine Variante ist ein bißchen kürzer, aber das ist eigentlich egal.
Übrigens, Gerechtigkeit halber: die Variante ist nicht meine. Ich habe
nach diesem Muster auch ähnliche Funktion für Arbeit über Puffer
gemacht.
Interessant ist Listing zu sehen:
erste ist "meine".
1
2f2: cf 93 push r28
2
2f4: df 93 push r29
3
2f6: ec 01 movw r28, r24
4
2f8: fe 01 movw r30, r28
5
2fa: 84 91 lpm r24, Z
6
2fc: 88 23 and r24, r24
7
2fe: 21 f0 breq .+8
8
300: 0e 94 ea 00 call 0x1d4
9
304: 21 96 adiw r28, 0x01
10
306: f8 cf rjmp .-16
11
308: df 91 pop r29
12
30a: cf 91 pop r28
13
30c: 08 95 ret
14
15
16
2f2: cf 93 push r28
17
2f4: df 93 push r29
18
2f6: fc 01 movw r30, r24
19
2f8: 84 91 lpm r24, Z
20
2fa: ef 01 movw r28, r30
21
2fc: 21 96 adiw r28, 0x01
22
2fe: 88 23 and r24, r24
23
300: 21 f0 breq .+8
24
302: 0e 94 ea 00 call 0x1d4
25
306: fe 01 movw r30, r28
26
308: f7 cf rjmp .-18
27
30a: df 91 pop r29
28
30c: cf 91 pop r28
29
30e: 08 95 ret
So oder so, es kommt nur einmal lpm. Compiler optimiert alles gut.
Spätestens seit dem SSL Bug sollte jeder wissen, dass man in
Programmiersprachen wie C niemals auf Klammern verzichten sollte.
Eben mal lcd_data durch ein kompliziertes Macro ersetzt und schon ist
alles kaputt.
Gruß Sven
... programmieren hat auch was mit ästhetik zu tun, der hier gezeigte
code ist typisch für halbwissende, wenn ihr solchen code irgendwo zeigt
könnt ihr gleich wieder nach hause gehen!
UND einzeilige if/else anweisungen immer schön brav zu klammern ist
klippschule und verbessert wohl kaum die lesebarkeit, aber pumpt das
listing auf!
// Sendet eine 4-bit Ausgabeoperation an das LCD
static void lcd_out( u8 data ) {
lcd_dataline_null();
if (data & 0x10) LCD_PORT_DB4 |= (1<<LCD_DB4);
if (data & 0x20) LCD_PORT_DB5 |= (1<<LCD_DB5);
if (data & 0x40) LCD_PORT_DB6 |= (1<<LCD_DB6);
if (data & 0x80) LCD_PORT_DB7 |= (1<<LCD_DB7);
lcd_enable_puls();
}
// Sendet eine 4-bit Ausgabeoperation an das LCD
static void lcd_out( u8 data ) {
lcd_dataline_null();
if (data & 0x10){
LCD_PORT_DB4 |= (1<<LCD_DB4);
}
if (data & 0x20){
LCD_PORT_DB5 |= (1<<LCD_DB5);
}
if (data & 0x40){
LCD_PORT_DB6 |= (1<<LCD_DB6);
}
if (data & 0x80){
LCD_PORT_DB7 |= (1<<LCD_DB7);
}
lcd_enable_puls();
}
genauso wenig wie kommentare dieser art ... außer man "spricht" die
sprache garnicht
wdt_reset(); // Watchdog auf Null
UND auch mal coding styles lesen, damit mal kappiert wird wo/wo nicht
leerzeichen hingehören
wenn schon dann eher so das ganze ...
void lcd_string_P(PGM_P data) {
u8 tmp = pgm_read_byte(data);
while (tmp != 0) {
lcd_data(tmp);
tmp = pgm_read_byte(++data);
}
}
UND auch mal über konsistenz im coding nachdenken - der code ist VOLL
von inkonsistenz
z.b. die function vor lcd_string_P() incrementiert den data pointer ganz
normal im parameter feld, also hatte dort der to noch keine
"leseschwäche wie behauptet" aber
'\0' anstatt 0 ist immer dumm
void lcd_string( u8 *data ) {
while( *data != '\0' )
lcd_data( *data++ );
}
Maxim B. schrieb:> ich habe jetzt ausprobiert, das Programm mit meiner Variante 2 bytes> kleiner, als von Apollo M ...
kann ich nicht bestätigen, sondern umgekehrt!
mit gcc v8.2 und -Os
//mein zweizeiler aus der pistole in 3sec
void lcd_puts_p(PGM_P sp) {
uint8_t s;
while (s=pgm_read_byte(sp++), s)
96: fc 01 movw r30, r24
98: 24 91 lpm r18, Z
9a: 01 96 adiw r24, 0x01 ; 1
9c: 21 11 cpse r18, r1
9e: fb cf rjmp .-10 ; 0x96 <lcd_puts_p>
lcd_data(s);
}
a0: 08 95 ret
//original
void lcd_string_P( PGM_P data ) {
uint8_t tmp=pgm_read_byte(data);
while (tmp != 0) {
lcd_data( tmp );
tmp = pgm_read_byte(++data);
96: fc 01 movw r30, r24
98: 24 91 lpm r18, Z
while (tmp != 0) {
9a: 21 11 cpse r18, r1
9c: 01 c0 rjmp .+2 ; 0xa0 <lcd_string_P+0xa>
}
}
9e: 08 95 ret
tmp = pgm_read_byte(++data);
a0: 01 96 adiw r24, 0x01 ; 1
a2: f9 cf rjmp .-14 ; 0x96 <lcd_string_P>
mt
... meine buchempfehlung für jene die c-programmierung wirklich mal
lernen wollen und "hart" genug sind, weil starker tabak wenn man dann
schrittweise kapiert, dass man eigentlich gar keine ahnung von der
sprache hatte!
Schellong, Moderne C-Programmierung
dann lernt ihr z.b. auch was ko-logik in c-programmierug bedeutet und
was man damit alles machen kann ...
liegt auch als pdf im web rum!
mt
Apollo M. (Firma: @home) (majortom)
>... programmieren hat auch was mit ästhetik zu tun, der hier gezeigte>code ist typisch für halbwissende, wenn ihr solchen code irgendwo zeigt>könnt ihr gleich wieder nach hause gehen!
Wenn Du jetzt noch lernst, beim posten die Code-Tags zu setzen, damit
das "Syntax-Highlighting" funktioniert, dann wird auch Dein Code noch
schöner.
Die Form von Code hat immer was mit dem eigenen Stil zu tun und ich habe
noch keinen Code gesehen, an dem ich nichts kritisieren könnte.
Apollo M. schrieb:> ... programmieren hat auch was mit ästhetik zu tun, der hier gezeigte> code ist typisch für halbwissende, wenn ihr solchen code irgendwo zeigt> könnt ihr gleich wieder nach hause gehen!
Ich glaube nicht, daß dieses Forum nur für Profis gedacht ist, daher muß
man nicht gleich alle Leute anpissen, die hier was veröffentlichen.
Man kann Tipps geben, dann aber bitte in freundlichem Ton.
Maxim B. schrieb:>> 1. viele triviale kommentare ohne informationsgehalt, anstatt>> vielsagende bezeichner zu verwenden!>> Lieber zu viel als zu wenig. Sonst vergesse ich bald selber, was und> warum so und nicht anders. Zeitverschwendung, ohne Kommentare zu> schreiben.
“Every time you write a comment, you should grimace and feel the failure
of your ability of expression.”
― Robert C. Martin, The Robert C. Martin Clean Code Collection
(Collection)
>“Every time you write a comment, you should grimace and feel the failure>of your ability of expression.”>― Robert C. Martin, The Robert C. Martin Clean Code Collection>(Collection)
Dem stimme ich zu hundert Prozent zu: Code muss so geschrieben sein,
dass Kommentare überflüssig sind.
Das Problem: Code und Kommentare laufen mit der Zeit immer auseinander.
Also: Kommentare weg, Code verbessern !
Marc schrieb:> Das Problem: Code und Kommentare laufen mit der Zeit immer auseinander.
Genau. Natürlich hat Uncle Bob auch dazu was schlaues gesagt:
“Redundant comments are just places to collect lies and misinformation.”
Peter D. schrieb:> Ich glaube nicht, daß dieses Forum nur für Profis gedacht ist, daher muß> man nicht gleich alle Leute anpissen, die hier was veröffentlichen.
Danke!
Ich bin natürlich kein Profi, ich verdiene mein Gehalt anders.
Was aber meine Kommentare angeht: einmal früher habe ich bemerkt, daß
ich kaum noch verstehe, was ich vor einem Jahr geschrieben habe. Seit
dem schreibe ich möglichst viele Kommentare. Wenn einem oder anderem
Profi das nicht gefällt... Na, man kann nicht für allen gut sein,
leider... :)
Kommentare schreibe ich FÜR MICH.
Übrigens, wie ich am Anfang schon geschrieben habe: es geht hier um
rtos.h und rtos.c. Alles andere ist nur als Zugabe zu betrachten, die
alles etwas verständlicher macht.
Stattdessen wird hier aus irgendwelchem Grund nur über meine Variante
von lcd.h - lcd.c diskutiert (die übrigens nach Anregung von Ihnen, Herr
Dannegger, gemacht wurde. Danke noch mal für Tipps!).
lcd.h - lcd.c funktioniert genau wie ich möchte. Ich habe dort seit
langer Zeit fast nichts geändert. Ich mache nur Anpassungen bei Pin-Def,
je nach der Platte. Einziges, was mir im Moment noch als fehlerhaft
erscheint: in Puffer-Mode möchte ich gerne auch blinkende Zeichen
ermöglichen. Darüber muß ich noch überlegen. Auch bessere Zusammenspiel
mit rtos wäre gut.
Hier gab es noch von Apollo M. ein Tipp, ein Buch zu lesen: "Schellong,
Moderne C-Programmierung". Leider muß ich sagen, daß dieses Buch, wie
auch viele anderen, gleiche Nachteil hat: zu oberflächlich. Viele Fragen
und Momente sind entweder nicht ausreichend erklärt oder gar nicht
erwähnt. Deshalb bin ich eigentlich hier in Forum (und nicht nur hier).
Viele Grüße!
Maxim B. schrieb:> Was aber meine Kommentare angeht: einmal früher habe ich bemerkt, daß> ich kaum noch verstehe, was ich vor einem Jahr geschrieben habe. Seit> dem schreibe ich möglichst viele Kommentare. Wenn einem oder anderem> Profi das nicht gefällt... Na, man kann nicht für allen gut sein,> leider... :)
Nun du könntest aber Vorschläge trotzdem annehmen.
Und der Vorschlag ist klar: Schreibe besseren Code.
Apollo M. schrieb:> //original> void lcd_string_P( PGM_P data ) {> uint8_t tmp=pgm_read_byte(data);> while (tmp != 0) {> lcd_data( tmp );> tmp = pgm_read_byte(++data);> 96: fc 01 movw r30, r24> 98: 24 91 lpm r18, Z> while (tmp != 0) {> 9a: 21 11 cpse r18, r1> 9c: 01 c0 rjmp .+2 ; 0xa0 <lcd_string_P+0xa>> }> }> 9e: 08 95 ret> tmp = pgm_read_byte(++data);> a0: 01 96 adiw r24, 0x01 ; 1> a2: f9 cf rjmp .-14 ; 0x96 <lcd_string_P>
Lieber Herr Apollo M.,
das ist nicht mein Code! Mein ist etwas anders:
1
tmp=pgm_read_byte(++data);
gibt es in meinem Code nicht!
So kleine Unterschiede machen schon große Unterschiede bei Optimieren
von Compiler. Deshalb passen Sie bitte auf, was Sie schreiben!
Karl M. schrieb:> Danke Peter,>> dass Du dein Projekt hier noch mal verlinks.> Ich verwende deinen Scheduler (peda) auch meinen Projekten und kann ihn> mit der Tastenentprellung (peda) nur empfehlen.
Hast Du keine Angst, dass Du auf deinen Schleimspur ausrutschst?
Cyblord -. schrieb:> Und der Vorschlag ist klar: Schreibe besseren Code.
Sage ich etwas dagegen?
Aber in der Funktion, über die Herr Apollo M. schrieb, scheint meine
Variante eher besser zu sein, als seine.
Außerdem hat er mich nicht überzeugt, wie er schrieb, man brauche wenige
Klammern. Ich habe in der Literatur genau Gegenteil gelesen: man mache
lieber zu viel Klammern als zu wenig. Und auch in der Literatur gibt es
Erklärungen, warum.
Apollo M. schrieb:> dann lernt ihr z.b. auch was ko-logik in c-programmierug bedeutet und> was man damit alles machen kann ...
Das gleiche, was alle anderen unter Short-Circuit-Evaluation verstehen
und was viele andere Sprachen auch können? Wieder was gelernt!
Dr. Sommer schrieb:> Apollo M. schrieb:>> dann lernt ihr z.b. auch was ko-logik in c-programmierug bedeutet und>> was man damit alles machen kann ...>> Das gleiche, was alle anderen unter Short-Circuit-Evaluation verstehen> und was viele andere Sprachen auch können? Wieder was gelernt!
Der Herr Apollo M. ist das Programmiereräquivalent der üblichen und
verhassten Rechtschreibfanatiker.
Es mag ja stimmen, dass man Code besser schreiben kann (speziell C ist
da ja sehr "variabel") Aber hier kam nur Herumgemäkle an Kleinigkeiten,
und nichts substantielles.
Leute wie dieser "Apollo M." machen dieses Forum so unangenehm...
Apollo M. schrieb:> // Sendet eine 4-bit Ausgabeoperation an das LCD> static void lcd_out( u8 data ) {> lcd_dataline_null();> if (data & 0x10) LCD_PORT_DB4 |= (1<<LCD_DB4);> if (data & 0x20) LCD_PORT_DB5 |= (1<<LCD_DB5);> if (data & 0x40) LCD_PORT_DB6 |= (1<<LCD_DB6);> if (data & 0x80) LCD_PORT_DB7 |= (1<<LCD_DB7);> lcd_enable_puls();> }
Was bitte ist das denn? Wer kommt hier auf die Idee jedes Bit einzeln zu
setzen?
Karl K. schrieb:> Was bitte ist das denn? Wer kommt hier auf die Idee jedes Bit einzeln zu> setzen?
Wahrscheinlich der Gleiche, der die Zuordung der Bits zu den Portbits
maximal variabel halten wollte. Wo liegt das Problem? Die 3us
CPU-Laufzeit?
> LCD_PORT &= 0x0F; // Pins low> LCD_PORT |= data & 0xF0; //high Nibble setzen
Nö, das geht nur bei eingeschränker Zuordung der Bits am Port.
Marc schrieb:> Dem stimme ich zu hundert Prozent zu: Code muss so geschrieben sein,> dass Kommentare überflüssig sind.
Es ist immer leichter, Dogmen aufzustellen, als sie auch einzuhalten.
Wenn es so leicht wäre, gäbe es die Kommentarfunktion ja nicht.
Ich schreibe lieber mal einen Kommentar, als 80 Zeichen lange Funktions-
und Variablennamen.
Die Vergabe von beschreibenden Namen ist ein wirklich schweres Thema.
Ich möchte nicht deutlich länger an der Namensvergabe grübeln, als an
dem eigentlichen Code.
Marc schrieb:> Das Problem: Code und Kommentare laufen mit der Zeit immer auseinander.
Aber auch Namen können veralten, wenn man eine Funktion verändert, z.B.
wenn ich eine Funktion universeller mache oder etwas daraus in eine
Unterfunktion auslagere.
Was ich extrem unleserlich finde, ist CamelCase. Ich benutze immer den
Unterstrich als Trenner in einem Namen.
Falk B. schrieb:> Wahrscheinlich der Gleiche, der die Zuordung der Bits zu den Portbits> maximal variabel halten wollte.
Genau deshalb.
Zuerst machte ich mit Def. drei Varianten: alles auf einem Port, Data
auf einem und E und RS auf einem anderen Port, und völlig frei. Aber am
Ende habe ich nur die freie Variante gelassen. Zeitunterschiede gegen
anderen Varianten sind unbedeutend. Aber die Platte kann viel bequemer
gemacht werden. Alles, was nicht für andere Funktionen gebraucht wird,
kann für LCD benutzt werden.
Ich versuche mich in Namen nach meinen Regeln zu halten: falls ich das
nicht vergesse, mache ich immer Prefix mit Filename und Unterstrich.
Z.B. void indikator_schreib_ind_puff(u8 a,u8 b,u8 c,u8 d) befindet sich
in indikator.c.
Es sei denn, ich benutze Bibliothek von anderen.
Karl K. schrieb:> Ist zehnmal so lang wie das nötige Write Enable von 300ns.
Das ist sehr wichtig, wenn zu berücksichtigen, daß E etwa 500 ns braucht
und zwischen Befehlen ca. 40-50 us zu warten ist :)
Ich habe übrigens gekuckt: lcd_out( data ); zusammen mit
lcd_enable_puls(); 500 ns braucht ca. 3,3 us (mit F_CPU = 16 MHz).
Maxim B. schrieb:> Das ist sehr wichtig, wenn zu berücksichtigen, daß E etwa 500 ns braucht> und zwischen Befehlen ca. 40-50 us zu warten ist :)
Wenn man linear programmiert freilich nicht. Wenn man einen
Displaybuffer verwendet und der µC zwischendrin was anderes machen kann,
braucht es Zehnmal so lange.
Das ist so typisch Arduino-Programming: starte die Messung - delay(1000)
- lese den Messwert. Und dann rumheulen: Mein µC ist zu langsam, ich
brauch einen schnelleren µC.
>Was ich extrem unleserlich finde, ist CamelCase. Ich benutze immer den>Unterstrich als Trenner in einem Namen.
Das fand ich am Anfang auch, aber ich habe eine Zeitlang Java gemacht
und dort ist es Standard. Deshalb habe ich mich auf die Konvention
"CamelCase" auch für C geeinigt.
Mit der Zeit gewöhnt man sich dran. oderEtwaNicht ? ;-)
Karl K. schrieb:> Wenn man einen> Displaybuffer verwendet und der µC zwischendrin was anderes machen kann,> braucht es Zehnmal so lange.
Stimmt schon.
Aber da ich PCB selber mache, ist für mich die Möglichkeit, PINs frei
bestimmen zu dürfen, am wichtigsten.
Übrigens, die Ausgabe kann man sehr leicht ändern, wenn man will. Statt
1
2
staticvoidlcd_out(u8data){
3
lcd_dataline_null();
4
if(data&0x10){
5
LCD_PORT_DB4|=(1<<LCD_DB4);
6
}
7
if(data&0x20){
8
LCD_PORT_DB5|=(1<<LCD_DB5);
9
}
10
if(data&0x40){
11
LCD_PORT_DB6|=(1<<LCD_DB6);
12
}
13
if(data&0x80){
14
LCD_PORT_DB7|=(1<<LCD_DB7);
15
}
16
lcd_enable_puls();
17
}
kommt
1
2
staticvoidlcd_out(u8data){
3
LCD_PORT&=0x0f;
4
LCD_PORT|=(data&0xf0);
5
lcd_enable_puls();
6
}
.
Statt 50 Cycle wird 28. Statt 3,125 us wird 1,75 us. Hilft das viel?
Peter D. schrieb:> Es ist immer leichter, Dogmen aufzustellen, als sie auch einzuhalten.
Dogma:
Schreibe, in den Kommentaren warum du etwas so tust.
Nicht, was du tust, denn das steht schon im Code.
Karl K. schrieb:> Wenn man einen> Displaybuffer verwendet und der µC zwischendrin was anderes machen kann,> braucht es Zehnmal so lange.
Wenn das irgendwie nicht bemerkt wurde:
LCD-Puffer wird nur jede 1 ms bedient. Auch für 4x20 LCD bedeutet das
nur 84 ms, das ist für Auge kaum zu merken.
Die Auslastung für LCD wird:
so wie das steht: 7/1000=0,7% (nur während Kopierens, danach nicht
mehr).
Alles auf einem Port: 3,5/1000=0,35%.
Ist das wirklich so kritisch?
... so da habe ich ja den finger richtig in die wunden gelegt, aber wir
können alle zufrieden sein, da an den comments offensichtlich wird, dass
hier einige noch mitdenken.
der hier gezeigte code ob mit sinnige oder unsinnige comennts wird jede
wette, keiner von uns nach kurzer zeit noch verstehen und darum gings
mir!
dieser code hier hat leider nur unqualität, lese doch mal bitte jemand
rtos.c/rtos.h und erkläre mir was das rtos.x hier zum scheduler macht
und wo es klemmt und z.b. welchen sinn die parameter "// die Aufgaben
bekommen je 3 Parameter: u16,s16,u8" haben, scheduler principle? round
robin, preemptive ...? nichts davon offenbart dieser code müllberg!
ich erkenne noch nicht einmal elementare queue functions - liegt aber
bestimmt an meiner sonnenbrille?!
bevor man irgend eine aufgabe dieser art angeht sollte mann/frau erstmal
grundsätzliche dinge darüber lesen und ein grundsätzliches verständnis
erlangen, und bitte auch die richtigen begrifflichkeiten verwenden.
hier http://www.cocoos.net/intro.html da könnt ihr euch mal die finger
ablecken, an dem beispiel wie ein sehender das macht. aber vorsicht,
dass ist richtig viel arbeit, und studiert doch mal den code dazu, dann
lernt ihr auch was dazu - ich habe das bereits hinter mir!
dick unterstrichen, eine der schwierigsten aufgaben, ist die
namensgebung von functions, variabeln ... ob mit suffix/prefix,
unterschrich, camel style, gross/klein, ... um eine logische strukture
des systems gut lesbar abzubilden.
diese aufgabe hat der to weder erkannt noch ansatzweise hinbekommen.
wenn wir hier nicht unter beobachtung wären, dann würde ich euch mal ein
paar gute pdf bookz zu embedded rtos hochladen, aber auch die muss man
selber lesen. ... und leider, die werden ja gleich wieder hier gelöscht!
einfach nur zum abtörnen ... was soll das, äh?
//rtos.c
/********************************************************/
/*** Fuer Ringpuffer TaskQueue *************************/
/********************************************************/
static u8 task_count = 0;
static u8 task_schwanz = 0;
static u8 task_kopf = 0;
static void task_count_inc(u8 *count, u8 max_wert){
(*count)++;
if(*count >= max_wert){
*count = 0;
}
}
mt
Apollo M. schrieb:> dieser code hier hat leider nur unqualitätApollo M. schrieb:> nichts davon offenbart dieser code müllberg!Apollo M. schrieb:> diese aufgabe hat der to weder erkannt noch ansatzweise hinbekommen.Apollo M. schrieb:> bevor man irgend eine aufgabe dieser art angeht sollte mann/frau erstmal> grundsätzliche dinge darüber lesen und ein grundsätzliches verständnis> erlangen, und bitte auch die richtigen begrifflichkeiten verwenden.Apollo M. schrieb:> einfach nur zum abtörnen ... was soll das, äh?
Kann bitte die Moderation hier eingreifen?
Ich denke, an dem gesamten Beitrag ist nichts konstruktives, dafür aber
vieles, was zumindest an Beleidigungen grenzt. Mich stört es, und mich
interessiert die ursprüngliche Diskussion zumindest als Mitleser.
Säbelzahm schrieb:> Wichtige Regeln - erst lesen, dann posten!>> Groß- und Kleinschreibung verwenden
... ich bin nicht regelgläubig, das ist eher was für katholiken, andere
leichtgläubige, arduino jünger oder was für das breite mittelmass das
sich hier tummelt!
jemand schrieb:> Ich denke, an dem gesamten Beitrag ist nichts konstruktives, dafür aber> vieles, was zumindest an Beleidigungen grenzt.
du wohnst auf eine ponnyhof, richtig? bist wahrscheinlich blind und
beschwerst dich gerne regelmäßig über zuviel/zuwenig sonnenschein?!
wenn ein blinder einen blinden hilft, dann fallen beide in die grube!
das wäre dann wohl für kleingeister immer eine beleidigung, habe ich das
richtig verstanden?
mt
Apollo M. schrieb:> wenn ein blinder einen blinden hilft, dann fallen beide in die grube!> das wäre dann wohl für kleingeister immer eine beleidigung, habe ich das> richtig verstanden?
Ja, so ist das.
Dein Wunsch, auf Klammer zu verzichten, macht Verdacht nahe, du bist ja
auch kein Profi, wie?
Apollo M. schrieb:> hier http://www.cocoos.net/intro.html da könnt ihr euch mal die finger> ablecken, an dem beispiel wie ein sehender das macht.
Nunja... Da scheint jemand den Präprozessor sehr zu lieben. Kennt aber
nichtmal den do-while-"Trick":
1
#define os_assert( test ) if ( !(test) ) {\
2
os_on_assert(__LINE__);\
3
}
Explizites Padding? Ernsthaft?
1
typedefstruct{
2
uint8_tsignal;
3
uint8_treserved;/* Alignment byte */
4
uint8_tpad0;
5
uint8_tpad1;
6
uint16_tdelay;/* Delay of posting in ticks */
7
uint16_treload;/* Reload value for periodic messages */
8
}Msg_t;
Überall nur uint8_t, uint16_t ... verwendet, keine sprechenden Aliase
wie pid_t oder time_t ... Jetzt irgendwie nicht so der Wahnsinn.
Dr. Sommer schrieb:> Überall nur uint8_t, uint16_t ... verwendet, keine sprechenden Aliase> wie pid_t oder time_t ... Jetzt irgendwie nicht so der Wahnsinn.
da bin ich bei dir!
@pid_t oder time_t, chibios kommt dir da mehr entgegen und läuft auch
auf avr und small 328p
Dr. Sommer schrieb:> Nunja... Da scheint jemand den Präprozessor sehr zu lieben. Kennt aber> nichtmal den do-while-"Trick":
der präprozessor ist ein wesentlicher teil der sprachdefinition von c,
die meisten rtos setzen entsprechende macros daher massiv ein, weil so
recht flexible das rtos configuriert werden kann.z.b. werden dann gerne
verschiedene dispatcher, dynamische/statische timer handler, ... zur
auswahl gestellt.
code macros in header files, ob mit oder ohne do{...}while(0) kapselung
sind standard in der landschaft, macros haben vor- und nachteile, ich
selber benutze sie häufig, anfänger sind regelmäßig darüber befremdet
...
ich habe hier einige rtos quellen rumliegen und jede hat irgendwas
besonderes gemacht, z.b. rtos für pic12/16 ist was anderes als für
pic18/24/32 oder arm/avr. ich kenne auch ein rtos wo jede task als
eigene isr läuft einschliesslich dem dispatcher - interessanter ansatz,
wenn kein richtiger sw stack existiert, wie bei pic16.
mt
Apollo M. schrieb:> der präprozessor ist ein wesentlicher teil der sprachdefinition von c,
Ja leider. Den sollte man so sparsam wie möglich einsetzen, und so viel
wie möglich mit (Inline-) Funktionen machen. In C++ geht das noch
deutlich besser. In beispielhaft gutem Code sollten jedenfalls nicht
wesentlich mehr Makros als die Include-Guards auftauchen...
Maxim B. schrieb:> Säbelzahn schrieb:> die Programme und die Ideen von> Anderen.>> Sollte ich Fahrrad selbst erfinden?> Selbst in Datenblatt stehen Programmbeispiele. Nicht benutzen?>> Autoren von Ideen habe ich genannt, noch eigene Ideen dazu gebracht...> Hoffentlich etwas brauchbares bekommen. Ich habe schon mit Scheduler> (aber die Variante ohne Variablen) ein Ding gemacht.>> Selbst J.S.Bach, mein Kollege aus Leipzig, hat die Tonleiter nicht> selber erfunden.
Nicht gut deutsch dies Depp.
@Sommer & Apollo
Habt es ihr schon gemerkt, dass ihr beiden euch über die Programmierung
eines Schedulers so unterhaltet, wie zwei Jungfrauen über Gruppensex?
Weder ihr noch die wissen wovon sie reden.