Forum: Mikrocontroller und Digitale Elektronik Probleme mit USART von STM32VL


von Jens K. (mister232)


Lesenswert?

Hallo Leute,

ich versuche gerade mit dem USART meines STM32VL_Discovery Boards zu 
arbeiten. Ich habe auch bereits des öfteren erfolgreich eine Verbindung 
zum Computer aufbauen können, doch jetzt scheint irgendetwas nicht zu 
stimmen. Ich habe ein Minimalprogramm geschrieben, welches ein Zeichen 
vom Computer empfängt und schaut ob es sich bei dem Zeichen um eine 1 
handelt. Falls ja, dann schickt der STM32 eine 2 an den Computer 
zurueck. Das Problem ist, dass er nun immer ein flasches Zeichen 
empfängt. Wenn ich eine 1 am Computer sende, dann empfängt das STM32 das 
ASCii-Zeichen 103. Wenn ich dann einstelle, dass er ueberpruefen soll ob 
es sich bei dem empfangenen Zeichen um eine 103 handelt, dann 
funktioniert alles einwandfrei, nur das am Computer statt einer 2 ein ? 
ankommt. Hier ist mein Quellcode:
1
#include "stm32f10x.h"
2
#include "Configure.h"
3
4
int main(void)
5
{
6
7
  SystemInit();
8
9
  UART_INIT(2);
10
11
  int i,data;
12
13
  while(1)
14
  {
15
       while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE)== RESET);
16
       data = USART_ReceiveData(USART2);
17
18
       if(data == '1')
19
       {
20
         while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
21
         USART_SendData(USART2, 2);
22
       }
23
24
       //for(i = 0; i < 2000000; i++);
25
  }
26
27
  return 0;
28
29
}

Und die Initialisierungsfunktion:
1
// Function to initialize USART-Register, needs the information which UART to initialize
2
int UART_INIT(int uart_x)
3
{
4
    // Define a variable of the structure to initialize GPIO
5
    GPIO_InitTypeDef GPIO_InitStructure;
6
    // Define initialize structure for UART
7
    USART_InitTypeDef  USART_InitStructure;
8
9
    if(uart_x == 1)
10
    {
11
      // Enable clocks BEFORE using/configuring peripherals that expect them to be running
12
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
13
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
14
      // Enable UART peripheral by activating clock
15
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
16
17
      //Configure USART1 Tx as output floating with 50MHz
18
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
19
      GPIO_InitStructure.GPIO_Speed  = GPIO_Speed_50MHz;
20
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
21
      GPIO_Init(GPIOA, &GPIO_InitStructure);
22
      //Configure USART1 Rx as alternate function push pull
23
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
24
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
25
      GPIO_Init(GPIOA, &GPIO_InitStructure);
26
27
      USART_InitStructure.USART_BaudRate = 38400;
28
      USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //Word Length = 8 Bits
29
      USART_InitStructure.USART_StopBits = USART_StopBits_1;  //Two Stop Bit
30
        USART_InitStructure.USART_Parity = USART_Parity_No ;   //No parity
31
      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  //Hardware flow control disabled (RTS and CTS signals)
32
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  //Receive and transmit enabled
33
34
        //Configure USART
35
        USART_Init(USART1,&USART_InitStructure);
36
37
        //Enable USART
38
        USART_Cmd(USART1, ENABLE);
39
    }
40
    else if(uart_x == 2)
41
    {
42
      // Enable clocks BEFORE using/configuring peripherals that expect them to be running
43
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
44
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
45
      // Enable UART peripheral by activating clock
46
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
47
48
      //Configure USART2 Tx as output floating with 50MHz
49
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
50
      GPIO_InitStructure.GPIO_Speed  = GPIO_Speed_50MHz;
51
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
52
      GPIO_Init(GPIOA, &GPIO_InitStructure);
53
      //Configure USART2 Rx as alternate function push pull
54
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
55
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
56
      GPIO_Init(GPIOA, &GPIO_InitStructure);
57
58
      USART_InitStructure.USART_BaudRate = 38400;
59
      USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //Word Length = 8 Bits
60
      USART_InitStructure.USART_StopBits = USART_StopBits_1;  //Two Stop Bit
61
        USART_InitStructure.USART_Parity = USART_Parity_No ;   //No parity
62
      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  //Hardware flow control disabled (RTS and CTS signals)
63
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  //Receive and transmit enabled
64
65
        //Configure USART
66
        USART_Init(USART2,&USART_InitStructure);
67
68
        //Enable USART
69
        USART_Cmd(USART2, ENABLE);
70
    }
71
    else
72
      // If there is a failure, then return 2 to flash error led
73
      return 2;
74
75
    // If it is all okay
76
    return 0;
77
}

