<求助帖>stm32串口接收发送出现“接收重复”、“接收位缺失”的现象/问题

关于“使用XCOM串口助手向单片机发送指令、单片机回复了重复多次”的问题

  最近在复习stm32串口通信时,简单包装了个接收串口数据的函数,并重定向了printf发送函数。测试功能大致是:XCOM(PC主机)像单片机发送一串字符后,单片机每接收一段即立刻向PC端回复一串字符串作为调试消息。测试代码如下有:

bsp_usart.c

#include "bsp_usart.h"
#include <stm32ff10x.h>

void Bsp_Usart1_Init(uint32_t bps)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = bps;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1, &USART_InitStructure);
	
	USART_Cmd(USART1, ENABLE);
	//打开串口1
}

void USART1_SendByte(uint8_t value)
{
	USART_SendData(USART1,value);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
}

uint8_t USART1_ReceiveByte(void)
{
	if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)!=RESET)
	{
		USART_ClearFlag(USART1,USART_FLAG_RXNE);
		return USART_ReceiveData(USART1);
	}
	return 0;
}

#if 1
#pragma import(__use_no_semihosting)     
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) //这里有的版本没有void会导致错误
{ 
	
}        
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 
FILE __stdout;
 
//重定向fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR & 0x40)==0);	//循环发送,直到发送完毕  
  USART_SendData(USART1,(uint8_t)ch);
	return ch;
}
#endif

main.c

#include<stm32f10x.h>
#include <stdio.h>
#include "delay.h"
#include "bsp_usart.h"


int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	Bsp_Usart1_Init(9600);		//串口1
	uint8_t a;
	
	printf("Hello World!\r\n");
	printf("你好,世界\r\n");
	
	while(1){
		Delay_us(10);
		a=USART1_ReceiveByte();
		if(a)
		{
			printf("%.2f",3.14f);
			printf("\r\n");
		}
	}
}

测试现象:

  烧录、运行上述代码到stm32f1单片机,打开串口助手XCOM并打开串口,单片机按键复位,上位机发送单串字符给单片机接收后,发现单片机会回复重复的两段消息?!,不禁然后感到十分的疑惑。。
在这里插入图片描述
  经过一番挣扎后,把上面的这段PC端发给单片机的消息解析成”以16进制发送“(勾选)的话,上面这两个字符其实是两个8位16进制码(ascii码),我板子接收两个回复两次是正常的:
在这里插入图片描述

  而我如果只发一个字符也就是一段8位数据的话,确实就只回复一次消息了:
在这里插入图片描述

  但是如果发三个字母、四个字母、五个字母。。n个字母呢?似乎发多少个并不会跟着就收到多少个然后相应地回复多少次。。。例如我发4个字符的字符,就只收到2个消息;发4~6个字符都是回复2次;
在这里插入图片描述

发7~13个字符,回复3次(可以理解是单片机其实只接收到了3次??)
在这里插入图片描述

加长到发送14~19个字符时,变成回复4段消息了(单片机似乎只接收了4次):
在这里插入图片描述

加长到发送20~26个字符,则回复5段消息;
发送27~33个字符,则回复6段消息;
发送34~50个字符,则回复7段消息;

关于“使用XCOM串口助手向单片机发送字段、回收字段有丢失”的问题

  对于上述问题,我觉得基本可排除不是printf发送函数的原因,并且若我单片机回收改为接收到的字符串返回,每次发送都很正常地只回复1次(当然可能其实也不一定是只接收到了1次,不懂。。),代码改动和测试结果如下:

	printf("Hello World!\r\n");
	printf("你好,世界\r\n");
	
	while(1){
		Delay_us(10);
		a=USART1_ReceiveByte();
		if(a)
		{
			printf("%c\n",a);
		}
	}

在这里插入图片描述
&emsp;
然后新的疑惑又来了(但我觉得刨下去应该跟上面的现象是一个原因导致。。),我发送若干长的字符串,单片机接收并返回的字符串超过3位后会丢失某几位!!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  总结问题:1)向下发送字符接收固定回复时,回复的消息数随PC端串口软件发送的字符串的字符数量而不对等的增加;2)向下发送字符回收发送下去的字符串时,回收的字符串若超过3位会丢失后续某好几位。。。
 上百度查询看到可能是片上串口接收缓冲区的大小问题,但是又更有点感觉像是没对上码的样子。。烦啊,解决不了这个很水的问题,太菜了,因此发成博客的形式希望求助大佬帮看一下,感谢呜呜呜~~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32上进行串口通信,可以通过以下步骤来实现串口接收发送: 1. 配置串口工作模式 在使用串口通信之前,需要先配置串口的工作模式。可以使用STM32的CubeMX软件进行配置,或者手动编写代码进行配置。配置包括波特率、数据、停止、校验等参数。 2. 发送数据 使用HAL库的函数可以轻松地发送数据。例如: ``` uint8_t txData[] = "Hello world!"; // 要发送的数据 HAL_UART_Transmit(&huart1, txData, sizeof(txData), HAL_MAX_DELAY); // 发送数据 ``` 在上面的例子中,使用HAL_UART_Transmit函数发送数据,第一个参数是串口句柄,第二个参数是要发送的数据,第三个参数是数据长度,第四个参数是最大等待时间。 3. 接收数据 使用HAL库的函数可以轻松地接收数据。例如: ``` uint8_t rxData[10]; // 接收数据的缓冲区 HAL_UART_Receive(&huart1, rxData, sizeof(rxData), HAL_MAX_DELAY); // 接收数据 ``` 在上面的例子中,使用HAL_UART_Receive函数接收数据,第一个参数是串口句柄,第二个参数是接收数据的缓冲区,第三个参数是数据长度,第四个参数是最大等待时间。 4. 中断接收数据 使用HAL库的函数可以在中断中接收数据。例如: ``` void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // USART接收中断回调函数 { if(huart -> Instance == USART1) // 判断是否为USART1接收中断 { uint8_t rxData = huart -> Instance -> DR; // 读取接收到的数据 // 处理接收到的数据 // ... HAL_UART_Receive_IT(&huart1, &rxData, 1); // 重新启动接收中断 } } ``` 在上面的例子中,使用HAL_UART_Receive_IT函数在中断中接收数据,第一个参数是串口句柄,第二个参数是接收数据的缓冲区,第三个参数是数据长度。 通过以上步骤,就可以在STM32上实现串口接收发送了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值