Forum: Mikrocontroller und Digitale Elektronik STM32F4 Discovery Board + USART


von opcode (Gast)


Angehängte Dateien:

Lesenswert?

Sehr geehrte Forummitlgieder,

ich versuche gerade über USART "Daten" vom STM32F4 Discovery an den 
Computer zu senden. Für den Computer benutze ich den USB zu RS232 
Konverter DA 70156 von Digitus. Bei meinen AVR Projekten habe ich mit 
diesem Konverter + einem MAX232 keine Probleme gehabt. Soweit ich weiß, 
sitzt im DA 70156 ein Pegelwandler der auf 3.3V Pegel arbeitet, daher 
auch der MAX232 mit 5V für die AVR Chips. Da aber der STM32F407 mit 3.3V 
Pegel arbeitet, habe ich den Konverter und den STM32F407 direkt 
verbunden.

Um zu gewissern, ob meine eingestellten Frequenzen (HSE und PLL) richtig 
sind, habe ich diese über den MCO2 Pin am DSO ausgegeben. Hierbei 
handelt es sich um ein Agilent Modell vom Typ 5462A mit 200MSPS und 
100MHz Bandbreite.

Das Signal ist zwar kein Rechtecksignal (Sinus verzerrt), aber die 
berechnete Frequenz stimmt der der Handberechnung überein.
Bild im Anhang. Ist das normal ?!

Folgende Einstellungen für HSE und PLL wurden durchgeführt:
HSE = 8 MHz
PLL_N = 240
PLL_M = 8
PLL_P = 2

Nach den in dem Datenblatt angegebenen Gleichungen ergibt folgendes:
SYSCLK = 120 MHz
HCLK = 120 MHz (Prescaler=1)
PCLK2 = 60 MHz (Prescaler=2)
PCLK1 = 30 MHz (Prescaler=4)

Am MCO2 wurde ausgegeben: SYSCLK/4; am DSO gemessen: 30.01 MHz.

Nach dieser "Verifizierung" der Frequenzen habe ich folgendes 
Beispielprogramm verwendet:
1
#include "stm32f4xx.h"
2
#include "stm32f4xx_gpio.h"
3
#include "stm32f4xx_rcc.h"
4
#include "stm32f4xx_usart.h"
5
6
void USART_puts(USART_TypeDef* USARTx, volatile char *s)
7
8
USART_InitTypeDef USART_InitStructure;
9
GPIO_InitTypeDef GPIOC2_InitStruct;
10
11
12
int main()
13
{
14
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
15
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
16
17
  SystemInit();
18
  SystemCoreClockUpdate();
19
20
  GPIOC2_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
21
  GPIOC2_InitStruct.GPIO_Mode = GPIO_Mode_AF;
22
  GPIOC2_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
23
  GPIOC2_InitStruct.GPIO_OType = GPIO_OType_PP;
24
  GPIOC2_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
25
  GPIO_Init(GPIOC, &GPIOC2_InitStruct);
26
27
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6); 
28
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);
29
30
  USART_InitStructure.USART_BaudRate = 128000;
31
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
32
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
33
  USART_InitStructure.USART_Parity = USART_Parity_No;
34
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
35
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
36
37
38
  USART_Init(USART6, &USART_InitStructure);
39
  USART_Cmd(USART6, ENABLE);
40
41
        USART_puts(USART6, "Hallo"); 
42
   
43
  while(1)
44
    {
45
46
    }
47
}
48
49
void USART_puts(USART_TypeDef* USARTx, volatile char *s)
50
{
51
  while(*s)
52
        {
53
    // wait until data register is empty
54
    while( !(USARTx->SR & 0x00000040) );
55
      USART_SendData(USARTx, *s);
56
      *s++;
57
        }
58
}

Ich habe PC6 mit TX des USB->RS232 Konverters verbunden und gebe mir die 
Daten mit dem Programm "hterm" aus.

Leider erhalte ich nur "kuriose" Zeichen in "hterm" und nicht den 
gewünschten String "Hallo".

Habe ich etwas bezüglich der Baudraten Einstellung vergessen ?!

Was mich auch wundert ist, dass ich in meiner Programmierumgebung CooCox 
CoIDE in die "main" Funktion den Funktionsaufruf
SystemInit() aufrufen muss, damit die Frequenzen für HSE und PLL richtig 
übernommen werden. Geschieht dies nicht automatisch über das File 
"startup_stm32f4xx.s" oder habe ich da etwas falsch verstanden ?!

Bin für jeden Tipp sehr dankbar.

mfGruß,
opcode

von holger (Gast)


Lesenswert?

>  USART_InitStructure.USART_BaudRate = 128000;

