Forum: Mikrocontroller und Digitale Elektronik UART per CMSIS (STM32f4) und pl2303 VCP


von Sven P. (der_sven)


Lesenswert?

Moin,

ich versuche grade einen UART auf dem stm32f3 (discovery-board) in 
Betrieb zu nehmen.

Funktioniert so mäßig

Der USB-TTL konverter ist mit einem PL2303 bestückt und mit dem µC via 
RX/TX (twistedpair) und Ground verbunden.

Das Terminal  zeigt leider nur quatsch an, aber immerhin scheint etwas 
anzukommen.

Der STM32 ist per CMSIS auf 9600 Baud konfiguriert. Wenn ich ein 'U' 
(01010101) sende kann ich auf dem DSO eine "Bitdauer" von ca. 325 µS 
ablesen.

Das macht nach Adamriese doch ca. 3000 bit/s. Komisch!

....

Die CMSIS Funktion rechnet ja den entsprechenden Wert für das BRR aus. 
Ich bin fast soweit meine eigene Unfähigkeit auf ST zu schieben, aber da 
es bei anderen ja scheinbar funktioniert....bin ich ratlos.

Vielleicht hab ich ja nen denkfehler. Ich wäre um Hinweise dankbar.

µC Code (angepasstes Bsp. aus dem Netz) ist:



/* Includes */
#include <stddef.h>
#include <stdio.h>
#include <stm32f4xx_conf.h>

// Function prototypes
void MySystemInit(void);

void USART_SendString(char* data);
int i;
// Main
int main(void)
{
// Controller initialisieren
SystemInit();
// MySystemInit initialisiert die GPIO's und den USART
MySystemInit();

// Sende Zeichen über USART
for(i=0;i<=10;i++)
{
USART_SendData(UART4, 'U');
// Warte bis die Übertragung beendet ist
while(USART_GetFlagStatus(UART4, USART_FLAG_TC) == RESET);
}
/*
// Sende ein String über USART
USART_SendString("Lorem ipsum dolores...\n");
// Warte bis die Übertragung beendet ist
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
*/
// Hauptschleife des Programms
// Nichts tun...
while(1)
{
}
}

// Initialisierung aller Ports, welche für mein Projekt benötigt werden
void MySystemInit(void)
{
// InitStructs erstellen
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;

// Clocks einschalten
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);


GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_UART4);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_UART4);
// USART1 RX-Pin initialisieren
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType= GPIO_OType_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOC, &GPIO_InitStructure);

// USART1 TX-Pin initialisieren
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOC, &GPIO_InitStructure);

// USART initialisieren
// Clocks
USART_ClockStructInit(&USART_ClockInitStructure);
USART_ClockInit(UART4, &USART_ClockInitStructure);

// 9600 Baud, 8Bit, No Parity, 1 StopBit, No FlowControl
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_HardwareFlowControl = 
USART_HardwareFlowControl_None;

USART_Init(UART4, &USART_InitStructure);
// USART an schalten
USART_Cmd(UART4, ENABLE);
}

Bild vom DSO kann ich grad nicht anhängen, Signalfolge ist LHLHLHLHLHH

Das Terminalprogramm gibt ferner, nicht verwunderlicher Weise einen 
Framingerror aus...

Schon mal herzlichen Dank für die Tips

von Juergen G. (jup)


Lesenswert?

1.
Wenn Deine Bitzeiten nicht stimmen, ueberpruef mal deinen Startup code. 
Speziell die Initialisierung der System Clock.
Manchmal wenn man einfach Dateien irgendwo aus dem Netz kopiert stimmt 
die Konfiguration nicht mit dem ueberein was man wirklich auf dem Board 
hat.

2.
Das ganze PinConfig musst Du nicht machen, bei den STM32's reicht es RX 
und TX auf AF zu stellen.

Bei mir tut folgender code seinen Dienst anstandslos.
Ist code von einem F0, also Pins anpassen falls Du den Code kopierst
1
void uart1_init(unsigned int baudrate){
2
  GPIO_InitTypeDef GPIO_InitStructure;
3
4
  // USART clock activation
5
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
6
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
7
8
  GPIO_StructInit(&GPIO_InitStructure);
9
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
10
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
11
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
12
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
13
  GPIO_Init(GPIOB, &GPIO_InitStructure);
14
15
16
  // USART config
17
  USART_InitTypeDef uInit;
18
  USART_StructInit(&uInit);
19
  uInit.USART_BaudRate = baudrate;
20
  uInit.USART_WordLength = USART_WordLength_8b;
21
  uInit.USART_StopBits = USART_StopBits_1;
22
  uInit.USART_Parity = USART_Parity_No;
23
  uInit.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
24
  uInit.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
25
  USART_Init(USART1, &uInit);
26
27
  // USART activate
28
  USART_Cmd(USART1, ENABLE);
29
30
   // activate Interrupt channel
31
   NVIC_InitTypeDef NVIC_InitStructure;
32
   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
33
   NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
34
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
35
   NVIC_Init(&NVIC_InitStructure);
36
37
   // activate Interrupts
38
   USART_ITConfig (USART1, USART_IT_RXNE, ENABLE);
39
40
}

