Forum: Mikrocontroller und Digitale Elektronik Verbindung zwischen PC und MSP430 über Hyperterminal -> UAR


von Andreas Witsch (Gast)


Lesenswert?

Hallo, ich hab 3 kleine Funktionen geschrieben mit denen ich gern daten
vom MSP430 an meinen PC übertragen wollte
Eine Interruptroutine sollte immer ein Zeichen nach dem anderen
verschicken, aber aus mir nicht bekannten gründen wird die nie
aufgerufen.
Ich Poste einfach mal die Funktionen:

void usart0_init_send() {

  P3SEL |= BIT5 + BIT4;   // P3.5 und P3.4 als USART TXD/RXD

  ME1 |= UTXE0;           // TX- und RX-modul erst mal anschalten
  UCTL0 |= CHAR;          // 8 data bits, 1 stop bit, no parity (8N1)
  UTCTL0 |= SSEL0;        // ACLK als UCLK festlegen
  UBR00 = 0x03;           // 9600 baud aus 32.768 kHz erzeugen
  UBR10 = 0x00;           // siehe application note tabelle 2, seite
10
  UMCTL0 = 0x4A;          // korrektur der division
  UCTL0 &= ~SWRST;        // USART freigeben
  IE1 |= UTXIE0;          // TX- Interrupt anschalten
  IFG1 &= ~UTXIFG0;       // initales interrupt-flag loeschen
  _BIS_SR(GIE);
}


#pragma vector=UART0TX_VECTOR
__interrupt void usart0_tx (void)
{
  if (outputBufferCounter<send_size)  {
    TXBUF0 = outputBuffer[outputBufferCounter++];
  } else {
    TXBUF0 = 0x0D;
    sendFlag = 1;
  }
}


void usart0_send(char* data, int bytes) {
  int i;
  send_size = bytes;
  sendFlag = 0;
  outputBufferCounter = 0;

  for(i=0;i<bytes;i++) outputBuffer[i] = data[i];

  usart0_init_send();
  while (sendFlag == 0);    // Warten bis fertig gesendet
  free(outputBuffer);
  IE1 &= ~(UTXIE0);     // Sendeinterrupt abschalten
}

