32f4,usart2fifo,2025

发布于:2025-04-04 ⋅ 阅读:(38) ⋅ 点赞:(0)

usart2fifo.h

#ifndef __USART2FIFO_H
#define __USART2FIFO_H

#include "stdio.h"	
#include "stm32f4xx_conf.h"
#include "sys.h" 
#include "fifo_usart2.h"


//extern u8 RXD2_TimeOut;//超时检测

//extern u8 Timer6_1ms_flag;


extern __IO bool Usart2_rxFrameFlag ;
extern __IO uint8_t Usart2_rxCmd[USART2_FIFO_SIZE] ;
extern __IO uint8_t Usart2_rxCount ;
//********************************************************************************
#define USART2_REC_LEN  			   256  	     //定义最大接收字节数 200
#define DIY_END_CODE_Before      0x0D  //每次发送的帧尾\n
#define DIY_END_CODE             0x0A  //每次发送的帧尾\n


extern u8  USART2_RX_BUF[USART2_FIFO_SIZE]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16   USART2_RX_STA;         		//接收状态标记	

extern  u16    USART2_Rec_Byte_Length;//接收长度,最大是200,在接收数组空间范围内?
extern  u8     USART2_Rec_Frame_Flag;//接收完整一帧标记=0,没接收完,=1接收完

void uart2_init(u32 baudRate);//设置串口1的波特率,以及初始化
void Clear_Uart2_RecBuf(void);//清空接收缓冲区
u8 Judge_Usart2_Response(char* fmt,...);//判断串口1接受到的字符串,比对
//if(Judge_Usart1_Response("OK"))只要存在OK连续两个就行,分大小写
//uyyOKoo
//https://www.cnblogs.com/zhanxiaohong0303/p/zz_2020_10_1.html
//将按照指定格式接收的数据赋值
u8 Get_Usart2_Data(int *x,float *y);
u8 Get_Usart2_Data2(float *x,float *y);

u8 Get_Usart2_S1(float *x);//旋转舵机
u8 Get_Usart2_S2(float *x);//爪子舵机
u8 Get_Usart2_S7(float *x);//步进电机

#endif



usart2fifo.c

#include "sys.h"
#include "usart2FIFO.h"	
#include "led.h"	
#include "stdlib.h"
#include "stdarg.h"
#include "stdio.h"
 	
#include "fifo_usart2.h"


__IO bool Usart2_rxFrameFlag = false;
__IO uint8_t Usart2_rxCmd[USART2_FIFO_SIZE] = {0};
__IO uint8_t Usart2_rxCount = 0;


//u8 RXD2_TimeOut=0;//超时检测
//u8 Timer6_1ms_flag=0;
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART2_RX_BUF[USART2_FIFO_SIZE];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART2_RX_STA=0;       //接收状态标记	
u16 USART2_Rec_Byte_Length=0;//接收长度,最大是200,在接收数组空间范围内?
u8  USART2_Rec_Frame_Flag=0;//接收完整一帧标记
			
			
			
			
			
			
			
//初始化IO 串口1 
//bound:波特率
void uart2_init(u32 baudRate)
{
   //GPIO端口设置
  GPIO_InitTypeDef     GPIO_InitStructure;
	USART_InitTypeDef    USART_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); //使能GPIOD时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART1时钟
 
	//串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_USART2); //GPIO5复用为USART2
GPIO_PinAFConfig(GPIOD,GPIO_PinSource6,GPIO_AF_USART2); //GPIO6复用为USART2
	
	//USART1端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6; //GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOD,&GPIO_InitStructure); //初始化PA9,PA10

   //USART1 初始化设置
	USART_InitStructure.USART_BaudRate = baudRate;//波特率设置
	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(USART2, &USART_InitStructure); //初始化串口2
	
	
	  USART_ClearFlag(USART2, USART_FLAG_TC);
		USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启相关中断,接收一个字节,就发生中断
	
	   USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//开启空闲中断
	   USART_ITConfig(USART2, USART_IT_ORE_RX, ENABLE);//开启空闲中断

		  USART_Cmd(USART2, ENABLE);  //使能串口2

}