Na wenn das mal nicht 115200 sein sollten;)

von opcode (Gast)


Lesenswert?

Guten Abend,

schön wäre es, wenn dieser Fehler "dort" wäre. Ich habe einige Baudraten 
durch versucht (1200, 2400, 9600 etc...) und dennoch kein Erfolg. Das 
hätte ich im Initialpost erwähnen müssen.

mfGruß,
opcode

von Rainer (Gast)


Lesenswert?

Hallo opcode,

ich weiss nicht, ob das dein Problem löst, aber ich würde zuerst

SystemInit();
SystemCoreClockUpdate();

ausführen und erst danach die Clocks für den USART und die GPIOs 
aktivieren.

Des weitern wäre es hilfreich wenn du mal eine bestimmte Baudrate (z.B. 
9600) einstellst und dann mal mit dem Oszi nachschaust, was am Tx-Pin 
des STM32 rauskommt. Am besten das Bild davon auch mal hier ins Formu 
stellen. Evtl. kann man dann mehr sagen.

Gruß
Rainer

von opcode (Gast)


Lesenswert?

Hallo Rainer,

ich habe SystemInit() und SystemCoreClockUpdate() nach oben geschoben 
und die Baudrate auf 9600 gestellt. Leider kein Erfolg.

Ich habe schon vorhin versucht mit dem DSO eine Datenübertragung am TX 
aufzunehmen, aber irgendwie kriege ich mit dem DSO kein Signal am TX. 
Müsste es kein Rechtecksignal bzw. sowas wie PWM sein ?! Also High und 
Low nur.

von opcode (Gast)


Lesenswert?

Ich kriege schon ein Signal, aber keine Bitfolge. Es ist wie ein 
abklingendes Sinussignal ?!

von mr. mo (Gast)


Lesenswert?

Mach mal ein Screen von dem Signal was am TX Pin des STM32 raus kommt.

von Jo D. (Firma: Jo) (discovery)


Lesenswert?

hallo,

ich habe jetzt nicht im Detail drüber geguckt, aber dieser Code hier hat 
bei mir funktioniert. Du kannst ja mal den Initialisierungsteil 
rauskopieren (du musst aber noch die Baudrate anpassen und die 
verwendeten Pins und auch den verwendeten USART.)

1
//-------------------------------------------STM32F4_USART-------------------------------------------------------
2
3
/* Beschreibung:
4
 * Ganze Strings mit Endezeichen werden interruptgesteuert empfangen und dann zurückgesendet.
5
 */
6
/*
7
8
Hinweis zum Clock fuer 8MHz Quarz, damit er auf 168MHz läuft (betrifft das stm32F4Discovery):
9
10
in der system_stm32f4xx.c muss eingetragen sein:
11
PLL_M = 8
12
13
in der stm32f4xx.h muss eingetragen sein:
14
HSE_VALUE = 8000000
15
*/
16
17
#include "stm32f4xx.h"
18
#include "stm32f4xx_gpio.h"
19
#include "stm32f4xx_rcc.h"
20
#include "misc.h"
21
#include "stm32f4xx_usart.h"
22
23
#define READ_BUFFER_SIZE 20
24
25
volatile char read_buffer[READ_BUFFER_SIZE];
26
volatile char read_buffer_single = 0;
27
volatile char string_complete = 0;
28
volatile int uart_str_count = 0;
29
30
void Delay(__IO uint32_t nCount)
31
{
32
  while(nCount--)
33
  {
34
  }
35
}
36
37
void USART_INIT_EXAMPLE(void)
38
{
39
  /* USARTx configured as follow:
40
        - BaudRate = 19200 baud
41
        - Word Length = 8 Bits
42
        - One Stop Bit
43
        - No parity
44
        - Hardware flow control disabled (RTS and CTS signals)
45
        - Receive and transmit enabled
46
  */
47
  GPIO_InitTypeDef GPIO_InitStructure;
48
  USART_InitTypeDef USART_InitStructure;
49
50
  /* Enable GPIO clock */
51
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
52
53
  /* Enable UART clock */
54
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
55
56
  /* Connect PXx to USARTx_Tx*/
57
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
58
59
  /* Connect PXx to USARTx_Rx*/
60
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
61
62
  /* Configure USART Tx as alternate function  */
63
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
64
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
65
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
66
67
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
68
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
69
  GPIO_Init(GPIOC, &GPIO_InitStructure);
70
71
  /* Configure USART Rx as alternate function  */
72
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
73
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
74
  GPIO_Init(GPIOC, &GPIO_InitStructure);
75
76
  USART_InitStructure.USART_BaudRate = 19200;
77
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
78
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
79
  USART_InitStructure.USART_Parity = USART_Parity_No;
80
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
81
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
82
83
  /* USART configuration */
84
  USART_Init(USART3, &USART_InitStructure);
85
86
  // Receive Interrupt enable
87
  USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
88
89
  /* Enable USART */
90
  USART_Cmd(USART3, ENABLE);
91
92
}
93
94
void UART_SEND_EXAMPLE(char byte)
95
{
96
    USART_SendData(USART3,byte);
97
    /* Loop until the end of transmission */
98
    while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET){}
