Hallo Wohl ein relativ triviales bzw. alltägliches Problem: Wie kann ich ein Byte am effizientesten seriell ausgeben? D.h. ich habe ein Byte, und dieses wird nun Bit für Bit an einem Port ausgegeben. Wie macht man sowas effizient - es würde mich sowohl AVR-Assembler als auch C interessieren. Gruss Michael
angenommen bei einer low to high transistion werden die daten übernommen: push temp push counter ldi counter, 8 _loop: clock_low daten_low shiftleft temp skip_if_carry_is_not_set daten_high clock_high dec counter branch_not_null _loop pop counter pop temp (das wäre jezt so meine Idee)
Hallo Ja, das mit dem Schieben hört sich schonmal nicht schlecht an! Ich glaube, in AVR-Assembler heisst der Befehl doch irgend was mit 'rotate' - rotieren ist ja im Prinzip das selbe. Nur finde ich leider keinen C-Operator (?) zum schieben. Gruss Michael
">>" Rechtschieben "<<" Linksschieben for(n=0;n<8;++n) { if (x & (1<<n)) { PORTx |= 0x01; } else { PORTx &= ~0x01; } } Fertich...
ne da heist das shl (shift left) benötigt wird heir der Arithmetische Shift! in C ist der ShiftOperator >> aber heir muß man vorsichtig sein ob der logische oder arithmetische Shift gemacht wird! (kann ggf das ergebnis unerwartet verändern!
Arithmetisch oder Logisch? Ihr verwirrt mich ;-) Naja, heisst dann wohl ausprobieren.
>Arithmetisch oder Logisch?
Hinweis: Probiere das mit negative Zahlen aus, dann findest Du den
Unterschied schneller ;-)
Du kannst in diesem Falle beides verwenden. Logischer Shift bedeutet, was rausgeschoben wird "fällt raus" (bzw in das Carry) und es wird immer eine 0 "reingeschoben". Arithmetischer Shift bedeutet, was rausgeschoben wird, wird dann wieder "reingeschoben" (sozusagen alles immer im kreis) (Meist nur beim Rechtsshift! Linksshift bekommt auch hier eine "0") Rotieren bedeutet, das Carry wird "reingeschoben" und was raus fällt ins Carry übertragen. Dies kann aber ggf. abweichen je nach Programmiersprache! In C z.B. ist es so, das der Shift nach links ein "logischer" ist, der Shift nach rechts meist ein Arithmetischer! Das Instruction Set zu AVR sagt: LSL Rd Logical Shift Left Rd(n+1) ← Rd(n), Rd(0) ← 0 Also Shift nach Links, 0 wird reingeschoben, Carry bleibt unbeeinflußt. LSR Rd Logical Shift Right Rd(n) ← Rd(n+1), Rd(7) ← 0 Also Shift nach Rechts, 0 wird reingeschoben, Carry bleibt unbeeinflußt. ROL Rd Rotate Left Through Carry Rd(0)←C,Rd(n+1)← Rd(n),C←Rd(7) Shift nach Links, Cary wird reingeschoben, erstes Bit kommt ins Carry ROR Rd Rotate Right Through Carry Rd(7)←C,Rd(n)← Rd(n+1),C←Rd(0) Shift nach Rechts, Cary wird reingeschoben, leztes Bit kommt ins Carry ASR Rd Arithmetic Shift Right Rd(n) ← Rd(n+1), n=0..6 Shift nach Rechts, Carry bleibt unbeeinflußt das Rausgeschobene Bit wird Links "drangesezt"
Wie waere es, die SPI-Schnittstelle zu benutzen? OK, dann geht es nicht an nem beliebigen Portpin, aber dafuer schneller als in Software. gruss, bjoern.
> Wie waere es, die SPI-Schnittstelle zu benutzen? OK, dann geht es
nicht an nem beliebigen Portpin, aber dafuer schneller als in
Software.
Eine Idee wäre es. Allerdings ist das empfangende Gerät ein M64282FP
(Bildwandlerchip der Gameboy-Kamera). Es sind 8 Bytes zu übertragen,
denen jeweils 3 Bit Adressinformation vorausgehen. Das ganze kann mit
500 kHz geschehen, aber auch deutlich langsamer. Naja, die 8 Bytes + 24
Bit kann ich auch etwas langsamer verkraften ;-)
">>" Rechtschieben | das ist links "<<" Linksschieben | das ist rechts for(n=0;n<8;++n) { if (x & (1<<n)) { PORTx |= 0x01; } else { PORTx &= ~0x01; } } @ Rahul, haste das mal auf einem Osci. gesehen ?
@mr Chip bei 500khz kann der AVR auch "ineffizent" das Bit rausschieben :D Da langweilt der sich doch nur :)
"Eine Idee wäre es. Allerdings ist das empfangende Gerät ein M64282FP (Bildwandlerchip der Gameboy-Kamera)." Japp, der kann auch bedeutend langsamer. Sag Bescheid, wenn du das mit den Registern hinbekommen hast. Ich hatte da so meine Probleme, um passable Einstellungen zu finden. gruss, bjoern.
x=1; for(n=0;n<7;++n) { if (y & x) portpin an; else portpin aus; x *=2; } besser so?
> Japp, der kann auch bedeutend langsamer.
Weisst du zufällig, wie langsam?
"Weisst du zufällig, wie langsam?" Ich glaube, da hab ich mich zu weit aus dem Fenster gelehnt. Soweit ich meinen alten Sourcecode auf die Schnelle durchschaut hab, hab ich keine Wartezeiten eingebaut und einfach nur dem Protokoll entsprechend einen Schritt nach dem Anderen ausgefuehrt. Ich hab ihn mal angehaengt, vielleicht hilft er dir irgendwie weiter. Der Mega8 lief auf 8Mhz und der Ram war mit Schieberegistern angebunden. gruss, bjoern.
Oh ich seh grad, die Inputs der GBCam waren auch mit am Schieberegister. Also gab es doch erhebliche Wartezeiten...
Und ums vollstaendig zu machen, hier noch Bilder vom Aufbau: http://www.lania.de/salival/bilder/gbcam gruss, bjoern.
So, ich hab meinen Code wieder halbwegs durchschaut, und ich hab mich scheinbar doch nicht zu weit rausgelehnt. Der Chip wird im Takt der AD-Wandlung angesteuert. Diese laeuft bei 8Mhz mit Prescaler 64 im Free-Running-Mode. Ergibt ca 9,6kHz und damit deutlich weniger als die maximalen 500kHz. gruss, bjoern.
@Rahul: oder so: unsigned char x=1; do if (y & x) portpin an; else portpin aus; while(x*=2); Der Clou ist, dass x "Zähler" und Maske in einem ist.
@Björn Müller: Danke für den Code! Ich konnte ihn ganz gut gebrauchen für meine eigene Implementation, da er deutlich mehr aussagt als das magere Datenblatt! Ich glaube sogar, es funktioniert auch - die Kamera reagiert nämlich auf die eingestellte Belichtungszeit. Doch leider misst der ADC nur 0 0 0 0 0 0 0 ..... 0 0 0 Der Vout Pin der Kamera habe ich direkt an den ADC-Eingang des AVR angeschlossen, ohne jegliche Zusatzbeschaltung. Ob dies wohl an den Kamera-Register-Einstellungen liegt? Ich verwende bisher Einstellungen von einer anderen Webseite. Werde es dann evtl. mal mit deinen versuchen, die sollten doch gehen?
Uuups...das mit dem 'Alles 0 0 0 0 0' war ein ganz dämlicher Fehler meinerseits. Immerhin bin ich jetzt soweit, dass ein verrauschtes 'Pixelmuster' herauskommt. Mit einem Bild hat dies noch wenig zu tun... Register?
Noch interessanter: Das Pixelmuster ist immer exakt das selbe, egal wie ich die Kamera halte, selbst nach einem kompletten Reset des ganzen Systems (= Strom weg & PC-Programm neu gestartet)
Wiegesagt, passende Registereinstellungen zu finden, ist das grosse Problem. Die einzelnen Einstellungen beeinflussen sich teilweise gegenseitig und bei unpassenden Einstellungen kommt nur Muell raus. Am besten waere es, alle Register per GUI vom PC aus einstellen zu koennen, und die Veraenderungen direkt zu vergleichen. Das waere bei mir der naechste Schritt gewesen, ich hab die PC-Software aber nie fertig geschrieben. Auf irgendner Page gabs auch Code mit automatischer Belichtung. Es koennten natuerlich auch Timingprobleme sein. Ach ja, folgende Seite kennst Du? Auf deren Basis hab ich die Ansteuerung programmiert: http://www.angelfire.com/de3/juliprograms/amr/gbcam.htm gruss, bjoern.
Jep, die Seite kenne ich - ist ebenfalls meine Grundlage. Mit deinen Einstellungen habe ich jetzt erste Ansätze eines Bildes entdecken können! Als nächstes schreibe ich jetzt mal kurz ein GUI für die Einstellungen, dann kann ich trial-n-error einfach ausprobieren.
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.