void USART2_IRQHandler(void)                	//串口2中断服务程序
{
		__IO uint16_t i = 0;

	//接收中断(接收到的数据必须是0x0a结尾)
	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  
	{
				// 未完成一帧数据接收,数据进入缓冲队列
				usart2_fifo_enQueue((uint8_t)USART2->DR);

				// 清除串口接收中断
				USART_ClearITPendingBit(USART2, USART_IT_RXNE);
	}
		
	
/**********************************************************
***	串口空闲中断
**********************************************************/
	else if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
	{
		// 先读SR再读DR,清除IDLE中断
		USART2->SR; USART2->DR;

		// 提取一帧数据命令
		Usart2_rxCount = usart2_fifo_queueLength(); //获取数据长度
   for(i=0; i < Usart2_rxCount; i++) 
   { 
	    Usart2_rxCmd[i] = usart2_fifo_deQueue();//拆解数据
			//printf("response data=%x\r\n",Usart2_rxCmd[i]);
	 }
	 
		// 一帧数据接收完成,置位帧标志位
		Usart2_rxFrameFlag = true;
	}

//溢出中断
  else if(USART_GetITStatus(USART2,USART_IT_ORE))
	{
			  USART_ClearFlag(USART2, USART_FLAG_ORE);
		USART_ReceiveData(USART2);
	}		
} 




void Clear_Uart2_RecBuf(void)//清空接收缓冲区
{
	u16 i;

	for(i=0;i<USART2_FIFO_SIZE;i++)
	{
		Usart2_rxCmd[i]=0;
	}
	USART2_Rec_Byte_Length=0;
	Usart2_rxFrameFlag=0;
}

//#include "stdlib.h"
//#include "stdarg.h"
//#include "stdio.h"  
//#include "string.h"  //str函数
//带不定长度参数的函数if(Judge_Usart1_Response("OK9999"))
u8 Judge_Usart2_Response(char* fmt,...)
{
	char p[USART2_FIFO_SIZE];
	va_list ap;
	//如果串口1没接收到一帧数据,那么返回0,结束本函数
	if(!Usart2_rxFrameFlag) return 0;
  //如果接收到一帧数据,到下面将需要判断的数据数据复制到p数组中
	va_start(ap,fmt);
	vsprintf((char*)p,fmt,ap);
	va_end(ap); //结束ap指针,必须结束
	//用strstr函数,将接收到的字符串和我们的数据进行对比,如果没有相等的那么返回0并结束函数,否则返回1说明判断有效
	if(strstr((char*)Usart2_rxCmd,p)==NULL) return 0;
	else return 1;
}


//获取指定格式字符串的部分数据
u8 Get_Usart2_Data(int *x,float *y)
{
	int xtemp;
	float ytemp;
	
	if(!Usart2_rxFrameFlag) return 0;
	//x=125,y=25.65\r\n
	sscanf((const char *)Usart2_rxCmd,"x1=%d,y=%f",&xtemp,&ytemp);
	*x=(int)xtemp;
	*y=(float)ytemp;
	return 1;
}

//获取指定格式字符串的部分数据
u8 Get_Usart2_Data2(float *x,float *y)
{
	float  xtemp;
	float ytemp;
	
	if(!Usart2_rxFrameFlag) return 0;
	//x=125,y=25.65\r\n
	if(Usart2_rxCmd[0]=='x' && Usart2_rxCmd[1]=='2')
	{
		sscanf((const char *)Usart2_rxCmd,"x2=%f,y=%f",&xtemp,&ytemp);
		*x=(float)xtemp;
		*y=(float)ytemp;
		return 1;
	}
	else return 0;

}
//https://www.cnblogs.com/zhanxiaohong0303/p/zz_2020_10_1.html

//获取指定格式字符串的部分数据
u8 Get_Usart2_S1(float *x)
{
	float xtemp;
//	if(!USART2_Rec_Frame_Flag) return 0;
	if(Usart2_rxCmd[0]=='t'&&Usart2_rxCmd[1]=='2')
	{
		sscanf((const char *)Usart2_rxCmd,"t2=%f",&xtemp);
		*x=(float)xtemp;	
		return 1;
	}
	else	return 0;
}
u8 Get_Usart2_S2(float *x)
{
	float xtemp;
	
//	if(!USART2_Rec_Frame_Flag) return 0;
	if(Usart2_rxCmd[0]=='t'&&Usart2_rxCmd[1]=='3')
	{
		sscanf((const char *)Usart2_rxCmd,"t3=%f",&xtemp);
		*x=(float)xtemp;
		return 1;
	}
	else	return 0;

}