Und jetz wollt ich gern mit dem Aufruf "usart0_send("test", 4);"
was an mein Hyperterminal schicken, aber das funktioniert nicht.
Wie gesagt ich glaub der Interrupt wird nich aufgerufen! Sieht da
irgendwer nen Fehler? Ich verzweifel! :(

von Jörg S. (Gast)


Lesenswert?

Man sollte aus dem "glauben" erst mal "wissen" machen.

IAR Compiler/Degugger? Breakpoint in der ISR setzen und schauen ob er
wirklich nicht in die Routine springt. Evt. auch mal die UART Register
beobachten.

von Andreas Witsch (Gast)


Lesenswert?

Ja gut ich weiß es weil genau das hab ich gemacht! :P

Aber warum? :(

von Ronny (Gast)


Lesenswert?

Mal aus dem Bauch heraus,ohne ins Datenblatt zu schauen....

Frage: Wann wird der Sende-Interrupt ausgelöst?Wenn eine aktuelle
Übertragung fertig ist oder wenn der Sendepuffer beschrieben werden
kann ohne das ein eventuell bereits drin stehendes Zeichen verloren
geht?

von Andreas Witsch (Gast)


Lesenswert?

Wenn der Sendepuffer beschrieben werden kann -> Laut Datenblatt, aber
ich nehm ehrlichgesagt an dass des auch gleichzeitig bedeutet dass das
Byte verschickt wurde(is für mich nich so direkt ersichtlich).

von Ronny (Gast)


Lesenswert?

Aber genau das is relevant.Weil sonst niemals der 1.Interrupt
auftritt,mit welchem das nächste (erste!!) Zeichen rausgeschiokt wird.
Notfalls kann man beim Aufruf von UARTsend schon das 1.Zeichen
rausschicken.

Auf diese Weise kann man übrigens auch nicht blockierende
Sende-Funktionen schreiben.Die Sendefunktion reiht die Daten in den
Sendepuffer ein und kehrt sofort zurück.Alles weitere geschieht quasi
im Hintergrund per Interrupt.

von Jörg S. (Gast)


Lesenswert?


von Steffen (Gast)


Lesenswert?

servus,
also ich mache als ersten funktionstest einer uart meist erstmal ein
echo, damit ich weiß das uart auch funzt...
desweiteren bitte mal den gesamten code posten...
watchdog abgeschaltet?
einstellungen am hyperterminal richtig (8N1)?
initialisierung der uart sieht gut aus, da vermute ich keinen
fehler...

gruß

von Steffen (Gast)


Lesenswert?

ist zwar ein ganz schönes durcheinander in deinem code, aber der fehler
liegt glaub ich in "void usart0_send(char* data, int bytes)" da
gehört glaub ich noch einmal die zeile
"TXBUF0 = outputBuffer[outputBufferCounter++];" hinein, das ding muss
erst einmal angestoßen werden, check das ma...
und "if (outputBufferCounter<send_size)" in der isr kannst dir
sparen, wenn du da auf "if (data[i] != '\0')" überprüfst und dir
den counter und die for-schleife ebenfalls sparst...

also ungefähr so:

#pragma vector=UART0TX_VECTOR
__interrupt void usart0_tx (void)
{
  if (data[i] != '\0')  {
    TXBUF0 = data[i++];
  } else {
    i = 0; // i ist global (ich weiß, nicht ganz fein)
  }
}

void usart0_send(char* data) {
  usart0_init_send(); // würde ich in die main verlagern genau wie den

                      // GIE
  TXBUF0 = data[i++];
  // IE1 &= ~(UTXIE0);     // Sendeinterrupt abschalten !!! wozu???
}

so, un jetz ab dafür...

von Andreas Witsch (Gast)


Lesenswert?

So Fehler gefunden: mein ACLK geht nidd... ich hab ka warum mir wurde
nur gesagt auf dem board ginge das nidd! o_O
aber jetz passt anscheinend meine synchonisation nimmer...
zumindest wird der interrupt imme rbrav ausgelöst und von allem was man
irgendwie intern ablesen kann wird das zeug verschickt... und extern seh
ich mit m oscar auch das es geht ABER es kommt drüben nix an -> baut
rate falsch eingestellt...

welche einstellungen kann ich für SMCLK nehmen für 9600 baut oder
kleiner?

von SupaChris (Gast)


Lesenswert?

ACLK geht nich? Also kein 32Khz Quarz auf dem Board, oder wie? Wenn man
mit der UART arbeiten will, sollte man den schon drauf machen. Dann
kann man mit dem DCO immer noch bequem den takt hochsetzen, aber ohne
den Quarz läuft der MSP mit dem internen RC Oszillator bei ~800Khz. Und
das ist wirklich ungefähr. Wenn man die Parameter für den
Baudratenteiler einstellt, funktionieren die nur bei Zimmertemperatur,
sobald es ne andere Temperatur oder andere Versorgungsspannung ist,
passt das nicht mehr. Da können auch deine Baudratenparameter nicht
passen. Da musst du bissl probieren. Ich hatte bei meinen MSPs immer so
um die 740khz, wäre also Teiler 77,08 für 9600 Baud. Also UBR00 = 4D;
Den Modulator musst du eventuell auch setzen, je nach wirklicher
Frequenz (mit dem Oszi messen).
Aber das ist dann alles andere als sinnvoll. Bau mal lieber den 32Khz
Quarz ein. Kostet ja nicht die Welt.

von Andreas Witsch (Gast)


Lesenswert?

Naja das Board gehört ja nidd mir! ;) aber das mit den ca 800 khz hab
ich auch ca ausgerechnet! :P ich hatte UBR00 = 47
aber ich muss das jetz erstma nochma gescheit mit nem oscar nachmessen!

von SupaChris (Gast)


Lesenswert?

Und dann wirds mal bissl kühler oder wärmer und nix geht mehr. Also
darauf würd ich mich nicht verlassen. Es sei denn, es ist ein neuer MSP
aus der x20xx Reihe, die haben Kalibrierwerte für die
Oszillatoren...damit gehts besser. Quarz wäre trotzdem gescheiter. Wem
gehört das Board denn?

von Steffen (Gast)


Lesenswert?

800000/9600 = 0x47???
holla,da haste wo eher mit ca. 680KHz gerechnet... (da kann schon ma
grütze am uart ankommen)
www.msp430.info sagt für 800kHz ->
UBR00=0x53; UBR10=0x00; UMCTL0=0x21; /* uart0 800000Hz 9600bps
(9603.84bps) */...
hab mir mein eigenes tool geschrieben, das sagt UMCTL0=0x92, und damit
lag ich bis jetzt bei jeder baud rate richtig...
aber dco is so'ne sache, der reagiert doch schon auf körperwärme ;)...

von SupaChris (Gast)


Lesenswert?

Jo, müssten 4D sein, hab ich mich wohl vertippt oder so. Aber der DCO
mit FLL+ läuft doch auch bei Temp-Schwankungen super ?!? Also ich konnt
da noch keine komischen Effekte feststellen, die Frequenz jittert nur
immer nen bissl, aber das is ja minimal, hatte mal bei 4,096Mhz aus dem
32Khz Quarz generiert ein Jitter von 12ns oder sowas.

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
Noch kein Account? Hier anmelden.