He estado creando prototipos de mi proyecto con el STM32F103 "Bluepill" y para el producto final quiero pasar al STM32F042F6 que tiene una huella TSSOP-20 más pequeña. Necesito usar UART en mis comunicaciones con el dispositivo, así que traté de crear un programa de transmisión UART simple para verificar que el periférico UART funcionaba correctamente. Aquí está mi código.
#include "stm32f0xx.h"
#include "stm32f0xx_hal.h"
#include "stm32f0xx_hal_conf.h"
void Startup_Sequence(void);
void Error_Handler(void);
void SystemClock_Config(void);
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle);
UART_HandleTypeDef UartHandle;
__IO ITStatus UartReady = RESET;
int main(void)
{
HAL_Init();
//SystemInit();
SystemClock_Config();
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
// Setup LED Pin
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Setup UART Tx Pin
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Setup UART Rx pin
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//Setup UART Instance
UartHandle.Instance = USART1;
UartHandle.Init.BaudRate = 9600;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
UartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
//Error handling
if(HAL_UART_Init(&UartHandle) != HAL_OK) {
Error_Handler();
}
Startup_Sequence();
HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(USART1_IRQn);
char hello[6] = "hello\n";
while(1) {
if(HAL_UART_Transmit_IT(&UartHandle, (uint8_t *)hello, 6) != HAL_OK) {
Error_Handler();
}
}
}
void Startup_Sequence(void) {
int i;
for (i=1; i<50;i++) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
HAL_Delay((1.0/i) * 1000);
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
}
void Error_Handler(void) {
while(1) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
HAL_Delay(1000);
}
}
/**
* Associates the interrupt handler with the UartHandle
*/
void USART1_IRQHandler(void) {
HAL_UART_IRQHandler(&UartHandle);
}
/**
* This function is called when transmitting
* @param UartHandle [Pointer to UartHandle]
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle) {
UartReady = SET;
}
/**
* This function is called when receiving
* @param UartHandle [Pointer to UartHandle]
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) {
UartReady = SET;
}
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType =
RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI48;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) !=
HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
El periférico UART se inicializa correctamente, porque el controlador de errores no se llama hasta después de que se haya completado Startup_Sequence(). Entonces, ¿por qué se llama a ErrorHandler cuando intento transmitir? He intentado enviar usando el modo de bloqueo, pero solo se agota el tiempo de espera cada vez.
EDITAR: he rastreado el error hasta la función de inicialización. Aquí está el registro de GDB https://hastebin.com/xopohaniyu.coffeescript pero no puedo encontrar ningún lugar donde no se devuelva HAL_OK.
¿Hay algún problema con mi configuración del periférico UART? ¿O hay un problema con el reloj del sistema? Por favor avise.
La configuración de GPIO es un poco más complicada y flexible en el F0. Aquí también debe establecer GPIO_InitStruct.Alternate = GPIO_AF1_USART1
, de lo contrario obtendrá algún valor aleatorio, porque es una variable automática unificada. Habilite las advertencias en el compilador y preste atención a ellas, están ahí por una razón.
HAL_UART_Transmit_IT()
se vuelve a llamar antes de que haya terminado la transmisión anterior. Debe esperar hasta que UartReady
se establezca la bandera y restablecerla antes de repetir.
chris stratton
chris stratton