Im Rahmen eines Projektes mit Schieberegistern (es werden definitiv mehr als 4 Schieberegister werden) benötigte ich eine bitweise Schiebefunktion für Arrays und ich habe doch tatsächlich keine Funktionen im Netz dafür gefunden (okay, soooo arg lange habe ich nicht gesucht).
Also selbst machen.
Das Ergebnis möchte ich hier posten für den Fall, dass das jemand ebenfalls gebrauchen kann. Der Einfachkeit halber habe ich das als Konsolenprogramm für den PC zuerst geschrieben, um die Funktionen zu testen. Das Ergebnis kann im Anhang gesehen werden, die Funktionen:
habe ich für AVR, STM32, STM8 und MCS51 getestet, sollten jedoch - weil reines C - auch mit jedem anderen in C programmierbaren Controller funktionieren.
Je nach Einsatzzweck und Schieberegisterlänge kann es sinnvoller sein, mit Pointer(n) und Bitmaske(n) nur das aus-/eingehende Bit zu bearbeiten. Just my 2 ct.
Je nach Einsatzzweck und Schieberegisterlänge kann es sinnvoller sein,
mit Pointer(n) und Bitmaske(n) nur das aus-/eingehende Bit zu
bearbeiten. Just my 2 ct.
Na ja, ich brauchte aber die "verschobenen" Bits im Array und nicht nur die Carryflags
habe ich für AVR, STM32, STM8 und MCS51 getestet, sollten jedoch - weil
reines C - auch mit jedem anderen in C programmierbaren Controller
funktionieren.
Naja, rein logisch mögen dein Funktionen korrekt sein, aber besonders auf kleinen uCs ohne Barrelshifter sind viele deiner Operationen eher "langsam".
1
cf=(*parray>>7)&0x01;
Sowas braucht 7 Schiebeoperationen auf dem AVR, je nach Compilerschlauheit auch noch ne Zählvariable für die Anzahl der Schiebungen. Man muss das Carrybit nicht zwingend in Bit 0 schieben und verarbeiten, das geht auch anders. Z.B. so.
Hattest Du tatsächlich eine Anwendung, wo Du durch mehr als 32 Bit durchschieben solltest und die Größe/Gesamtmenge nicht von vornherein feststand? CRC für beliebige Datenströme wäre so ein Fall. Ist aber selten variabel und gleichzeitig >32 Bit.
Schieberegister klingt ehr nach festen Dimensionen, wo der Standardweg ein "Bitpointer" ist, also ein Bit-Set/Get mit Index++/-- ist.
Anmerkungen: Das Schieben um 8 sollte von nahezu allen Compilern in direkten Byte-Zugriff umgesetzt werden.
Ein Erweitern auf uint16 vor dem Schieben ist nicht notwendig, (integral promotion)
Wenn der Prozessor 16-Bit-Register hat, sollte 16-Bit schieben nicht langsamer sein als 8bit. Für reine 8-Bit-Prozessoren kann ein Bitdangeling schneller sein.
attest Du tatsächlich eine Anwendung, wo Du durch mehr als 32 Bit
durchschieben solltest und die Größe/Gesamtmenge nicht von vornherein
feststand? CRC für beliebige Datenströme wäre so ein Fall. Ist aber
selten variabel und gleichzeitig >32 Bit.
Momentan geht es um eine - für meine Begriffe - sehr sehr große Modelleisenbahnanlage, gemischt aus alten und neuen Teilen eines Bekannten. Das ist, für mich der Wahnsinn in Tüten, denn er hat 167 verschiedene Lokomotiven (Sammler halt), die zum Teil sogar älter sind als ich (das Modell, das Original sowieso) und baut diese Lokomotiven auf Digitalsteuerung um, die Weichen (momentan sind es 72) jedoch nicht.
Die Anzahl der Weichen kann noch wachsen. Für dieses Ansteuern werden Schieberegister verwendet (hier braucht es noch kein bitweises Schieben über ein Array).
Er baut jedoch auch einen kleinen Rummelplatz auf (natürlich nicht so groß und schön wie im Miniaturwunderland), deren Beleuchtung und Lichtspiele mit SMD-Leds realisiert und mittels Schieberegistern angesteuert werden sollen. Die Lauflichter dieser Lichtspiele werden geshiftet und es steht noch nicht fest, wieviele es für einzelne Modelle es werden. Das bisher größte Modell hat 96 LED's. Mindestens hierfür bedarf es des Schiebens über ein Array.
Die Lauflichter dieser Lichtspiele werden
geshiftet und es steht noch nicht fest, wieviele es für einzelne Modelle
es werden. Das bisher größte Modell hat 96 LED's. Mindestens hierfür
bedarf es des Schiebens über ein Array.
Mag sein, dass es ein Missverständnis ist: ich sehe noch nicht, warum man über das Array schieben sollte.
Eine typische Implementierung: Ich habe 12 Bytes, in die ich die neuen Muster schreibe und die ich regelmäßig (x Mal pro Sekunde) alle en Block raushaue. Oder ich takte ein Muster zyklisch durch die Kette, jeweils eine LED weiter.
In beiden Fällen shiftet man nicht durchs Array. Stell Dir einfach die Frage, ob Du es auch bei 1000 Bytes machen würdest. Oder ob es auch auf festen Mustern (aka ROM) funktionieren sollte.
Beispiel
1
uint8_tLEDs[12];
2
// "on == 0": LED aus. "on != 0": an
3
externvoidshift_LED(uint8_ton);
4
5
voidrauspusten(uint8_t*LEDs,intn)
6
{
7
while(n-->0)
8
{
9
uint8_tc=*LEDs++;
10
11
// ausgerollt, weil alles andere den Aufwand hier nicht lohnt
12
shift_next(c|0x80);
13
shift_next(c|0x40);
14
shift_next(c|0x20);
15
shift_next(c|0x10);
16
shift_next(c|0x08);
17
shift_next(c|0x04);
18
shift_next(c|0x02);
19
shift_next(c|0x01);
20
}
21
}
22
23
/* eine beliebige LED setzen/löschen */
24
voidSetLED(uint8_t*LEDs,uint8_tidx)
25
{
26
LEDs[idx/8]||=1<<(idx%8);
27
}
28
voidClrLED(uint8_t*LEDs,uint8_tidx)
29
{
30
LEDs[idx/8]&=~(1<<(idx%8));
31
}
(wenn man sizeof übergibt, kann man auch die Grenzen abfragen. Oder man arbeitet auf festen Arrays)
Ich denke nicht :)
Sein Vorschlag: denke dir du müsstest das aus dem Rom lesen und ins Schieberegister schreiben. Das Rom kann man schlecht schieben ;)