前提声明:此文章仅列举我在学习探索过程中遇到的困惑与思考,可能稍微偏硬核一点,并不会花费篇幅说明专业名词解释,也并不一定代表我的观点在客观上是正确的,欢迎大家批评指正,希望我的思考可以帮到和我有过同样困惑的初学者朋友们
在USART程序设计之中断接收中需要学习的核心函数是:
HAL_UART_Receive_IT(&huart1, &rx, 1);
也就是一个中断函数,那么在这个过程中需要注意的最大陷阱就是中断嵌套的优先级问题,通俗点说就是需要让滴答定时器的中断优先级比这个核心函数的优先级高,否则在对应的callback函数中像HAL_Delay()之类的函数就无法使用,程序会由于优先级bug卡死,那么以下便是我对这个经典bug的一些发现
1:优先级分组问题:比如说原本程序的优先级分组是4,后面临时修改为2,也就是添加
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
这行代码可以放在void HAL_MspInit(void)里面,HAL_Init()后面之类的,但一定不能放到MX_USART1_UART_Init()后面,否则会导致USART1_IRQn内部的抢占优先级混乱,具体什么原因怎么个混乱法本人能力有限就不深入研究了,就挺神奇,用串口调试软件试了几个小时才试出来的。
2:SysTick_IRQn的优先级(大坑!):在void HAL_MspInit(void)中覆盖它是无效的,因为在主函数的SystemClock_Config();中它会被再次覆盖,所以正确的方法是在HAL_Init()中的if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) 这行中直接修改TICK_INT_PRIORITY的底层值(我一开始的默认值是15UL)来调整SysTick_IRQn的优先级,这样后面即使再覆盖底层不变也是一样的,也就是说哪怕在HAL_Init()里面直接用HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0)来覆盖它的优先级也是无效的。
小tip:可以把这几行代码制作为USART的串口输出和输入反馈数据,这样就可以通过串口调试助手来实时观察串口的信号变化和需要监视的中断函数优先值变化,挺方便:
uint32_t priorityGroup = NVIC_GetPriorityGrouping();
uint32_t interruptPrioritya = NVIC_GetPriority(SysTick_IRQn);
uint32_t interruptPriorityb = NVIC_GetPriority(USART1_IRQn);
sprintf(str,"Group: %lu,Prioritya:%lu,Priorityb:%lu00\r\n",
priorityGroup,interruptPrioritya,interruptPriorityb);
HAL_UART_Transmit(&huart1,(unsigned char *)str, strlen(str), 50);
除此之外我还发现串口发送信息这个功能本身可能存在不灵敏的问题,不知道是不是串口调试助手这个软件的问题,偶尔就会存在发着发着就发不出去无反馈的情况,一般重新导入程序即可
以上便是我从晚上6点搞到凌晨4点得到的小小经验,希望可以对和我一样过困惑的同学们有所启发