Forum: Mikrocontroller und Digitale Elektronik STM32 und usart1/2 Initialisierung


von Wolfram L. (amazon)


Angehängte Dateien:

Lesenswert?

Hallo,
es geht um den Prozessor STM32F107VC auf einem Olimex Board 
32P107.Programmierung mit CoIDE
Ich habe jetzt seit 2h versucht herauszufinden warum USART1 einwandfrei 
funktioniert aber USART2 keinen Mux tut.
Vielleicht habe ich bei der Initialisierung ja was übersehen und jemand 
kann mir einen Tipp geben. Oder vielleicht messe ich an den falschen 
Pins. Sind nicht beide UARTS gleichberechtigt ?
Schönen Gruß
Wolfram

von LTC1043 (Gast)


Lesenswert?

USART1_SendString("Uart1\n");
  while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

  USART1_SendString("Uart2\n");
-------------^
  while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
---------------------------------------^


Weil du 2 mal auf USART1 sendest?

von Wolfram L. (amazon)


Angehängte Dateien:

Lesenswert?

Sorry, das war ein copy and paste Fehler... (weil ich die 
Stringvariablen getauscht hatte)
im orginal ist es wie hier:

int main(void)
{
// Controller initialisieren

SystemInit();

InitUart1();
InitUart2();

while(1)
{
  delay_nus(10000);
  USART1_SendString("Uart1\n");
  while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  USART2_SendString("Uart2\n");
  while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
}
}

Tut aber eben dennoch nicht...

von (prx) A. K. (prx)


Lesenswert?

RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART2
      -^-                    -^-

von Wolfram L. (amazon)


Lesenswert?

A. K. schrieb:
> RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART2
>       -^-                    -^-
Ja da hatte ich auch vermutet und rumgedoktert, aber laut Doko solls so 
sein:

fuer UART1
/**
  * @brief  Enables or disables the High Speed APB (APB2) peripheral 
clock.
  * @param  RCC_APB2Periph: specifies the APB2 peripheral to gates its 
clock.
  *   This parameter can be any combination of the following values:
  *     @arg RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, 
RCC_APB2Periph_GPIOB,
  *          RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, 
RCC_APB2Periph_GPIOE,
  *          RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, 
RCC_APB2Periph_ADC1,
  *          RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, 
RCC_APB2Periph_SPI1,
  *          RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1(!!!!), 
RCC_APB2Periph_ADC3,
  *          RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, 
RCC_APB2Periph_TIM17,
  *          RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, 
RCC_APB2Periph_TIM11
  * @param  NewState: new state of the specified peripheral clock.
für UART2:
/**
  * @brief  Enables or disables the Low Speed APB (APB1) peripheral 
clock.
  * @param  RCC_APB1Periph: specifies the APB1 peripheral to gates its 
clock.
  *   This parameter can be any combination of the following values:
  *     @arg RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, 
RCC_APB1Periph_TIM4,
  *          RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, 
RCC_APB1Periph_TIM7,
  *          RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, 
RCC_APB1Periph_SPI3,
  *          RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, 
RCC_APB1Periph_USART4,
  *          RCC_APB1Periph_USART5, RCC_APB1Periph_I2C1, 
RCC_APB1Periph_I2C2,
  *          RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, 
RCC_APB1Periph_BKP,
  *          RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC,
  *          RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, 
RCC_APB1Periph_TIM14
  * @param  NewState: new state of the specified peripheral clock.

Warum die beiden unterschiedliche Clock sources verwenden(sollen) ist 
mir unklar.

von Wolfram L. (amazon)


Lesenswert?

Wolfram L. schrieb:
> Warum die beiden unterschiedliche Clock sources verwenden(sollen) ist
> mir unklar.
Ist mir jetzt klar wenn man ins Blockschaltbild sieht.. nur USART1 ist 
auf dem HighSpeed IO Bus "APB2"..

von Wolfram L. (amazon)


Lesenswert?

A. K. schrieb:
> RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART2

Tut leider immer noch nicht... ;-(

von (prx) A. K. (prx)


Lesenswert?

Du solltest entweder die primären Pins von UART2 verwenden, oder das 
Remapping auf die verwendeten sekundären Pins einrichten.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Um den USART2 mit PD5/PD6 nutzen zu können müssen die Pins geremapt 
werden.
Siehe als "Alternate functions" "Remap"

von Wolfram L. (amazon)


Lesenswert?

A. K. schrieb:
> primären Pins von UART2

Aber ich dachte ich benutze die primären(!) Pins ? Woran erkennt man das 
?

>müssen die Pins geremapt werden

Das habe ich auch mal versucht, leider auch ohne Erfolg, kann es sein, 
dass die Reihenfolge der Config falsch ist ?
Hier der letzte Versuch:

void InitUart2(void)
{
  // Initialize Structs
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  USART_ClockInitTypeDef USART_ClockInitStructure;
  // Enable clocks
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOD, 
ENABLE);
  //RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  // USART1 RX-Pin initialize PD6
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  // USART1 TX-Pin initialize PD5
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  /* Remap USART, as USART2 is used as alternate pins on PD5/6*/
  GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);

  // USART initialize
  USART_ClockStructInit(&USART_ClockInitStructure);
  USART_ClockInit(USART2, &USART_ClockInitStructure);

  USART_InitStructure.USART_BaudRate = 9600;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_HardwareFlowControl = 
