【32学习问题:三】串口接收字符串只能接收一两个的原因:printf()函数

项目场景:

上位机发送字符串(总共7个字符),单片机进行解析,然后进行开灯等操作`

问题描述

`上位机发送了总共7个字符,比如 ABCDEFG 但是用正点的代码修改后,只能接收到AB两个字符:

void USART1_Init(u32 bound)
{
   //GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
 
	
	/*  配置GPIO的模式和IO口 */
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX			   //串口输出PA9
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;	    //复用推挽输出
	GPIO_Init(GPIOA,&GPIO_InitStructure);  /* 初始化串口输入IO */
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX			 //串口输入PA10
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;		  //模拟输入
	GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
	

   //USART1 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
	USART_Init(USART1, &USART_InitStructure); //初始化串口1
	
	USART_Cmd(USART1, ENABLE);  //使能串口1 
	
	USART_ClearFlag(USART1, USART_FLAG_TC);
		
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断

	//Usart1 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、	
}

/*******************************************************************************
* 函 数 名         : USART1_IRQHandler
* 函数功能		   : USART1中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/ 
void USART1_IRQHandler(void)                	//串口1中断服务程序
{
	char USART_ReceiveString[50];													//接收PC端发送过来的字符														
	int  Receive_sum = 0;
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
	{
	  	Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
			USART_ReceiveString[Receive_sum++] = Res;		//通过USART1串口接收字符	
	 }
		printf("USART_ReceiveString: %s  ",&USART_ReceiveString);  //串口打印出接收到的字符串
	  printf("Receive_sum: %d  ",Receive_sum);                      


---结果:
![XCOM串口调试](https://img-blog.csdnimg.cn/db346ca9296447c6bfa67ba9661f7ef7.png)
# 解决过程:
> 提示:刚开始按照其他博客的,**不要有中断嵌套**:把中断分级改为 10> ![更改优先级](https://img-blog.csdnimg.cn/8d096354c67e4232ac78ba1d4dad43db.png)
> 结果:和之前一样
然后继续参考其他博客,发现大家写的中断接收字符串函数都是这样的,但他们没有问题,,,,
然后,突然想到**printf()**, 这个是后来自己加的,(且之前有项目里面也是因为在中断里加了这个导致延迟),所以:
      **在中断注释掉,改放入main函数中去:**
    ![注释掉printf函数](https://img-blog.csdnimg.cn/13a6b835ea45441d893ad2786453e567.png)![main函数打印接收结果](https://img-blog.csdnimg.cn/6b2798bab5fc4bc09e6433c21154f934.png)
      

     结果:**完整接收7个字符!**
![在这里插入图片描述](https://img-blog.csdnimg.cn/ea7b1dc4047a4540b19d91f0be6df6c2.png)
# 原因分析:
应该是,printf()打印函数,他会占用一定时间,也许就导致串口中断接收过程中,造成了时延等问题,混乱了。
教训(第二次):**不要在中断函数里,用printf()来调试!**



  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用printf函数可以将接收到的字符串打印到串口或者调试助手上,以下是一个示例代码: ``` #include "stdio.h" #include "string.h" #include "stm32f4xx.h" #define RX_BUFFER_SIZE 512 uint8_t rx_buffer[RX_BUFFER_SIZE]; // 定义接收缓存区 uint16_t rx_counter = 0; // 定义接收计数器 void USART2_IRQHandler(void) { if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) { uint8_t data = USART_ReceiveData(USART2); rx_buffer[rx_counter++] = data; if (data == '\n' || rx_counter >= RX_BUFFER_SIZE) { rx_buffer[rx_counter] = '\0'; // 在字符串末尾添加'\0' printf("Received string: %s\n", rx_buffer); rx_counter = 0; // 接收计数器清零 } } } int main(void) { // 初始化串口 USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure); USART_Cmd(USART2, ENABLE); while (1) { // 主循环中进行其他操作 } } ``` 在串口中断处理函数中,当接收到字符'\n'时或者接收计数器达到缓存区大小时,将接收缓存区中的字符串打印到串口或者调试助手上,然后将接收计数器清零。 需要注意的是,在使用printf函数进行调试时,需要在工程设置中开启printf重定向功能。具体操作方法可以参考相关资料或者开发板的用户手册。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值