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


von Nils (Gast)


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:
1
 
2
void usart1_init(void) {
3
  USART_InitTypeDef       usart_i;
4
      USART_ClockInitTypeDef  usart_c;
5
  GPIO_InitTypeDef        gpio_i;
6
7
  GPIO_PinRemapConfig(GPIO_Remap_USART1,DISABLE);
8
9
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,   ENABLE);
10
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
11
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,  ENABLE);
12
13
  /* TX */
14
  gpio_i.GPIO_Pin   = GPIO_Pin_9;
15
  gpio_i.GPIO_Speed = GPIO_Speed_50MHz;
16
  gpio_i.GPIO_Mode  = GPIO_Mode_AF_PP;
17
  GPIO_Init(GPIOA, &gpio_i);
18
19
  /* RX */
20
  gpio_i.GPIO_Pin   = GPIO_Pin_10;
21
  gpio_i.GPIO_Speed = GPIO_Speed_50MHz;
22
  gpio_i.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
23
  GPIO_Init(GPIOA, &gpio_i);
24
25
  /* 115200 8n1 */
26
  usart_i.USART_BaudRate              = 115200;
27
      usart_i.USART_HardwareFlowControl   = USART_HardwareFlowControl_None;
28
      usart_i.USART_Mode             = USART_Mode_Rx | USART_Mode_Tx;
29
      usart_i.USART_Parity        = USART_Parity_No;
30
      usart_i.USART_StopBits        = USART_StopBits_1;
31
      usart_i.USART_WordLength            = USART_WordLength_8b;
32
33
      usart_c.USART_Clock        = USART_Clock_Enable;
34
      usart_c.USART_CPHA        = USART_CPHA_1Edge;
35
      usart_c.USART_CPOL        = USART_CPOL_Low;
36
  usart_c.USART_LastBit        = USART_LastBit_Disable;
37
38
  USART_ClockInit(USART1, &usart_c);
39
  USART_Init(USART1, &usart_i);
40
41
  /* enable RXNE interrupt */
42
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
43
44
  NVIC_EnableIRQ(USART1_IRQn);
45
46
  USART_Cmd(USART1,ENABLE);
47
}

RX/TX/ISR:
1
void usart1_putc(char c){
2
  while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
3
  USART_SendData(USART1, c);
4
  return;
5
}
6
7
void usart1_puts(char *str){
8
  while(*str != 0) {
9
    usart1_putc(*(str++));
10
  }
11
  return;
12
}
13
14
uint8_t usart1_getc(void) {
15
  while((USART1->SR & USART_SR_RXNE) == 0);
16
17
  return USART1->DR & 0x1FF;
18
}
19
20
void USART1_IRQHandler(void) {
21
  char c;
22
  
23
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
24
//    c = (char)USART_ReceiveData(USART1);
25
    c = usart1_getc();
26
27
    USART_SendData(USART1, c);
28
  }
29
}

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:
1
0a00aaa?l/{
2
           ~_v}_vB}?l?la/{B_v_v/{/{B?l}0_v}_vX/{/{Ba}B/{_v_v_v}BX_v
3
                                                                   ~?l?l0?l0/{}_v?l}Xa?l?l}a0/{
4
                                                                                               ~}}XX_vBa?lXX}B}?l
5
                                                                                                                 ~aB
6
                                                                                                                    ~?l/{
7
                                                                                                                         ~0?l0?l_v
8
                                                                                                                                  ~_v0
9
                                                                                                                                      ~/{/{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)


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)


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)


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
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.