USART_HardwareFlowControl_None;

  USART_Init(USART2, &USART_InitStructure);
  USART_Cmd(USART2, ENABLE);
}

von (prx) A. K. (prx)


Lesenswert?

Wolfram L. schrieb:
> Aber ich dachte ich benutze die primären(!) Pins ?

Bei UART1 ja. Bei UART2 liegen auch auf PortA, nicht PortD.

> Woran erkennt man das ?

Eingehende Lektüre der Reference.

von (prx) A. K. (prx)


Lesenswert?

Wolfram L. schrieb:
> Hier der letzte Versuch:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOD,
      -^-                                            -^-

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Poste doch nochmal die "STM32_USART_Test.c" wie sie jetzt aus sieht, 
falls es immer noch nicht geht.

von Wolfram L. (amazon)


Angehängte Dateien:

Lesenswert?

Markus Müller schrieb:
> Poste doch nochmal die "STM32_USART_Test.c"

Und bitte...

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Die Zeile ist falsch:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOD, 
ENABLE);

Also der "RCC_APB1PeriphClockCmd" >> "APB1" kann nie den 
RCC_APB2Periph_GPIOD im APB2 aktivieren.

siehe auch hier:
Beitrag "Re: STM32 und usart1/2 Initialisierung"

von Wolfram L. (amazon)


Lesenswert?

Markus, danke für den Hinweis, da hast Du wohl recht.

Markus Müller schrieb:
> Die Zeile ist falsch:
> RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOD,
> ENABLE);

Also stattdessen müsste es wohl so sein:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

Dann sind doch beide richtig Enabled... ? hab ich so jetzt verstanden, 
ABEr GRRRRRRR Hat leider auch nicht geholfen.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Ja, klar geht das nicht.
Du hast in der main() die Initialisierung der UASRT 1 deaktiviert / 
auskommentiert.
Darin wird der Clock für "RCC_APB2Periph_AFIO" aktiviert, also das auch 
noch in die Initialisierung von Uart 2 rein nehmen.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Du solltest eine allgemeine RCC Initialisierung machen, mit der die 
ganzen GPIO/AFIO Clocks alle aktiviert werden und auch alle anderen 
Pins, die keine Alternative Funktion haben.
Dann brauchst Du nur noch bei der Initialisierung der verwendeten 
Peripherie (z.B. UART) den Clock aktivieren.
Damit ist die Initialisierung leichter und man kann je nach genutzter 
Peripherie auch einfacher/übersichtlicher die zugehörigen Clocks 
aktivieren.

von (prx) A. K. (prx)


Lesenswert?

Im Gegenteil. Die Idee, in jedem Modul alles einzuschalten, was darin 
verwendet wird, ist sehr vernünftig. Es schadet ja nichts, die AFIO 
mehrfach einzuschalten. Es global an einer Stelle einzuschalten 
bedeutet, einer sauberen Modularisierung des Codes Knüppel zwischen die 
Beine zu werfen.

Er hat einfach nur vergessen, die AFIO auch im zweiten Modul 
einzuschalten.

von Wolfram L. (amazon)


Angehängte Dateien:

Lesenswert?

Markus Müller schrieb:
> Darin wird der Clock für "RCC_APB2Periph_AFIO" aktiviert, also das auch
> noch in die Initialisierung von Uart 2 rein nehmen.

Arrrggggr - Ja klar jetzt gehts auch !!;-) Freu


>Du solltest eine allgemeine RCC Initialisierung machen,...
Ja ich denke dies ist der bessere Weg, sonst konfiguriert man sich 
jeweils etwas weg was noch gebraucht wird. quod erat demonstrandum


Die Hardware geht jetzt, jetzt versuch ich mich mal an Interrupt 
basiertem USART...Gibts da auch solche Stolperfallen ? ;-)

Im Anhang nochmal der Code DER für USART1 und USART2 auf STM32F017VC mit 
Olimex STM32P107 Board der funktioniert, falls das mal jemand sucht.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Bei den Interrupts gibt es kein extra Clock der aktiviert werden muss, 
dafür muss man sich vorher gedanken machen wie viele priorisierte 
Interrupts man hat und wie viele Interrupts mit der gleichen Prio 
laufen.
Sie auch "NVIC_PriorityGroupConfig()" und in der Doku lesen, ich weiß 
das gerade nicht genau auswendig.

In jedem Fall, der Interrupt mit der gleichen "PreemptionPriority" kann 
einen anderen mit der gleichen "PreemptionPriority" nicht unterbrechen.
Hingegen der mit einer höherwertigen "PreemptionPriority" schon.
Ich weiß grad nur nicht was höherwertig ist, der mit der kleineren oder 
größeren Zahl.
Der "IRQChannelSubPriority" definiert nur die Reihenfolge, wenn mehrere 
Interrupts mit der gleichen "PreemptionPriority" gleichzeitig kommen, 
unterbrechen sich aber nicht gegenseitig.

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.