usart串口发送与接收问题

news/2024/11/14 15:40:21/

项目场景:

串口通信可以说很常用的一种通信方式,例如 蓝牙通信 openmv 与串口 通信 等等 


问题描述

1.我们在进行数据传输过程中数据不时出现丢失的情况,偶尔会丢失一部分数据,导致数据部分缺失,或者出现乱码的问题,所以说代码需要准确性。

2.比如我们发送一组数据(1,2,3,4,5)放在数组里面,你想读取 USART1_RX_BUF[1] 是什么 通过 printf 打印 USART1_RX_BUF[1];这时如果你用整形 也就是:

(printf("%d",USART1_RX_BUF[1])

你就会发现 你打印的数据 是48 向上加,就不是你想要得到的值. 


原因分析:

原因1:如果将接收到的数据直接进行处理,单片机处理数据很快,就有可能出现数据丢失等情况,为了增强接收数据的准确性,我们添加一些数据帧头帧尾的检测,便于数据处理的更加准确。

原因2:经过不断的调试判定是数据类型问题,就在一个个的改动,也是碰巧发现 接受数组里面是字符型 更改后[ printf("%c", USART1_RX_BUF[1] ] 这样就可以接受到你想要的数据了。


解决方案:

通过在监视串口的数据不断的尝试,调试出适合自己的程序;

下面直接上代码

毕业学长看完给的建议:
第一:在一组数据进行传输的时候如果想要准确性,单靠帧头帧尾还不行,因为你发送的数据会出现和帧头帧尾同样的数据,较好的解决办法是在数据末尾加上CRC校验的数据,收到这组数据后同样先进行CRC校验,校验结果一致的情况下才能用这一组数据


第二:我看你用的是单字节接收,这个时候程序就要知道要接收多少个字节,单靠超时或者你可能会用到的帧尾的话就显然不能保证很靠谱,有一种解决方法是在发送的数据中加入数据长度,在中断里进行判断, 这是比较简单的一种方法,但是这种数据的结构特别常用,等下我可以给你看看我实际项目用到的协议帧是怎么定义的,基本就是按照MODBUS的格式来的


第三:可以尝试用DMA或者DMA+队列的方式直接接收一帧完整的数据

usart.c

#include "usart.h"		 u8 USART1_RX_BUF[USART1_REC_LEN];     //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.
//½ÓÊÕ״̬
//bit15£¬	½ÓÊÕÍê³É±êÖ¾
//bit14£¬	½ÓÊÕµ½0x0d
//bit13~0£¬	½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿
u16 USART1_RX_STA=0;       //½ÓÊÕ״̬±ê¼Ç	#ifdef USART1_PRINTF
int fputc(int ch,FILE *p)  //º¯ÊýĬÈϵģ¬ÔÚʹÓÃprintfº¯Êýʱ×Ô¶¯µ÷ÓÃ
{USART_SendData(USART1,(u8)ch);	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);return ch;
}
#endif/*******************************************************************************
* º¯ Êý Ãû         : USART1_Init
* º¯Êý¹¦ÄÜ		   : USART1³õʼ»¯º¯Êý
* Êä    Èë         : bound:²¨ÌØÂÊ
* Êä    ³ö         : ÎÞ
*******************************************************************************/ 
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);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	 //´ò¿ªÊ±ÖÓ/*  ÅäÖÃGPIOµÄģʽºÍIO¿Ú */GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX			   //´®¿ÚÊä³öPA9GPIO_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			 //´®¿ÚÊäÈëPA10GPIO_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); //³õʼ»¯´®¿Ú1USART_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;//ÇÀÕ¼ÓÅÏȼ¶3NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//×ÓÓÅÏȼ¶3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQͨµÀʹÄÜNVIC_Init(&NVIC_InitStructure);	//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷¡¢	
}/*******************************************************************************
* º¯ Êý Ãû         : USART1_IRQHandler
* º¯Êý¹¦ÄÜ		   : USART1ÖжϺ¯Êý
* Êä    Èë         : ÎÞ
* Êä    ³ö         : ÎÞ
*******************************************************************************/ 
//void USART1_IRQHandler(void)                	//´®¿Ú1ÖжϷþÎñ³ÌÐò
//{
//	u8 r;
//	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //½ÓÊÕÖжÏ
//	{
//		r =USART_ReceiveData(USART1);//(USART1->DR);	//¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý
//		USART_SendData(USART1,r);
//		while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
//	} 
//	USART_ClearFlag(USART1,USART_FLAG_TC);
//} 
/*******************************************************************************/ 
void USART1_IRQHandler(void)                	//´®¿Ú2ÖжϷþÎñ³ÌÐò
{u8 r;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //½ÓÊÕÖжÏ{r =USART_ReceiveData(USART1);//(USART1->DR);	//¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ýif((USART1_RX_STA&0x8000)==0)//½ÓÊÕδÍê³É{if(USART1_RX_STA&0x4000)//½ÓÊÕµ½ÁË0x0d{if(r!=0x0a)USART1_RX_STA=0;//½ÓÊÕ´íÎó,ÖØпªÊ¼else USART1_RX_STA|=0x8000;	//½ÓÊÕÍê³ÉÁË }else //»¹Ã»ÊÕµ½0X0D{	if(r==0x0d)USART1_RX_STA|=0x4000;else{USART1_RX_BUF[USART1_RX_STA&0X3FFF]=r ;USART1_RX_STA++;if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ	  }		 }}   		} } 	 

usart.h

#ifndef __usart_H
#define __usart_H#include "system.h" 
#include "stdio.h" #define USART1_PRINTF#define USART1_REC_LEN  			200  	//¶¨Òå×î´ó½ÓÊÕ×Ö½ÚÊý 200
#define EN_USART1_RX 			1		//ʹÄÜ£¨1£©/½ûÖ¹£¨0£©´®¿Ú1½ÓÊÕextern u8  USART1_RX_BUF[USART1_REC_LEN]; //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.Ä©×Ö½ÚΪ»»Ðзû 
extern u16 USART1_RX_STA;         		//½ÓÊÕ״̬±ê¼Ç	void USART1_Init(u32 bound);#endif

 main.c

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"int main()
{u8 sf[10];u16 i=0;u8 t;u8 len;	
// int16_t data1;
// int16_t data2;
// int16_t data3;
// int16_t data4;SysTick_Init(72);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //ÖжÏÓÅÏȼ¶·Ö×é ·Ö2×éLED_Init();USART1_Init(9600);while(1){if(USART1_RX_STA&0x8000){					   len=USART1_RX_STA&0x3fff;//µÃµ½´Ë´Î½ÓÊÕµ½µÄÊý¾Ý³¤¶Èprintf("\r\nÄú·¢Ë͵ÄÏûϢΪ: ");for(t=0;t<len;t++){sf[t]=USART1_RX_BUF[t];
//				USART_SendData(USART1, USART1_RX_BUF[t]);         //Ïò´®¿Ú1·¢ËÍÊý¾Ý
//				while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//µÈ´ý·¢ËͽáÊø}if(sf[3]=4){led1=0;}printf("%c",sf[0]);printf("\r\n");//²åÈë»»ÐÐUSART1_RX_STA=0;}
//		else 
//		{
//			
//		i++;
//		if(i%200==0)
//		{
//			led1=!led1;
//		}
//		if(i%200==0)
//		{
//			printf("521.521.521.521.521.\r\n");
//		}
//		delay_ms(10);
//	}
}
}