u8 Get_Usart2_S7(float *x)
{
	float xtemp;
	if(Usart2_rxCmd[0]=='t'&&Usart2_rxCmd[1]=='7')
	{
			sscanf((const char *)Usart2_rxCmd,"t7=%f",&xtemp);
		*x=(float)xtemp;
		return 1;
	}
	else	return 0;
//	if(!USART2_Rec_Frame_Flag) return 0;

}
//*******************************
//int main(void)
//{ 
// 
//	u8 t;
//	u8 len;	
//	u16 times=0;  
//	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
//	delay_init(168);		//延时初始化 
//	uart_init(115200);	//串口初始化波特率为115200
//	LED_Init();		  		//初始化与LED连接的硬件接口  
//	while(1)
//	{
//		if(USART_RX_STA&0x8000)
//		{					   
//			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
//			printf("\r\n您发送的消息为:\r\n");
//			for(t=0;t<len;t++)
//			{
//				USART_SendData(USART1, USART_RX_BUF[t]);         //向串口1发送数据
//				while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
//			}
//			printf("\r\n\r\n");//插入换行
//			USART_RX_STA=0;
//		}else
//		{
//			times++;
//			if(times%5000==0)
//			{
//				printf("\r\nALIENTEK 探索者STM32F407开发板 串口实验\r\n");
//				printf("正点原子@ALIENTEK\r\n\r\n\r\n");
//			}
//			if(times%200==0)printf("请输入数据,以回车键结束\r\n");  
//			if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
//			delay_ms(10);   
//		}
//	}
//}


 
//void Clear_Openmv_Rxbuff(void)
//{
//	u8 *p,i;
//	p=openmv_rx_data;
//	for(i=0;i<Rx_Length;i++)
//	{
//		*p++=0;
//	}
//	length=0;
//	rx_flag=0;
//}

//u8 Judge_Openmv_Response(char* fmt,...)
//{
//	char p[30];
//	if(!rx_flag) return 0;
//	va_list ap;
//	va_start(ap,fmt);
//	vsprintf((char*)p,fmt,ap);
//	va_end(ap); 
//	if(strstr((char*)openmv_rx_data,p)==NULL) return 0;
//	else return 1;
//}

//		if(Judge_Openmv_Response("OK"))
//		{
//			Clear_Openmv_Rxbuff();
//			LCD_ShowString(0,16,"OK");
//		}


fifo_usart2.h

#ifndef __FIFO_USART2_H
#define __FIFO_USART2_H

#include "sys.h"
#include "stdbool.h"

/**********************************************************

**********************************************************/

#define 	USART2_FIFO_SIZE   128


typedef struct {
	uint16_t buffer[USART2_FIFO_SIZE];
	__IO uint8_t ptrWrite;
	__IO uint8_t ptrRead;
}USART2_FIFO_t;

extern __IO USART2_FIFO_t rx2FIFO;

void     usart2_fifo_initQueue(void);
void     usart2_fifo_enQueue(uint16_t data);
uint16_t usart2_fifo_deQueue(void);
bool     usart2_fifo_isEmpty(void);//bool需要添加stdbool.h头文件
uint16_t usart2_fifo_queueLength(void);

#endif

fifo_usart2.c

#include "fifo_usart2.h"

/**********************************************************
**********************************************************/

__IO USART2_FIFO_t rx2FIFO = {0};

/**
	* @brief   初始化队列
	* @param   无
	* @retval  无
	*/
void usart2_fifo_initQueue(void)
{
	rx2FIFO.ptrRead  = 0;
	rx2FIFO.ptrWrite = 0;
}

/**
	* @brief   入队
	* @param   无
	* @retval  无
	*/
void usart2_fifo_enQueue(uint16_t data)
{
	rx2FIFO.buffer[rx2FIFO.ptrWrite] = data;
	
	++rx2FIFO.ptrWrite;
	
	if(rx2FIFO.ptrWrite >= USART2_FIFO_SIZE)
	{
		rx2FIFO.ptrWrite = 0;
	}
}

/**
	* @brief   出队
	* @param   无
	* @retval  无
	*/
uint16_t usart2_fifo_deQueue(void)
{
	uint16_t element = 0;

	element = rx2FIFO.buffer[rx2FIFO.ptrRead];

	++rx2FIFO.ptrRead;

	if(rx2FIFO.ptrRead >= USART2_FIFO_SIZE)
	{
		rx2FIFO.ptrRead = 0;
	}

	return element;
}

/**
	* @brief   判断空队列
	* @param   无
	* @retval  无
	*/