99
}
100
101
void UART_SEND_TEXT_EXAMPLE(char *buffer)
102
{
103
  while (*buffer)
104
  {
105
    UART_SEND_EXAMPLE(*buffer);
106
    buffer++;
107
  }
108
}
109
110
void NVIC_INIT_EXAMPLE(uint16_t IRQ)
111
{
112
  NVIC_InitTypeDef NVIC_InitStructure;
113
114
  NVIC_InitStructure.NVIC_IRQChannel = IRQ;
115
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ Channel wird enabled
116
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // Die Priorität --> kleine Zahlen = hohe Priorität
117
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
118
  NVIC_Init(&NVIC_InitStructure);
119
}
120
121
void USART3_IRQHandler(void)
122
{
123
  if (USART_GetITStatus(USART3,USART_IT_RXNE) == SET)
124
  {
125
      USART_ClearITPendingBit(USART3,USART_IT_RXNE);
126
127
       // Daten aus dem Puffer lesen
128
        read_buffer_single = (USART3->DR & (uint16_t)0x01FF);
129
130
        if ( string_complete==0 )
131
             {
132
              //Bedingungen für ein Ende des Strings
133
                   if (read_buffer_single!='\n' && read_buffer_single!='\r' && uart_str_count<READ_BUFFER_SIZE-1)
134
                   {
135
                     read_buffer[uart_str_count]=read_buffer_single;
136
                       uart_str_count++;
137
                   }
138
                   else
139
                   {
140
                     read_buffer[uart_str_count]='\0';
141
                       uart_str_count=0;
142
                       string_complete=1;
143
                   }
144
             }
145
  }
146
}
147
148
149
int main(void)
150
{
151
152
  // Systemclock auf 168MHz (stm32F4Discovery mit 8MHz Quarz)
153
  SystemInit();
154
155
  // Initialisieren der Schnittstelle
156
  USART_INIT_EXAMPLE();
157
158
  // Interruptcontroller für RX-Interrupt konfigurieren
159
  NVIC_INIT_EXAMPLE(USART3_IRQn);
160
161
162
  //nun Text auf der ser. Schnittstelle empfangen und zurücksenden.
163
while(1)
164
    {
165
    if (string_complete)
166
    {
167
      // Echo des gesendeten Strings erzeugen
168
      // Achtung der String muss mit '\n' oder '\r' abgeschlossen werden beim Sender
169
      UART_SEND_TEXT_EXAMPLE((char*)read_buffer);
170
      string_complete = 0;
171
    }
172
    }
173
}

von holger (Gast)


Lesenswert?

>Ich kriege schon ein Signal, aber keine Bitfolge. Es ist wie ein
>abklingendes Sinussignal ?!

Dann schliess mal Ground mit an.

von opcode (Gast)


Lesenswert?

Guten Abend,

ich werde erst morgen daran weiter arbeiten können und melde mich dann 
zurück.

Wünsche einen schönen Abend und mfGruß,
opcode

von Jo D. (Firma: Jo) (discovery)


Lesenswert?

> Folgende Einstellungen für HSE und PLL wurden durchgeführt:
> HSE = 8 MHz
> PLL_N = 240
> PLL_M = 8
> PLL_P = 2

Du hast PLL_N auf einem anderen Wert!
Diese Einstellungen sind richtig (in der system_stm32f4xx.c):
1
/************************* PLL Parameters *************************************/
2
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
3
#define PLL_M      8
4
#define PLL_N      336
5
6
/* SYSCLK = PLL_VCO / PLL_P */
7
#define PLL_P      2
8
9
/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
10
#define PLL_Q      7
11
12
/******************************************************************************/

von opcode (Gast)


Lesenswert?

muss ich PLL_N auf 336 haben ?! Das brauch ich ja nur, wenn das STM32F4 
Board mit 168 MHz betrieben werden soll. Ich habe aber PLL_N so 
umgeändert, dass SYSCLK 120 MHz ist, so dass ADCLK 30 MHz. Somit kann 
ich mich an die Abtastraten-Angaben im Datenblatt beziehen, da diese ja 
auch für ADCLK 30 MHz angegeben sind.

Hab ich hier ein Denkfehler ?!

mfGruß,
opcode