http://www.ppmy.cn/news/813387.html

相关文章

【STM32训练—SIM900A模块】第二篇、STM32驱动SIM900A发送中文和英文短信

目录 第一部分、前言 1、准备知识 2、调试目的 3、模块和单片机的接线方式 第二部分、工程代码 1、代码功能描述 2、SIM900A发送英文短信的代码 3、SIM900A发送中文短信的代码 4、main.c文件代码 第三部分、总结 1、效果图片和视频 2、感谢 3、完整的工程代…

STM32 USB声卡 CUBEMX配置 极简配置十分钟解决 STM32+PCM5102A

1.综述 USB声卡无非就是USB将PCM数据给I2S外设或SAI外设通过I2S输出给DAC转为模拟信号后&#xff0c;连接上耳机。 就算名贵的意大利数字界面也不例外。 2.分步 2.1 USB接收音频数据 2.2 将音频数据发送给DAC 3.开工 开工前啰嗦两句&#xff1a; 笔者分别使用了STM32F1…

国际短信发不出去是怎么回事?

越来越多的企业选择出海市场&#xff0c;在拓展国际业务的时候大多都会选择使用国际短信&#xff0c;这就增加了国际短信的使用率。国际短信有专属的短信通道&#xff0c;和普通的短信一样也有营销和应用短信的区分&#xff0c;发送内容的限制也是非常多的&#xff0c;每个国家…

基于Stm32f103针对TM1640驱动数码管

最近&#xff0c;在学习stm32f103芯片的使用&#xff0c;发现单片机很多东西&#xff0c;必须亲力亲为去写一遍才会明白里面的坑&#xff01;第一次写&#xff0c;有问题请大佬指出。 之前学习了一下TM1640芯片&#xff0c;一直没有时间在开发板上实践&#xff0c;直到最近才写…

安卓手机短信发不出去设置方法

安卓手机短信发不出去设置方法 1. 在电话拨号界面输入&#xff1a;*#*#4636#*#*&#xff0c;如图(注意&#xff1a;下图中少一个*)&#xff1a; 2. 然后出现工程界面&#xff1a; 3. 选手机信息&#xff0c;在下面找到SMCC&#xff1a; 4. 这时要注意了&a…

短信发送显示服务器失败,手机短信发不出去怎么办 手机故障解决方法【方法步骤】...

手机短信发不出去怎么办? 短信可以由移动通信终端(手机)始发&#xff0c;也可由移动网络运营商的短信平台服务器始发&#xff0c;还可由与移动运营商短信平台互联的网络业务提供商SP(包括ICP、ISP等)始发。平常我们除了打电话就会使用到短信&#xff0c;如果短信发不出去就糟糕…

【STM32训练—SIM900A模块】第一篇、电脑的串口助手驱动SIM900A发送中文和英文短信

目录 第一部分、关于SIM900A的基本知识 1、SIM900A的通信方式 2、SIM900A的供电方式 3、常用指令的含义 第二部分、利用电脑串口助手实现SIM900A发送英文和中文短信 一、发送英文短信 1、发送SIM卡检测指令和信号质量检测指令 2、发送英文短信指令 3、我手机上面显示…

7-2 九牛一毛

7-2 九牛一毛 分数 5 全屏浏览题目 切换布局 作者 陈越 单位 浙江大学 这是一道脑筋急转弯题&#xff1a;猪肉一斤 15 元&#xff0c;鸡肉一斤 20 元&#xff0c;那么一毛钱能买多少头牛&#xff1f; 答案是&#xff1a;9 —— 因为“九牛一毛”。 本题就请你按照这个逻辑…