我看官方给出 32G 实现 UART4 下 DMA 软件超时的方法,实际上还是用了串口中断,既然要用串口中断,直接用串口中断不就好了?MCU还是在不停被打断,意义不大。
最近用32G 比较多,开始的时候用RTOS 比如 迟老师的 CosyOS,慢慢开始觉得还是裸机比较爽。
脱离 RTOS 作超时判断比较麻烦一点,刚好在看32G的文档的时候,注意到 DMA_URnR_DONE 和 DMA_URnR_DONEH 寄存器。
这两个寄存器主要是用来记录当前读取了多少,那么如果在规定时间内,检查 DMA_URnR_DONE 和 DMA_URnR_DONEH 的数量大于0而且没有变化,那就不是超时了?
主循环中直接
unsigned int req_length = DMA_UR4R_DONE | (DMA_UR4R_DONEH << 8);
if (req_length > 0)
{
if (modbus_rx_last_count != req_length)
{
os_timer_restart_8(&modbus_rx_timeout);
modbus_rx_last_count = req_length;
}
else
{
if (os_timer_expired_8(&modbus_rx_timeout))
{
// 收到数据了
DMA_UR4R_CR = 0; // 停止接收
DMA_UR4R_DONE = 0;
DMA_UR4R_DONEH = 0;
IO_RS485_TC = ENABLE_WRITE; // 转入发送状态
{
int resp_length = modbus_response(
1,
modbus_rx_buffer,
req_length,
modbus_tx_buffer,
&modbus_main_mapping);
if (resp_length > 0)
{
// 需要发送
DMA_UR4T_AMT = (resp_length - 1);
DMA_UR4T_AMTH = (resp_length - 1) >> 8;
DMA_UR4T_STA = 0;
DMA_UR4T_CR = 0xC0;
}
else
{
// 不需要发送
modbus_start_recv();
}
}
}
}
}
}
其中 modbus_rx_timeout 是一个定时器,可以用 os_timer_expired_8 函数来判断是否超时,或者用 os_timer_restart_8(&modbus_rx_timeout); 来重新开始计时。
我实验了一下,没有发现什么问题
我就没有想明白,为什么官方实现的方式要用 串口中断,是不是有什么隐情?还是说官方的那种方式比较稳定,而这个方式不太稳定?请指教