von Manfred B. (manib)


Lesenswert?

Hi Sven,


kennst du schon Uwe's Seite. Er hat fertige Librarys geschrieben die das 
alles übernehmen:

http://mikrocontroller.bplaced.net/wordpress/?page_id=609

Viel Erfolg!
ManiB

von Sven P. (der_sven)


Lesenswert?

Manfred Becker schrieb:
> Hi Sven,
>
>
> kennst du schon Uwe's Seite. Er hat fertige Librarys geschrieben die das
> alles übernehmen:
>
> http://mikrocontroller.bplaced.net/wordpress/?page_id=609
>
> Viel Erfolg!
> ManiB

Hi Manfred,

herzlichen Dank für den Link! Der Code funktioniert einwandfrei! Da für 
STM32F4!!! geschrieben, konnte ich die Libs einbinden ohne eine einzige 
Anpassung vorzunehmen. :) Top! So wie ich das sehe auch ansonsten eine 
sehr lohnenswerte HP für alle die mit dem discoveryboard rumspielen! 
Props an Uwe also :)

beste Grüße

Sven

von Sven P. (der_sven)


Lesenswert?

Juergen G. schrieb:
> 1.
> Wenn Deine Bitzeiten nicht stimmen, ueberpruef mal deinen Startup code.
> Speziell die Initialisierung der System Clock.
> Manchmal wenn man einfach Dateien irgendwo aus dem Netz kopiert stimmt
> die Konfiguration nicht mit dem ueberein was man wirklich auf dem Board
> hat.

Hallo Jürgen,

danke genau daran hat's gelegen. In dem Startup code wurde von einem 
25MHz Quarz ausgegangen, verbaut ist ein 8MHz Quarz :) LoL

Ich hab Deinen Code grad mal an den F4 angepasst. Neben der Anpassung 
der Busses, muss scheinbar noch

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);

aufgerufen werden. Der F4 hat anscheinend nur ein  "GPIO alternate 
function high register" (AFR), der F0 hingegen 2 (AFRH und AFRL). Es 
werden aber trotzdem 2 Werte (geshiftet) und geschrieben.


Also herzlichen Dank nochmal!

Sven




Hier der angepasste Code mit 115200 Baud und USART2 an PA2/PA3

#include "stm32f4xx_conf.h"

void uart2_init(){
  GPIO_InitTypeDef GPIO_InitStructure;

  // USART clock activation
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);


  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  // USART config
  USART_InitTypeDef uInit;
  USART_StructInit(&uInit);
  uInit.USART_BaudRate = 115200;
  uInit.USART_WordLength = USART_WordLength_8b;
  uInit.USART_StopBits = USART_StopBits_1;
  uInit.USART_Parity = USART_Parity_No;
  uInit.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  uInit.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_Init(USART2, &uInit);

  // USART activate
  USART_Cmd(USART2, ENABLE);
/*
   // activate Interrupt channel
   NVIC_InitTypeDef NVIC_InitStructure;
   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);

   // activate Interrupts
   USART_ITConfig (USART1, USART_IT_RXNE, ENABLE);
*/
}

int main()
{
  int i;
  SystemInit();
  uart2_init();
  // Sende Zeichen über USART
  for(i=0;i<=10;i++)
  {
  USART_SendData(USART2, 'U');
  //Warte bis die Übertragung beendet ist
  while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
  }
  while(1)
  {
  }
}

von Juergen G. (jup)


Lesenswert?

Ja, das mit der GPIO_PinAFConfig ist richtig.

Ich hab den Code auf die Schnelle einfach aus einem bestehenden 
(aelteren) Projekt kopiert, bei dem ein F0 verwendet wurde.

Diesen Code nehme ich (fast) immer als Basis fuer die STM32's, egal 
welcher Kern.

von Juergen G. (jup)


Lesenswert?

Kleiner Nachtrag noch fuer die jenigen die oben geposteten Code 
verwenden.

Da dieser Code auf Interrupts basiert, muss noch eine ISR geschrieben 
werden die die Daten entsprechend "verdaut".

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.