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
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!
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 ?
"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.
"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.
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.
@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.