von opcode (Gast)


Lesenswert?

Guten Abend,

ich habe nun zwei Versuche durchgeführt:

1.) Am Computer TX und RX verbunden und somit ein Echo Test 
durchgeführt: Erfolgreich

2.) Am STM32F4 Discovery TX und RX verbunden und über SemiHosting 
(SH_SendString) das Empfangene in der im RX-Interrupt zum Computer 
gesendet.
Auch das verlief erfolgreich.

Nun vermute ich sehr stark, dass die Pegel des STM32F4 Discovery Boardes 
mit dem der USB-RS232 Konverter nicht "harmonieren?"

mfGruß,
opcode

von Jan (Gast)


Lesenswert?

holger schrieb:
>>Ich kriege schon ein Signal, aber keine Bitfolge. Es ist wie ein
>>abklingendes Sinussignal ?!
>
> Dann schliess mal Ground mit an.

von opcode (Gast)


Lesenswert?

Ground habe ich natürlich angeschlossen gehabt.

von Simon K. (simon) Benutzerseite


Lesenswert?

Schaltplan und Bilder vom Aufbau her!

von opcode (Gast)


Lesenswert?

Schaltplan ?!

STM32F4 Disocvery Board: PC6 ---- TX  (Pin 3) USB-RS232 Konverter
STM32F4 Disocvery Board: PC7 ---- RX  (Pin 2) USB-RS232 Konverter
STM32F4 Disocvery Board: GND ---- GND (Pin 5) USB-RS232 Konverter

Schaltplan vom USB-RS232 Konverter habe ich nicht. Ist ein gekaufter 
Konverter. Hersteller: Digitus; Modell: DA70156
Chipsatz: FTDI / FT232RL

http://www.digitus.info/sv/produkter/zubehoer/adapter-und-konverter/usb-seriell-adapter-usb-20-da-70156/

Bilder kann ich morgen posten.

mfGruß,
opcode

von holger (Gast)


Lesenswert?

>Soweit ich weiß,
>sitzt im DA 70156 ein Pegelwandler der auf 3.3V Pegel arbeitet, daher
>auch der MAX232 mit 5V für die AVR Chips. Da aber der STM32F407 mit 3.3V
>Pegel arbeitet, habe ich den Konverter und den STM32F407 direkt
>verbunden.

Wenn der AVR einen MAX232 brauchte, dann braucht der STM32 einen
MAX3232. Du kannst den STM32 da nicht direkt anschliessen. Die
Signale müssen invertiert werden. Ausserdem kommen aus dem Ding
vermutlich Pegel größer als 3,3V raus.

von Simon K. (simon) Benutzerseite


Lesenswert?

opcode schrieb:
> Schaltplan ?!
Schaltplan. Ein Bild, wo drauf ersichtlich ist, welche Verbindungen du 
vorgenommen hast.

> STM32F4 Disocvery Board: PC6 ---- TX  (Pin 3) USB-RS232 Konverter
> STM32F4 Disocvery Board: PC7 ---- RX  (Pin 2) USB-RS232 Konverter
> STM32F4 Disocvery Board: GND ---- GND (Pin 5) USB-RS232 Konverter
Ja, genau. Mit anderen Worten:
"Ich brauche keinen Schaltplan, hier ist eine kurze Angabe, wie ich was 
verbunden habe. Der Fehler liegt hier eh nicht, also braucht ihr auch 
keinen Schaltplan zu sehen.".

> Bilder kann ich morgen posten.
Mach mal.

von opcode (Gast)


Lesenswert?

Ok Simon.

Morgen werde ich auch ein Schaltplan posten.

Danke dir.

von opcode (Gast)


Lesenswert?

@Holger:
Morgen werde ich mir den MAX3232 besorgen und diesen mit 0.1uF 
Kondensatoren zwischen USB->RS232Konverter und STM32F4 Discovery Board 
schalten.

mfGruß,
opcode

von opcode (Gast)


Lesenswert?

Liebe Forummitglieder,

das Problem wurde mit dem Pegelwandler MAX3232 gelöst. Die Daten kommen 
nun richtig an.

Vielen Dank für eure Hilfe.

Einen Schaltplan mit der MAX3232 Lösung folgt demnächst.

mfGruß,
opcode

von opcode (Gast)


Angehängte Dateien:

Lesenswert?

Sehr geehrte Forummitlgieder,

im Anhang nun der Schaltplan für die serielle Verbindung zwischen 
STM32F407 Discovery Board und PC/Notebook.

mfGruß,
opcode

von opcode (Gast)


Lesenswert?

Nachtrag: Für die Kondensatoren Cx mit x=1 bis 5 gilt: 100nF

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.