Hallo zusammen,
trotz der vielen Beiträge zum UART hier im Forum finde ich meinen Fehler
nicht. Da ich gerade ausprobiere, wie der UART funktioniert, habe ich
eine kleine Anwendung geschrieben, die die LED Ports meines TelosB
toggeln soll. Der Code dazu ist folgender:
#include <io.h>
#include <signal.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Watchdog deaktivieren
/*
* LEDs initialisieren
*/
P5DIR |= 0x70; // LED-Pins -> Output pins
P5OUT |= 0x70; // LED-Pins high -> LEDs leuchten NICHT
P5OUT &= ~(1<<5); // LED1 low -> LED1 leuchtet
/*
* UART konfigurieren
*/
P3SEL = 0x30; // P3.4 und P3.5 als UART0 TXD/RXD
ME1 |= UTXE0 + URXE0; // TX- und RX-Modul aktivieren
// Baudraten einstellen
UCTL0 |= CHAR; // 8 data bits, 1 stop bit, no parity (8N1)
UTCTL0 |= SSEL0; // ACLK als UCLK festlegen
UBR00 = 0x03; // 9600 baud aus 32768 Hz erzeugen
UBR10 = 0x00; // Vgl. App. Note Tabelle 2, Seite 10
UMCTL0 = 0x4A; //
UCTL0 &= ~SWRST; // UART freigeben
IE1 |= URXIE0; // TX- und RX-Interrupts aktivieren
IFG1 &= ~UTXIFG0; // Initiales Interruptflag löschen
IFG1 &= ~URXIFG0; // Initiales Interruptflag löschen
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
}
/*
* Auslösen, wenn Zeichen empfangen wurde.
*/
interrupt(UART0RX_VECTOR) uart0rx_irq(void)
{
// Toggle LEDs wenn Interrupt kam
P5OUT ^= 0x70;
// UART behandeln
IFG1 &= ~URXIFG0;
}
Verbunden ist der TelosB per USB und als Terminalprogramm verwende ich
cutecom. Dass der TelosB etwas empfängt, erkenne ich an den kleinen
Rx-LEDs, aber dennoch wird kein Interrupt ausgelöst, was ich daran
erkenne, dass die LED an Port 5 nicht getoggelt werden. Sieht hier
jemand, wo mein Fehler liegt?
Vielen Dank für die Hilfe und einen guten Rutsch ins neue Jahr! :)
Florian
Moin,
das hab ich ausprobiert und leider klappt es nicht, obwohl ich mich
schon darüber gewundert habe, dass das überhaupt kompiliert g ;) Wie
soll denn entschieden werden, welcher Interrupt überhaupt ausgelöst
wurde? Schließlich hat der F1611 2 unabhängige UARTs. Was ich oben
übrigens noch vergessen hatte zu sagen, war, dass ich den Code per
MSPGCC übersetze.
Dann schau mal in der io.h nach dem Controller und wie da die Interrupts
definiert sind. Das Bsp. oben ist für einen Mega8. Deinen Controller
kenn ich gar nicht ;)
Oder probier es mit ISR(UART0RX_vect) oder ISR(UART0RX_VECTOR)
EDIT:
Du kannst auch im Datenblatt nach der Nummer deines Interrupt Vektors
Schauen und ISR(_VECTOR(11)) schreiben. 11 ist beim Mega8 der USART_RX
Vektor, die Nummer musst halt anpassen.
Ich wühle mich gerade durch die Doku und durch die Header. Da das alles
noch sehr neu für mich ist, hab ich da noch Berührungsängste ;D Aber
vielen Dank für den Tipp. Und jetzt versuch ichs nochmal mit
_VECTOR(11).
Ist es btw egal, ob man ISR(_VECTOR(11)) oder interrupt(MEIN_VECTOR)
funktionsname(void) schreibt? Die zweite Schreibweise funktioniert
zumindest bei GPIO IRQs.
2. Deinem Programm fehlt noch die msp430x16x.h damit der Kompiler auch
weiß, welchen Prozessor du benutzt.
3. Der USART0_RX_Vector ist beim F1611 nicht auf der 11
4. Funktioniert denn das Demo-Programm ( fet140_uart01_09600_2.c ) von
TI in unveränderter Form?
5. Vor der Initialisierung der USART sollte man das SWRST Bit setzen.
6. und jetzt das entscheidende: Deinem Programm fehlt die Hauptschleife.
Nach Ausführung des 1. RX-Interrupts (falls er bis dahin überhaupt
kommt) schmiert dein Controller gnadenlos ab, weil nach dem
Ich ich bin mir relativ sicher, dass man ISR(...) verwenden soll. Warum
genau, hab ich keine Ahnung aber ein Auszug aus der interrupt.h:
/** \def ISR(vector [, attributes])
\ingroup avr_interrupts
\code #include <avr/interrupt.h> \endcode
Introduces an interrupt handler function (interrupt service
routine) that runs with global interrupts initially disabled
by default with no attributes specified.
The attributes are optional and alter the behaviour and resultant
generated code of the interrupt routine. Multiple attributes may
be used for a single function, with a space seperating each
attribute.
Valid attributes are ISR_BLOCK, ISR_NOBLOCK, ISR_NAKED and
ISR_ALIASOF(vect).
\c vector must be one of the interrupt vector names that are
valid for the particular MCU type.
*/
Also einfach ISR(...) verwenden, das funktioniert garantiert.
Ok, also msp430x16x.h sagt folgendes:
#define USART0RX_VECTOR 18 /* 0xFFF2 USART 0 Receive, I2C tx/rx */
#define UART0RX_VECTOR USART0RX_VECTOR
d.h. UART0RX_VECTOR ist korrekt. Und auch die
interrupt(...)-Schreibweise funktioniert bei mir, da ich das mit GPIOs
schon ausprobiert habe. Ich tippe nun darauf, dass der eigentliche
Fehler irgendwie in der Konfiguration des UART liegt. Vielleicht habe
ich dem UART gar nicht die richtige Taktquelle gegeben. Das schau ich
mir mal an.
Felix C. wrote:
> Ich ich bin mir relativ sicher, dass man ISR(...) verwenden soll. Warum> genau, hab ich keine Ahnung aber ein Auszug aus der interrupt.h:> Also einfach ISR(...) verwenden, das funktioniert garantiert.
Bei einem AVR bestimmt. Aber ein MSP430 ist nun mal kein AVR. Und der
mspgcc ist halt an solchen Stellen anders als der avr-gcc. Also völlig
nutzloser Beitrag.
@ Florian: Hast du mein Posting gelesen?
@Christian: Ja, habe ich, der ist sehr hilfreich, danke! Ich baue gerade
alles ein, was du vorschlägst. Schleife, Header und SW-Reset, allerdings
klappt es nach wie vor nicht so. Ich werd nun mal das TI Beispiel
ausprobieren, um deine Frage zu beantworten.
@christian
>5. Vor der Initialisierung der USART sollte man das SWRST Bit setzen.
Ist in dem Fall durch Reset des µC automatisch gesetzt!
>6. und jetzt das entscheidende: Deinem Programm fehlt die Hauptschleife.>Nach Ausführung des 1. RX-Interrupts (falls er bis dahin überhaupt>kommt) schmiert dein Controller gnadenlos ab, weil nach dem>_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt> das Nirvana kommt.
Auch in diesem Fall ist die Hauptschleife unnötig, da der µC im
Sleep-Modus ist und im Hauptprogramm nie aufgeweckt wird. Nur
innerhalb der ISR wird der µC kurz aufwachen. Ausserhalb davon nicht!
Ich tippe auch eher auf fehlenden ACLK
Gut, in dem speziellen Fall kann man die Schleife wohl weglassen, man
darf aber dann wirklich niemals aufwachen. Wollte nur so viele
fehlerquellen wie möglich ausschließen.
@Christian: Was meinst du mit "Wie deine UART Verbindung" aussieht? Ich
kommuniziere per USB?! :D
@Stefan: Öhhm, bedeutet dass, dass ich den UART0 per USB überhaupt nicht
ansteuern kann und dafür nur UART1 verwenden kann?
Hm, und den UART0 haben sie zum Spaß draufgebaut oder wie steuert man
den an? :D Aber vielen Dank für den Hinweis, da wär ich im Leben nicht
drauf gekommen ;) Ich gehe nun einfach mal davon aus, dass ich den Rest
von alleine schaffe, andernfalls meld ich mich natürlich wieder ;)
Wünsche Euch nun einen guten Rutsch ins neue Jahr und dass ihr mir so
hilfsbereit bleibt! :D
Florian
>Hm, und den UART0 haben sie zum Spaß draufgebaut oder wie steuert man>den an?
Der ist an eine Steckerleiste herausgeführt und kann individuell
beschaltet werden.
Florian wrote:
> @Christian: Was meinst du mit "Wie deine UART Verbindung" aussieht? Ich> kommuniziere per USB?! :D
Sorry, dachte da hängt noch irgendwas an UART0, weil du die ganze Zeit
davon redetest.
> @Stefan: Öhhm, bedeutet dass, dass ich den UART0 per USB überhaupt nicht> ansteuern kann und dafür nur UART1 verwenden kann?
Jo, ist halt hart-verdrahtet erst ma auf dem Board. Stört ja auch nicht,
im Gegenteil, an der USART0 hängt ja der RF-Transceiver, wenn ich das
richtig sehe. Und da geht ja nur ent oder weder.
Hallo zusammen und frohes Neues!
Ich habe nun die obigen Erkenntnisse alle im geposteten Quellcode
verarbeitet, aber weiterhin wird kein IRQ ausgelöst, was mich
mittlerweile etwas frustriert. Ich würde mich freuen, wenn ihr euch den
überarbeiteten Code nochmal anschauen könntet, um mich ggf. auf Fehler
hinzuweisen, die ich einfach nicht finde.
Vielen Dank!
Schwieriger Fall... und das gleich zu Beginn von 2009 ;-)
1.) Läuft der Quarz jetzt überhaupt?
Oszi zur Hand zum Überprüfen?
Wenn nicht, ACLK an P5.6 (LED3) ausgeben lassen. Ist zwar nicht die
feine Art, aber wenn ACLK wenigstens irgendwas macht, sollte die LED3
leuchten, allerdings deutlich dunkler, als wenn Du sie per I/O anmachst!
2.) Erwartet dein Terminalprogramm einen Hardwarehandshake per RTS/CTS?
Das ist auf Deinem Board nicht so nicht verdrahtet... vielleicht mal im
Terminalprogramm abschalten wenn möglich.
...ähh.... Terminalprogramm sendet auch mit 9600bd und 8N1... ???
3.) Gibt es zu diesem Board keine funktionierende Firmware, die per USB
angesprochen irgendwas vernünftiges macht, so daß man zumindest mal
Hardwarefehler ausschließen kann?
1. Ein Oszilloskop hab ich leider nicht, aber ich werde mal die andere
Methode ausprobieren. Andererseits bleibt dem Ding eigtl. gar keine
andere Möglichkeit als zu funktionieren, denn der µC funktioniert ja und
eine andere Taktquelle gibts offenbar nicht.
2. Das Programm hab ich auf 9600/8N1 eingestellt, werde aber nochmal
probieren, ob es mit den RTS/CTS-Einstellungen funktioniert.
3. Nunja, das einzige was ich sicher weiß, ist, dass ich das Gerät per
USB flashen kann. Eine Firmware gibt es meines Wissens leider nicht.
Selbst die Dokumentation ist ja ziemlich dürftig.
>1. Ein Oszilloskop hab ich leider nicht, aber ich werde mal die andere>Methode ausprobieren. Andererseits bleibt dem Ding eigtl. gar keine>andere Möglichkeit als zu funktionieren, denn der µC funktioniert ja und>eine andere Taktquelle gibts offenbar nicht.
Oh doch! Der µC läuft sicher mit dem internen DCO als Taktquelle!
>2. Das Programm hab ich auf 9600/8N1 eingestellt, werde aber nochmal>probieren, ob es mit den RTS/CTS-Einstellungen funktioniert.
Hardwarehandshake sollte aus sein!
>3. Nunja, das einzige was ich sicher weiß, ist, dass ich das Gerät per>USB flashen kann. Eine Firmware gibt es meines Wissens leider nicht.>Selbst die Dokumentation ist ja ziemlich dürftig.
Das macht mich gerade auch stutzig!
Der USB <-> UART Wandler geht ja auf UART1, gleichzeitig aber auch an
BSL (den Bootloader) zum Flashen des Controllers. Vielleicht ist das ja
das Problem. Mit den Steuerleitungen aus dem FT232BM wird das "Gezappel"
gemacht, um den MSP in den Bootloadermodus zu bringen. Wenn die
Steuerleitungen jetzt aber dauerhaft auf dem "falschen" Potential
liegen, dann kann dadurch z.B. die Reset-Leitung gezogen bleiben, so
dass der µC erst gar nicht läuft....?!
1. Wieder was dazugelernt :)
2. Hardware- und Softwarehandshake waren stets deaktiviert.
3. Ich verstehe zwar nicht so recht, wie diese elektrotechnischen
Abläufe funktionieren, allerdings verstehe ich aus deiner
Schlussfolgerung, dass das der Grund dafür sein könnte, dass der µC gar
nicht erst anfängt zu arbeiten. Dies kann ich aber deshalb verneinen,
weil ich in meinem Programm eine LED anschalte und nach dem Flashen
leuchtet diese auch, ergo muss das Programm abgearbeitet worden sein,
was wiederum bedeutet, dass der µC nach dem Flashvorgang funktioniert.
Und was nun?
Ich hab das nun mal getestet, und zwar mit diesem Code:
1
#include<msp430x16x.h>
2
#include<io.h>
3
#include<signal.h>
4
5
intmain(void)
6
{
7
WDTCTL=WDTPW+WDTHOLD;// Watchdog deaktivieren
8
9
/*
10
* LEDs initialisieren
11
*/
12
P5DIR|=0x70;// LED-Pins -> Output pins
13
P5OUT|=0x70;// LED-Pins hochziehen -> LEDs leuchten NICHT
14
P2SEL|=0x01;// ACLK-Funktion auswählen, Input by default
15
16
P5OUT&=~0x40;// Blaue LED zum Leuchten bringen
17
18
// Delay zum Vergleich
19
volatileunsignedinttmp;
20
for(tmp=0;tmp<65000;tmp++);
21
P5OUT&=~0x10;// Rote LED: Timer vorbei
22
23
// ACLK auf LED legen
24
while(1){
25
switch(P2IN&1)
26
{
27
case0:P5OUT&=~0x40;// Blaue LED zum Leuchten bringen
28
break;
29
case1:P5OUT=0xFF;// LEDs ausschalten
30
}
31
}
32
}
Er soll so funktionieren, dass zu Beginn die blaue LED leuchtet und nach
einem Delay von ca. 1 Sekunde der Wert aus ACLK jeweils auf die blaue
LED geschrieben wird.
Meine Beobachtung ist, dass sich nach dem Delay keine
Intensitätsveränderung der Lichtstärke der blauen LED ergibt, was
bedeuten würde, dass ACLK permanent 0 ist. Wie ist deine Meinung dazu?
(Oder hab ich nur mal wieder einen Fehler im Quellcode?! ;)
Nee, so funktioniert das nicht.
An P2.0 wird zwar ACLK ausgegeben, da hängt aber nichts dran!
Du sollst P5.6 nehmen, da dann ACLK direkt auf LED3 ausgegeben wird:
Also probier mal das:
1
#include<msp430x16x.h>
2
#include<io.h>
3
#include<signal.h>
4
5
intmain(void)
6
{
7
WDTCTL=WDTPW+WDTHOLD;// Watchdog deaktivieren
8
9
/*
10
* LEDs initialisieren
11
*/
12
P5DIR|=0x70;// LED-Pins -> Output pins
13
P5OUT|=0x70;// LED-Pins hochziehen -> LEDs leuchten NICHT
Achsoo, jetzt versteh ich, was du meintest! Man erkennt einen
Intensitätsunterschied, d.h. die ACLK ist wohl in Ordnung ;) Nun stehen
wir allerdings wieder vor dem gleichen Problem wie am Anfang :/
>d.h. die ACLK ist wohl in Ordnung ;)
Nun ja, wir wissen nur, dass ACLK zappelt... aber nicht ob die
Frequenz stimmt und er sauber clockt!
>Nun stehen wir allerdings wieder vor dem gleichen Problem wie am Anfang :/
In der Tat und mir gehen langsam die Ideen aus...
... ach Du lieber Himmel....!!!
Könnte sein, dass Du gerade einem HW-Bug aufgesessen bist!
Kannst Du mal schauen, ob auf Deinem Board die 'A' oder 'B'-Revision des
F1611 verbaut ist? Bei 'A' gibt es folgenden Bug:
US14 - Bug description:
Module: USART0, USART1, UART Mode: Lost character start edge
When using the USART in UART mode with UxBR0 = 0x03 and UxBR1 = 0x00,
the start edge of received characters may be ignored due to internal
timing conflicts within the UART state machine. This condition does not
apply when UxBR0 is > 0x03.
Workaround:
None
In dem Falle würde ich mal 4800bd probieren:
U1BR0 = 0x06, U1BR1 = 0x00, U1MCTL = 0x6F
Hi, in der ganzen Doku finde ich nichts von einer Revisionsnummer des
1611. Das einzige, was ich sagen kann ist, dass der gesamte
Sensornetzknoten in der Revision B vorliegt, aber ob das miteinander in
Zusammenhang steht, weiß ich nicht.
Ich hab's mir jetzt nicht komplett durchgelesen, aber bei UART Problemen
würde ich immer erst vom MSP in Richtung PC testen (Also TX). Dann ist
man sich schon mal sicher das der UART vom MSP korrekt funktioniert.
Wenn das geht mit RX anfangen.
>immer erst vom MSP in Richtung PC testen (Also TX). Dann ist>man sich schon mal sicher das der UART vom MSP korrekt funktioniert.
In diesem speziellen Fall eben nicht, denn der (eventuell vorhandene)
Bug betrifft ja nur RX!
yay, der Knüller ist ja, dass der MSP so auf dem Board befestigt ist,
dass man nicht draufschauen kann, da an der Seite genau die
Akkustromversorgung draufgebaut ist ;) Der erste Link, den ich mal
gepostet habe, zeigt ein Bild vom Gerät, dann wisst ihr was ich meine.
Ich werde es einfach mal mit einer anderen Baudrate probieren, tut ja
keinem weh ;) Wenn's dann immer noch nicht funktioniert, kann ich ja
trotzdem nochmal, wie von Jörg vorgeschlagen, den Tx ausprobieren, um zu
sehen, ob der Fehler tatsächlich nur im Rx-Modul liegt.
Hab nun das Ding etwas verbogen, um auf den µC zu schauen. Das ist
Revision B. Und demzufolge war zu erwarten, dass auch eine Änderung der
Baudrate keine Abhilfe schafft. Dann geh ich mal eben einkaufen und
hoffe, dass ich währenddessen eine Eingebung habe... oder ihr ;)
An dieser Stelle nochmal vielen Dank, dass ihr mich so tatkräftig
unterstützt!
>In diesem speziellen Fall eben nicht, denn der (eventuell vorhandene)>Bug betrifft ja nur RX!
Schon richtig, aber selbst wenn's einer mit dem Bug ist, muss man die
Fehlersuche ja nicht unnötig schwierig machen :)
Tja, hier mal noch ein paar Punkte die ich checken bzw. ausprobieren
würde, wenn ich das Teil vor mir liegen hätte (in loser Reihenfolge):
- Im ersten Post hast Du geschrieben:
>Dass der TelosB etwas empfängt, erkenne ich an den kleinen Rx-LEDs
Das wäre also RXLED# vom FT232BM. Blinkt das immer noch, d.h. es kommen
überhaupt irgendwelche Daten vom Usb beim Telos an?
- Vielleicht passt die Kombination von Terminalprogramm und
FTDI-USB-Treiber nicht recht zusammen und die Baudrate sowie das
Protokoll (8N1) werden nicht so übertragen wie im TP eingestellt?
Vielleicht mal anderes Terminalprog probieren und neuesten VCP-Treiber
für FT232BM installieren.
- Die tatsächliche Frequenz des Quarzes wäre mir immer noch suspekt.
Aber ohne Oszi schwer zu überprüfen. Eine Überprüfung des Quarzes auf
"groben Unfug" vielleicht mittels Timer-gesteuertem LED-Blinken und
damit "abschätzen" der Quarzfrequenz.
- Ich kenne MSPGCC nicht, aber vielleicht ist die Interrupt-Definition
doch nicht richtig?! Ich würde den Datenempfang mal per Polling von
URXIFG versuchen. Dabei auch mal das URXEIE-bit setzen, damit auch
fehlerhaft empfangene Zeichen das URXIFG-Flag setzen.
- TX hast Du ja schon ausprobiert, bis dahin ;-)
Guten "Abend" ;)
Ich habe nun nochmal einiges getestet, u.a. das Tx-Modul, welches
zunächst nicht funktionierte, dann aber plötzlich doch Informationen
übertragen hat, nachdem ich am USB-Anschluss gerüttelt habe. Da wurde
mir plötzlich klar, dass es doch ein "Hardwarefehler" sein könnte,
allerdings der Natur, dass der Kontakt zwischen Buchse und Stecker immer
wieder unterbrochen wird. Nachdem ich den Stecker dann fest auf die
Kontakte gedrückt habe, funktionierte das Senden einwandfrei.
In der Hoffnung, dass das auch der Grund für die fehlgeschlagenen
Empfangsversuche war, habe ich dann auch das Rx-Programm nochmal
ausprobiert, welches immer noch nicht funktionierte. Da allerdings auch
das Senden manchmal nicht klappte, obwohl die Kontakte fest
aufeinanderlagen, konnte ich das Problem nach kurzer Zeit am
Terminalprogramm fest machen, welches sonderbarerweise latent zwischen
den Schnittstellen /dev/ttyUSB0 und /devUSB1 wechselt. Nachdem man es
dann aber mehrfach neugestartet hat, läuft es irgendwann in einer
Konfiguration, die mit der Schnittstelle des Geräts einher geht und
diese dann während des Betriebs nicht wieder wechselt. Und dann
funktioniert auch das Empfangen. "Ich fühl' mich wie Jesus am
Ostersonntag."
Vielen Dank an die vielen Helfer, ohne euch wär ich schon längst
verzweifelt!