¿Cómo hacer que USART y USB-Serial funcionen en la placa de descubrimiento STM32F4?

5

Estoy programando un chip STM32F407VG en la placa de descubrimiento STM32F4 usando CooCox CoIDE. He unido un programa basado en algunos ejemplos y tutoriales que encontré en línea para obtener USART1 a través de los pines PB6 y PB7, y USB-serie a través del puerto microusb. Puedo hacer que ambos trabajen de forma independiente, pero cuando los pongo juntos, el USART no funciona correctamente y, a veces, arroja basura. Parece que la inicialización del reloj del sistema cambió mi velocidad de transferencia de USART de 9600, pero no estoy seguro de cómo solucionarlo.

Aquí está mi código:

#define HSE_VALUE ((uint32_t)8000000) /* STM32 discovery uses a 8Mhz external crystal     */

#include <stdio.h>
#include "misc.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx_conf.h"
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_exti.h"

#include "usbd_cdc_core.h"
#include "usbd_usr.h"
#include "usbd_desc.h"
#include "usbd_cdc_vcp.h"
#include "usb_dcd_int.h"

#define MAX_STRLEN 12 // max string length in characters
volatile char received_string[MAX_STRLEN+1];
volatile uint32_t ticker, downTicker;

/*
 * The USB data must be 4 byte aligned if DMA is enabled. This macro handles
 * the alignment, if necessary (it's actually magic, but don't tell anyone).
 */
__ALIGN_BEGIN USB_OTG_CORE_HANDLE  USB_OTG_dev __ALIGN_END;

// This funcion initializes the USART1 peripheral
void init_USART1(uint32_t baudrate){

    GPIO_InitTypeDef GPIO_InitStruct;                       // this is for the GPIO pins used as TX and RX
    USART_InitTypeDef USART_InitStruct;                     // this is for the USART1 initilization
    NVIC_InitTypeDef NVIC_InitStructure;                    // this is used to configure the NVIC (nested vector interrupt controller)

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);  // Peripheral clock for USART1 (APB2) --> other USART uses APB1
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);   // Peripheral clock for GPIOB (PB6 = TX, PB7 = RX)

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;     // Pins 6 (TX) and 7 (RX) are used
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;               // the pins are configured as alternate function so the USART peripheral has access to them
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;          // this defines the IO speed and has nothing to do with the baudrate!
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;             // this defines the output type as push pull mode (as opposed to open drain)
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;               // this activates the pullup resistors on the IO pins
    GPIO_Init(GPIOB, &GPIO_InitStruct);                     // now all the values are passed to the GPIO_Init() function which sets the GPIO registers

    /* The RX and TX pins are now connected to their AF
     * so that the USART1 can take over control of the
     * pins
     */
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);

    /* Now the USART_InitStruct is used to define the
     * properties of USART1
     */
    USART_InitStruct.USART_BaudRate = baudrate;             // the baudrate is set to the value we passed into this init function
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;// we want the data frame size to be 8 bits (standard)
    USART_InitStruct.USART_StopBits = USART_StopBits_1;     // we want 1 stop bit (standard)
    USART_InitStruct.USART_Parity = USART_Parity_No;        // we don't want a parity bit (standard)
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // we don't want flow control (standard)
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // we want to enable the transmitter and the receiver
    USART_Init(USART1, &USART_InitStruct);                  // again all the properties are passed to the USART_Init function which takes care of all the bit setting

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);          // enable the USART1 receive interrupt

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;       // we want to configure the USART1 interrupts
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;// this sets the priority group of the USART1 interrupts
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;      // this sets the subpriority inside the group
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         // the USART1 interrupts are globally enabled
    NVIC_Init(&NVIC_InitStructure);                         // the properties are passed to the NVIC_Init function which takes care of the low level stuff

    USART_Cmd(USART1, ENABLE);                              // This enables the complete USART1 peripheral
}

/* This function is used to transmit a string of characters via
 * the USART specified in USARTx.
 *
 * It takes two arguments: USARTx --> can be any of the USARTs e.g. USART1, USART2 etc.
 *                         (volatile) char *s is the string you want to send
 *
 * Note: The string has to be passed to the function as a pointer because
 *       the compiler doesn't know the 'string' data type. In standard
 *       C a string is just an array of characters
 *
 * Note 2: At the moment it takes a volatile char because the received_string variable
 *         declared as volatile char --> otherwise the compiler will spit out warnings
 * */
void USART_puts(USART_TypeDef* USARTx, volatile char *s){

    while(*s){
        // wait until data register is empty
        while( !(USARTx->SR & 0x00000040) );
        USART_SendData(USARTx, *s);
        *s++;
    }
}

/* Initialize USB, IO, SysTick, and all those other things you do in the morning */
void init()
{
    /* Set up the system clocks */
    SystemInit();

    /* Setup SysTick or CROD! */
    SysTick_Config(SystemCoreClock / 1000);


    /* Setup USB */
    USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_CDC_cb, &USR_cb);

    /* Set up USART */
    init_USART1(9600);

}

/* Main function */
int main(void)
{

    init();

    while (1)
    {
        uint8_t theByte;
        if (VCP_get_char(&theByte))
        {
            VCP_put_char(theByte);
        }
    }

    return 0;
}

// Interrupt Handlers

void SysTick_Handler(void)
{
    ticker++;
    if (downTicker > 0)
    {
        downTicker--;
    }
}

void OTG_FS_IRQHandler(void)
{
  USBD_OTG_ISR_Handler (&USB_OTG_dev);
}

void OTG_FS_WKUP_IRQHandler(void)
{
  if(USB_OTG_dev.cfg.low_power)
  {
    *(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ;
    SystemInit();
    USB_OTG_UngateClock(&USB_OTG_dev);
  }
  EXTI_ClearITPendingBit(EXTI_Line18);
}

// this is the interrupt request handler (IRQ) for ALL USART1 interrupts
void USART1_IRQHandler(void){

    // check if the USART1 receive interrupt flag was set
    if( USART_GetITStatus(USART1, USART_IT_RXNE) ){

        static uint8_t cnt = 0; // this counter is used to determine the string length
        char t = USART1->DR; // the character from the USART1 data register is saved in t

        if( (t != '\n') && (cnt < MAX_STRLEN) ){
            received_string[cnt] = t;
            cnt++;
        }
        else{ // otherwise reset the character counter and print the received string
            cnt = 0;
            USART_puts(USART1, received_string);
            //USART_puts(USART1, "\n");
            //memset(received_string, 0, MAX_STRLEN+1);
        }
    }
}

Aquí está el ejemplo de USART: enlace

y aquí está el ejemplo de USB: enlace

    
pregunta user2218339

1 respuesta

11

Resulta que el valor HSE en el archivo stm32f4xx.h se estableció en 25000000 como predeterminado. Entré y edité el valor a 8000000 y ahora funciona.

Así que entra en cmsis_boot > stm32f4xx.h > línea 92:

Cambiar de

#define HSE_VALUE ((uint32_t)25000000)

a

#define HSE_VALUE ((uint32_t)8000000)
    
respondido por el user2218339

Lea otras preguntas en las etiquetas