SDCC Char in BIT

Gast #135532
Lesenswert?

Hallo zusammen,
ich programmiere 8051 µC und bin jetzt von ASM auf C umgestiegen.
Nun zu meinem Problem.

Ich möchte einen Wert in ein Schieberegister schreiben um später eine 7
- Segment LED anzusteueren.

mom. mache ich es auf die Folgende art :

   P2_4=0;   //CLK 0
   P2_3=0;   //BIT0
   P2_4=1;   //CLK 1

   P2_4=0;   //CLK 0
   P2_3=0;   //BIT1
   P2_4=1;   //CLK 1
    .....
   P2_4=0;   //CLK 0
   P2_3=0;   //BIT7
   P2_4=1;   //CLK 1

Mein Wunschdenken wäre ein folgender Code :

int count;  //Zähler
char wert;
wert = 01010101B ; //Ein Binärer Wert der Als char abgelegt wird
count=0;
while(count<8)
{
 P2_4=0;
 P2_3=wert[count]; //Das entsprechende Bit aus dem Wert
 P2_4=1;
}


Kann mir jemand bei diesem Problem helfen?
Ist dies realisierbar.
THX und MFG  + Guten Rutsch

Marek Swierzy
Gast #135533
Lesenswert?

Hi

unsigend char i;  //Zähler
unsigend char wert = 0x55;

for(i=0;i<8;i++)
{
   P2_4=0;
   if(wert&1) P2_3=1;
   else P2_3=0;
   P2_4=1;
   wert>>=1;
}

So geht das hardwareunabhängig. Je nach Compiler kann man aber evtl.
noch was optimieren um die if-Abfrage zu vermeiden.

Matthias
Gast #135534
Lesenswert?

unsigned char i;  //Zähler
unsigned char wert = 0x55;

for (i = 0; i < 8; i++)
{
   P2_4 = 0;
   P2_3 = (wert & (1 << i)) ? 1 : 0;
   P2_4 = 1;
}

So wird "wert" nicht zerstört, compilerabhängig ist's auch nicht.
Gast #135535
Lesenswert?

Hi

(1 << i) ist aber ein Ausdruck den man lieber nicht zur Laufzeit
auswerten will. Übliche 8 bitter haben keinen Barrel-Shifter was diesen
Ausdruck dann doch etwas langsam macht. Dann lieber eine zusätzliche
Variable anlegen in die man wert vorher reinkopiert.

Matthias
Gast #135536
Lesenswert?

"Übliche 8-Bitter"? Welche?

Im AVR-Befehlssatz (jedenfalls des Mega128) gibt es die Befehle LSR und
LSL - beide benötigen einen Taktzyklus.

Der MCS51 hat zwar keinen Shift-, dafür aber einen Rotate-Befehl, und
der benötigt 12 Takte, was einem "Instruction Cycle" dieses
hocheffizienten Prozessorkerns entspricht.

Der von mir früher verwendete 6809 kann sowas natürlich auch, aber der
ist - wenn auch mit dem HC11 nah verwandt - kein Microcontroller.

Dennoch kann ich das Argument der Langsamkeit nicht nachvollziehen.
Gast #135537
Lesenswert?

Hi

die 1 wird bei jedem Schleifendurchlauf um einen anderen Wert
geshiftet. Zuerst 0 dann 1 usw. D.h. beim letzten Schleifendurchlauf
muß die 1 erst 7 mal geshiftet werden. Das ist alles aber nicht
effektiv.

Mit einem Barrel-Shifter meine ich keineswegs die simplen
Rotations/Shift-Befehle der üblichen 8-Bitter sondern eben einen
Barrel-Shifter der solche Verschiebungen effektiv in einem Takt (egal
ob 1, 4 oder 7 Stellen) erledigt.

Matthias
Gast #135538
Lesenswert?

Ah, Du hast recht. Das ist sowohl beim MCS51 als auch dem AVR in der Tat
so. Wie primitiv.

Der letzte Prozessor, den ich gewissermaßen im Schlaf in Assembler
programmiert habe, ist der von mir hochgeschätzte 6809, der kann in
einem Befehl ein 8-Bit-Register um mehr als ein Bit verschieben und
braucht dafür je nach Adressierungsart zwei oder mehr Taktzyklen.

Naja, das Gute setzt sich bekanntlich nicht durch, sonst hätte es
x86-PCs nie gegeben - und der 6809, der immerhin 1979 auf den Markt
kam, wäre mehr Leuten bekannt.

Ich würde nun - gerade als C-Anfänger - aber sowieso davon Abstand
halten, AVRs in C zu programmieren (Harvard-Architektur mit getrennten
RAM- und ROM-Adressräumen, was vom C-Compiler kaum unterstützt wird).
Gast #135540
Lesenswert?

Es geht ja gar nicht um eine Umwandlung von Bit nach Char, sondern
darum, eine Art Software-SPI zu realisieren.

In Assembler ist das natürlich kein Problem, und ein brauchbarer
C-Compiler wird das möglicherweise auch anständig hinoptimieren können,
wobei die von Mathias angeratene Variante (Wert kopieren und dann darauf
den ursprünglichen Algorithmus anwenden, der die Kopie zerstört) vom
Compiler am besten interpretiert werden dürfte.
Gast #135541
Lesenswert?

Hmm ... weiß jemand, unter welchen Umständen ein C Compiler
Rotate-Instruktionen benutzt, bzw. wie man ihn dazu bringt, es zu tun?

Zur Not kann man natürlich auch Inline Assembler ins Programm einbauen.
Aber bei einer 7-Segment Ansteuerung ist es auch wurscht, ob die Routine
100 oder 150 Takte braucht, denn sie wird ja höchstens (ein 4-stelliges
Display vorausgesetzt) alle 2,5ms aufgerufen.

Übrigens würde ich nicht "einfach so" C einsetzen. Bei kleineren
Sachen ohne komplexe Funktionen/Berechnungen, wo nur mit ein paar Bits
jongliert wird, ist Assembler oft die bessere Wahl.
Gast #135543
Lesenswert?

@Marek: Was magst Du mit "diese Routinen" meinen?
In der Diskussion ging es um die Umsetzung von C-Konstrukten in
Maschinenbefehle verschiedener Prozessoren, die - je nach Typ - das
eine oder andere nicht können, so daß es aufwendig mit mehreren
Befehlen implementiert werden muss.
Hilfreich beim Verständnis ist daher Wissen über den
Assemblerbefehlssatz des verwendeten Prozessors.
Gast #135544
Lesenswert?

Grundsatzdikussion olé! :)

>Übrigens würde ich nicht "einfach so" C einsetzen. Bei kleineren
>Sachen ohne komplexe Funktionen/Berechnungen, wo nur mit ein paar
Bits
>jongliert wird, ist Assembler oft die bessere Wahl.

Warum? Eine LED blinken lassen kann man auch in C. Der einzige für mich
nachvollziehbare Grund ASM zu verwenden ist die größere Performance,
bzw. die wesentlich effizientere Speichernutzung. So lange man genug
Flash-Kapazität und CPU-Power zur Verfügung hat ist C sicherlich nich
schlecht als Assembler.
Jeder wie er kann und will halt :)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren