Hallo zusammen,
ich bin noch dabei, C zu lernen.
Aktuell benötige ich eine Funktion, die die Nummer eines Kanals und die
dorthin zu schreibenden Daten als Parameter erhält und dann mittels
einfachem bitbanging des latch enable eines 74HC573 die Daten in diesen
reinschreibt. Die clk_regx_oben/clk_regx_unten sind Symbole für
Bitpositionen in den Ausgangsregistern der Ports, die an die jeweiligen
LEs angeschlossen sind, latch ist ein Symbol für den Ausgangsport=Bus zu
den 74HC573.
Im Prinzip sind es in allen case-Fällen die gleichen Abläufe, nur eben
mit unterschiedlichen Bits(=latch enable) verschiedener Portregister.
Ausdrücklich sei erwähnt: es funktioniert gut, ich suche also keine
Fehler.
Die Umsetzung in Assembler (siehe Anhang) ist sehr schnell, hat aber
recht großen Platzbedarf. Im aktuellen Projekt stört das auch überhaupt
nicht, aber geht es in C nicht noch irgendwie besser?
(Wie ich es in Assembler besser löse, weiß ich und das ist auch nicht
die Frage)
Compiler ist der IAR, Optimierung auf Platzbedarf, Prozessor der
STM8S105.
Auszug aus meiner bisherigen Lösung:
1
#define clk_reg1_oben PC_ODR_ODR3
2
#define clk_reg2_oben PC_ODR_ODR2
3
#define clk_reg3_oben PC_ODR_ODR1
4
#define clk_reg1_unten PA_ODR_ODR6
5
#define clk_reg2_unten PA_ODR_ODR5
6
#define clk_reg3_unten PA_ODR_ODR4
7
#define latch PB_ODR
8
9
...
10
11
voidlatching_data(intchannel,intdata)
12
{
13
14
// Daten auf den Bus legen
15
16
latch=data;
17
18
// LE des Registers 1 auf low setzen (sollte ohnehin low sein)
19
// clk_reg1_oben = OFF;
20
// LE für mindestens 10 Takte auf high setzen
21
// clk_reg1_oben = ON;
22
// shortwait();
23
// LE wieder auf low setzen, mit diesem Pegelwechsel
Ich bin da noch nicht 100% sattelfest, die Bits der Register sind wohl
als bitfield (?) definiert:
Auszug aus iostm8s105s4.h:
1
typedefstruct
2
{
3
unsignedcharODR0:1;
4
unsignedcharODR1:1;
5
unsignedcharODR2:1;
6
unsignedcharODR3:1;
7
unsignedcharODR4:1;
8
unsignedcharODR5:1;
9
unsignedcharODR6:1;
10
unsignedcharODR7:1;
11
}__BITS_PB_ODR;
Heißt das dann also, ich müßte die Funktion so:
1
voidlatching_data(__BITS_PB_ODRchannel,intdata)
definieren?
Aber wie verwende ich das dann weiter in der Funktion? Setze ich dann
einfach channel an die Stelle von clk_reg1_oben in meiner Funktion?
(große Fragezeichen über dem Kopf)
Hab das mal schnell ausprobiert.
Hmm, das geht nur, wenn ich mein restliches Programm umschreibe, weil
ich dort natürlich überall channel als int einsetze, (ich seh gerade,
char bzw. besser uint8_t würde reichen) wenn ich die Funktion aufrufe.
Das macht natürlich die weitere Nutzung dieser Funktion schwieriger.
Mir wäre jetzt doch eine Lösung lieber, die als Parameter die Nummer des
Channels und das zu schreibende Byte übernimmt. Das kommt meiner
Denkweise im restlichen Programm mehr entgegen als die Übergabe der
Bitbezeichnung.
> clk_reg1_oben = OFF;> clk_reg1_oben = ON;> shortwait();> clk_reg1_oben = OFF;
Die erste Zeile ist überflüssig. Der Normalzustand ist ja wohl off.
So bleibt nur eine Funktion, die etwas "on" setzt, wartet und es dann
wieder "off" setzt.
Ich würd das Port auf on setzen.
Warten.
Alle auf off setzen.
@C-Anfänger (Gast)
>Im Prinzip sind es in allen case-Fällen die gleichen Abläufe, nur eben>mit unterschiedlichen Bits(=latch enable) verschiedener Portregister.>Ausdrücklich sei erwähnt: es funktioniert gut, ich suche also keine>Fehler.>Die Umsetzung in Assembler (siehe Anhang) ist sehr schnell, hat aber>recht großen Platzbedarf.
Wie groß? die paar Bytes können kaum ins gewicht fallen. Eine generische
Funktion mit den Portnummern als Parameter wird auch nicht kleiner, denn
die muss das alles ausrechnen.
> Im aktuellen Projekt stört das auch überhaupt>nicht, aber geht es in C nicht noch irgendwie besser?
Was ist daran nicht gut? Klar kann man die Portnummern als Adresse oder
Index übergeben, aber das macht es nicht notwenigerweise besser oder
kleiner.
Besonders als Anfänger und C-Einsteiger sollte man seine Zeit und
Energie nicht mit Pseudo-Optimierungen verschwenden. Als
fortgeschittener und Profi auch nicht.
https://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Prinzipien_der_Optimierung
Manchmal hilft es aber beim Verständnis (evtl. auch für spätere
Projekte) sich mehrere Möglichkeiten anzuschauen oder zu überlegen.
Deswegen ist der Gedanke "gehts auch anders oder sogar besser" gar nicht
schlecht.
Vorab vielen Dank für die Antworten und freundlichen Anregungen.
@NJ
> OFF=0 und ON=1...
Ja, hab ich vergessen zu kopieren.
Vielen Dank für Deine pfiffige Lösung, die allerdings bei anderer
Verteilung der Portbits nicht mehr funktioniert. :-)
@bitschubser
> Die erste Zeile ist überflüssig. Der Normalzustand ist ja wohl off.
Ja, das ist eine Angstzeile, die von den ersten Versuchen noch übrig
ist. Ist tatsächlich überflüssig.
@Falk: Ja, Du hast recht, das Codegrößenargument/der Optimierungsgedanke
ist dumm. Ich komme ursprünglich eher von Seiten der Hochsprachen. (hab
viel Turbopascal programmiert früher) Da stößt man sich daran, dass man
sechsmal praktisch das Gleiche im Quelltext hinschreibt. Der Gedanke,
dass das vielleicht irgendwie eleganter geht und man selbst nur
Scheuklappen vor den Augen hat, drängt sich förmlich auf. Deswegen
fragte ich hier. Mein Gedanke war, dass es doch irgendwie möglich sein
muss, die sechs Bitbezeichnungen zu strukturieren und in eine
durchzählbare arrayähnliche Aufzählung zu fassen, sowas wie Enumeration
oder eben ein Array.
@Michael:
Deine Lösung habe ich noch nicht ganz verstanden, geht aber, glaub ich
zumindest verstehen zu können, in meine gedankliche Richtung. Vielen
Dank dafür. Damit beschäftige ich noch mal intensiver.
Leider muss ich jetzt erst familiären und gesellschaftlichen overhead
abarbeiten, bevor ich wieder ans Hobby darf. ;-)
@ C-Anfänger (Gast)
>fragte ich hier. Mein Gedanke war, dass es doch irgendwie möglich sein>muss, die sechs Bitbezeichnungen zu strukturieren und in eine>durchzählbare arrayähnliche Aufzählung zu fassen, sowas wie Enumeration>oder eben ein Array.
Das ist machbar, läuft aber auch wieder auf eine mehr oder minder
manuelle Unterscheidung in einer untergeordneten Funktion hinaus. So
macht es der Arduino. Das ist aber weder kleiner noch schneller. Die
C-Freaks machen das mit bösen Macros. Das willst du aber nicht wirklich.
Arrayzugriffe auf IO-Register oder gar IO-Bits sind und bleiben eher
exotisch und anstrengend. Da sollte man lieber die Schreibarbeit
investieren und es gut sein lassen. Es gibt wichtiger Dinge in der
Programmierung.
Hier mal ein Beispiel für eine Macrolösung, wenn gleich das Problem
etwas anders lag. Siehe Anhang.
C-Anfänger schrieb:> @NJ>> OFF=0 und ON=1...>> Ja, hab ich vergessen zu kopieren.>> Vielen Dank für Deine pfiffige Lösung, die allerdings bei anderer> Verteilung der Portbits nicht mehr funktioniert. :-)
Ja, sollte nur eine Möglichkeit für den speziellen Fall zeigen ;)
Ansonsten hat Falk schon recht, um die manuelle Unterscheidung kommst Du
nicht herum und da lohnt sich i.d.R. der Aufwand nicht.
Ist aber doch immerhin eine Erkenntnis :D
NJ schrieb:> Ist aber doch immerhin eine Erkenntnis :D
Auf jeden Fall, vielen Dank dafür. :-)
Das Gefühl für die Möglichkeiten und Grenzen von C, die Vertrautheit mit
der Sprache muss sich bei mir noch bilden.
Falk B. schrieb:> Hier mal ein Beispiel für eine Macrolösung, wenn gleich das Problem> etwas anders lag. Siehe Anhang.
Du meinst diesen Teil hier?