Hallo, ich nutze einen EFM8SB1 MC auf einem SLSTK2010A Board von Silabs und möchte den Wert einer gesteuerten Stromquelle über den UART ausgeben. Nun habe ich mir bereits mehrere Beispiele durchgelesen und verschiedene Methoden ausprobiert, aber das Hyperterminal will nichts anzeigen. Der Fehler wird vermutlich sehr einfach und dumm sein, da ich relativ neu auf dem Gebiet bin. In einem Demo-Programm vom Hersteller wird das wie im angehängten Bild gemacht (links die Main, rechts die Interrupt Datei), wobei mir die Reihenfolge eher unüblich erscheint. Erst wird das Transmit-Flag gesetzt, dann in der Transmit ISR das Byte mit SBUF0=Byte ausgegeben. Funktioniert so auch. Aber eigentlich wird das TI Flag doch erst nach dem Senden gesetzt? Meine Vorgehensweise nun (IREF0CN0 ist das Byte, in dem der Stromwert ist): SI_INTERRUPT (UART0_ISR, UART0_IRQn) { if(SCON0_TI==1) { LED0=0; IE|=IE_ES0__DISABLED; //disable UART interrupts SCON0_TI=0; //clear transmit flag SBUF0= IREF0CN0; IE|=IE_ES0__ENABLED; //enable UART interrupts } } Es passiert, wie gesagt, nichts. Muss evtl der Code selbst verändert werden oder nur an anderer Stelle stehen, oder fehlt irgendeine Configuration? Die Baud Rate passt auf jeden Fall.
Bist Du sicher, dass der Wert überhaupt im Terminal darstellbar ist gemäss einer ASCII-Tabelle? Zum testen kannst Du ja einfach mal ein Zeichen schicken. z.B.
1 | SBUF0 = 'T'; |
:
Bearbeitet durch User
Mustermann schrieb: > Es passiert, wie gesagt, nichts. Setzt Du irgendwo in der main() das SCON0_TI flag? Das muss genau 1x gesetzt werden um damit den Interrupt "anzustoßen". Alternativ schreibt man ein Byte ins SBUF0 register, denn das TI Flag wird auch nach dem Senden eines Bytes von der Hardware gesetzt.
Bei einem Boolean musst du bei ner if-Abfrage nicht ==1 oder ==True machen, da reicht es einfach if(flag){ Wenn flag 1 } zu machen
SklavenTreiber schrieb: > Bei einem Boolean musst du bei ner if-Abfrage nicht ==1 oder ==True > machen, da reicht es einfach > if(flag){ > Wenn flag 1 > } > zu machen Das das ja nix mit dem Problem zu tun hat, nehme ich an, dass Du nur einen Verbesserungsvorschlag zum Kodierstil geben wolltest. Dem möchte ich jedoch ein ABER hinzufügen. In der Fallunterscheidung werden Wahrheitswerte betrachtet. Soweit richtig. Das ein Boolean nicht zwangsläufig verglichen werden muss, ist bis dahin auch korrekt. Allerdings soll der Code ja auch lesbar sein. Wenn Du daher eine Variable wie "isValid" oder "receiverReady" oder eine Funktion wie "available()" abfragst, dann ist das gut verständlich und lesbar, weil man die Bedeutung und die Aussage sofort versteht. Wenn man aber sowas wie "SCON0_TI" betrachtet, dann ist es durchaus sinnvoll, den Vergleich komplett auszuschreiben. SCON0_TI ist wenig bezeichnend und könnte ja auch außer true (1) oder false (0) vielleicht auch mal eine 3 enthalten. Das weiß man nur, wenn man weiß was SCON0_TI genau ist. Daher ist
1 | if(SCON0_TI==1) { |
2 | } |
schon genau richtig. Noch schöner wäre es, wenn man anstelle der "1" eine bezeichnende Konstante verwendet. Zum Beispiel
1 | if( SCON0_TI == TX_INTERRUPT_FLAG_SET) { |
2 | } |
Aber das nur als kleiner Einwand - man muss nicht immer alles auf's Minimum wegkürzen. Das erschwert oft nur die Arbeit... insbesondere, wenn man nach einem halben Jahr den Code nochmal ändert. ;)
Ja, das hat nichts mit dem Thema zu tun. Da es eine 3 enthalten könnte hab ich extra „bei Boolean“ geschrieben und ja du hast recht, manchmal ist es besser es auszuschreiben aber in diesem Fall würde ich es persönlich weglassen. Ist wohl Geschmackssache.
Kein Sklaventreiber schrieb: > Zum Beispiel > if( SCON0_TI == TX_INTERRUPT_FLAG_SET) { > } Das kann in die Hose gehen, wenn SCON0_TI tatsächlich Flags enthält. Denn wenn mehrere Flags gesetzt sind, ist der Vergleich falsch. Dann schriebe man besser:
1 | if( SCON0_TI & TX_INTERRUPT_FLAG_SET ) { |
2 | }
|
Und achte darauf, dass hier das genaue Ergebnis ebenfalls nicht ausgewertet wird. Wie SklavenTreiber schon schrieb.
Johnny B. schrieb: > Bist Du sicher, dass der Wert überhaupt im Terminal darstellbar ist > gemäss einer ASCII-Tabelle? > Das wäre eine Überlegung wert. Es ist halt ein 8 Bit Register, und der problemlosen Kompilierung habe ich entnommen, dass es geht. Allein daran wird's aber nicht liegen, denn ich habe es zuvor mit einem char versucht, mit dem selben Ergebnis. >Setzt Du irgendwo in der main() das SCON0_TI flag? Das muss genau 1x >gesetzt werden um damit den Interrupt "anzustoßen". Nicht in der Main, sondern in der Timer ISR zuvor. Ich will mit einem Rotary Encoder die Stromquelle steuern (habe noch SEHR mit dem Entprellen zu kämmpfen) und den Wert dann über UART ausgeben.
Kein Sklaventreiber schrieb: > Wenn Du daher eine Variable wie "isValid" oder "receiverReady" oder eine > Funktion wie "available()" abfragst, dann ist das gut verständlich und > lesbar, weil man die Bedeutung und die Aussage sofort versteht. Da gebe ich dir absolut recht. Schön ist mein bisheriger Code nicht. Ich muss nur gerade Prioritäten setzen. Muss mich für einen Job in Windeseile komplett von 0 auf 100 in das Thema MC hineinlesen und bin heilfroh, wenn das Programm am Ende funktioniert - derzeit hänge ich an diesem Thema und dem Entprellen des Encoders. Schönheits-OPs kommen dann später... Ich frage mich halt, was ich im Gegensatz zum Demoprogramm vergessen habe. Dort wird auch konkret nur gesagt SBUF0=Byte; Die zugehörige ISR wird auch aufgerufen, habe da eine LED getriggert. Nur scheint er den Wert nicht ins Transmit Register schreiben zu wollen oder daran hängen zu bleiben.
Hier noch die Interrupt.c Es geht um die Timer2 ISR und die UART ISR. Sorry für den schlechten Stil. Grüße
Kein Sklaventreiber schrieb: > SCON0_TI ist wenig > bezeichnend und könnte ja auch außer true (1) oder false (0) vielleicht > auch mal eine 3 enthalten. Nö, das ist ein einzelnes Bit - nur 0 und 1 sind möglich. Wir sind hier auf einem 8051, da gibt es bit-adressierbaren Speicher.
Habe hier keinen EFM8SB1 sondern EFM8BB1 da muss zuerst die Pin-Matrix angeschaltet werden: XBR0 |= (1 << (0)); // cross-bar enable UART0 pins XBR2 |= (1 << (6)); // cross-bar enable all pins Dann hatten die Demo-Boards das Problem, dass TX als Open-Drain nicht ging, daher: // P0.4 - UART0 TX - PUSH_PULL P0MDOUT |= (1 << (4)); Habe mal ein Demo-Programm angehängt. Dann gab es noch den Bug, dass auf den Demo-Boards der USB-seriell Chip nur eine Baudrate verträgt, nämlich 115200 Jim M. schrieb: > Wir sind hier auf einem 8051, da gibt es bit-adressierbaren Speicher Gibt es bei vielen ARM auch und ist sehr nützlich :-)
Lothar schrieb: > Habe hier keinen EFM8SB1 sondern EFM8BB1 da muss zuerst die > Pin-Matrix > angeschaltet werden: > > XBR0 |= (1 << (0)); // cross-bar enable UART0 pins > XBR2 |= (1 << (6)); // cross-bar enable all pins > > Dann hatten die Demo-Boards das Problem, dass TX als Open-Drain nicht > ging, daher: > > // P0.4 - UART0 TX - PUSH_PULL > P0MDOUT |= (1 << (4)); > Werde ich versuchen, danke! Melde mich dann hier mit dem Ergebnis.
Es hat tatsächlich an dem Push-Pull und dem Crossbar-Register gelegen. Jetzt bekomme ich zumindest schon mal ein Signal über den UART. Danke!
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.