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