Zur Verbindung mit dem Computer nutze ich uebrigens einen USB zu RS232 
Converter von Digitus. Aber wie gesagt, dass hat alles schon mal 
funktioniert. Ich bin leider fuer die nächsten Wochen nicht zu hause und 
habe somit keinen Zugriff auf meine Programm zu hause (sonst wuerde ich 
da nachschauen). Ich bin mir aber sicher das es so schonmal funktioniert 
hat.

Am Computer nutze ich Tera Term Pro mit den entsprechenden Einstellungen 
fuer die Baudrate etc.

von Bastler (Gast)


Lesenswert?

Versuch mal:

>if(data == '1')
if(data == "1")
oder
if(data == 0x31)


>USART_SendData(USART2, 2);
USART_SendData(USART2, "2");
oder
USART_SendData(USART2, 0x32);

von Kindergärtner (Gast)


Lesenswert?

Bastler schrieb:
>>if(data == '1')
> if(data == "1")
bockmist, das fragt ab ob das empfangene Byte gleich einem Pointer 
ist, der in den Flash zeigt, an dem sich ein Byte mit 49 befindet. Der 
Vergleich auf '1' war schon richtig, der mit 0x31 ist dasselbe.

Bastler schrieb:
> USART_SendData(USART2, "2");
Hier gilt ebenfalls, das er wahrscheinlich keinen Pointer in den Flash 
umherschicken will. '2' war richtig. Bitte C lernen...

Das Problem ist wohl eher in der UART-Konfiguration zu suchen. Also 
Baudrate (kann die überhaupt von der Hardware produziert werden oder 
wird da fröhlich gerundet??), Clock-Source (hoffentlich nicht RC-Osc).

von Bastler (Gast)


Lesenswert?

Sorry, dann hab ich es verwechselt.

Oben steht trotzdem
>USART_SendData(USART2, 2);

und nicht
USART_SendData(USART2, '2');

von Kindergärtner (Gast)


Lesenswert?

Bastler schrieb:
> Oben steht trotzdem
Oh stimmt, es muss natürlich '2' und nicht 2 sein.

von Jens K. (mister232)


Lesenswert?

Habe das Programm nun mal ein bisschen abgeändert.
1
#include "stm32f10x.h"
2
#include "Configure.h"
3
4
int main(void)
5
{
6
7
  SystemInit();
8
9
  UART_INIT(2);
10
11
  GPIO_INIT(9,'C', 0);
12
13
  int i,data;
14
15
  while(1)
16
  {
17
       while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE)== RESET);
18
       data = USART_ReceiveData(USART2);
19
20
       if(data == '1')
21
       {
22
         GPIOC->BSRR = GPIO_Pin_9;
23
         for(i = 0; i < 100000; i++);
24
         GPIOC->BRR = GPIO_Pin_9;
25
       }
26
27
       for(i = 0; i < 2000000; i++);
28
  }
29
30
  return 0;
31
32
}
Bevor ich dieses Programm getest habe und feststellen musste, dass ich 
immernoch ein falsches Zeichen empfange, hatte ich noch eine weitere 
Zeile eingefuegt, in welcher ich mir selbst die 1 sende. Dann habe ich 
einen Kurzschlussstecker auf den USART2 gesteckt und siehe da es 
funktionierte.

von Jens K. (mister232)


Lesenswert?

