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();
}
}
}