Moin, ich habe zur Verfügung ein Mikrocontrollerboard 644P, der zwei USARTs besitzt. Es kommen Daten (Koordinaten x und y) von PC über die serielle Schnittstelle (RS232) an USART0. Dann muss ab dem USART1 die empfangenen Daten über die serielle Schnittstelle (RS485) an zwei Motorsteuerungen zugeschickt werden. Darüber hinaus besitzen die beide Motorsteuerungen ein RS485-Anschluß als serielle Schnittstelle, um die Daten zu aufzunehmen. Das erste Steuerprogramm(geschrieben in c++), das zur Übertragung von Daten ab dem PC zum Mikrocontrollerboard 644P über die RS232 dient, läuft einwandfrei. Aber das zweite Steuerprogramm (geschrieben in C unter AVRstudio), das zur Übertragung von Daten ab dem Mikrocontrollerboard 644P über die USART0 und USART1 dient, läuft nicht. Die folgende Bedingungen if(uart_count==2 && control==0) und if(uart_count==2 && control==1) werden ewig ausgeführt und die andere Befehle des Main-Programms werden nicht durchgeführt. Außerdem sieht es so aus, wie meine beide Interruptroutine überhaupt nicht ausgeführt wurden. Bitte, kann jemand mir helfen. Ich komme einfach nicht klar. Meine Code liegen im Anhang. Danke im Voraus. mfg monkeydluffy
> Das erste Steuerprogramm(geschrieben in c++), das zur Übertragung > von Daten ab dem PC zum Mikrocontrollerboard 644P über die RS232 > dient, läuft einwandfrei. Was heißt das? Kommen die Daten am µC korrekt an. Hast du das kontrolliert? (Ob dein PC-Programm läuft oder nicht, interessiert hier nicht wirklich. Da kommt was über die Serielle und der µC muss das korrekt empfangen. Für uns hier im Forum ist in erster Linie nur der Teil interessant) So wie ich das sehe, machst du den Kardinalfehler schlechthin: Du willst alles gleichzeitig entwicklen. Eine vernünftige Entwicklungsstrategie sieht aber so aus: Sieh zu, dass du dich immer nur auf EINEN Aspekt konzentrierst, der möglichst von nichts anderem abhängt. D.h. um die UART0 (die vom PC) zu testen, konzentrier dich NUR auf diese UART und sieh zu, dass du die korrekt in Betrieb nimmst und zwar in einer testbaren Form! Testbare Form heißt an dieser Stelle NICHT die Zeichen an die UART1 weiter zu geben. Denn die UART1 ist noch nicht getestet und wenns nicht funktioniert, dann weißt du nicht ob es an der UART0 oder an der UART1 liegt. Insofern hast du daher beim Testen eine Abhängigkeit zwischen diesen beiden Teilsystemen, die du unter keinen Umständen haben willst. Ich nenn das gerne: Du eröffnest einen 2-Frontenkrieg. Und den haben schon ganz andere als du verloren. Die Devise lautet "abspecken". Einzelsysteme schaffen, die auch einzeln mit möglichst wenig drumherum testbar sind. Nicht davon ausgehen, dass du keine Fehler machen wirst. Du MACHST Fehler (wie wir alle), d.h. du musst dir selbst deine 'Meilensteine' so setzen, dass du Fehler möglichst früh bemerkst. Wenn ich ein Auto entwickeln soll, dann ist ein erster Test mit dem kompletten Auto viel zu spät. Mein erster Test wird vielleicht sein, ob ich das Getriebe auf der Werkbank drehen kann, ob ich es schalten kann, ob das immer noch funktioniert, wenn ich es mit einer Bohrmaschine antreibe. Und erst dann wird das Getriebe als vorgetestete Komponente ins Auto eingebaut. Dann baut man den Kabelbaum mal losgelöst vom Auto in der Werkstatt auf und hängt da Ersatzteile drann um zu sehen, ob alles funktioniert. So was > Außerdem sieht es so aus, wie meine beide Interruptroutine überhaupt > nicht ausgeführt wurden. darf bei dem Programmstand, den du da präsentierst, überhaupt nicht mehr auftreten. Das hättest du längst vorher abtesten müssen, ob deine UART0 korrekt Receive Interrupts auslöst oder nicht.
Hi, Danke Karl für deine schnelle Antwort und ausführliche Ratschläge. Ich habe deine Tipps befolgt und habe versucht, ein Zeichen 'B' im UDRO zu schreiben. Dann habe ich versucht, dieses Zeichen nach UDR1 zu übertragen. Leider bekommt UDR0 und UDR1 kein Zeichen. Bitte, kannst du mir segen, was ich falsch mache. ich bin einfach jetzt verwirrt. Danke im voraus.
Hi >while(!(UCSR0A & (1<<RXC0)) ); .... > UDR0 = 'b'; >return UDR0; Das kann nicht gehen. UDR0 sind praktisch zwei Register. Beim Scheiben nach UDR0 greifst du auf das 'UDR0' für TX zu. Beim Lesen auf das 'UDR0' von RX. MfG Spess
>habe deine Tipps befolgt und habe versucht, ein Zeichen 'B' im UDRO zu
Hast Du nicht.
Ist die Zuweisung UDR0='b' überhaupt zulässig?
Ich frage mich allen Ernstes, was so schwer daran ist, wenn dein erstes Testprogramm (und bitte: schreibs neu! nimm nicht den alten Code her und kommentiere wie ein Wahnsinniger aus - da verliert man ganz schnell den Überblick) erst mal so aussieht
1 | #include <avr/io.h> |
2 | |
3 | #define FOSC 8000000 // Clock Speed
|
4 | #define BAUD 9600UL
|
5 | |
6 | // Berechnungen zur Baudrate:
|
7 | |
8 | #define UBRR_VAL ((FOSC+BAUD*8)/(BAUD*16)-1) // clever runden
|
9 | |
10 | |
11 | void USART_Init (unsigned int ubrr) |
12 | {
|
13 | UBRR0H = (unsigned char)(ubrr>>8); |
14 | UBRR0L = (unsigned char) ubrr; |
15 | |
16 | UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (0<<RXCIE0)|(0<<TXCIE0); |
17 | UCSR0C = (1<<USBS0) | (0<<UCSZ02)|(1<<UCSZ01)|(1<<UCSZ00); |
18 | }
|
19 | |
20 | unsigned char USART0_Receive (void) |
21 | {
|
22 | while(!(UCSR0A & (1<<RXC0)) ) |
23 | ;
|
24 | return UDR0; |
25 | }
|
26 | |
27 | void USART0_Transmit (unsigned char data) |
28 | {
|
29 | while ( !(UCSR0A & (1<<UDRE0)) ) |
30 | ;
|
31 | UDR0 = data; |
32 | }
|
33 | |
34 | int main (void) |
35 | {
|
36 | USART_Init(UBRR_VAL) ; // USART Initialization |
37 | |
38 | while(1) |
39 | {
|
40 | USART0_Transmit( 'X' ); |
41 | }
|
42 | }
|
Und das testest du erst mal. Und zwar in dem du Hyperterminal (oder HTerm) am PC an die entsprechende COM Leitung ansetzt. Solange du im Hyperterminal keine X auftauchen siehst, brauchst du nämlich überhaupt nicht weiter machen - denn dann ist an deiner Konfiguration grundsätzlich was faul. Meistens ist es die FOSC Angabe, die nicht mit der Realität übereinstimmt. Es könnte aber auch ein falsch gekreuztes Kabel sein. Daher muss man das testen! Und getreu dem Motto 'So einfach wie möglich testen', testet man zunächst die Richtung vom µC zum PC. Denn wir wissen, dass die Serielle am PC funktioniert! Was wir nicht wissen ist, ob die UART0 im µC Bytes so absetzt, dass sie der Baudrate entsprechen, bzw. ob das Kabel richtig ist. Aber zumindest ist eine Unbekannte dahingehend weggefallen, dass wir 100% wissen: Der Empfänger (bzw. die Serielle Schnittstelle dort) ist auf jeden Fall korrekt - wenn irgendwo ein Fehler ist, dann sicher nicht dort. Wenn das dann funktioniert, dann wird auch die umgekehrte Senderichtung auf Anhieb funktionieren. ABER: Auch das testen wir sofort wieder (es könnte ja auch sein, dass das Kabel einen Fehler hat). UNd zu diesem Behufe wird das Testprogramm abgewandelt:
1 | int main (void) |
2 | {
|
3 | char c; |
4 | |
5 | USART_Init(UBRR_VAL) ; // USART Initialization |
6 | |
7 | while(1) |
8 | {
|
9 | c = USART0_Receive(); |
10 | USART0_Transmit( c ); |
11 | }
|
12 | }
|
Alles was du im Hyperterminal tippst, muss vom µC zurückgeschickt werden und wird dann vom Hyperterminal angezeigt. Das das zurückschicken funktioniert, wissen wir bereits. Das wurde im vorhergehenden Test nachgewiesen, dass das so ist. D.h. dieser Test ist spezifisch auf das 'Senden vom PC zum µC'. Kriegst du das Echo beim Tippen, dann machst du auch mal den Gegentest: Du legst einen Ziegelstein auf die PC-Tastatur (so dass der PC dauersendet) und steckst das Kabel aus: Das Echo muss sofort aufhören. Steckst du das Kabel wieder an, muss das Echo wieder da sein. Erst dann kann man guten Gewissens sagen: Nach menschlichem Ermessen ist damit die UART0 erst mal soweit in Betrieb genommen worden, dass es sich um ein zumindest in den Grundzügen getestetes Subsystem handelt. Hab keine Scheu davor dir Testprogramme zu machen, die nur zu dem Zweck da sind, dass etwas getestet wird! Den Code kannst du danach immer noch weiterverwenden. Hab auch keine Scheu davor, mal Code zu löschen (anstatt auszukommentieren). Ein Programmierer löscht in seinem Berufsleben sicherlich 10 mal mehr Code als dann letzendlich übrig bleibt. Viel wichtiger ist es, dass dein Code ÜBERSICHTLICH ist. Mit verstreuten Codefetzen zwischen seitenweise auskommentiertem Code kann man aber nicht von Übersichtlichkeit sprechen.
Hallo, danke schön nochmal für die ausführlichen Erklärungen. Ich weiße nicht, was denn los mit mir ist. Vielen dank für die Tipps. mfg monkeydluffy
Moin, Nochmal danke schön Karl Heinz für deine Tipps Ich habe die Beispielcode, die du mir gezeigt hat, verwendet und habe die USART0 in Betrieb genommen. Die beide Teste haben mit Erfolgreich geklappt. Aber jetzt, stelle ich mich die Frage, wie ich der USART1 (RS485) in Betrieb nehmen kann. Wie sollen sich die beide USARTs die Daten austauchen? Bitte, schlagen sie mir einige Tipps vor. Danke im Vorraus. mfg monkeydluffy
Luffy Monkey schrieb: > Aber jetzt, stelle ich mich die Frage, wie ich der USART1 (RS485) in > Betrieb nehmen kann. Erst mal: Genau wie die andere. Du brauchst irgendwas, mit dem du kontrollieren kannst, ob das was du sendest, korrekt ist. > Wie sollen sich die beide USARTs die Daten > austauchen? Nix gelernt aus dem Vorgehen? Du willst schon wieder den übernächsten Schritt zuerst machen. Wie da jetzt die Daten von der einen USART zur anderen kommen, ist zum jetzigen Zeitpunkt noch uninteressant. Dafür gibt es 2 (eigentlich 3) Themenkreise, die viel interessanter sind. 1) USART1 in Betrieb nehmen. Erst mal genau so, wie die 0-er 2) USART0 auf Interrupt Betrieb umstellen. Wenn ein Zeichen empfangen wird, soll ein Interrupt ausgelöst werden. (und im Testprogramm dann sofort wieder zurückgeschickt werden) 3) USART1 auf Interrupt Betrieb umstellen. Und erst jetzt sind die Einzelteile vorhanden, dass man sich überlegen kann, wie man dann in der main() Hauptschleife eintreffende Zeichen von der einen UART an die andere weitergibt. Erst mal nur weitergeben, später dann ein Regelwerk da drüber legen, welches regelt was wann und warum weitergeleitet wird. Es ist immer das gleiche Spiel: Erst mal macht man sich die Basiskomponenten klar und testet die. Und dann arbeitet man sich schrittweise an die gewünschte Funktionalität ran.
Eigenes Protokol ausdenken bzw. was ist mit dem Protokol der Motorsteuerungen ? Also wenn die Motorsteuerungen an dem gleichen RS485 Port dranhängen dann muß in deren Protokoll eine Adresse drin sein bzw. eine Achsnummer. Du könntest das Protokoll einfach weiterbenutzen, aber dann stellt sich die frage warum du überhaupt einen µC drin hast. Was hattest du denn eigentlich mit dem µC vor ?
Ok, danke schön Karl Heinz. Ich mache weiter. mfg monkeydluffy
Und als nächstes sollte man sich mal darüber Gedanken machen, was Uwe da gesagt hat: Nach welchem Protokoll soll die Übertragung vom PC zum µC laufen. So wie das aussieht machst du dir da selber das Leben schwer in dem du überhaupt kein Protokoll hast. Statt dessen hast du das gemacht, was am Dümmsten ist: Der PC sendet einfach und der µC soll irgendwie auseinanderklamüsern, was was ist.
Hi, ich habe gerade mein USART1 getestet. Der Test war eine ziemliche gute Lektion für mich. Kurz gesagt, ich habe geschafft, der USART1 in Betrieb zu nehmen. Jetzt werde ich versuchen, USART0 auf Interrupt Betrieb umzustellen. Danke eure Hilfe. mfg monkeydluffy
Moin, ich habe der USART1 mit Interrupt umgestellt und bin ziemlich zufrieden. Aber ich komme nicht klar, wenn ich der USART0 mit Interrupt umstelle. Bitte, kann jemand mir helfen. danke im Voraus. mfg monkeydluffy
Moin, ich habe der USART0 und USART1 auf Interrupt Betrieb umgestellt und bin ziemlich mit den Ergebnissen froh. ich habe versucht, die Kommukation zwischen der USART0 und USART1 Im Interrupt Betrieb aufzubauen. Von mir aus, das scheint gut zu laufen und der Test hat auch geklappt. Sei ihr mit meinen C-Coden einverstanden ? Oder soll ich noch was in meinem C-Code berücksichtigen ? Danke im voraus. mfg monkeydluffy.
Hi Du gibst die Interrpts RXCIE0, TXCIE0 und TXCIE1 frei. Hast aber nur die Interruptroutinen ISR(USART0_RX_vect) und ISR(USART1_TX_vect). > ISR (USART1_TX_vect) >{ > UDR1 = data0 ; >} Dieser Interrupt wird ausgelöst, wenn USART1 ein Byte übertragen hat. Damit produzierst du einen kontinuierlichen Datenstrom. MfG Spess
Hallo, spess53 scchrieb: > ISR (USART1_TX_vect) >{ > UDR1 = data0 ; >} > Dieser Interrupt wird ausgelöst, wenn USART1 ein Byte übertragen hat. > Damit produzierst du einen kontinuierlichen Datenstrom. Wie kann ich die Erzeugung eines kontinuierlichen Datenstroms vermeiden ? Danke im Voraus. mfg
Hi >Wie kann ich die Erzeugung eines kontinuierlichen Datenstroms vermeiden >? Indem du zum Senden keinen Interrupt benutzt. MfG Spess
Hi,
Spess53 schrieb:
> Indem du zum Senden keinen Interrupt benutzt.
Das heißt, alle Interruptroutine müssen deaktiviert werden. Oder nur die
Interruptroutine ISR(USART1_TX_vect) muss deaktiviert werden.
mfg
Luffy Monkey schrieb: > Hi, > > Spess53 schrieb: > >> Indem du zum Senden keinen Interrupt benutzt. > > Das heißt, alle Interruptroutine müssen deaktiviert werden. Oder nur die > Interruptroutine ISR(USART1_TX_vect) muss deaktiviert werden. Wenn du nur den Sende-Interrupt deaktivierst, dann reicht das schon. Du willst ja nicht das Komplettsystem beeinträchtigen, nur weil da jetzt eine Übertragung komplett rausgegangen ist.
Ooops Das hier
1 | /*-- Interruptroutine USART1 beim Senden --*/
|
2 | |
3 | ISR (USART1_TX_vect) |
4 | {
|
5 | UDR1 = data0 ; |
6 | }
|
ist ja kompletter Quatsch. Der Interrupt wird ausgelöst NACHDEM das Zeichen gesendet wurde. Tu dir selbst einen Gefallen und hol dir zb vom Peter Fleury die UART Lib. Sonst hampelst du noch 2 Wochen an dieser Problematik herum. Dort kannst du dir ansehen, wie man die Sache mit Interrupts vernünftig angeht und was man sonst noch so braucht - zb eine FIFO, die eingehende Zeichen zwischenspeichert solange das Programm anderweitig beschäftigt ist und sich nicht darum kümmern kann die Zeichen abzuholen.
Hi, Vielen für die Tipps, ich werde die UART Lib von Peter Fleury ansehen. mfg monkeydluffy
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.