APM32F107串口中断接收丢包
APM32F107在串口同时发送和接收的情况下串口接收丢字节,具体表现为偶发进入串口接收中断了,但是USART_FLAG_RXBNE标志位没有触发,导致读不到这个字节进而丢字节,通过计数发现进入中断的次数与实际应该收到的字节数一致。1、发送是阻塞式发送的,没有用发送中断,排除进入的是发送中断的可能。2、出现这种情况时打断点看了,其他的溢出及错误标志位并没有置位,也打印检查了,没有置位。
3、排查代码了没有在其他地方主动调用USART_RxDatad读取。
4、串口中断优先级已调至最高。
5、只接收不发送不会丢字节,挂一晚上都不丢,只要一发送接收就会丢。
发送代码:
void Uart1_Send(char buf)
{
uint16_t data_9th = buf;
dog_feed_count_clean(); // 循环清除喂狗变量,超过DOG_PROTECT_TIME_100MS不清除则认为主循环异常,并停止喂狗。
if (g_rParameters.sPort[0].ucParity == UART_CHK_MARK)
{
data_9th |= (1 << (uart1_data_bit - 1));
}
else if (g_rParameters.sPort[0].ucParity == UART_CHK_SPACE)
{
data_9th &= ~(1 << (uart1_data_bit - 1));
}
WAIT_TX_EMPTY; // wait data register empty//等待发送完
USART_TxData(USART1, data_9th);
}
接收中断:
void USART1_IRQHandler(void)
{
uint8_t data;
uint8_t longth = g_sParameters.sPort[0].ucDataSize;
if (USART_ReadStatusFlag(USART1, USART_FLAG_OVRE) == SET)
{
// 由软件清0,先读取USART_STS寄存器,再读USART_DATA寄存器完成清0。
USART_RxData(USART1);
}
if (USART_ReadStatusFlag(USART1, USART_FLAG_RXBNE) == SET)
{
data = (uint8_t)USART_RxData(USART1); // fetch recv data from buffer
if (g_sParameters.sPort[0].ucParity != UART_CHK_NONE)
{
data = data & (~(1 << longth)); // 去掉校验位
}
if (AtCmd_enter_mode(0, data) == 1)
{
packet_count = 0;
}
else
{
packet_count = 0;
uart1_rx_ringbuf_push(&uart1_rx_ringbuf, data);
// uart_rec_len ++;
}
usart_recv_total_len++;
}
timer_pack_reset_func();
}
感觉应该不会呀!
F107的主频近百兆呢!处理一个kbps级别的通讯。
即使错误进入了串口接收中断了,只要没有读出 ,下次仍然会进入串口中断 风暴之眸 发表于 2025-4-24 11:29
感觉应该不会呀!
F107的主频近百兆呢!处理一个kbps级别的通讯。
即使错误进入了串口接收中断了,只要没有 ...
你是极海的技术支持么? 检查你其它地方程序吧不知道你波特率用的多少我115200的很多都是中断收发也没出现大概率的丢包,不行你就上DMA 我不是技术支持。版主们应该是! 这部分代码看不出问题噢,需要更多的代码内容才能分析
建议先排查两个方面:
[*]中断处理函数中清除过载标志在判断接收buff非空之前,是否已经发生过载,但被清除。
[*]检查发送速度和接收速度是否一致,如果发送和接收时的速度不一致,可能导致数据丢失。
这个真心没有遇到过。
我们使用的是应答方式来通讯。直接全双工的方式,还真没有实践过 更神奇的是我用STM32F107的例程代码就没问题,APM的例程和STM的例程都已经删除的只剩串口部分了,没有其他代码,HCLK、PCLK时钟也检查了完全一致,串口寄存器值也完全一致 Gfan 发表于 2025-4-24 18:00
这部分代码看不出问题噢,需要更多的代码内容才能分析
建议先排查两个方面:
1、没有,后面我代码修改了,没发现过载
2、波特率是一致的,而且只发送或者只接受都不会有问题
另外我用STM32F107的例程代码就没问题,APM的例程和STM的例程都已经删除的只剩串口部分了,没有其他代码,HCLK、PCLK时钟也检查了完全一致,串口寄存器值也完全一致。
这个真心没有遇到过。不过丢包影响很大么。大数据量丢一两个也是很正常啊,或者你开开奇偶校验事实。 感觉这个bug还有点严重,不过倒是可以通过对数据帧添加校验来workaround掉。
解决了,库函数有问题:
void USART_TxData(USART_T* usart, uint16_t data)
{
usart->DATA_B.DATA = data;
}
这个DATA_B.DATA只使用了DATA寄存器的9位没使用保留的部分,换为以下方式就没问题
void USART_TxData(USART_T* usart, uint16_t data)
{
usart->DATA = data;
}
猜测,DATA寄存器会有两个,一个是TX的一个是RX的,但为了兼容性在逻辑地址上是一个,当执行写寄存器操作时会映射到TX的DATA寄存器,执行读操作时映射到RX的DATA寄存器,而官方库这种只操作DATA寄存器一部分bit的写法可能会导致逻辑地址与物理地址的映射错乱,也就造成了只有在发送时才会导致接收丢包这种现象,这只是我的猜测,还得官方解释一下。
不过,这么容易复现的严重问题竟然在官方库出现了,确实不应该啊,而且竟然用ST的库没问题,难道用这个片子的都在用ST的库? 本帖最后由 Gfan 于 2025-4-29 10:35 编辑
xiaoqilo 发表于 2025-4-26 20:24
解决了,库函数有问题:
void USART_TxData(USART_T* usart, uint16_t data)
{
你好呀,我们尝试复现问题,但使用我们的SDK,并未出现丢包情况,是否方便提供更多信息,以便定位问题呢?
[*]您是怎么判断数据丢失的呢?是少了数据个数,还是数据内容有错误?
[*]出错的概率大概是多少?比如是偶尔出现还是比较频繁?
[*]方便的话,能简单说下您的测试方案吗?
串口通信线路可能受到周围环境中的电磁干扰 确认发送端和接收端的波特率设置一致,并且是双方都支持的标准值。 中断服务函数执行时间过长 优化中断服务函数的代码,尽量减少不必要的操作。 使用环形缓冲区 检查地线是否完整,避免共模干扰。 都是32位的地址寻址,读9位和读32位应该是一样的呀!
页:
[1]
2