蓝桥杯练习——STM32串口接收中断只有效执行了一次的问题

博客讲述了在STM32F103RBT6开发过程中遇到的串口接收中断问题,即串口只能接收一次数据且第二次接收数据时出现错误。作者发现接收数据从第二位开始才是有效值,并且之后不再进入接收中断。为了解决这个问题,作者引入了IDLE中断,通过检测IDLE中断来判断一帧数据的结束。在IDLE中断中清空接收缓冲区并处理接收到的数据。经过这样的修改,串口能够正常接收和处理数据。然而,即使取消修改后的代码,问题也没有再次出现,这仍然是一个未解之谜。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实践场景:

提示:这里简述项目相关背景:

STM32板子型号:STM32F103RBT6

内容:将RTC的初值设置为23:59:55,并将时间显示在LCD屏上,通过串口发送"XX:XX:XX",XX分别表示时、分、秒,可以完成时钟的重新配置。若发送数据不符合规定,则不做更改。

使用的串口类型:蓝桥杯比赛的串口 AccessPort
在这里插入图片描述


问题描述

串口接收中断出现的问题:

1、串口只能执行第一次接收中断,并在LCD屏幕上成功显示

2、第二次通过串口发送数据时,debug查看发现接收时数据出现错误,表现为接收数据第二位开始才是有效值,之后再进行发送则不再进入接收中断

3、(作者也不知道的问题)在通过对1和2的问题进行修改之后(方法在后面),重新注释掉修改的代码进行编译,发现问题也不会重新出现,如果有知道原因的朋友,欢迎评论区探讨。


一、有问题的串口配置:

u8 uart_buf[8];
u8 uart_count=0;
_Bool rtc_flag = 0 ;
void USART2_IRQHandler(void)
{
  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
  {
	USART_ClearITPendingBit (USART2, USART_IT_RXNE);
    /* Read one byte from the receive data register */
    uart_buf [uart_count++] = USART_ReceiveData(USART2);
		
	if(uart_count >= 8)
    {			
		uart_count = 0;	
		rtc_flag = 1;
		USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);		
    }		
  }
}

中断的开启:

USART_Cmd(USART2, ENABLE);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

以上的配置一开始只能进行一次正常的数据接收。


解决办法:

通过IDLE中断RXNE中断结合: 实现接收一个字节,产生RXNE中断,一帧数据(串口一次接收的数据)接收后 ,产生IDLE中断

例:串口收到一个字节,产生8次RXNE中断和1次IDLE中断

一帧数据:
比如说单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据。IDLE中断就是串口收到一帧数据后产生的中断。


解决方案:

IDLE中断
一、F1系列的单片机:“先读SR寄存器,再读DR寄存器”。
二、F0系列的单片机:需要用ICR寄存器清楚。
由于我用的是F1系列的单片机,处理方法如下:

1、串口初始化函数中,使能IDLE中断

USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);

2、串口中断函数中,添加IDLE中断处理:

	else if(USART_GetITStatus(USART2,USART_IT_IDLE) != RESET)//接收到一帧数据
	{
		USART2->SR;//先读SR
		USART2->DR;//再读DR
		uart_count = 0;
		printf("%s", uart_buf);
	}

最后一个问题:就是在编译了一次IDLE中断处理之后,再注释掉添加的IDLE中断,就没有出现原来的问题了,不是很明白是怎么回事。不过加上IDLE中断是真的不用担心是不是接受完一帧数据了。


完整代码链接: STM32F103RBT6单片机修改RTC时钟初值的串口接收中断问题。.
原帖地址: https://blog.youkuaiyun.com/main_h_/article/details/55668953.
十分感谢原帖楼主的分享。

### 第十四届蓝桥杯嵌入式类别真题 针对第十四届蓝桥杯嵌入式类别的竞赛,官方提供了多份真题文档供参赛者练习和准备。这些真题涵盖了不同难度级别的挑战项目,旨在测试选手对于硬件设计、编程逻辑以及实际操作能力的理解。 #### 题目概述 一份典型的第十四届蓝桥杯嵌入式类别真题可能涉及如下几个方面: - **硬件平台**:基于STM32或其他微控制器开发板。 - **任务描述**:实现特定功能的应用程序编写,比如定时器中断处理、串口通信等基本外设驱动[^1]。 具体到代码层面,在给定的例子中展示了如何通过TIM7定时器每过0.1秒触发一次回调函数`HAL_TIM_PeriodElapsedCallback()`来增加计数变量`count_tim7`;同时也给出了UART接收完成后的回调函数`HAL_UART_RxCpltCallback()`,用于逐字节读取并存储接收到的数据至数组`rxdata[]`内[^2]。 ```c // 定义全局变量 uint16_t count_tim7 = 0; char rxdata[10]; uint8_t rxdat; unsigned char rx_pointer; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM7) { // 判断是否为TIM7定时器溢出事件 count_tim7++; } } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart == &huart1){ rxdata[rx_pointer++] = rxdat; // 将接收到的数据存入缓冲区 } HAL_UART_Receive_IT(&huart1, &rxdat, 1); // 继续等待下一个字符的到来 } ``` 上述代码片段实现了两个重要的功能模块——定时器周期性事件响应与异步串行数据接收,并且采用了中断方式提高系统的实时性和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值