Forum: Mikrocontroller und Digitale Elektronik STM32F103 usart Probleme beim Senden / empf. mit Interrupt


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Nils (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich sitze gerade an einem STM32F103VCT6 mit PL2303.
Die Elektronik funktioniert, die Demo-Applications zum Board laufen 
tadellos, auch die zum USART.

Senden mittels dieser Funktionen funktioniert. Beim Empfangen bekomme 
ich nur wahllose Zeichen, auch wenn ich die ganze Zeit das Selbe sende.

Hier die USART-Routinen,

init:
 
void usart1_init(void) {
  USART_InitTypeDef       usart_i;
      USART_ClockInitTypeDef  usart_c;
  GPIO_InitTypeDef        gpio_i;

  GPIO_PinRemapConfig(GPIO_Remap_USART1,DISABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,   ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,  ENABLE);

  /* TX */
  gpio_i.GPIO_Pin   = GPIO_Pin_9;
  gpio_i.GPIO_Speed = GPIO_Speed_50MHz;
  gpio_i.GPIO_Mode  = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &gpio_i);

  /* RX */
  gpio_i.GPIO_Pin   = GPIO_Pin_10;
  gpio_i.GPIO_Speed = GPIO_Speed_50MHz;
  gpio_i.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &gpio_i);

  /* 115200 8n1 */
  usart_i.USART_BaudRate              = 115200;
      usart_i.USART_HardwareFlowControl   = USART_HardwareFlowControl_None;
      usart_i.USART_Mode             = USART_Mode_Rx | USART_Mode_Tx;
      usart_i.USART_Parity        = USART_Parity_No;
      usart_i.USART_StopBits        = USART_StopBits_1;
      usart_i.USART_WordLength            = USART_WordLength_8b;

      usart_c.USART_Clock        = USART_Clock_Enable;
      usart_c.USART_CPHA        = USART_CPHA_1Edge;
      usart_c.USART_CPOL        = USART_CPOL_Low;
  usart_c.USART_LastBit        = USART_LastBit_Disable;

  USART_ClockInit(USART1, &usart_c);
  USART_Init(USART1, &usart_i);

  /* enable RXNE interrupt */
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

  NVIC_EnableIRQ(USART1_IRQn);

  USART_Cmd(USART1,ENABLE);
}

RX/TX/ISR:
void usart1_putc(char c){
  while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  USART_SendData(USART1, c);
  return;
}

void usart1_puts(char *str){
  while(*str != 0) {
    usart1_putc(*(str++));
  }
  return;
}

uint8_t usart1_getc(void) {
  while((USART1->SR & USART_SR_RXNE) == 0);

  return USART1->DR & 0x1FF;
}

void USART1_IRQHandler(void) {
  char c;
  
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
//    c = (char)USART_ReceiveData(USART1);
    c = usart1_getc();

    USART_SendData(USART1, c);
  }
}

Ich sitze da jetzt schon ein Weilchen dran und komme nicht auf die 
Lösung...
Der IRQ-Handler wird aufgerufen und er sendet auch, jedoch jedesmal 
"random"-Zeichen.
Hier die Ausgabe, ich habe die ganze Zeit auf 'a' gedrückt im  Terminal:
0a00aaa?l/{
           ~_v}_vB}?l?la/{B_v_v/{/{B?l}0_v}_vX/{/{Ba}B/{_v_v_v}BX_v
                                                                   ~?l?l0?l0/{}_v?l}Xa?l?l}a0/{
                                                                                               ~}}XX_vBa?lXX}B}?l
                                                                                                                 ~aB
                                                                                                                    ~?l/{
                                                                                                                         ~0?l0?l_v
                                                                                                                                  ~_v0
                                                                                                                                      ~/{/{B}a

Baudrate usw stimmt, ich kann mit usart_puts/putc gesendete Strings und 
Zeichen richtig empfangen.

Ich hoffe ihr könnt mir da helfen.

Gruss,
Nils

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Nils schrieb:
> void USART1_IRQHandler(void) {
>   char c;
>
>   if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
> //    c = (char)USART_ReceiveData(USART1);
>     c = usart1_getc();
>
>     USART_SendData(USART1, c);
>   }
> }

Setze mal bitte das Flag RXNE auch direkt in der ISR zurück.
Benutze USART_SendData() nicht direkt in der ISR, und reduiziere zu 
Testzwecken mal die Baudrate. Ich will dir auch nicht verschweigen, das 
die sch31$$ Prolific Wandler hier immer arge Probleme gemacht haben. 
Teste also am besten auch mal ein direktes Loopback von TXD zu RXD.

: Bearbeitet durch User
von Nils (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hehe, ja das Problem mit den Profilic-Wandlern kenne ich gut und Rx/Tx 
brücken habe ich als erstes ausprobiert, aber vergessen vorhin zu 
schreiben.
Ebenso habe ich den Code auf zwei anderen identischen Boards 
ausprobiert.

Ein angeschlossenes Oszi an Tx und 0x55 sowie 0xAA (bin: 0101... / 
1010...) in einer Schleife gesendet bringt mir keine 01010101...-Muster, 
sondern wie auf der Terminalausgabe, wirre Zeichen.
Ich habe die jetzt nicht verglichen, kein Speicheroszi, wird sehr 
aufwendig, aber es sieht wirklich so aus, als ob der Controller diese 
Zeichen sendet.

Zurücksetzen auf 19200 und 9600 Baud hat auch nicht funktioniert, selbes 
Ergebnis.


Setze ich in der ISR das Bit zurück, dann bekomme ich wiederum das selbe 
seltsame Ergebnis.
In anderen Implementationen von USART-Treibern im Netz wird 
USART_SendData auch in der ISR verwendet, z.B. hier 
http://pandafruits.com/stm32_primer/stm32_primer_uart.php

So wie es aussieht wird die ISR dauer-befeuert. Ich habe ein 
usart_putc('>') in die ISR eingefügt und mein Terminalfenster ist sofort 
voll mit spitzen Klammern...

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Nils schrieb:
> So wie es aussieht wird die ISR dauer-befeuert.

Genau das ist das Symptom, wenn man nicht sofort das anfordernde Bit 
zurücksetzt, hat mich zumindest beim GPIO Interrupt auch schon mal ne 
Stunde gekostet. Es reicht auch nicht, das irgendwo im Hauptprogramm 
oder woanders zu machen, die ISR sitzt dann ständig auf der Leitung.

> gpio_i.GPIO_Mode  = GPIO_Mode_IN_FLOATING;

Stell das auch mal auf Pullup und sorge dafür, das am RXD Pin nix 
passiert. Wird die ISR dann auch immer noch gezündet?

: Bearbeitet durch User

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.