bool usart2_fifo_isEmpty(void)
{
	if(rx2FIFO.ptrRead == rx2FIFO.ptrWrite)
	{
		return true;
	}

	return false;
}

/**
	* @brief   计算队列长度
	* @param   无
	* @retval  无
	*/
uint16_t usart2_fifo_queueLength(void)
{
	if(rx2FIFO.ptrRead <= rx2FIFO.ptrWrite)
	{
		return (rx2FIFO.ptrWrite - rx2FIFO.ptrRead);
	}
	else
	{
		return (USART2_FIFO_SIZE - rx2FIFO.ptrRead + rx2FIFO.ptrWrite);
	}
}

测试main.c

#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
#include "usart2fifo.h"
#include "fifo_usart2.h"

int main(void)
{
	u16 i=0;
	float rotate_angle,grab_angle,stepper_mm;
//	int x;
//	float y;
	
	Nvic_Init(NVIC_PriorityGroup_4);//中断分组第四组 高优先打断低优先
	Set_Nvic_Irq(USART1_IRQn,0,3);//设置串口1的中断等级;
  Delay_Init();//延时函数默认中断优先级是最低的。
	
	
	LED_Init();//LED灯初始化
  BEEP_Init();//蜂鸣器初始化
	
	uart1_init(115200);//设置串口1的波特率是115200
  uart2_init(115200);
	Usart_SendByte(USART1,'a');//测试单字节发送函数
	Usart_SendByte(USART1,'b');//测试单字节发送函数
	
	Usart_SendString(USART1,"tab\r\n");//测试字符串发送函数
	printf("hello world\r\n");//这个也能用,测试printf函数

	printf("LED=1,%d\r\n",i);//这个也能用,测试printf函数
	Printf(USART1,"LED=0,%d\r\n",i);//这个也能用,测试大写的Printf函数

	while(1)
	{
		
  //*********************************************  串口屏HMI命令解析
   //*********************************************
   //*********************************************
   //*********************************************
   //*********************************************

		if(Usart2_rxFrameFlag==true)
		{
		
												{
													
													//将接收的数据通过串口1输出,验证数据
						//			Usart_SendString(USART1,Usart2_rxCmd);
						//			
						//			for(i=0;i<Usart2_rxCount;i++)
						//			{
						//				Usart_SendByte(USART1,Usart2_rxCmd[i]);
						//			}
												Usart_SendByte(USART1,Usart2_rxCmd[Usart2_rxCount-1]);
						//			Usart_SendByte(USART1,Usart2_rxCmd[Usart2_rxCount-2]);
						//			Usart_SendByte(USART1,Usart2_rxCmd[Usart2_rxCount-1]);
												}
								if(Usart2_rxCmd[Usart2_rxCount-1]==0x0a) //如果接收到的最后的数据是约定好的帧尾,最后面的0x0a
								{
									
											printf("0d ok\r\n");

									if(Usart2_rxCmd[Usart2_rxCount-2]==0x0d)  //前一个0x0d
									{
										
										    printf("0d 0a ok\r\n");
									      USART2_Rec_Frame_Flag=1;//接收标记等于1,在哪里清0?在判断里面清0
										
													if(Judge_Usart2_Response("stop"))
													{
														printf("stop\r\n");
//														machine_stop_flag=1;
//														machine_start_flag=0;
														Clear_Uart2_RecBuf();
													}
												else	if(Get_Usart2_S1(&rotate_angle))  //旋转舵机旋转一个角度
													{
													//	Servo1_move(rotate_angle,1200,270);
														printf("rotate_angle=%f\r\n",rotate_angle);
														Clear_Uart2_RecBuf();
													}	
													else	if(Get_Usart2_S2(&grab_angle)) //抓手舵机旋转一个角度
													{
													//	servohandflag =1;
														
														Clear_Uart2_RecBuf();
													}	
													else	if(Get_Usart2_S7(&stepper_mm))  //步进电机运动到绝对坐标,以回0的位置为原点
													{
													//	hmi_stepper_mm_flag=1;
														//move(stepper_mm);
														printf("stepper_mm=%f\r\n",stepper_mm);
														Clear_Uart2_RecBuf();
													}	
 
									
												else Clear_Uart2_RecBuf();
												} 
											}
								
			Usart2_rxCount=0;//长度清零,给下次使用
			Usart2_rxFrameFlag=false;
      Clear_Uart2_RecBuf();
		}


		
	}
}


在这里插入图片描述