Hallo,
ich bin in meinem letzen Jahr für Schule und muss mein Abschlussprojekt
bestehen. Bei meinem Abschlussprojekt handelt es sich um ein mobiler
Roboter und ich hab die Aufgabe in meiner Gruppe, ein Empfängerprogramm
zu schreiben das die gesendeten Daten von einer Fernsteuerung erkennt
und dann bearbeitet sodass dann der uC erkennt ob der Roboter nach
links/rechts/nach vorn/nach hinten bzw. schnell oder langsam fahren
soll.
Ich habe das Programm im AVR Studio 4 geschrieben und als ich es gestern
testen wollte also als mein Roboter gestern die Daten von der
Fernsteuerung empfing da reagierte er überhaupt nicht.
Hab das Programm jetzt schon so oft durchgeschaut doch finde den Fehler
nicht.
Das Unterprogramm für die Empfangsroutine befindet sich bei
"SerComm.asm" (Anhang), mein Lehrer hat mir das gegeben da ich es in
meinem Hauptprogramm ergänzen muss dass überhaupt mein Programm
nachfragen geht ob Daten sich im Empfangspuffer befinden.
Das Hauptprogramm befindet sich bei PWM-Programm.aps(Anhang).
Ich wäre für jede Hilfe SEHR dankbar da es sich wie schon gesagt um mein
Abschlussprojekt handelt und dieses bestehen möchte!
Ich bin für jede Frage offen.
mfg Roberto
Hallo,
um was für eine "Fernbedienung" handelt es sich?
Die meisten arbeiten mit Infrarot-Licht; mit einer seriellen
Schnittstelle, für die die Routinen in "SerComm.asm" vorgesehen sind,
haben die nichts am Hut ...
Das kann ich dir nicht so genau sagen. Diese Fernbedinung hat eine
andere Gruppe gebaut. Antenne, zwei joysticks für Richtung bzw. PWM. Man
hat mir nur gesagt dass Baudrate bzw. Datenformat bei Fernbedienung
sowohl beim Roboter gleich sein sollen und über eine Antenne werden die
Signale von der Fernbedienung abgesendet und von einer Antenne die am
Roboter angerichtet ist empfangen.
Meyer Bob schrieb:
> Man> hat mir nur gesagt dass Baudrate bzw. Datenformat bei Fernbedienung> sowohl beim Roboter gleich sein sollen
nicht nur sein sollen, sondern müssen damit sie sich verstehen.
Hol dir doch als erstes mal alle! Informationen zu deiner Aufgabe.
Welche Baudrate, Anzahl der Stopbits, Anzahl der Bits (8/9?), welche
Daten (bzw das Protokoll) wird verwendet. Ebenso wichztig ist die
verwendete Hardware, klar AVR aber mit welchem Quarz, an welcher UART?
Wie sagtst du denn deinen Mitstreitern was sie steuern sollen, einigt
euch auf die Schnittstelle (Variable oder Funktionsaufruf) und
beschreibt diese genau.
Dann schau dir an was an deiner UART so ankommt, liefert die
Fernbedienung die Signale? Oder nimm einen PC mit Hyperterminal und
sende ein paar Daten (mit der richten Baudrate und Konfiguration) und
schau ob diese überhaupt empfangen werden.
jl schrieb:
> Hol dir doch als erstes mal alle! Informationen zu deiner Aufgabe.> Welche Baudrate, Anzahl der Stopbits, Anzahl der Bits (8/9?), welche> Daten (bzw das Protokoll) wird verwendet.
Hab ich alles, die Fernbedienung ist was die Baudrate, Anzahl der
Stopbits und Anzahl der Bits betrifft genau so eingestellt wie der
Roboter.
Aber was meinst du mit Protokoll....gib ein Beispiel bitte.
> Ebenso wichztig ist die> verwendete Hardware, klar AVR aber mit welchem Quarz, an welcher UART?
Mach dir da mal keine Sorgen, wir haben uController-Boards wenn ich
richtog versteh was du damit meinst...
aber was meinst du mit dem Quarz?
> Wie sagtst du denn deinen Mitstreitern was sie steuern sollen, einigt> euch auf die Schnittstelle (Variable oder Funktionsaufruf) und> beschreibt diese genau.
Das Problem ist dass ich nicht so richtig verstehe von was du sprichst,
ich bin kompletter Amateur darin...mir wurde noch nicht so richtig
erklärt was ich Berücksichtigen muss bei der UART.
Meyer Bob schrieb:
> Aber was meinst du mit Protokoll....gib ein Beispiel bitte.
Was geht alles über die Leitung. Anzahl Bytes/Bits, gibt es eine
Prüfsumme.
Gibt es eine Rückmeldung.... Das nennt man Protokoll.
>> Ebenso wichztig ist die>> verwendete Hardware, klar AVR aber mit welchem Quarz, an welcher UART?>> Mach dir da mal keine Sorgen, wir haben uController-Boards wenn ich> richtog versteh was du damit meinst...
Er möchte wissen, was für ein "uController-Boards" es gehau ist.
Verwendeter Prozessor; idealerweise einen Schaltplan
> aber was meinst du mit dem Quarz?
Mit welcher Taktfrequenz wird der Prozessor betrieben. Interner
RC-Oszillator, Quarz, Oszillator, eventuelle DIV8-Vorteiler gesetzt?
>> Wie sagtst du denn deinen Mitstreitern was sie steuern sollen, einigt>> euch auf die Schnittstelle (Variable oder Funktionsaufruf) und>> beschreibt diese genau.>> Das Problem ist dass ich nicht so richtig verstehe von was du sprichst,
Tja, das ist schlecht.
Wenn ich Dir sagen, ich habe ein Modellauto und Du sollst eine Steuerung
dazu bauen (mehr erzähle ich nicht), kannst Du überhaupt nichts machen.
Wenn Du mir sagst, die Fernbedienung hat zwei Knüppel und ein Rad, kann
ich damit immer noch nichts anfangen. Ich muss wissen, was genau auf
meinem UART ankommt, wenn man auf der FB den Knüppel bewegt. Wird
dadurch nur ein Bit gesetzt oder gar ein Analogwert übermittelt....
Hallo Bob,
noch ein Versuch den Begriff Protokoll zu erklären:
Dein Empfänger (Roboter) muß verstehen, was die Fernbedienung "sagt".
Dazu muß bekannt sein, mit dem einfachsten begonnen:
Mit welcher Baudrate wird übertragen, das ist die Anzahl der Bits die
pro
Sekunde übetragen werden -muß bei Sender und Empfänger gleich sein!
Wie wird Übertragen:
Startbit, 8 Datenbits, ggf. ein Paritybit (=Prüfbit) 1 oder 2 Stoppbits?
Das Paritybit wird entweder gesetzt, wenn dei Anzahl der "Einsen" gerade
oder ungerade ist. (Am Anfang würde ich erst mal die Auswertung dieses
Bit
weglassen.
Dann wie ist das Kommando aufgebaut?
Mit anderen Worten "Sprechen Sender und Empfänger die gleiche Sprache?"
und welche?
Ich kann (leider) kein Chinesisch, ich höre zwar daß ein Chinese
spricht,
("Die Baudrate und die Bitseinstellung beim Uart stimmt") aber ich
verstehe nicht was er sagt. (Was bedeutet das Übertragene Byte)
Erst, wenn Du die obigen Fragen geklärt hast, hast Du eine gute Chance
die
Fehler zu finden.
Eventuell mitlesende Chinesen mögen mir den Vergleich ihrer Person mit
mit einem Uart verzeihen, aber ich wollte es mal an einem allgenei
verständlichen Beispiel erklären.
Christian H. schrieb:
>Was geht alles über die Leitung. Anzahl Bytes/Bits, gibt es eine
Prüfsumme.
Gibt es eine Rückmeldung.... Das nennt man Protokoll.
Alles geht wireless...nichts mit Leitung. Es werden 5 Byte gesendet. Das
erste Byte enthält die Anzahl der zu erwartenden Zeichen. Die 4 anderen
Bytes sind für die beiden Joysticks. Ein Joystick für die
GEschwindigkeit und ein anderer für die Richtung.D.h. zwei Bytes für die
horizontale Stellung und die vertikale Stellung eines Joysticks. Beim
ersten Joystick nehmen wir also noch die vertikale Stellung für die
Geschwindigkeit und beim zweiten Joystick die horizontale Stellung für
die Richtung.
Das heisst also das zweite Byte das empfangen wird ist das Byte für die
vertikale Stellung des ersten Joysticks.Das dritte Byte ist dann das
Byte für die horizontale Stellung des Joysticks(benötigen wir also
nicht)
Das vierte Byte für die vertikale Stellung der zweiten
Joysticks(benötigen wir nicht) und das fünfte Byte für die die
horizontale Stellung des zweiten Joysticks für die Richtungen.
> Er möchte wissen, was für ein "uController-Boards" es gehau ist.> Verwendeter Prozessor; idealerweise einen Schaltplan
Schaltplan hab ich nicht, kann aber mal erklären was alles so drauf ist:
Atmega32, bei all seinen Ausgängen sind Pins von denen man mit Kabelen
das Signal abgreifen kann und auf LED's gehen kann.
Anschliessend befindet sich eine RS-232 Schnittstelle auf dem Board, I²C
schnittstelle um den Controller zu programmieren.
> Mit welcher Taktfrequenz wird der Prozessor betrieben. Interner> RC-Oszillator, Quarz, Oszillator, eventuelle DIV8-Vorteiler gesetzt?
Auf dem Board ist ein 16MHz Quarz bzw externer Quarz also.
> Wenn ich Dir sagen, ich habe ein Modellauto und Du sollst eine Steuerung> dazu bauen (mehr erzähle ich nicht), kannst Du überhaupt nichts machen.>> Wenn Du mir sagst, die Fernbedienung hat zwei Knüppel und ein Rad, kann> ich damit immer noch nichts anfangen. Ich muss wissen, was genau auf> meinem UART ankommt, wenn man auf der FB den Knüppel bewegt. Wird> dadurch nur ein Bit gesetzt oder gar ein Analogwert übermittelt....
Wir arbeiten hier nicht mit einer Schnittstelle.Wir benötigen nur eine
Schnittstelle um den uC der Roboters zu programmieren.
Alle Daten werden wireless gesendet und auch wireless empfangen.
Guter Rat schrieb:
> Mit welcher Baudrate wird übertragen, das ist die Anzahl der Bits die> pro> Sekunde übetragen werden -muß bei Sender und Empfänger gleich sein!> Wie wird Übertragen:> Startbit, 8 Datenbits, ggf. ein Paritybit (=Prüfbit) 1 oder 2 Stoppbits?> Das Paritybit wird entweder gesetzt, wenn dei Anzahl der "Einsen" gerade> oder ungerade ist. (Am Anfang würde ich erst mal die Auswertung dieses> Bit> weglassen.
19200 Baud, also Teiler 51, 8 Datenbits, keine PArität, 1 Stoppbit.
>> Dann wie ist das Kommando aufgebaut?> Mit anderen Worten "Sprechen Sender und Empfänger die gleiche Sprache?"> und welche?> Ich kann (leider) kein Chinesisch, ich höre zwar daß ein Chinese> spricht,> ("Die Baudrate und die Bitseinstellung beim Uart stimmt") aber ich> verstehe nicht was er sagt. (Was bedeutet das Übertragene Byte)
Sender und EmpfÄnger sind beide mit Assembler programmiert.
Jap, UART ist also keine Schnittstelle?
Ich fand die Idee gut mit dem Hyperterminal zu arbeiten um zu sehen was
die Fernbedienung zur UART Schnittstelle schickt.
Gruß
Andi
PS.: und woanders werd ich angemault wenn ich nach dem AD9283 und Vpp
frag!
Wenn jemand Dinge falsch benennt, dann muss man ihn auch darauf
hinweisen dürfen. Ob Daten nun über Funk, über ein Kabel oder über
Glasfaser übertragen werden ist völlig egal: Wenn zwei Geräte
miteinander Daten austauschen, so tun sie dies eben über eine
Schnittstelle.
Meyer Bob schrieb:
> mensch, ich möchte doch nur geholfen bekommen und nicht hier mit blöden> Kommentaren über meine Ausdrücke zugespammt werden!
Dann bist du hier falsch ;-)
Nee, aber mal wirklich. Woher sollen wir wissen warum Dein Roboter nicht
das macht was er soll, wenn wir nicht mal den Schaltplan kennen.
Mal ins Blaue geraten:
- Batterien der Fernbedienung alle
- Zwar ein 16 MHZ Quartz dran, der Controller läuft aber intern auf 8MHz
- Kabel ab, bzw. kalte lötstelle
Geh so vor, dass du einzelne Komponenten testen kannst, damit du
ausschließen kannst und nicht nur ins blaue rätst.
Mein Roboter soll NUR die Daten die er empfängt verarbeiten und
entsprechend auf die Ausgänge geben wo ich möchte. Da muss man nicht
mehr wissen, Baudrate und all das hab ich schon gesagt, ich möchte nur
dass jemand sich mein Programm anschaut un eventuelle Fehler mir
mitteilen kann mehr nicht.
Hallo Bob,
langsam sehe ich schwarz für das Projekt.
Die Leute wollen Dir helfen, aber mit Kommentaren
Deinerseits wie "Sender und EmpfÄnger sind beide mit Assembler
programmiert." Oder Daß Kabel am ATMEGA32 sind die zu LEDs gehen
kann keiner hilfreiche Tipps geben.
Daß die Joystickstellungen als Bytes übertragen werden werden
kann sich jeder hier im Forum denken, nur heißt z.B.
0xFF Joytick ist "vorne" und was soll das Teil dann tun
oder 0x80 Joystick ist in der Mitte oder oder.........
(Hoffentlich ist wenigstens bekannt was 0x80 bedeutet)
Wie schon Datasheeet schrieb würde ich Komponenten einzeln!!!!!
austesten und dann den nächsten Schritt machen.
Und ob Sender und Empfänger in Assembler, C oder was auch immer
programmiert sind ist sowas von egal........
Ich würde halt (in Assembler kein Problem wenn mans kann)
so vorgehen:
Z.B. im Sekunden (oder auch anderem Abstand) z.B. das Kommando
bzw. die Bytefolge Joystick in der Mitte senden.
Dann am Senderausgang Checken ob diese Bytefolge gesendet wird.
Am Empfänger messen ob sie richtig ankommt.
Messen ob das Teil reagiert wie gewünscht.
Und mit dem AVR Studio läßt sich auch ein Assemblerprogramm
Schritt für Schritt ausführen...............
Ok, Eingabe sind etwas lästig, aber für einen grundsätzlichen Test
reicht es alle mal.
Ansonsten empfehle ich die Kristallkugel!!!
Du möchtest, daß sich jemand Dein Programm ansieht und Fehler findet,
ohne vorher überhaupt zu wissen, was es genau (... GENAU!!!) tun soll?
Ja, wir sind ja alle Hellseher hier ... darum sind wir hier ...
Gruß
Jobst
Das Programm soll Daten empfangen können, am zweiten Byte erkennen
können op der Roboter schnell (0xFF) oder gar nicht 0x80 oder nach
hinten 0x00 fahren soll.
Am fünften Byte soll es erkennen ob es nach links 0x00, gerade aus 0x80
oder nach rechts 0xFF fahren soll.
Mal eine Zusammenfassung - was wir eigentlich schon am Anfang erwartet
hätten:
Es kommen 5 Bytes mit 19200 8N1 am UART an.
1. Byte unwichtig (Inhalt 4?)
2. Byte Geschwindigkeit (0xFF max. vorwärts, 0x80, stop, 0x00 max.
rückwärts)
3. Byte unwichtig
4. Byte unwichtig
5. Byte Richtung (0xFF max. rechts, 0x80 gerade, 0x00 links)
... woran erkennst Du, welches Byte welches ist? Ich meine - gibt es
eine Startmarkierung?
Nun die zweite Hälfte der Infos die wir gerne hätten:
An welchen Ausgängen (1) werden wie (2) welche Motoren (wofür? 3)
angesteuert?
Sind das nur zwei Räder, und die Richtung wird durch unterschiedliche
Drehzahlen festgelegt. Oder gibt es einen Antrieb und ein gelenktes Rad?
Gruß
Jobst
typisch Schule, hast du verstanden was du da machen sollst und wie der
Code der dir zur Verfügung steht funktioniert? Hast du die UART und das
Interruptsystem ansatzweise begriffen? Wenn nein, dann ist jetzt die
Zeit gekommen.
Sorry, aber das musste erstmal sein. Hier versuchen dir alle zu helfen
und dir Vorgehensweisen zur eigenständige Fehlersuche aufzuzeigen da wir
alle keine Glaskugel haben.
Les mal "http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART" und
vergleiche was im Lehrerfile drinsteht
Lehrercode:
;LDI temp, 0b10011000 ; Sender & Empfänger einschalten
; OUT UCSRB, temp ; RXC Interrupt einschalten
; UDRE Interrupt nocht NICHT einschalten
AVR-Tutorial:_UART
sbi UCSRB, RXCIE ; Interrupt bei Empfang
sbi UCSRB, RXEN ; RX (Empfang) aktivieren
dein Code:
LDI temp, 0b00010000
OUT UCSRB,temp
und jetzt die Frage: empfängst du irgendwas in deiner Interruptroutine?
Jobst M. schrieb:
> ... woran erkennst Du, welches Byte welches ist? Ich meine - gibt es> eine Startmarkierung?
Die Bytes werden im Doppelregister Z gespeichert (vom Sender aus) und
mein Programm lädt nun diese Bytes aus dem Doppelregister und dann
inkrementiere ich einfach das Doppelregister so oft dass ich dann die
Bytes herauslade die ich gern hätte.
> Nun die zweite Hälfte der Infos die wir gerne hätten:>> An welchen Ausgängen (1) werden wie (2) welche Motoren (wofür? 3)> angesteuert?> Sind das nur zwei Räder, und die Richtung wird durch unterschiedliche> Drehzahlen festgelegt. Oder gibt es einen Antrieb und ein gelenktes Rad?
Wir benutzen 2 Motoren MFA 950 D series 4,5 - 15V DC.
Beide Motoren für zwei Räder und dann haben wir noch ein Stützrad.
Hab den Schaltplan der Hauptplatine des Roboters als Anhang reingesetzt.
Dort seht ihr alles detailliert.
Hab mich geirrt, es ist KEIN atmega32 sondern Atmega16L.
Der L298 IC ist die Motorsteuerung. Für die PWM benutzen wir PD4 und PD5
vom uC und für die Motorsteuerung PB0,PB1,PB3 und PC2.
jl schrieb:
> Lehrercode:> ;LDI temp, 0b10011000 ; Sender & Empfänger einschalten> ; OUT UCSRB, temp ; RXC Interrupt einschalten> ; UDRE Interrupt nocht NICHT einschalten>>> AVR-Tutorial:_UART> sbi UCSRB, RXCIE ; Interrupt bei Empfang> sbi UCSRB, RXEN ; RX (Empfang) aktivieren>>>> dein Code:> LDI temp, 0b00010000> OUT UCSRB,temp>>> und jetzt die Frage: empfängst du irgendwas in deiner Interruptroutine?
Ja, die Signale die man mir sendet. Ich hab Timer2 genommen und sein
Compare Match auf 130 gesetzt dass er dann bei 130 immer ein Interrupt
auslöst und die Rotuine aufruft die dann schauen geht ob etwas neues im
Z Register steht.
Ich versteh aber nicht wieso mein Lehrer RXCIE initialisiert wenn wir
was empfangen doch schon einen separaten Interrupt erzeugen bzw mit
Timer2 ?
Meyer Bob schrieb:
> Die Bytes werden im Doppelregister Z gespeichert (vom Sender aus)
Wie kommt denn der Sender an das Z-Register :-?
Die Daten kommen doch über RxD an ...
Die im Plan vorhandenen Anschlüsse für Sensoren werden nicht benutzt?
Gruß
Jobst
Darf ich mal was fragen?
Ich machs einfach mal (und niemand sollte mir da böse sein).
Ich seh gerade nicht wie der Atmel mit dem Wireless Modul verbunden ist,
ich meine irgendwoher muß doch das Signal in den Atmega16L, seh ich da
gerade was nicht?
Andreas G. schrieb:
> Ich seh gerade nicht wie der Atmel mit dem Wireless Modul verbunden ist
Suchen Sie die RXD-Leitung :-) - da wird das VERMUTLICH angeschlussen.
Gruß
Jobst
Jobst M. schrieb:
> Wie kommt denn der Sender an das Z-Register :-?> Die Daten kommen doch über RxD an ...>> Die im Plan vorhandenen Anschlüsse für Sensoren werden nicht benutzt?
Die Fernbedienung hat auch eine Interruptroutine wo sie ihre Werte in
das Z Register speichert das sich in der Interruptroutine befindet.
Andreas G. schrieb:
> Darf ich mal was fragen?> Ich machs einfach mal (und niemand sollte mir da böse sein).> Ich seh gerade nicht wie der Atmel mit dem Wireless Modul verbunden ist,> ich meine irgendwoher muß doch das Signal in den Atmega16L, seh ich da> gerade was nicht?
Eine Huckepack Platine befindet sich über der Hauptplatine und darauf
befindet sich dann ein Wireless Modul bzw. XBEE. Sein RxD Signal wird
dann anschliessend nach unten auf die Hauptplatine bzw. uController
geführt.
Meyer Bob schrieb:
> Jobst M. schrieb:>> Wie kommt denn der Sender an das Z-Register :-?>> Die Daten kommen doch über RxD an ...> Die Fernbedienung hat auch eine Interruptroutine wo sie ihre Werte in> das Z Register speichert das sich in der Interruptroutine befindet.>>>> Die im Plan vorhandenen Anschlüsse für Sensoren werden nicht benutzt?>
Nein. Wie haben sie das herausgefunden?
jetzt fang ich nochmal von vorne an:
was ist deine Aufgabe? Welche Schnittstellen (Interface) sind zu deinen
Mitstreitern definiert worden?
Du schreibst jetzt allen ernstes das deine Kollegen von der
Fernbedienung dir in das Z-Register schreiben und dann pfuschst du ihnen
in der UART Routine/Konfiguration herum?
Kann man denn das Signal vom XBee-Modul (wenn es XBee ist) an den
RxD-Pin einfach so anschliessen? Mir war mal so als hätte ich hier was
darüber gelesen, TTL und RS232 und so....wäre nur so eine Idee das dort
das Problem liegt....
Meyer Bob schrieb:
> Die Fernbedienung hat auch eine Interruptroutine wo sie ihre Werte in> das Z Register speichert das sich in der Interruptroutine befindet.
Aha. Der Sender speichert seine Daten im Z-Register und damit hast Du im
Steuerprozessor des Roboters automatisch Zugriff auf diese Daten?
Sie werden also gar nicht übertragen, sie sind einfach da ... ist ja
schön ... was sollen wir eigentlich noch prüfen?
Das ist unglaublich, das kenne ich auch von unseren Lehrlingen. Die sind
nicht in der Lage strukturiert zu denken und diese Gedanken dann auch
noch für Aussenstehende verständlich in Worte zu fassen. Das lernen die
bei uns im ersten Lehrjahr: Funktionsbeschreibungen zu schreiben!
Zuerst erzählst Du uns, daß Du nichts mit dem Sender am Hut hast und nun
erzählst Du uns sowas.
Die Daten müssen übertragen werden und das passiert seriell.
Du machst die Fernbedienung an und die fängt an munter Daten zu senden.
Nun machst Du den Empfänger/Roboter an.
Dieser empfängt irgendein Zeichen mitten aus diesem Datenstrom und geht
davon aus, daß es sich um das erste von 5 handelt - oder wie sieht das
aus?
Gruß
Jobst
Meyer Bob schrieb:
>>> Die im Plan vorhandenen Anschlüsse für Sensoren werden nicht benutzt?>>>> Nein. Wie haben sie das herausgefunden?
...
Wo ist die Kamera? Ist das hier 'Verstehen Sie Spaß?' ?
Ich habe eine Frage formuliert ... nichts herausgefunden.
Aber jetzt wissen wir auch das.
Gruß
Jobst
Andreas G. schrieb:
> Kann man denn das Signal vom XBee-Modul (wenn es XBee ist) an den> RxD-Pin einfach so anschliessen? Mir war mal so als hätte ich hier was> darüber gelesen, TTL und RS232 und so....wäre nur so eine Idee das dort> das Problem liegt....
Ob da TTL, RS232 oder Netzspannung anliegt, hat auf die Funktion dieses
Projekts vermutlich keine Auswirkungen ...
Gruß
Jobst
Jobst M. schrieb:
> Aha. Der Sender speichert seine Daten im Z-Register und damit hast Du im> Steuerprozessor des Roboters automatisch Zugriff auf diese Daten?> Sie werden also gar nicht übertragen, sie sind einfach da ... ist ja> schön ... was sollen wir eigentlich noch prüfen?
Nein. Die Daten weren ins Z-Register gespeichert und dann von einem XBEE
der an der Fernbedienung ist gesendet.
> Zuerst erzählst Du uns, daß Du nichts mit dem Sender am Hut hast und nun> erzählst Du uns sowas.
Doch, ich weiss nur einige Informationen über die Fernbedienung. Die
Fernbedienung packt die Daten ins Z-Register sendet sie über den XBEE
(TXD) an mein Roboter und dieser empfängt sie dann mit einem XBEE bzw.
im Hauptprogramm sollen die Daten die im Z-Register gespeichert sind
verarbeitet werden.
> Die Daten müssen übertragen werden und das passiert seriell.> Du machst die Fernbedienung an und die fängt an munter Daten zu senden.> Nun machst Du den Empfänger/Roboter an.> Dieser empfängt irgendein Zeichen mitten aus diesem Datenstrom und geht> davon aus, daß es sich um das erste von 5 handelt - oder wie sieht das> aus?
Gehen wir davon aus dass Fernbedienung und Roboter, beide, an sind. die
Fernbedienung wird betätigt und sendet nun Daten an den Roboter. Dieser
verarbeitet diese dann und wenn während der Verarbeitung die Position
der Joysticks auf der Fernbedienung verändert wird dann soll nicht der
Roboter die vorherige Stellung der Joysticks noch ausführen sondern
direkt gleichzeitig die neue Stellung ausführen.
Beispiel: Sender sendet nun, der Roboter empfängt und ist erst bei der
Verarbeitung der zweiten Bytes. Direkt wir die Joystickstellung
verändert z.B. soll der Roboter nun langsam fahren und nach links. Dann
fährt der Roboter schnell (da das zweite Byte noch ausgeführt wird) und
dann nach links und dann erst fährt er langsam.
stell dir doch mal die einfache Frage: wie kommen die Daten vom XBEE in
dein Z-Register?
Zwischen AVR und XBEE ist viel Platz und nur ein paar Drähte. Ja und die
hängen an der UART. Also muss deine UART funktionieren und das tut sie
nicht. Also kommt nichts im Z-register an was du verarbeiten kannst.
Schau dir das Lehrerprogramm an und das Tutorial von der AVR UART. dann
sollte etwas klar werden.
Meyer Bob schrieb:
> Doch, ich weiss nur einige Informationen über die Fernbedienung. Die> Fernbedienung packt die Daten ins Z-Register
DAS interessiert keinen Menschen.
Wie die Fernbedienung die Daten auf den Weg bringt ist ihre Sache.
Das einzige was interessiert ist: Wie sehen die Daten aus.
> sendet sie über den XBEE> (TXD) an mein Roboter und dieser empfängt sie dann mit einem XBEE
Auch das interessiert im Grunde niemanden.
Die Daten kommen für dein Programm an der UART an. Wie sie dort
hingekommen sind, durch Kabel, über Funk oder per berittenem Boten, ist
deinem Programm egal. Die UART ist deine Schnittstelle, an der du die
Daten abholst.
> Gehen wir davon aus dass Fernbedienung und Roboter, beide, an sind.
Davon gehst du besser nicht aus.
Du gehst besser davon aus, dass du in den Datenbytes EINDEUTIG erkennen
kannst, welches das erste Byte der Nachrichtensequenz ist. Dazu
schreibst du dir auf Papier ein paar derartige vollständige Nachrichten
hin. Dann setzt du dich hin und deckst vom Anfang der ersten Nachricht
an gerechnet eine beliebie Byteanzahl ab (möglichst kein Vielfaches von
5). Und dann fragst du dich, wenn du den Rest siehst: Woran kann ich
erkennen, wo die nächste Nachricht anfängt.
Und wenn du das nicht eindeutig regeln kannst, dann musst du mit den
Leuten reden, die die Fernsteuerung bauen. Ihr MÜSST es schaffen, dass
der Empfänger EINDEUTIG feststellen kann, wann eine neue Nachricht
anfängt. Selbst dann, wenn man mitten in die Übertragung einsteigt.
Gerade bei Funk und bei mobilen Einheiten mit ständig wechselnden
Empfangsbedingungen muss man immer damit rechnen, dass ein Byte verloren
geht.
Karl heinz Buchegger schrieb:
> Gerade bei Funk und bei mobilen Einheiten mit ständig wechselnden> Empfangsbedingungen muss man immer damit rechnen, dass ein Byte verloren> geht.
Nicht nur das, es können auch Übertragunsfehler auftreten (ich weiss
nicht, wie gut der XBee da mitmacht). Stell Dir mal vor, der Roboter
steht vor einem Abhang und Du gibst das "Zurück"-Signal. Im gleichen
Moment öffnet Dein Nachbar seine Garage (hat vielleicht zufällig auch
einen XBee integriert). Dein Roboter bekommt leider ein "volle Kraft
Voraus" mit.
Ups, erkläre das mal Deinen Mitstreitern.
Dh.
Der Sender muss ein eindeutiges Startbyte senden (jetzt kommt die
Übertragung). Dann kommen die Daten. Im Anschluss eine Prüfsumme (CRC).
Der Roboter wartet, bis er ein Startbyte empfängt. Dann sammelt er
erstmal die sechs folgenden Bytes und überprüft die Prüfsumme. Ist alles
korrekt,
wird der Befehl ausgeführt.
Wenn man noch sicherer sein möchte, muss die FB den Befehl mehrfach
senden.
Idealerweise wird dann noch ein Wiederholungszähler eingebaut. Die
Datenübertragung sieht dann so aus:
1. START; 0x01; 5 Befehlsbytes; CRC
2. START; 0x02; 5 Befehlsbytes; CRC
3. START; 0x03; 5 Befehlsbytes; CRC
Erst wenn alle drei Befehle gleich sind, wird der Befehl angenommen.
Stimmt etwas nicht, wird ein Notprogramm gestartet (alle Motoren Stop).
Dabei muss natürlich sichergestellt werden, dass START in keinem der
anderen Bytes vorkommen kann (zB START = 0x55; falls CRC == 0x55 dann
CRC = 0x56; Befehlsbytes != 0x55).
jl schrieb:
> Schau dir das Lehrerprogramm an und das Tutorial von der AVR UART. dann> sollte etwas klar werden.
Nein...mir ist noch immer nichts klar...
Ich habe euch gesagt was ihr wissen wolltet, Baudrate und all das. Ich
weiss nicht mehr was ich euch noch sagen soll denn ich habe überhaupt
keinen richtigen Überblick über die Programmierung.
Niemand hat von einer Fehlermeldung oder so was gesprochen.
Meyer Bob schrieb:
> Ich habe euch gesagt was ihr wissen wolltet, Baudrate und all das. Ich> weiss nicht mehr was ich euch noch sagen soll denn ich habe überhaupt> keinen richtigen Überblick über die Programmierung.> Niemand hat von einer Fehlermeldung oder so was gesprochen.
Sagen wirs so: Die Leute haben einfach angst, dass euer Projekt an der
Stelle mächtig in die Hose geht, und zwar aus gutem Grund.
Da hier viele schon komplexere Projekte hinter sich haben, können sie
auch die Fehlerquellen einschätzen
Fehlerquellen sind u.a.
- Die Funkübertragung an sich, die gestört sein kann: Bits kippen um,
Bytes werden nicht erkannt usw usf. Stell dir einfach einen schlechten
Radiosender vor und dann übertrag damit mal Daten.
- Sofern etwas durchkommt - schön, damit ist das "physical layer" da und
man kann Daten übertragen. Der nächste Schritt ist dann
- Datenauswertung. Die eingegangenen Daten müssen korrekt sein. Wenn sie
das nicht sind muss eine Fehlerkorrektur / erneute Übertragung
stattfinden. Das wär das sogenannte "link layer". In deinem Fall ist er
mit dem "network layer" vermischt, siehe auch das was Christian H.
ausführlich beschreibt:
> 1. START; 0x01; 5 Befehlsbytes; CRC> 2. START; 0x02; 5 Befehlsbytes; CRC> 3. START; 0x03; 5 Befehlsbytes; CRC
Das kann man schon mit Stolz als Datenpaket bezeichnen.
Zuguterletzt kommt dein "Application Layer" - die Auswertung der
Befehlsbytes und Ausführung des Befehls.
Phantomix Ximotnahp schrieb:
> Fehlerquellen sind u.a.
Dazu kommt, dass es meiner Meinung nach unpraktisch ist, eine Auswertung
in diesem Schwierigkeitsgrad in Assembler zu pogrammieren. Da kann
einfach viel zu viel passieren und man muss viel zu viel bachten was
einem sonst der Compiler abnimmt. Das fängt bei Buffersystematiken,
Fehlerauswertung an und hört bei Umrechnereien auf.
Wird das aber von jemanden bearbeitet, der so offensichtlich daneben
steht wie der TO, dann grenzt das an Selbstmord.
Aber sei es wie es sei.
Du musst systematisch vorgehen.
Vergiss erst mal die Motoren.
Du brauchst eine Möglichkeit, wo du dir ansehen kannst, was dein Roboter
empfangen hat.
Und du brauchst eine Möglichkeit, wie du dem Roboter zu Testzwecken über
eine andere Schnittstelle Daten unterjubeln kannst.
Zum ersten Punkt:
Ideal wäre ein LCD, auf dem man sich die 5 empfangenen Bytes ausgeben
lässt
Zum zweiten Punkt:
Ideal wäre ein serielle Verbindung zu einem PC über die man dem Roboter
die Datenbytes per Tastatur (zb von einem Terminalprogramm aus)
übertragen kann.
Dann hat man erst mal reproduzierbare Testbedingungen, die man auch
auswerten kann. Ohne solche reproduzierbare Testbedingungen und vor
allen Dingen ohne eine Möglichkeit, wie man sich die empfangenen Daten
ansehen kann, ist das alles sehr, sehr, sehr schwer zu debuggen.
es fehlt schon mal das komplette Verständniss wie ein Controller
funktioniert mit seinen Hardwareblöcken (z.B die UART und wofür sie
gebraucht wird), oder was das simple Lehrerbeispiel darstellt (UART
Treiber). Entweder hat der TO die ganze Zeit geschlafen oder der Lehrer
hat den nötigen Stoff nicht vermittelt.
Naja und als nächstes fehlt es wohl auch an der Teamarbeit.
So, brauch nun eure Hilfe bei einer anderen Sache.
Ich muss nun die Spannung der Versorgungsbatterie auf dem PC mittels VBA
anzeigen. Aber zuerst muss ich den analogen Wert der Spannung in den
A/D-Wandler des Controllers geben, hatte aber bis jetzt noch überhaupt
nichts mit A/D-Wandlern zu tun...was muss ich da tun, wie muss ich da
vorgehen und was muss ich beachten dabei ??
mfg
Die Schnittstelle funktioniert endlich...jetzt fehlt nur noch die
initialisierung von Timer1 und da hab ich auch schon meine erste Frage:
Ich empfange ja Werte die zwischen 0-1000 gross sind. Der empfangene
Wert lade ich in meine Zwischenvariable temp und möchte nun diese
Variable in OCR1AL und OCR1AH setzen aber wie geht das...wie kann ich so
zu sagen temp in zwei teilen um dann dementsprechend die beiden Register
zu initialisieren??
Kommentare zu den Lehren und oder Schülern und deren Doffheit erspare
ich mir lieber.
Wenn Du schon den Wert 0000 bis 1000, also 2 Byte vorliegen hast,
ist das doch ganz einfach:
Liegt der Wert in ZH:ZL
heißt es
STS OCRA1L,ZL
STS OCRA1H,ZH
Wenn es im Templ temph (r16 und r17)
schreibe
STS OCRA1L,r16
STS OCRA1H,r17
und dann paßt es.
Kannst das ganze im AVR-Studio ganz einfach simulieren.
Die Assembler-Befehle sind in der Hilfe recht ordentlich beschrieben,
etwas Englisch-Kenntnisse vorausgesetzt.
Weiterhin viel Erfolg bei dem (grausamen) Spiel.
Ah ok.
Aber vorher möchte ich es aber lieber mit zwei uC-Boards ausprobieren
also das eine Board als Sender und das andere als EmpfÄnger und verbinde
die beide dann mit einem gekreuztem Kabel.
Und nun sage ich dass den Wert den wir empfangen in temp geladen werden
soll.
Und wie soll ich temp(Wert zwischen 0-1000) jetzt in beide Register
laden?
Meyer Bob schrieb:
> Ah ok.> ...> Und wie soll ich temp(Wert zwischen 0-1000) jetzt in beide Register> laden?
Also doch nicht ok?
Es gab doch gerade den "Guten Rat". Den musst Du nur befolgen.
Was verstehst Du daran nicht?
Nochmal von vorn:
Meine Aufgabe ist es mit Timer1 zwei PWM-Signale zu erzeugen (was
momentan überhaupt NICHT der Fall ist, da wir noch NIE mit Timer1
gearbeitet haben)
Ich bin so verzweiffelt wie noch nie !
Ich gebe in mein Programm einfach normale Werte auf OCR1AL und OCR1BL
und auf dem Oszilloskop bekomme ich sehr seltsame Kurven raus.
Mein Lehrer hat mir gesagt dass wir das ICR Register benutzen MÜSSEN und
dieser mit einem Wert initialisieren müssen dass die Frequenz der
Motoren bzw. die Periodendauer 1 ms sprich 1kHz ist.
Wie soll ich das machen??
Bei der Arbeit mit Mikrocontrollern ist es wichtig, das Datenblatt zu
lesen. Das für den Atmega16L gibt es hier:
http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf
Man schalte die Lesezeichen ein, suche dort 16-bit Timer/Counter1 und
klick.
Bitte komplett und eventuell mehrfach lesen.
Im Anschluss an die Beschreibung der Unit kommen alle dafür relavanten
Register. Man muss sich genau überlegen, was man wo reinschreibt. Das
ist beim ersten Mal eine Arbeit auf zwei Stunden und dann läuft die PWM.
Eine kleine Stolperfalle ist, dass man die Ausgangspins noch richtig
konfigurieren muss (DDRx).
Hier gibts sogar ein Beispiel für Timer 1 in Assembler:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM
Grüße,
Peter
Peter Diener schrieb:
> Bei der Arbeit mit Mikrocontrollern ist es wichtig, das Datenblatt zu> lesen. Das für den Atmega16L gibt es hier:>> http://www.atmel.com/dyn/resources/prod_documents/...>> Man schalte die Lesezeichen ein, suche dort 16-bit Timer/Counter1 und> klick.> Bitte komplett und eventuell mehrfach lesen.>> Im Anschluss an die Beschreibung der Unit kommen alle dafür relavanten> Register. Man muss sich genau überlegen, was man wo reinschreibt. Das> ist beim ersten Mal eine Arbeit auf zwei Stunden und dann läuft die PWM.>> Eine kleine Stolperfalle ist, dass man die Ausgangspins noch richtig> konfigurieren muss (DDRx).>> Hier gibts sogar ein Beispiel für Timer 1 in Assembler:>> http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM>>> Grüße,
Danke!
Zumindest hab ich jetzt ein anderes Signal als vorhin auf dem Oszi xD
Jetzt sind solche Sinuswellen mit nem knicks auf dem Oszi...
Hab mal meine initialisierung hier:
; Timer 1 initialisieren
LDI temp, 0
OUT TCNT1L, temp
OUT TCNT1H, temp
LDI temp, 0xE8
OUT ICR1L, temp
LDI temp, 0x03
OUT ICR1H, temp
LDI temp, 0b00000010
OUT TCCR1A, temp
LDI temp, 0b00011010
OUT TCCR1B, temp
ICR1 ist auf (Dezimal) 1000 eingestellt da wir eine Frequenz von 1kHz
möchten.
TCCR1 hat als Teiler 8 und wir arbeiten nach der Methode '14'.
OCR1A + B werden uns gesendet.
Sind die Register die ich initialisiert habe richtig um auf eine
Periodendauer von 1kHz zu kommen??
In TCCR1A stellt man mit COM1xy ein, ob die Pins, die PWM ausgeben
können, das tun und wenn ja, wie. Steht im Datenblatt auf Seite 110.
Normal Port Operation (was du mit TCCR1A = 0 eingestellt hast) bedeutet,
dass die Pins keine PWM ausgeben, sondern normale Digitalports sind. Das
war sicher nicht deine Absicht.
Mode 14 ist in Ordnung für eine Motorsteuerung, aber die Bits sollte man
dann schon richtig einstellen.
Dazu Table 47 auf Seite 112 lesen, die besagt folgende Biteinstellungen,
damit Mode 14 eingestellt ist:
WGM13 = 1
WGM12 = 1
WGM11 = 1
WGM10 = 0
WGM11 und WGM10 sind Teil des TCCR1A. WGM13 und WGM10 stehen in TCCR1B.
Gehen wir es also mal der Reihe nach durch:
wir fangen mit TCCR1A an und schauen an, wie wir das einstellen wollen:
Nehmen wir an, wir möchten eine nicht invertierte, normale PWM. Wir
wollen also, dass beim Zählwert BOTTOM der Pin eingeschaltet wird und
bei Compare Match aus und das für beide Ausgänge. Wir haben "FAST PWM",
daher gilt Table 45. Also: "Clear OC1A/OC1B on compare match, set
OC1A/OC1B at BOTTOM"
Daher stellen wir ein:
COM1A1 = 1
COM1A0 = 0
COM1B1 = 1
COM1B0 = 0
"Force Output Compare" wollen wir nicht, also:
FOC1A = 0
FOC1B = 0
Und die restlichen haben wir uns vorher schon überlegt:
WGM11 = 1
WGM10 = 0
Da kommt dann insgesamt raus:
TCCR1A:
COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
1 0 1 0 0 0 1 0
Wir weisen also zu:
1
LDI temp, 0b10100010
2
OUT TCCR1A, temp
Jetzt machen wir das gleiche für TCCR1B:
Input Capture betreiben wir nicht, also stellen wir ein:
ICNC1 = 0
ICES1 = 0
Die Waveformgeneration-Einstellung haben wir uns schon vorher überlegt,
also:
WGM13 = 1
WGM12 = 1
Jetzt bleibt noch die "Clock Selection".
Durch 8 möchtest du teilen. Warum? Wenn du das nicht tust, kannst du
nachher die Pulsweite genauer einstellen. Also tu ich das mal nicht.
"clkI/O/1 (No prescaling)" stelle ich ein:
CS12 = 0
CS11 = 0
CS10 = 1
Da kommt dann insgesamt raus:
TCCR1B:
ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
0 0 0 1 1 0 0 1
Wir weisen also zu:
1
LDI temp, 0b00011001
2
OUT TCCR1B, temp
TCNT1 müssen wir nicht beschreiben, es ist nach dem Reset auf Null
gesetzt und darf ruhig von dort aus loszählen. Auch wenn es von einer
anderen Zahl aus loszählt, macht das nichts.
OCR1A und OCR1B erkläre ich später.
ICR1 ist noch wichtig. Damit stellt man den TOP Wert ein bei Mode 14.
Wir teilen den Takt nicht runter, der Zähler läuft also mit der
Quartzfrequenz. Und die kennen wir nicht genau. Du hast geschrieben, es
sind 16 MHz. Das glauben wir so einfach mal nicht. Das wäre zusammen mit
einem Atmega8L ein Designfehler. Der Controller darf mit maximal 8 MHz
betrieben werden.
Aber gut, ich rechne mal für 16 MHz.
Du wolltest 1 kHz PWM-Grundfrequenz, der Zähler soll also jede ms
überlaufen. Was müssen wir dann als TOP-Wert einstellen?
Die erste Formel auf Seite 104 gibt Aufschluss darüber, was man als
TOP-Wert einstellen muss (selber nachrechnen). Ich komme auf 15999. Das
ist in Hex 0x3E7F. Man beachte den Hinweis mit den 16 Bit-Registern auf
Seite 92.
Wir weisen also zu:
1
ldi r17,0x3e
2
ldi r16,0x7f
3
out ICR1H,r17
4
out ICR1L,r16
TIMSK und TIFR brauchen wir nicht, da wir keine Interrupts verwenden
(noch nicht ;) ).
Jetzt dürfen wir die Compareregister auf die der Pulsweite
entsprechenden Werte setzen:
Ich stell mal ungefähr 25% (4000) bei dem einen und 50% (8000) bei dem
anderen ein:
1
ldi r17,0x0f
2
ldi r16,0xa0
3
out OCR1AH,r17
4
out OCR1AL,r16
5
6
ldi r17,0x1f
7
ldi r16,0x40
8
out OCR1BH,r17
9
out OCR1BL,r16
So und jetzt noch die Ports als Ausgänge definieren.
Table 31 auf Seite 63 sagt uns, dass OC1A und OC1B die entsprechenden
PWM-Ausgänge sind und diese auf den Pins PD4 und PD5 liegen.
Deswegen setzen wir das Datenrichtungsregister von Port D entsprechend
so, dass diese beiden Pins auf jeden Fall Ausgänge sind. An dieser
Stelle sollte man gleich alle anderen Pins auch richtig setzen oder
alternativ die Werte nur reinodern.
Wir weisen also zu:
1
LDI temp, 0b00110000
2
OUT DDRD, temp
So und das ganze jetzt zusammengefasst und in der richtigen Reihenfolge.
Wir wollen schließlich erst alles konfigurieren und dann erst den Timer
einschalten.
1
;Portrichtung PD4 und PD5 auf Ausgang
2
LDI temp, 0b00110000
3
OUT DDRD, temp
4
;ICR1 konfigurieren; TOP Wert auf 15999 -> 1 kHz PWM bei 16 MHz Takt
5
ldi r17,0x3e
6
ldi r16,0x7f
7
out ICR1H,r17
8
out ICR1L,r16
9
;TCCR1A konfigurieren: non inverting PWM auf beiden Ausgängen, Mode 14
10
LDI temp, 0b10100010
11
OUT TCCR1A, temp
12
;TCCR1B konfigurieren: Mode 14, Clocksource = MCLK / 1 -> Timer ist jetzt an
13
LDI temp, 0b00011001
14
OUT TCCR1B, temp
15
16
;So und jetzt noch die von mir willkürlich gewählte Testpulsweite einstellen
17
ldi r17,0x0f
18
ldi r16,0xa0
19
out OCR1AH,r17
20
out OCR1AL,r16
21
22
ldi r17,0x1f
23
ldi r16,0x40
24
out OCR1BH,r17
25
out OCR1BL,r16
Eine kleine Motivation am Rande:
1
DDRD=0b00110000;
2
ICR1=15999;
3
TCCR1A=0b10100010;
4
TCCR1B=0b00011001;
5
OCR1A=4000;
6
OCR1B=8000;
Das macht genau das gleiche.
Das war aber jetzt genug Denkanstoß, für die serielle Schnittstelle
bitte selber machen.
Grüße,
Peter
VIELEN DANK!
Die PWM funktioniert :D:D
Nur noch ne Kleinigkeit...
Ich empfange ja Werte die im Z-Register stehen und die zwischen 0-255
sind.
Diesen Wert setz ich in den LOW-Bereich des Y-Registers also so:
LD YL, Z+
Diesen Wert vergleiche ich dann mit zwei anderen Werten um zu schauen ob
der Roboter schnell oder langsam fahren soll (also für die PWM).
CPI YL, 0x91
BRSH UP
Nun springen wir dementsprechend auf den Befehl wo der Roboter schnell
fahren soll.
UP: LDI temp, 0x80
SUB YL, temp ; hier ziehen wir dann vom empfangenen Wert 128 ab
da der empfangene Wert (gehen wir davon aus dass dieser 210 ist) grösser
als 127 ist und weil wir bei 0 anfangen wollen.
LDI temp2, 0x7E
MUL YL, temp2 ; Hier multiplizieren wir den Wert mit 128 um auf
ca. 15999 zu kommen.
Nun möchte ich diesen Wert auf OCR1AL+H geben aber wie geht das??
Hab das geschrieben:
OUT OCR1AL, YL
OUT OCR1AH, YH
Aber mein Oszilloskop sagt mir dass das falsch ist ;(
Meyer Bob schrieb:
> LDI temp2, 0x7E> MUL YL, temp2 ; Hier multiplizieren wir den Wert mit 128 um auf> ca. 15999 zu kommen.>> Nun möchte ich diesen Wert auf OCR1AL+H geben aber wie geht das??> Hab das geschrieben:>> OUT OCR1AL, YL> OUT OCR1AH, YH
Instruction Set ansehen!
Das Ergebnis vom MUL findet sich in den Registern r0, r1
Nochmals der Hinweis:
Im AVR-Studio sind unter Assembler - Hilfe die Befehle mit
jeweils einem Beispiel aufgeführt. Da steht dann auch daß
ggf. nicht jeder Befehl mit jedem Register funktioniert.
(Dann meldet der Assembler Fehler).
Übrigens paß auf beim mul-Befehl, der schreibt Hardware-bedingt
in die Register r0 und r1! Wenn die Register anderweitig verwendet
sind kann es zu seltsamen Reaktionen kommen.
Der Mul-Befehl weiß natürlich nicht ob Du -oder jemand anders- r0 und r1
verwendet! Der schreibt das Ergebnis der Multiplikation einfach ins
Register!
Meyer Bob schrieb:
> Und wie soll ich das nun schreiben? o.O
Was für eine Frage?
Nochmal: Wenn du Assembler programmierst, dann brauchst du das
Instruction Set. Hol es dir von Atmel.
AUch AVR-Studio hat es mit. Einfach den Cursor auf den Befehlscode
setzen und F1 drücken.
Und dann machst du erst mal deine Hausaufgaben:
Wie sieht der Assemblercode aus für
(Y << 7) - (Y << 2)
Wieviele Instructionen brauchst du dafür?
Wieviele Takte macht das dann?
(Hinweis: Y<<7 ist die C-Schreibweise für: Ein Register um 7 Bit nach
links schieben)
Und dann das ganze für MUL nochmal.
Meyer Bob schrieb:
> Wäre das dann richtig:>> OUT OCR1AL, r0> OUT OCR1AH, r1
Nein: Abschnitt "Accessing 16-bit Registers" im Datenblatt beachten.
Beim Schreiben H vor L und beim Lesen L vor H.
"To do a 16-bit write, the high byte must be written before the low
byte. For a 16-bit read, the low byte must be read before the high
byte."
Meyer Bob schrieb:
> Wo finde ich diesen Instruction set?
Na wo wohl?
Das entsprechende Dokument für Atmel Prozessoren kann man bei Intel
downloaden
(Ne, Scherz. Natürlich bei www.atmel.com. Das war jetzt wahnsinnig
schwer zu erraten)
Meyer Bob schrieb:
> Wo finde ich diesen Instruction set?
Sag mal, handelt es sich um das Abschluusprojekt Eurer Theater-AG?
Das könnte manches erklären!
Karl heinz Buchegger schrieb:
.
> AUch AVR-Studio hat es mit. Einfach den Cursor auf den Befehlscode> setzen und F1 drücken.
Ich drück F1 und lande dann immer bei irgendeiner Suchmaschine
> Wie sieht der Assemblercode aus für> (Y << 7) - (Y << 2)> Wieviele Instructionen brauchst du dafür?> Wieviele Takte macht das dann?> (Hinweis: Y<<7 ist die C-Schreibweise für: Ein Register um 7 Bit nach> links schieben)
Und was ist die Assemblerschreibweise? ;)
> Und dann das ganze für MUL nochmal.
Wieso dann nochmal für MUL wenn ich jetzt die Schiebevariante nehme?
Meyer Bob schrieb:
> Karl heinz Buchegger schrieb:>> .>> AUch AVR-Studio hat es mit. Einfach den Cursor auf den Befehlscode>> setzen und F1 drücken.>> Ich drück F1 und lande dann immer bei irgendeiner Suchmaschine
Im AVR-Studio?
Dann ist da was falsch konfiguriert.
>>> Wie sieht der Assemblercode aus für>> (Y << 7) - (Y << 2)>>> Wieviele Instructionen brauchst du dafür?>> Wieviele Takte macht das dann?>> (Hinweis: Y<<7 ist die C-Schreibweise für: Ein Register um 7 Bit nach>> links schieben)>> Und was ist die Assemblerschreibweise? ;)
Ich denke das ist DEIN Abschlussprojekt.
Du wirst doch wohl noch ein Register nach links oder rechts schieben
können.
Hol dir endlich von Atmel das verdam... Instruction Set.
Das ist ja nicht auszuhalten. Ein Assembler Programmierer, der seine
Befehle nicht kennt.
>>> Und dann das ganze für MUL nochmal.>> Wieso dann nochmal für MUL wenn ich jetzt die Schiebevariante nehme?
Weil du dann zb feststellen würdest, welches davon schneller ist, also
weniger Takte verbraucht.
Du könntest auch das Register 128 mal mit sich selbert addieren.
Würdest du das etwa tun, nur weil das hier jemand vorbringt?
Christian H. schrieb:
> Einfach mal vergleichen, was schneller ist.>> Ach ja, ich glaube MUL arbeitet nur mit 8bit.
8 * 8 -> 16 Bit Ergebnis
Für ihn perfekt, wenn er die Register frei hat.
Karl heinz Buchegger schrieb:
> Christian H. schrieb:>> Einfach mal vergleichen, was schneller ist.>>>> Ach ja, ich glaube MUL arbeitet nur mit 8bit.>> 8 * 8 -> 16 Bit Ergebnis>> Für ihn perfekt, wenn er die Register frei hat.
Ja, da hast du recht.
Das steht bei der Hilfe:
mul r5,r4 ; Multiply unsigned r5 and r4
movw r4,r0 ; Copy result back in r5:r4
Nun versteh ich aber nicht wieso wenn wir r0 ind r4 laden, wird dann r1
automatisch in r5 geladen oder wei?
Meyer Bob schrieb:
> mul r5,r4 ; Multiply unsigned r5 and r4>> movw r4,r0 ; Copy result back in r5:r4>> Nun versteh ich aber nicht wieso wenn wir r0 ind r4 laden, wird dann r1> automatisch in r5 geladen oder wei?
movw - move word, also 16 Bit, also 2 Register
Karl heinz Buchegger schrieb:
>> mul r5,r4 ; Multiply unsigned r5 and r4>>>> movw r4,r0 ; Copy result back in r5:r4>>>> Nun versteh ich aber nicht wieso wenn wir r0 ind r4 laden, wird dann r1>> automatisch in r5 geladen oder wei?>> movw - move word, also 16 Bit, also 2 Register
Aber ich dachte r4 wäre der Faktor mit dem r5 multipliziert wird??
Meyer Bob schrieb:
> Karl heinz Buchegger schrieb:>>> mul r5,r4 ; Multiply unsigned r5 and r4>>>>>> movw r4,r0 ; Copy result back in r5:r4>>>>>> Nun versteh ich aber nicht wieso wenn wir r0 ind r4 laden, wird dann r1>>> automatisch in r5 geladen oder wei?>>>> movw - move word, also 16 Bit, also 2 Register>> Aber ich dachte r4 wäre der Faktor mit dem r5 multipliziert wird??
In dem Beispiel ja.
Niemand hindert dich daran, das Ergebnis der Multiplikation in ein
anderes Registerpärchen umzukopieren, wenn du nach der Multiplikation r4
oder r5 noch brauchst.
Du kannst damit machen was du willst. Und wenn du das Ergebnis der
Multiplikation (welches in 2 Registern vorliegt) auf die Register r4 und
r5 kopieren möchtest, dann möchtest du das. Weder Atmel noch der µC
hindern dich daran.
MUL reg1, reg2
multipliziert den Inhalt des Registers reg1 mit dem Inhalt des Registers
reg2. Das Ergebnis, welches dann 16 Bit hat, liegt in den Registern r0
und r1. Was du im Anschluss mit den Registern r0:r1 machst .... bleibt
dir überlassen.
Meyer Bob schrieb:
> LDI temp2, 0x7E> MUL temp, temp2>> MOVW temp2, r0>> OUT OCR1AH, temp> OUT OCR1AL, temp2>> Das müsste doch jetzt funktionieren oder???
Kommt drauf an, was sich hinter temp und temp2 verbirgt.
Aber warum lädst du nicht gleich OCR1AH aus r0 und OCR1AL aus r1? Das
ist wahrscheinlich zu banal.
Meyer Bob schrieb:
> Das heisst dann muss ich diesen MOVW überhaupt nicht machen?
Warum solltest du?
Ein MOVW macht einen Move des Inhalts eines Registerpärchens in ein
anderes Registerpärchen. Hat ja nichts mit einer Multiplikation zu tun.
Und jetzt hol dir endlich das verdammte Instruction Set Manual von
Atmel. Da kannst du nämlich schön sauber nachlesen, was die einzelnen
Befehle eigentlich machen.
Ist gut...brauch das nicht mehr.
Hab das PWM am Laufen ;)
Einen GROSSEN Dank an alle.
Und den grössten Lob geht aber an Peter Diener. Ohne deine
Initialisierungen wäre ich verloren gewesen. :)
Nun gehts an den A/D-Wandler :P
Sobald ich ne Frage hab meld ich mich. ;)
Meyer Bob schrieb:
> Ist gut...brauch das nicht mehr.
Ach?
> Hab das PWM am Laufen ;)
Die PWM
Puls - Weiten - Modulation ist nach den Regel der deutschen Sprache
weiblich. Die Modulation, nicht das Modulation.
(Das könnte sich in deinem Abschlussprojekt schlecht ausnehmen, wenn du
Abkürzungen verwendest, von denen du noch nicht einmal weißt, was sie
bedeuten und du daher welchen Artikel verwenden musst.
> Nun gehts an den A/D-Wandler :P> Sobald ich ne Frage hab meld ich mich. ;)
Warts ab, ob dir dann noch jemand antwortet :-)
Ein Assembler Programmierer der sich weigert das Instruction Set Manual
downzuloaden. Ich hab schon viel erlebt, aber sowas ist selbst mir noch
nicht untergekommen. Was kommt als nächstes? Urlaub in USA ohne ein Wort
Englisch zu können und ohne Wörterbuch? Das hingegen hab ich schon
miterlebt: deutsche Frau, die sich in Florida im Motel beim Checkin
masslos darüber aufregt, dass hier keiner Deutsch spricht :-)
Bei uns nennt man das "Befehlsliste", gut zu wissen dass die auch anders
heisst ;)
Auf die Rechtschreibung schau ich nicht ^^ als nicht-Deutscher ist mein
Deutsch regelrecht GUT !
Hoffe zumindest dass mir noch irgendjemand antwortet :P
Meyer Bob schrieb:
> Das heisst dann muss ich diesen MOVW überhaupt nicht machen?
Hast du eigentlich eine Zeile an deinem Projekt schon selbst
geschrieben? Ich verstehe echt nicht, warum immer so viele dieses
Betruegereien mitmachen :-/
Peter Stegemann schrieb:
> Hast du eigentlich eine Zeile an deinem Projekt schon selbst> geschrieben? Ich verstehe echt nicht, warum immer so viele dieses> Betruegereien mitmachen :-/
Ich habe ALLES selber geschrieben bis jetzt. Das mit Timer1 konnte ich
nicht wissen und mit der Schnittstelle hatte ich noch nicht genügend
Erfahrung.
Ich betrüge nicht, ich informiere mich.
Das mit dem SELBER Geschrieben ist doch nicht mal so falsch....
Hat er es doch über die Tastatur reingeklopft, ups, geschrieben.
Oder doch copy and paste?????
Bin mal gespannt wie das Theaterstück weiter geht,
mit dem A/D-Wandler gibt es noch Freude!
Es ist nur seltsam, dass an manchen Stellen völlig unerwartete
Lichtblicke durchschienen.
Woanders nennt man so was "Täterwissen".
Ich halte die ganze Nummer für ein bait.
@Meyer Bob
Du hättest dich mal ruhig bei kbuchegg bedanken können. Der hat nämlich
die Sache auf den Punkt gebracht.
Du bastelst da rum, aber raffst nur die Häfte. Die Leute, die hier
schreiben, bemühen sich wirklich sehr um dich, das sind hier zum Teil
diplomierte, vielleicht promovierte Ingenieure, und das hab ich noch
nicht oft so hier im Forum gesehen, und was machst du? Du machst mehr
oder weniger Copy&Paste und kriegst es noch nichtmal auf die Reihe dir
dein Handwerkszeug zu besorgen.
Klingt hart, aber ich musste das jetzt mal schreiben.
Heini schrieb:
> Ich halte die ganze Nummer für ein bait.
Ich schaue mir das ganz auch nur noch amüsiert an.
Vor allem verblüfft mich das totale Desinteresse ...
Gruß
Jobst
"zielorientiert" heisst das...
Wenn andere meine Arbeit machen und ich sie dann abgebe, ist
mein Aufwand optimal.
Alle, die sich hier aufregen, sind doch nur neidisch, weil sie
immer alles selber machen!
@ Peter Diener
Wie bist du auf 15999 gekommen?
hab alle Werte in die Formel getan:
1kHz = 16MHZ/ (2 x 1 x TOP)
Formelumstellung nach Top:
TOP = 16MHz / 2kHz = 8000 ???
Kannst du mir bitte erklären welche Werte du genommen hast evtl. ob ich
mich mit den Werten geirrt hab?
mfg
Meyer Bob schrieb:
> @ Peter Diener>> Wie bist du auf 15999 gekommen?> hab alle Werte in die Formel getan:
Welche Formel hast du genommen?
> 1kHz = 16MHZ/ (2 x 1 x TOP)
Warum 2?
Du benutzt Fast PWM. Das ergibt bei jedem Sweep durch den Timerrange
einen kompletten Puls.
Das ist auch völlig logisch.
Bei 16 Mhz und einem Vorteiler von 1 muss der Timer jedesmal 16000
Zählvorgänge in einem PWM-Durchgang machen, damit er in 1 Sekunde 1000
komplette PWM-Durchgänge schafft.
Meyer Bob schrieb:
> Und warum dann 15999 anstatt 16000?
Wenn du von 0 wegzählst und 3 Zählvorgänge machen sollst, ehe du wieder
bei 0 bist, wie weit musst du dann zählen
0, 1, 2, 0, 1, 2
| |
+--------+
Es wird bis 2 gezählt und damit hat man 3 Zählvorgänge bis man einmal
rundum ist. Also ist die höchste Zahl, bis zu der gezählt werden muss,
immer um 1 kleiner als die Anzahl der Zählvorgänge für einmal rundum.
Oder anders ausgedrückt: Eine Minute hat zwar 60 Sekunden, aber die
höchste 'Sekundennummer' ist 59. Nach der 59 wird wieder bei 0
angefangen. Der Sekundenzeiger tickt aber 60 mal für eine Runde auf dem
Zifferblatt.
> Und habe nicht so richtig verstanden wieso man diese '2' unterm Bruch> weglassen kann...
Du solltest dir die Formel aussuchen, die zum eingestellten Modus passt.
Es macht wenig Sinn, wenn du Fast-PWM Modus benutzt und du dann die
FOrmel für Phase/Frequency-correct PWM benutzt.
Karl heinz Buchegger schrieb:
> Meyer Bob schrieb:>> Und warum dann 15999 anstatt 16000?>> Wenn du von 0 wegzählst und 3 Zählvorgänge machen sollst, ehe du wieder> bei 0 bist, wie weit musst du dann zählen>> 0, 1, 2, 0, 1, 2>> | |> +--------+>> Es wird bis 2 gezählt und damit hat man 3 Zählvorgänge bis man einmal> rundum ist.
Ja, aber wenn man nun z.B. den Startwert rechnen möchte von TCNT0 dann
hat man ja folgende Formel:
Die Frequenz soll 440 Hz(LA) sein.
Frequenz = Systemtakt / (2 x Vorteiler x Zählschritte)
= Systemtakt / (2 x Vorteiler x (256-x))
256-x = Systemtakt / (2 x Vorteiler x 440 Hz)
x = 256 - (Systemtakt / (2 x Vorteiler x 440 Hz))
x = 185 = Startwert
256 - x = 256 - 185 = 71 = Zählschritte
Und nun muss man also den Wert "185" in den TCNT Register eintragen und
nicht 184 ! So hab ich es auf jedenfall in der Schule gelernt...oder ist
das falsch?
>>> Und habe nicht so richtig verstanden wieso man diese '2' unterm Bruch>> weglassen kann...>> Du solltest dir die Formel aussuchen, die zum eingestellten Modus passt.> Es macht wenig Sinn, wenn du Fast-PWM Modus benutzt und du dann die> FOrmel für Phase/Frequency-correct PWM benutzt.
Ich habe die Formel benutzt die mir Peter Diener auf Seite 104
vorgeschlagen hat...
Meyer Bob schrieb:
> nicht 184 ! So hab ich es auf jedenfall in der Schule gelernt...oder ist> das falsch?
Du sollst nachdenken wie es zu den Formeln kommt und nicht blind
auswendig lernen.
Was macht der Timer? Was bedeutet das daher?
(Und du sollst auch nicht Äpfel mit Birnen vergleichen. Du redest von
einem Startwert vorgeben. Das hat aber nicht das Geringste mit den
Hardware-PWM Modi zu tun. Von 185 bis 256 sind es 71 Zählschritte, schon
richtig. Aber der Zähler zählt ja gar nicht bis 256. Als 8 Bit Zähler
ist bei 255 Schluss, und dann gehts mit 0 weiter.)
>>> Und habe nicht so richtig verstanden wieso man diese '2' unterm Bruch>>> weglassen kann...>>>> Du solltest dir die Formel aussuchen, die zum eingestellten Modus passt.>> Es macht wenig Sinn, wenn du Fast-PWM Modus benutzt und du dann die>> FOrmel für Phase/Frequency-correct PWM benutzt.>> Ich habe die Formel benutzt die mir Peter Diener auf Seite 104> vorgeschlagen hat...
Und nochmal:
Du sollst selber denken was du tust und nicht einfach nur blind
abschreiben. Hast du dasselbe Datenblatt benutzt wie er?
Peter Diener hat sich die Mühe gemacht, dir lang und breit die
Einstellung des Timers und wie man zu ihr kommt zu erklären. Für den
Fall: Modus 14! Also Fast-PWM!
Ich, als Unbeteiligter und wahrscheinlich auch viele andere Mitleser
haben mir das gemerkt. Nur du, derjenige den es eigentlich betrifft,
hast dir das nicht gemerkt. Sagt dir das irgendetwas?
Es ist wirklich nicht zuviel verlangt, wenn du beim Nachrechnen der
Werte, die Überschrift des Kapitels überprüfst, ob du auch tatsächlich
die Formel für Fast-PWM benutzt oder ob du im falschen Kapitel
nachsiehst.
Ok, habs jetzt verstanden.
Wie schon gesagt, hab die PWM am laufen aber das Problem jetzt...ich
sende und sende und sehe auch dass was gesendet wird...aber ich empfange
nicht das Z-Register, mit den Bytes, mit dem Programm was ich
geschrieben hab.
Habe die Schnittstelle genau überprüft, Baudrate und alles und es ist
alles gleich...
Der Sender ist zu 100% richtig da der Lehrer den gemacht hat.
Sender :
LDI temp, 0b10011000
OUT UCSRB, temp
LDI temp, 0x86
OUT UCSRC, temp
;Baudrate initialisieren
LDI temp, 0x00
OUT UBRRH, temp
LDI temp, 0x33
OUT UBRRL, temp
Empfänger :
; Serielle Schnittstelle initialisieren
LDI temp, 0b10010000
OUT UCSRB,temp
LDI temp, 0b10000110 ; asynchron, Parameter 8N1
OUT UCSRC,temp
LDI temp, 0
OUT UBRRH, temp
LDI temp, 51
OUT UBRRL, temp
Ist alles gleich und nun die Empfangsroutine (Vorher wird ein Interrupt
ausgelöst wenn sich was im UDR befindet und in dieser ISR wird das
Z-Register empfangen und am Ende der ISR wird dieser Unterprogramm
aufgerufen):
RCECHR: LDI ZL, LOW(R_str+1) ; +1 da erstes Byte Stringlänge ist
LDI ZH, HIGH(R_str+1)
LD temp, Z+
OUT PORTA, temp ; hier müsste ich im grunde gesehen den
ersten empfangenen Wert auf den LED's sehen...es passiert aber überhaupt
nix, die LED'S gehen beliebig an und aus und als PWM wird nicht den Wert
angezeigt den ich sende sondern der die die LED's anzeigen, also die
ganze Zeit etwas anderes.
CPI temp, 0x91 ; empfangener Wert mit 145 vergleichen
BRSH UP ; grösser oder gleich 145 dann nach
; vorne fahren bzw. auf 'UP' springen
CPI temp, 0x6F ; empfangener Wert mit 111 vergleichen
BRLO DOWN ; wenn kleiner als 111 dann nach hinten fahren
; bzw. auf DOWN springen
Wo ist da der Fehler???
Meyer Bob schrieb:
> Der Sender ist zu 100% richtig da der Lehrer den gemacht hat.
Ich kenne auch solche Lehrer. Denn Lehrer haben immer recht.
> in dieser ISR wird das Z-Register empfangen
Du empfängst kein Z-Register, sondern musst die Empfangenen Daten
irgendwo ablegen. Meinetwegen auch in das Z-Register.
Das wird in meinem Interrupt gemacht:
isr_rxc: PUSH temp
IN temp, SREG
PUSH temp
PUSH i
PUSH j
PUSH ZL
PUSH ZH
PUSH XL
PUSH XH
LDS ZL, R_ptrL
LDS ZH, R_ptrH
LDS i, R_chr
LDS j, R_exch
IN temp, UDR
ST Z+, temp
INC i
CP i, j
BREQ irx_1
STS R_chr, i
STS R_ptrL, ZL
STS R_ptrH, ZH
RJMP irx_e
irx_1: CLR temp
STS R_chr, temp
STS R_sts, temp
LDI XL, LOW (R_str+1)
LDI XH, HIGH(R_str+1)
ADD XL, j
ADC XH, temp
irx_2: LD temp, -Z
ST -X, temp
DEC i
BRNE irx_2
LDS temp, R_exch
ST -X, temp
RCALL RCECHR
irx_e: POP XH
POP XL
POP ZH
POP ZL
POP j
POP i
POP temp
OUT SREG, temp
POP temp
RETI
LDS ZL, R_ptrL
LDS ZH, R_ptrH
LDS i, R_chr
LDS j, R_exch
IN temp, UDR
ST Z+, temp
INC i
CP i, j
BREQ irx_1
Wenn die beiden gleich sind, wird IMHO R_ptrL/R_ptrH nie wieder auf den
Anfang des Empfangsbuffers zurückgesetzt.
Meyer Bob schrieb:
> Versteh ich nicht...
Dann spiel Computer und schleuse händisch am Papier 10 Bytes durch deine
Interrupt Routine durch und sieh nach was R_ptrL/R_ptrH machen.
(Kann natürlich auch sein, dass ich falsch liege)
Karl heinz Buchegger schrieb:
> ann spiel Computer und schleuse händisch am Papier 10 Bytes durch deine> Interrupt Routine durch und sieh nach was R_ptrL/R_ptrH machen.>> (Kann natürlich auch sein, dass ich falsch liege)
hm, ich gebe momentan die Werte die ich sende durch einen Potentiometer
ein.
Kannst du mir nicht einfach sagen was der Fehler genau ist...denn was so
ll ich machen um zu sehen was R_ptrL/R_ptrH machen?
> Der Sender ist zu 100% richtig da der Lehrer den gemacht hat.
Das ist eine Annahme die du nicht treffen darfst.
1.) Lehrer sind auch nur Menschen und Irren ist menschlich. (meine
Lehrer waren damals teilweise ausserordentlich "menschlich").
2. Selbst wenn es sich um "proven code" handelt heisst das nicht dass
dieser in jedem Kontext direkt wieder funktioniert. Gerade in Assembler
ist saubere Modularisierung eher schwer bis unmöglich und braucht
genaueste Schnittstellenbeschreibung.
Karl heinz Buchegger schrieb:
> Wenn die beiden gleich sind, wird IMHO R_ptrL/R_ptrH nie wieder auf den> Anfang des Empfangsbuffers zurückgesetzt.
Normalerweise doch da ich in meinem Unterprogramm ja als erstes den
Pointer initialsiere?
Meyer Bob schrieb:
> Karl heinz Buchegger schrieb:>> Wenn die beiden gleich sind, wird IMHO R_ptrL/R_ptrH nie wieder auf den>> Anfang des Empfangsbuffers zurückgesetzt.>> Normalerweise doch da ich in meinem Unterprogramm ja als erstes den> Pointer initialsiere?
Wo?
Meyer Bob schrieb:
> Kannst du mir nicht einfach sagen was der Fehler genau ist...denn was so> ll ich machen um zu sehen was R_ptrL/R_ptrH machen?
Du sollst Computer spiele.
Schnapp dir Papier und Bleistift und spiel den Code durch
Du hast irgendwo Speicher
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | ....
+---+---+---+---+---+---+---+---+---+
Dann gibts da noch 2 Speicherzellen, die R_ptrL/R_ptrH heißen und die
offensichtlich auf den Anfang dieses Speichers zeigen sollen und
anzeigen, wo das nächste Byte, welches über die USART hereinkommt
abgelegt werden soll. Nehmen wir mal an, das ist alles richtig
aufgesetzt und R_ptr zeigt auf den Anfang dieses Speichers
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | ....
+---+---+---+---+---+---+---+---+---+
^
|
+-----------+
|
R_ptr |
+-----+ |
| o---------+
+-----+
OK. Das erste Byte kommt, die ISR wird aufgerufen
Was passiert?
LDS ZL, R_ptrL
LDS ZH, R_ptrH
In den Z-Pointer wird der Inhalt von R_ptr geladen
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | ....
+---+---+---+---+---+---+---+---+---+
^^
|+---------------------------------+
+-----------+ |
| |
R_ptr | Z-Poiner |
+-----+ | +-----+ |
| o---------+ | o----------+
+-----+ +-----+
LDS i, R_chr
LDS j, R_exch
i und werden mit der momentanen Anzahl an Zeichen im Buffer geladen. Das
waren 0. j kriegt die Anzahl an erwarteten Zeichen, sagen wir 5
IN temp, UDR
ST Z+, temp
Die USArt wird ausgelesen und das Byte dorthin abgelegt, wo der Z
Pointer hinzeigt. Der Z-Pointer wird um 1 erhöht
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | ....
+---+---+---+---+---+---+---+---+---+
^ ^
| +-----------------------------+
+-----------+ |
| |
R_ptr | Z-Poiner |
+-----+ | +-----+ |
| o---------+ | o----------+
+-----+ +-----+
INC i
Dann wird die ANzahl der empfangenen Zeichen um 1 erhöht
CP i, j
BREQ irx_1
und entschieden, ob es schon genug sind. Sind es noch nicht. 1 ist da, 5
wollen wir. Also gehts weiter:
STS R_chr, i
STS R_ptrL, ZL
STS R_ptrH, ZH
i abspeichern (also die 1) und den Z-Pointer nach R_ptr abspeichern,
damit beim nächsten ISR Aufruf der Z-Pointer wieder mit dem Wert geladen
werden kann, wo das nächste Zeichen abgelegt werden soll
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | ....
+---+---+---+---+---+---+---+---+---+
^^
|+-----------------------------+
+-------+ |
| |
R_ptr | Z-Poiner |
+-----+ | +-----+ |
| o---------+ | o----------+
+-----+ +-----+
RJMP irx_e
und Ende der ISR
So. Jetzt kommen die nächsten Zeichen herein.
Bei jedem wird der Z-Pointer um 1 erhöht und jeweils der R_ptr
nachgezogen.
Jetzt nehmen wir einmal an, dass es genug Zeichen sein werden, damit sie
ausgewertet werden.
Also: Die ISR wird aufgerufen. Das ist die Situation im Speicher
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | ....
+---+---+---+---+---+---+---+---+---+
^
|
+---+
R_ptr |
+-----+ |
| o---------+
+-----+
Der Z-Pointer wird wieder eingerichtet
LDS ZL, R_ptrL
LDS ZH, R_ptrH
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | ....
+---+---+---+---+---+---+---+---+---+
^^
|+------------+
+---+ |
R_ptr | Z-Pointer |
+-----+ | +-----+ |
| o---------+ | o------+
+-----+ +-----+
IN temp, UDR
ST Z+, temp
Das zeichen wird abgelegt und der Z-Pointer um 1 weiter
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | ....
+---+---+---+---+---+---+---+---+---+
^ ^
| +--------+
+---+ |
R_ptr | Z-Pointer |
+-----+ | +-----+ |
| o---------+ | o------+
+-----+ +-----+
INC i
ein Zeichen mehr
CP i, j
BREQ irx_1
und diesmal sinds genug!
Wie gehts weiter
irx_1: CLR temp
STS R_chr, temp
STS R_sts, temp
LDI XL, LOW (R_str+1)
LDI XH, HIGH(R_str+1)
ADD XL, j
ADC XH, temp
R_chr wird auf 0 gesetzt, R_sts wird auf 0 gesetzt und die empfangenen
Bytes werden umkopiert
irx_2: LD temp, -Z
ST -X, temp
DEC i
BRNE irx_2
Der Z-Pointer bewegt sich dabei wieder an den Anfang des Buffers zurück.
ISt alles umkopiert, sieht die Sache so aus:
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | ....
+---+---+---+---+---+---+---+---+---+
^ ^
+----------------------------+
+---+ |
R_ptr | Z-Pointer |
+-----+ | +-----+ |
| o---------+ | o------+
+-----+ +-----+
ST -X, temp
RCALL RCECHR
Dann machst du noch was mit dem X-Pointer und rufst die Verarbeitung
auf.
Ist die Vorbei wird die ISR verlassen.
Aber was ist mit R_ptr (low und High). Die zeigen nicht mehr dort hin,
wo das nächste zu empfangende Byte abgelegt werden soll.
Kommt das nächste Byte rein, dann wird es hier
+---+---+---+---+---+---+---+---+---+
| | | | | * | | | | | ....
+---+---+---+---+---+---+---+---+---+
^
|
+---+
R_ptr |
+-----+ |
| o---------+
+-----+
abgelegt.
Es sollte aber hier
+---+---+---+---+---+---+---+---+---+
| * | | | | | | | | | ....
+---+---+---+---+---+---+---+---+---+
^
|
+-----------+
|
R_ptr |
+-----+ |
| o---------+
+-----+
abgelegt werden, denn schliesslich beginnt ja jetzt die nächste
Nachricht vom Sender!
Und da R_ptr nie auf den Anfang zurückgesetzt wird, wandert er immer
weiter durch den Speicher, bis beim Ablegen der empfangenen UART Daten
irgendwann Speicher überschrieben wird, der definitiv nicht mehr zum
Speicher gehört, der für den Empfangsbuffer vorgesehen war.
Ich sehe nirgends in deinem Code eine Stelle, an der R_PtrL bzw R_PtrH
wieder auf den Anfang des Bufferspeichers zurückgesetzt wird.
Meyer Bob schrieb:
> RCECHR: LDI ZL, LOW(R_str+1) ; +1 da erstes Byte Stringlänge ist> LDI ZH, HIGH(R_str+1)>> LD temp, Z+
und was hat das mit R_PtrL bzw R_PtrH zu tun?
Karl heinz Buchegger schrieb:
> Meyer Bob schrieb:>> RCECHR: LDI ZL, LOW(R_str+1) ; +1 da erstes Byte Stringlänge ist>> LDI ZH, HIGH(R_str+1)>>>> LD temp, Z+>> und was hat das mit R_PtrL bzw R_PtrH zu tun?
Hab mich verschaut...sorry.
Jetzt versteh ich die ganze Empfangsroutine. :)
Dankeschön !
Soll ich das dann so machen:
RCALL RCECHR
LDI temp, 0
STS R_ptrL, temp
STS R_ptrH, temp
irx_e: POP XH
POP XL
POP ZH
POP ZL
POP j
POP i
POP temp
OUT SREG, temp
POP temp
RETI
Hab es damit probiert und klappt noch immer nicht...
Der Karl Heinz hat das doch so gut erklärt,
aber Du hast es immer noch nicht gerafft.
Mit Deinem Code
LDI temp, 0
STS R_ptrL, temp
STS R_ptrH, temp
Setzt Du den Zeiger auf die Adresse 0x0000, und an der gibt
es gar kein DRAM.
Warum schreibst Du nicht
LDI temp, high(empf_buf)
STS R_ptrH, temp
LDI temp, low(empf_buf)
STS R_ptrL, temp
Dann sollte wenigstens der Zeiger wieder auf den Beginn des
Empfangsstrings zeigen.
Für "empf_buf" mußt Du natürlich den Namen einsetzen, mit dem
Du den Speicher wo der Empfangsstring hin kommt benannt hast.
Ich glaube daß das "R_str" bei Dir heißt.
Auch im Simulator des AVR-Studios läßt sich soetwas, wenn auch
mit einiger "Tipperei" austesten, langsam, aber es geht zur
Not.
...
RCALL RCECHR
LDI temp, high(R_str+1)
STS R_ptrH, temp
LDI temp, low(R_str+1)
STS R_ptrL, temp
irx_e: POP XH
POP XL
POP ZH
POP ZL
POP j
POP i
POP temp
OUT SREG, temp
POP temp
RETI
...so?
Es funktioniert...mit dem einzigen Nachteil...beim Empfang zeigt der
Oszilloskop mir den Wert nur 1 Sekunde an bzw. er empfängt den Wert
nicht ständig...woran könnte das liegen?
Hab das geschrieben;
LDI temp, high(R_sts)
STS R_ptrH, temp
LDI temp, low(R_sts)
STS R_ptrL, temp
Damit gehts aber er zeigt mir den Empfangswert nur eine Sekunde an und
dann nichts mehr...
Ich kenn jetzt nicht genau alle Details eurer Schaltung &
Programmierung. Kann es aber vielleicht sein, dass der Sender nur einen
geänderten Zustand (neue Stellung der Joysticks) sendet und nicht
kontinuierlich?
Ist aber nur so eine Idee.
Es könnte auch ein ganz banaler Programmfehler sein.
Bisher haben wir ja immer nur kleine Ausschnitte gesehen.
Spielt für mich allerdings keine Rolle mehr. Ich bin raus. Für meinen
Geschmack und unter Bedachtnahme dass es sich um ein Abschlussprojekt
handelt, wurde hier sowieso schon zu viel und bei zu banalen Dingen
geholfen. Ein Abschlussprojekt soll ja auch einen Sachverhalt (welchen?)
dokumentieren und dieses Ziel sehe ich für mich persönlich mitlerweile
gefährdet. Aber das ist IMHO
Jetzt weiss ich zu mindest warum mir keiner mehr hilft...vielen Dank -.-
Wie wenn es euer Abschlussprjekt ist..hätt es auch anders benennen
können dann wärt ihr bestimmt mit was anderem gekommen...
Hab mich ständig bei jedem bedankt, frag mich nur was ich falsch gemacht
hab..bin eben sehr schwer von Verstand aber das intressiert doch niemand
hier..
Was Du falsch gemacht hast? Ich spreche jetzt nicht von den Fehlern im
Programm.
Bisher hast Du dir allen in den Ar*** schieben lassen. Von Dir kam nur
grob vermurkster Code. Wenn man Dir konstruktive Hilfe anbot, kommt nur
ein "verstehe ich nicht" - und zwischen den Zeilen "will ich auch nicht
verstehen". Sorry, aber so kommt es rüber.
Wenn man Dir sagt, du sollst alles schrittweise auf dem Papier
durchgehen, kommt ein "verstehe ich nicht". Erklärt man Dir, wie das
gemeint ist, kommt ein "Danke, brauche ich nicht mehr"
Karl heinz Buchegger schrieb:
> Und jetzt hol dir endlich das verdammte Instruction Set Manual von> Atmel. Da kannst du nämlich schön sauber nachlesen, was die einzelnen> Befehle eigentlich machen.
Meyer Bob schrieb:
> Ist gut...brauch das nicht mehr.> Hab das PWM am Laufen ;)> Einen GROSSEN Dank an alle.
Dann schreibst Du:
> Ich habe ALLES selber geschrieben bis jetzt.
Danach übernimmst Du den von anderen vorgeschlagenen Code blind in Dein
Programm. Das alles sind auch nur Vorschläge, da bisher noch niemand den
kompletten Code gesehen hat. Die Vorschläge sind also nicht an Deinen
Code angepasst; das musst Du aber selber machen.
Und so weiter, und so fort...
Ja, es soll aber überhaupt nicht so rüber kommen, kann mich sehr
schlecht in Deutsch ausdrücken, kommt vielleicht davon weil ich kein
Deutscher bin ;)
Ich habe nicht alles blind in mein Programm kopiert sondern habe zu erst
versucht es zu verstehen und dann habe ich es nochmal selbst hinein
geschrieben.
Das mit dem "ich habe ALLES selber geschrieben" war so gemeint dass ich
sozusagen den Rahmen schon hatte, aber kleinere aber uach sehr wichtige
Details gefehlt haben.
Hatte gestern Abend sehr viel nachgedacht und bin dann schlussendlich
auf eine plausible Lösung gekommen und habe mein Fehler gesehen. Was ich
sende empfange ich gleichzeitig.
Hatte Karl heinz Buchegger erklärung etwas falsch vrstanden und es war
mein Fehler dass ich 2 Minuten drauf geschrieben hab "hab ich nicht
verstanden" tut mir sehr leid...
Wenn jemand auf den Vorschlag "Hol Dir das Instruction Set"
"Brauch ich nicht" antwortet, dem ist nicht zu helfen, der
will sich nicht helfen lassen, ich nenne das "Beratungsresistent".
Selbst ich, der schon >30 Jahre in Elektronik-Entwicklung
erfolgreich unterwegs ist, beschaffe mir bei einem für mich neuen
µP das Instruction Set (selbst bei bekannter µP-Familie) und!
Datenblatt.
Ich will nämlich wissen wie! das Teil funktioniert und ob die
gewünschten Funktionen einfach oder evtl. überhaupt machbar sind.
Meyer Bob schrieb:
> Hab mich ständig bei jedem bedankt,
Darum gehts in diesem Fall gar nicht. Zumindest nicht für mich.
Für mich geht es darum dass du einen Abschluss für etwas bekommst, wovon
du ziemlich offensichtlich keine Ahnung hast.
Ich weiß nicht um welchen Abschluss es sich dabei handelt, aber ich
möchte nicht in der Situation sein, einen 'Mitarbeiter mit Abschluss' zu
bekommen, dem ich als aller erstes erst mal ein halbes Jahr lang die
Grundlagen beibringen muss. Neben meiner eigentlichen Arbeit,
wohlgemerkt! Denn eigentlich hat er ja einen Abschluss, also ein
Zeugniss welches aussagt, dass er einen gewissen Level aufweist,
zumindest die Grundlagen daher mitbringt.
Dass man dem Nachwuchs einmal ein wenig weiterhilft, ist unter uns
Klosterschwestern Ehrensache. Dass jemand beim Gedanken an seine
Abschlussarbeit nervös ist und sich in etwas verrennt und man ihm da
wieder raushilft ist auch Ehrensache. Aber alles hat irgendwo seine
Grenzen.
Guter Rat schrieb:
> Wenn jemand auf den Vorschlag "Hol Dir das Instruction Set"> "Brauch ich nicht" antwortet, dem ist nicht zu helfen, der> will sich nicht helfen lassen, ich nenne das "Beratungsresistent".>> Selbst ich, der schon >30 Jahre in Elektronik-Entwicklung> erfolgreich unterwegs ist, beschaffe mir bei einem für mich neuen> µP das Instruction Set (selbst bei bekannter µP-Familie) und!> Datenblatt.> Ich will nämlich wissen wie! das Teil funktioniert und ob die> gewünschten Funktionen einfach oder evtl. überhaupt machbar sind.
Ich sagte das weil ich es schon bei Hand hatte ohne es zu wissen, wie
shcon gesagt, bei uns nennt man das Befehlsliste und als ich die sah bei
atmel.com brauchte ich sie mir ja nicht mehr dort anzuschauen da ich sie
ja in meinem Kursus vom Lehrer hatte.
Karl heinz Buchegger schrieb:
> Dass man dem Nachwuchs einmal ein wenig weiterhilft, ist unter uns> Klosterschwestern Ehrensache. Dass jemand beim Gedanken an seine> Abschlussarbeit nervös ist und sich in etwas verrennt und man ihm da> wieder raushilft ist auch Ehrensache. Aber alles hat irgendwo seine> Grenzen.
Ich konnte die Überschrift dieses Threads auch Hobby Projekt nennen.
Ich bin keiner der blind copie paste macht ohne nachher zu wissen wie
das was ich programmiert habe funktioniert, ganz im Gegenteil. Ich
zerbreche mir den Kopf wie ihr darauf gekommen seid denn meine Erfahrung
die ich bis jetzt in Assembler hab (ca. 1 Jahr) ist einfach nicht gross
genug um selbst Fehler zu finden etc. Wenn ich dan nachvollzogen habe
wie ihr darauf gekommen seit schreibe ich es selbst in mein Programm und
arbeite weiter daran.
Manchmal bin ich zu "Übermotiviert" und möchte alles sehr schnell in
Gang bringen...aber aus Fehlern lernt man...
1 Jahr "Erfahrung" in Assembler und dann diese Antworten,
ich glaub das nicht. Die Hilfetips sind so gut, da sollte man
bereits nach ein paar Tagen, wenn auch langsam, mit klarkommen.
Schreib das Programm entweder komplett fertig (mit Fehlern) oder besser,
nimm Dir kleine Bröckchen vor und teste diese einzeln. Wenn dann
einzelne Teile nicht funktionieren, poste deinen kompletten und
compilierbaren Code. Das kann sich dann jemand ansehen (falls Du nocn
nicht jeden hilfswilligen vergrault hast).
Du solltest auch genau schreiben, was nicht funktioniert und wie es
funktionieren soll. Nur zu schreiben "PWM" geht nicht, reicht nicht aus.
Aber ich befürchte, dass du damit auch nicht weiter kommen wirst.