历史上的今天
今天是:2025年03月25日(星期二)
2019年03月25日 | STM32的CubeMX关于串口中断
2019-03-25 来源:eefocus
1、关于串口的初始化函数:
MX_USART2_UART_Init()---波特率、奇偶校验等配置
HAL_UART_Init()---会将 huart->RxState = HAL_UART_STATE_READY;
HAL_UART_MspInit()---GPIO,中断优先级等配置
2、当需要使用中断接收时需要调用
HAL_UART_Receive_IT()---配置接收的缓冲区指针,数量,huart->RxState = HAL_UART_STATE_BUSY_RX;,最后使能相应中断
3、当中断发生时,执行
HAL_UART_IRQHandler()--判断中断的类型,在此处我用到的是非空中断,那么会继续调用UART_Receive_IT(huart);
这个函数会首先判断串口的接收状态huart->RxState == HAL_UART_STATE_BUSY_RX,若果为真就进行数据的保存,进 如 果达到规定的传输数量就会关闭中断,改变huart->RxState = HAL_UART_STATE_READY;然后执行HAL_UART_RxCpltCallback();如果不为真,就清除接收中断标志。
4、HAL_UART_RxCpltCallback()这个函数里尽可能的少些代码否则影响效率,如果想再次开启中断,可以在这里调用 HAL_UART_Receive_IT(),进行再次接收
下面说说我遇到的问题:
初始化串口完毕后,调用一次HAL_UART_Receive_IT(&huart2,uxComDMA.ucRxBuf,ONE_BYTE),进行一个字节的中断接收,然后在HAL_UART_RxCpltCallback()函数里,进行帧头的校验和传输数量的计算,然后继续开启。代码如下
//如果计算的数量大于规定的数量,说明传输出错。丢弃,判定上位机发送是否错误
if(usRecLength > DMA_BUF_MAX)
{
uxComDMA.ucRxBuf[eMsg_DTH] = APP_NULL;
uxComDMA.ucRxBuf[eMsg_DTL] = APP_NULL;
uxComDMA.usRxLen = APP_NULL;
PTCL_Dbg("计算数量大于规定数量");
}
//接收的数量大于等于计算的数量
if(uxComDMA.usRxLen >= usRecLength)
{
uxComDMA.uxReceiveFlag = eAppTrue;//标记接收完成。---此时不再调用HAL_UART_Receive_IT()
}
else//继续接受下一个数据
{
HAL_UART_Receive_IT(&huart2, uxComDMA.ucRxBuf+uxComDMA.usRxLen,ONE_BYTE);
}
当正确接收一帧数据后,便不再开启,直到这一阵数据处理完,主程序再次调用HAL_UART_Receive_IT()进行下一轮的接收。
那么问题来了:规定的协议是8个字节,在正确接收到8个字节后便不再开启中断接收,主函数执行数据帧的处理完毕后才会开启。但是如果上位机一次一共发送了10个字节,前8个字节是正确的一帧,后面2个无用。当下位机接收到8个字节便关闭了中断,处理完后再次开启。然后上位机再发来数据,发现下位机再也不能执行HAL_UART_RxCpltCallback(),协议就报废了。
调试后发现,后来接收数据时虽然可以进入中断并且执行了UART_Receive_IT();但是huart->RxState 的值不是HAL_UART_STATE_BUSY_RX导致不能继续执行传输完成回调。疑问是,最后一次开启中断接收时调用HAL_UART_Receive_IT()函数确实将 huart->RxState = HAL_UART_STATE_BUSY_RX;
PTCL_Dbg("初始化接收的状态%d",HAL_UART_Receive_IT(&huart2,uxComDMA.ucRxBuf,ONE_BYTE));//串口2的接收中断
函数返回值为HAL_OK
PTCL_Dbg("串口的接收状态%#x\r\n",huart2.RxState);----确实不等于HAL_UART_STATE_BUSY_RX,而是等于 HAL_UART_STATE_READY
// huart2.RxState = HAL_UART_STATE_BUSY_RX; ----加上这句话,可以解决问题
这是为什呢?
解决上述问题:
关于上述问题的总结:后两个字节传输时,已经关闭了中断,但是硬件将ORE位(溢出标志,看数据手册)置一和RXNE位置一。当调用HAL_UART_Receive_IT()函数时,会同时使能EIE、PEIE、RXNEIE三个中断。第一次我手动将RXNE位清除,但是没有清除ORE位,造成调用就会立即产生中断(溢出中断)。当执行HAL_UART_IRQHandler()函数时:




关于HAL库,更多的是考虑到安全性和兼容性所以代码量比较大,一开始使用不会像我们使用寄存器那么随意,所以必须深入看源码,才能更好的使用。
史海拾趣
|
用一个嵌入式设备把一个usb的拨号上网设备 用ppp拨号上网,然后通过以太网口提供ppp oe服务,要能够使这个设备能够支持snmp管理,可是拨号上网设备的ip又要能够传给以太网口接着的路由器或者机器。其实就是一个支持snmp的modem。不过那位大侠能帮个 ...… 查看全部问答> |
|
LM317常用作电压稳压器中的调整元件,这里给大家介绍一个不寻常的应用,只要配上不多的外部元件,可以使一个12V的小灯泡闪烁发光。 如图,采用所给的元件参数值和信号,当电路接通以后,小灯泡将以4Hz的频率闪烁,当然,若改变元件参数(R2 ...… 查看全部问答> |
|
雜訊排除(Noise Rejection) 樹狀切換 是一種將掃描器的通道分成數組,每一組都有自己的主要開關的方法。 如果沒有使用樹狀切換法的話,每個通道都會直接透過其雜散電容貢獻一些雜訊,但若透過樹狀切換方式的話,群組內並聯通道的電容值會與單 ...… 查看全部问答> |
|
可以通过浏览器访问交换机的web界面对交换机进行各种参数的设置,请问这种是如何实现的?是不是首先在本地建立好相关函数,然后通过web界面经由web服务器调用这些函数?能详细一些最好,谢谢! … 查看全部问答> |
|
建立XILINX FPGA开发中的ModelSim仿真环境方法 FPGA的开发中,仿真环节是必不可少的,而ISE自带的仿真工具只能仿真一些简单的HDL代码,无法仿真使用Coregen生成的IP,这个时候最简单的方式就是使用ModelSim。本文介绍如何在Xilinx FPGA开发环境中,建立ModelSim仿真环境。其实方法有多种,这里使 ...… 查看全部问答> |
|
急!如何将cadence原理图,PCB转换成protel格式 拿到一套评估板,代理商给的资料是用cadence设计的,我一般画图用Altium Designer,各位高手给指点一下,怎样才能将cadence原理图,PCB转换成protel格式… 查看全部问答> |
|
使用tms320f2812芯片,在线仿真时CAn运行正常,可烧写到flash后,其他部分运行正常,只有CAN不能通信,这是怎么回事啊?请教大家!… 查看全部问答> |




