小伙子也是满怀斗志,计划使用cubemx和HAL库开发,底层勾勾点点,只把应用层移植过来,简单快速。但有时候,理想和现实总是差一点“运气”和细心....
一切准备就绪,代码移植过来,呵,不出意外的话肯定有意外...不但通讯没成功,点个灯都灭了,然后开始仿真、屏蔽代码,一部分一部分排除法...最终定位在了串口中断上,不管有没有数据来,都会疯狂的进中断。
校验位错误,看起来很奇怪,外部串口已经断开了,理论上不会再进中断了才是,现在还报了个校验位错误,然后开始疯狂百度,找不到头绪了,可把孩子急坏了。
最后实在是没办法了,就帮小伙子调试一下吧,不调不信,一调差点给我整崩溃了,这不最近调蓝牙模组,突然又遇到这个问题了,忽然想起来这个事情,就简单记录一下,希望可以帮助一些小伙伴排忧解难,特别是用hal库的小伙伴
一般我们使用cubemx配置串口的时候,仅仅是配置了一些参数、IO等,串口号名称不能像IO口一样定义label。
void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
UART_HandleTypeDef huart2;
/**
* @brief This function handles USART2 global interrupt / USART2 wake-up interrupt through EXTI line 26.
*/
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
#if 1
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
#else
HAL_UART_IRQHandler(&BluetoothUart);
#endif
/* USER CODE END USART2_IRQn 1 */
}
相信不少同学在开发的时候,对于一些定义命名都喜欢“顾名思义”,也是变量命名的一种最基本要求,加入用了4个串口,各自负责不同的功能,这样命名,谁看得出来哪个串口是干什么用的:
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
UART_HandleTypeDef huart3;
UART_HandleTypeDef huart4;
UART_HandleTypeDef ble_uart;
UART_HandleTypeDef print_uart;
UART_HandleTypeDef gsm_uart;
UART_HandleTypeDef gps_uart;
static void BluetoothUartInit(void)
{
BluetoothUart.Instance = USART2;
BluetoothUart.Init.BaudRate = 115200;
BluetoothUart.Init.WordLength = UART_WORDLENGTH_8B;
BluetoothUart.Init.StopBits = UART_STOPBITS_1;
BluetoothUart.Init.Parity = UART_PARITY_NONE;
BluetoothUart.Init.Mode = UART_MODE_TX_RX;
BluetoothUart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
BluetoothUart.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&BluetoothUart) != HAL_OK)
{
Error_Handler();
}
HAL_UART_Receive_IT(&BluetoothUart, &ble_com.recbyte, 1);
}
BluetoothUart->Instance = 0x400044000;
huart2->Instance = 0;
#define PERIPH_BASE (0x40000000UL) /*!< Peripheral base address */
#define APBPERIPH_BASE (PERIPH_BASE)
#define USART2_BASE (APBPERIPH_BASE + 0x00004400UL)
uint32_t isrflags = READ_REG(huart->Instance->ISR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
uint32_t cr3its = READ_REG(huart->Instance->CR3);
uint32_t errorflags;
uint32_t errorcode;
#define USART_ISR_PE_Pos (0U)
#define USART_ISR_PE_Msk (0x1UL << USART_ISR_PE_Pos) /*!< 0x00000001 */
#define USART_ISR_PE USART_ISR_PE_Msk /*!< Parity Error */
#define USART_CR1_PEIE_Pos (8U)
#define USART_CR1_PEIE_Msk (0x1UL << USART_CR1_PEIE_Pos) /*!< 0x00000100 */
#define USART_CR1_PEIE USART_CR1_PEIE_Msk /*!< PE Interrupt Enable */
CR1 = 0x20001160;
ISR = 0;
//最终计算
isrflags & USART_ISR_PE = 0&1 = 0;
cr1its & USART_CR1_PEIE = 0x20001160&(1<<8) = 0x100;
触发PE错误条件是,当然满足了,我觉得触发这个错误可能纯属偶然...
/* UART parity error interrupt occurred -------------------------------------*/
if (((isrflags & USART_ISR_PE) != 0U) && ((cr1its & USART_CR1_PEIE) != 0U))
{
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_PEF);
huart->ErrorCode |= HAL_UART_ERROR_PE;
}
为了不受cubemx生成代码影响,可以采取宏定义的方法:
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
#if 0
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
#else
HAL_UART_IRQHandler(&BluetoothUart);
#endif
/* USER CODE END USART2_IRQn 1 */
}
问题就到这里了,问题不大,却需要多多留心!
END