Jedes Mal wenn ich eine 1 am Computer sende kommt ein g an. Ich habe 
gerade auch mal den direkten COM-Port des Computers ausprobiert, 
allerdings mit dem gleichen Ergebnis

von Uwe (Gast)


Lesenswert?

Sende doch mal ne 0x55 am rPI und gucks dir auf dem Oszi an, danach das 
gleiche am PC. Wie lang sind die High und Low pulse ?

von Jens K. (mister232)


Lesenswert?

Werde ich nachher mal ausprobieren. Das witzige ist ja: Sende ich am PC 
eine 1 und empfange die gleich wieder, so empfange ich eine 1. Sende ich 
am mikroprozessor eine 1 und empfange die gleich wieder, dann empfange 
ich eine 1. Sende ich aber vom Computer zum Mikroprozerssor oder vom 
Mikroprozessor zum Computer, dann empfängt der Partner jeweils ein g.

von ssssssssssssssssssssss (Gast)


Lesenswert?

Jens K. schrieb:
> Werde ich nachher mal ausprobieren. Das witzige ist ja: Sende ich am PC
> eine 1 und empfange die gleich wieder, so empfange ich eine 1. Sende ich
> am mikroprozessor eine 1 und empfange die gleich wieder, dann empfange
> ich eine 1. Sende ich aber vom Computer zum Mikroprozerssor oder vom
> Mikroprozessor zum Computer, dann empfängt der Partner jeweils ein g.

Die Frage ist eher was für eine 1 du sendest ... dez oder ascii

von Jens K. (mister232)


Lesenswert?

Eine ASCii 1 -> '1'

Auf dem Scope sehe ich diese uebrigens auch

von Jens K. (mister232)


Lesenswert?

Die baudrate scheint auch zu stimmen. Ein Bit hat etwa 110us. Das sind 
dann doch ungefähr 9600 Baus oder?

von Jens K. (mister232)


Lesenswert?

Ich habe das Problem nun gelöst. Fuer alle die ebenfalls auf der Suche 
nach einer Lösung sind, hier nun die Lösung:

Zur Festlegung der Baudrate hatte ich folgende Befehlzeile eingefuegt:
1
USART_InitStructure.USART_BaudRate = 9600;

Diese Anweisung scheint sich auf einen System-Takt zu beziehen, welcher 
sich irgendwo in den Tiefen irgendeines Header-Files befindet.

Nach endlosem Suchen auf unzähligen Seiten im Internet habe ich folgende 
Anweisung gefunden:
1
USART1->BRR = (SystemCoreClock / 9600);

Diese Anweisung bezieht sich auf den aktuellen tatsächlichen Systemtakt 
und kann daher auch auf jedem STM32 genutzt werden, unabhängiog vom 
System-Takt.

Also einfach obige Anweisung durch die andere ersetzen und es 
funktioniert.

War ja klar dass es mal wieder an der Baudrate lag :-)

von Kindergärtner (Gast)


Lesenswert?

Jens K. schrieb:
> USART1->BRR = (SystemCoreClock / 9600)
Die SystemCoreClock ist eine ordinäre globale C-Variable, die von dem 
Clock Setup Code (der aus einem Excel-"Programm" aus generiert wird) 
gesetzt wird, der zB in ST's Beispielcodes verwendet wird. Also wie zu 
Beginn vermutet verkorkste Baudrate. So eine Zeile befindet sich auch in 
den ST-Beispielcodes zum UART...
Diese Zeile funktioniert natürlich auch nur, wenn der UART direkt aus 
dem Haupttakt versorgt wird; da die STM32 aber eine ganze Reihe von 
Takten und variablen Prescalern haben, muss das gar nicht der Fall sein. 
Dazu gibts ein schönes Diagramm im Reference Manual im Abschnitt "RCC".

von Jens K. (mister232)


Lesenswert?

Wo findet man eigentlich diese ST Beispielcodes? Ich finde nur das 
Reference Manual

von Kindergärtner (Gast)


Lesenswert?

Im Archiv der Standard Periphal Library: 
http://www.st.com/web/en/catalog/tools/PF257890

Im Pfad 
STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples

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.