1.CubeMX生成的代码工程结构是比较合理的,但需要注意HAL库代码中初始化函数的调用顺序。
以串口初始化为例,勾选生成.c/.h文件后,CubeMX会把所有的串口外设放在usart.c中进行初始化,不同的串口间,使用不同的MX_U(S)ARTx_Init对串口外设进行配置,共用弱定义HAL_UART_MspInit进行引脚和中断的底层配置。
调用关系是,MX_UART4_Init-->HAL_RS485Ex_Init-->HAL_UART_MspInit,相当于底层配置和开启中断的操作是在外设初始化进行了一半时开始的。若需要自己实现每个串口一个私有的MspInit,那么初始化的顺序应该是,要把中断的配置和使能,放在最后的部分。
下面只有第一个函数正确。
/*正确的操作:先配置底层IO,再配置外设,最后配置中断*/
void BSP_RS232_Init(void)
{
MX_RS232_MspInit();
MX_UART4_Init();
/* UART4 interrupt Init */
HAL_NVIC_SetPriority(UART4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(UART4_IRQn);
__HAL_UART_ENABLE_IT(&huart4,UART_IT_RXNE);//接收中断
}
/*错误的操作1:*/
void BSP_RS232_Init(void)
{
MX_RS232_MspInit();//在此开启了中断
MX_UART4_Init();
}
/*错误的操作2:*/
void BSP_RS232_Init(void)
{
MX_UART4_Init();
MX_RS232_MspInit();//在此开启了中断
}
2.串口RXNE中断里一定不要打印(400M主频,波特率4800时打印才不会影响通信),不然就ORE溢出了,触发ORE中断后也要处理
/**
* 串口4中断服务函数
*/
void UART4_IRQHandler(void)
{
if(__HAL_UART_GET_FLAG(&huart4,UART_FLAG_RXNE)!=RESET)//接收到数据
{
RS232_Receive(UART4->RDR);
}
else
{
__HAL_UART_CLEAR_IT(&huart4, UART_CLEAR_OREF);
}
}
3.若串口中断里进行上传OS队列等OS相关操作,一定要将串口中断优先级降至可受OS管理的级别,不然会出现不上传队列、丢包的现象
void BSP_RS232_Init(void)
{
MX_RS232_MspInit();
MX_UART4_Init();
__HAL_UART_ENABLE_IT(&huart4,UART_IT_RXNE);//接收中断
/* UART4 interrupt Init */
HAL_NVIC_SetPriority(UART4_IRQn, 0x05, 0);//因为会在中断中调用OS相关API,优先级不能高于OS管理的范围
HAL_NVIC_EnableIRQ(UART4_IRQn);
}