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
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
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.
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
"Ü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.
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
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).
Eine direkte Umwandlung von Bit nach CHAR ist nicht möglich ? Wäre nice wenn dies gehen würde, oder ist dass nur über ein Strukt realisierbar ?
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.
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.
Das ist mir schon aufgefallen. Ich Programmmiere seid 3 Jahren C/C++ aber diese Routinen sind mir nicht bekannt wo findet man informationen darüber ?
@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.
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 :)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.