STM32 MPU6050 源码

MPU6050型号

商家描述:此六轴模块采用先进的数字滤波技术,能有效降低测量噪声,提高测量精度。模块内部集成了运动引擎DMP,获取四元数得到当前姿态。姿态测量精度0.01度,稳定性极高,性能甚至优于某些专业的倾角仪!此六轴模块采用高精度的陀螺加速度计 MPU6050,通过处理器读取 MPU6050 的测量数据然后通过串口输出,免去了用户自己去开发MPU6050 复杂的 I2C 协议,同时精心的 PCB 布局和工艺保证了 MPU6050 收到外接的干扰最小,测量的精度最高。

模块发送至上位机每帧数据分为 3 个数据包,分别为加速度包,角速度包和角度包,3个数据包顺序输出。波特率 115200 时每隔 10ms 输出 1 帧数据,波特率 9600 时每隔 50ms 输出一帧数据。

通信协议:电平:TTL 电平,波特率:115200/9600,停止位 1,校验位 0。

源码分析

整体流程是:初始化,然后反复通过串口接收数据,取走数据。(因为不改写模块的配置,所以不考虑向模块发送数据部分)

初始化:配置系统时钟、初始化IO口、中断优先级初始化、初始化串口、初始化延时函数

配置系统时钟

//配置系统时钟
void RCC_Configuration(void)
{
	ErrorStatus HSEStartUpStatus;                    //定义外部高速晶体启动状态枚举变量

	RCC_DeInit();                                    //复位RCC外部设备寄存器到默认值
	RCC_HSEConfig(RCC_HSE_ON);                       //打开外部高速晶振
	HSEStartUpStatus = RCC_WaitForHSEStartUp();      //等待外部高速时钟准备好
	if(HSEStartUpStatus == SUCCESS)                  //外部高速时钟已经准别好
	{
		FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //开启FLASH预读缓冲功能,加速FLASH的读取。所有程序中必须的用法.位置:RCC初始化子函数里面,时钟起振之后
		FLASH_SetLatency(FLASH_Latency_2);                    //flash操作的延时
			
		RCC_HCLKConfig(RCC_SYSCLK_Div1);               //配置AHB(HCLK)时钟等于==SYSCLK
		RCC_PCLK2Config(RCC_HCLK_Div1);                //配置APB2(PCLK2)钟==AHB时钟
		RCC_PCLK1Config(RCC_HCLK_Div2);                //配置APB1(PCLK1)钟==AHB1/2时钟
			 
		RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  //配置PLL时钟 == 外部高速晶体时钟 * 9 = 72MHz
		RCC_PLLCmd(ENABLE);                                   //使能PLL时钟
   
		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)    //等待PLL时钟就绪
		{
		}
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);            //配置系统时钟 = PLL时钟
		while(RCC_GetSYSCLKSource() != 0x08)                  //检查PLL时钟是否作为系统时钟
		{
		}
	}
}

初始化IO口


//IO口配置
//用法:用哪个打开那个
void GPIO_Configuration(void)
{
	GPIO_InitTypeDef   GPIO_InitStructure;   //定义名为GPIO_InitStructure的结构体类型变量

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  //打开GPIOB的时钟,并使能。
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);  //打开GPIOC的时钟,并使能。
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);  //打开GPIOD的时钟,并使能。
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //打开GPIOA的时钟,并使能。
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD, ENABLE);  //打开GPIOB和GPIOD的时钟,并使能。
	//配置PD10口:
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_9;              //选定哪个IO口 现选定PD9口和PD10口
//	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;                       //设定IO口的模式为上拉输入
//	//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	                 //如果IO口的模式是输入,GPIO_Speed可以不赋值
//	GPIO_Init(GPIOD, &GPIO_InitStructure);	/* PC6 */                    //初始化GPIOD

	//配置PA口:
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;              //选定哪个IO口 现选定PA0口和PA1口
//	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		             //设定IO口的模式为推挽输出
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;	                 //设定IO口的输出速度为2MHz
//	GPIO_Init(GPIOA, &GPIO_InitStructure);	/* PC6 */                    //初始化GPIOD
	
	//配置PD口:
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;              //选定哪个IO口 现选定PD0123口
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		             //设定IO口的模式为推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	                 //设定IO口的输出速度为50MHz
	GPIO_Init(GPIOD, &GPIO_InitStructure);	                             //初始化GPIOD

	//配置PD口:
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;              //选定哪个IO口 现选定PD2口
//	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		             //设定IO口的模式为推挽输出
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;	                 //设定IO口的输出速度为2MHz
//	GPIO_Init(GPIOD, &GPIO_InitStructure);	/* PC6 */                    //初始化GPIOD

	//配置3个LED灯:PB12、PB13、PB14:
	GPIO_SetBits(GPIOB,  GPIO_Pin_0 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14);	         //关闭3个LED灯:PB12、PB13、PB14,输出高电平
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;	             //选定PB12、PB13、PB14
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		             //设定IO口的模式为推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;		             //设定IO口的输出速度为2MHz
	GPIO_Init(GPIOB, &GPIO_InitStructure);					             //初始化GPIOB
}

中断优先级初始化

//中断IO口配置
//用法:用哪个打开那个
void EXTI_Configuration(void)
{
	EXTI_InitTypeDef EXTI_InitStructure;						   //定义一个结构体变量

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 		   //打开APB2总线复用时钟
	
	//外部中断线10配置:
	EXTI_ClearITPendingBit(EXTI_Line10);						   //清除中断挂起位 外部中断线10
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;		       //选择是中断触发还是事件触发,现在选择的是中断触发
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;	       //触发方式:现在选择的是下降沿触发
	EXTI_InitStructure.EXTI_Line = EXTI_Line10;				       //选择哪个IO口作为中断输入,现在选择的是PD10口
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;					   //使能中断
	EXTI_Init(&EXTI_InitStructure);							       //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource10);   //选择GPIO管脚作为外部中断线路
	//外部中断线9配置:
	EXTI_ClearITPendingBit(EXTI_Line9);						       //清除中断挂起位 外部中断线9
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;		       //选择是中断触发还是事件触发,现在选择的是中断触发
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;	       //触发方式:现在选择的是下降沿触发
	EXTI_InitStructure.EXTI_Line = EXTI_Line9;				       //选择哪个IO口作为中断输入,现在选择的是PD9口
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;					   //使能中断
	EXTI_Init(&EXTI_InitStructure);							       //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource9);    //选择GPIO管脚作为外部中断线路
}

中断优先级管理

//中断优先级配置
//用法:用哪个打开那个
void NVIC_Configuration(void)
{
	NVIC_InitTypeDef    NVIC_InitStructure; 					   //定义用于配置中断的结构体变量

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                //中断优先级分组  抢占式优先级别设置为2位;响应优先级占2位
	
	//外部中断线10优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;           //指定中断源
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	   //抢占优先级1
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;             //指定响应优先级别1
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	               //使能外部中断通道
//	NVIC_Init(&NVIC_InitStructure);							       //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
	//外部中断线9优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;             //指定中断源  
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	   //抢占优先级 暂时没有
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;             //指定响应优先级别2
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	               //使能外部中断通道
//	NVIC_Init(&NVIC_InitStructure);							       //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
	//串口1中断优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;              //通道设置为串口1中断  
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	   //抢占优先级1
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;             //指定响应优先级别1
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	               //打开中断
//	NVIC_Init(&NVIC_InitStructure);							       //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
	//串口1用DMA接收中断优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;       //通道设置为串口DMA通道4中断  
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	   //抢占优先级1
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;             //指定响应优先级别1
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	               //打开中断
//	NVIC_Init(&NVIC_InitStructure);							       //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
	//串口2中断优先级设置(RS485)
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;			   //指定中断源
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	   //抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;             //指定响应优先级别1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	               //打开中断
	NVIC_Init(&NVIC_InitStructure);							       //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	//串口3中断优先级设置(RS485)
//	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;			   //指定中断源
//  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	   //抢占优先级1
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;             //指定响应优先级别1
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	               //打开中断
//	NVIC_Init(&NVIC_InitStructure);							       //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

//	//串口1用DMA接收优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;       //DMA1通道5中断 
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	   //抢占优先级1
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;             //指定响应优先级别1
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	               //打开中断
//	NVIC_Init(&NVIC_InitStructure);							       //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

//	//串口4中断优先级设置(RS485)
//	NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;			   //指定中断源
//  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	   //抢占优先级1
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;             //指定响应优先级别1
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	               //打开中断
//	NVIC_Init(&NVIC_InitStructure);							       //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

//	//串口5中断优先级设置(RS485)
//	NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;			   //指定中断源
//  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	   //抢占优先级1
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;             //指定响应优先级别1
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	               //打开中断
//	NVIC_Init(&NVIC_InitStructure);							       //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	
	//通用定时器2中断优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM2中断
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级1级
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级3级
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
//	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器	
	
	//通用定时器3中断优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级1级
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //从优先级3级
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
//	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
	
	//通用定时器4中断优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM4中断
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级1级
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级3级
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
//	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器	
	
	//通用定时器5中断优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;  //TIM5中断
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级1级
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级3级
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
//	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器	
	
	//通用定时器6中断优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;  //TIM6中断
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级1级
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级3级
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
//	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器	
	
	//通用定时器7中断优先级设置
//	NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;  //TIM7中断
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //抢占优先级1级
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级3级
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
//	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器					 
}

串口初始化

//串口1初始化
void USART1_Config(void)		//初始化 配置USART1
{
	GPIO_InitTypeDef     GPIO_InitStructure;   //串口端口配置结构体变量
	USART_InitTypeDef    USART_InitStructure;  //串口参数配置结构体变量

	//第1步:打开GPIO和USART部件的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);	 //打开GPIOA时钟和GPIOA复用时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	//打开串口复用时钟
	USART_DeInit(USART1);  //复位串口1

	//第2步:将USART1 Tx(发送脚)的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;			   //串口1发送脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		   //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	   //输出速度50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);				   //初始化GPIOA
														  
	//第3步:将USART Rx(接收脚)的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;			   //串口1接收脚
	//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空输入
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//上拉输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);				   //初始化GPIOA

	//第4步:配置USART1参数
	USART_InitStructure.USART_BaudRate             = 115200;							 //波特率设置:115200
	USART_InitStructure.USART_WordLength           = USART_WordLength_8b;			 //数据位数设置:8位
	USART_InitStructure.USART_StopBits             = USART_StopBits_1;				 //停止位设置: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);										 //初始化USART1

    //打开发送中断和接收中断(如果需要中断)
	//USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  // 使能指定的USART1发送中断 ;
  	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 使能指定的USART1接收中断 ;

	//第5步:使能 USART1, 配置完毕
	USART_Cmd(USART1, ENABLE);							   //使能 USART1

    //如下语句解决第1个字节无法正确发送出去的问题
    USART_ClearFlag(USART1, USART_FLAG_TC);                //清串口1发送标志	
}


//串口2初始化
void USART2_Config(void)   //初始化 配置USART2
{
	GPIO_InitTypeDef    GPIO_InitStructure;	   //串口端口配置结构体变量
	USART_InitTypeDef   USART_InitStructure;   //串口参数配置结构体变量

	//使能 USART2 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);	//打开串口复用时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);   //打开PA端口时钟

	//将USART2 Tx(发送脚)的GPIO配置为推挽复用模式   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;				  //选定哪个IO口 现选定PA2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;           //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		  //设定IO口的输出速度为50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);    				  //初始化GPIOA

	//将USART2 Rx(接收脚)的GPIO配置为浮空输入模式														  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;				  //选定哪个IO口 现选定PA3
	//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	  //浮空输入
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//上拉输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);                    //初始化GPIOA
	  
	//配置USART2参数
	USART_InitStructure.USART_BaudRate = 115200;	                    //波特率设置:115200
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	    //数据位数设置:8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1; 	        //停止位设置: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);                       //初始化USART2
	
	//打开发送中断和接收中断(如果需要中断)
	//USART_ITConfig(USART2, USART_IT_TXE, ENABLE);  // 使能指定的USART2发送中断
  	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 使能指定的USART2接收中断

	//使能 USART2, 配置完毕
	USART_Cmd(USART2, ENABLE);                             // USART2使能

	//如下语句解决第1个字节无法正确发送出去的问题
    USART_ClearFlag(USART2, USART_FLAG_TC);                //清串口2发送标志
}

//串口3初始化
void USART3_Config(void)   //初始化 配置USART3
{
	GPIO_InitTypeDef GPIO_InitStructure;	  //串口端口配置结构体变量
	USART_InitTypeDef USART_InitStructure;	  //串口参数配置结构体变量

	//使能 USART3 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);	//打开串口复用时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   //打开PB端口时钟
  	
	//将USART3 Tx(发送脚)的GPIO配置为推挽复用模式   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;				  //选定哪个IO口 现选定PB10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;           //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		  //设定IO口的输出速度为50MHz
	GPIO_Init(GPIOB, &GPIO_InitStructure);    				  //初始化GPIOB
	
	//将USART3 Rx(接收脚)的GPIO配置为浮空输入模式														  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;				  //选定哪个IO口 现选定PB11
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	  //浮空输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);                    //初始化GPIOA
	  
	//配置USART3参数
	USART_InitStructure.USART_BaudRate = 2400;	                    //波特率设置:2400
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	    //数据位数设置:8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1; 	        //停止位设置: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(USART3, &USART_InitStructure);                       //初始化USART3
	
    //打开发送中断和接收中断(如果需要中断)
	//USART_ITConfig(USART3, USART_IT_TXE, ENABLE);  // 使能指定的USART3发送中断
  	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 使能指定的USART3接收中断

	//使能 USART3, 配置完毕
	USART_Cmd(USART3, ENABLE);                             // USART3使能

	//如下语句解决第1个字节无法正确发送出去的问题
    USART_ClearFlag(USART3, USART_FLAG_TC);                //清串口3发送标志
}

//串口4初始化
void UART4_Config(void)   //初始化 配置USART4
{
	GPIO_InitTypeDef GPIO_InitStructure;	   //串口端口配置结构体变量
	USART_InitTypeDef USART_InitStructure;	   //串口参数配置结构体变量

	//使能 UART4 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);	//打开串口复用时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);   //打开PC端口时钟
	
	//将USART4 Tx(发送脚)的GPIO配置为推挽复用模式   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;				  //选定哪个IO口 现选定PC10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;           //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		  //设定IO口的输出速度为50MHz
	GPIO_Init(GPIOC, &GPIO_InitStructure);    				  //初始化GPIOC

	//将UART4 Rx(接收脚)的GPIO配置为浮空输入模式														  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;				  //选定哪个IO口 现选定PC11
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	  //浮空输入
	GPIO_Init(GPIOC, &GPIO_InitStructure);                    //初始化GPIOC
	  
	//配置UART4参数
	USART_InitStructure.USART_BaudRate = 2400;	                    //波特率设置:2400
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	    //数据位数设置:8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1; 	        //停止位设置: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(UART4, &USART_InitStructure);                       //初始化UART4
	
	//打开发送中断和接收中断(如果需要中断)
	//USART_ITConfig(UART4, USART_IT_TXE, ENABLE);  // 使能指定的UART4发送中断
  	USART_ITConfig(UART4, USART_IT_RXNE, ENABLE); // 使能指定的UART4接收中断

	//使能 UART4, 配置完毕
	USART_Cmd(UART4, ENABLE);                             // UART4使能

	//如下语句解决第1个字节无法正确发送出去的问题
    USART_ClearFlag(UART4, USART_FLAG_TC);                //清串口4发送标志
}

//串口5初始化
void UART5_Config(void)   //初始化 配置UART5
{
	GPIO_InitTypeDef GPIO_InitStructure;		//串口端口配置结构体变量
	USART_InitTypeDef USART_InitStructure;		//串口参数配置结构体变量

	//使能 UART5 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);	//打开串口复用时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);   //打开PC端口时钟
	
	//将UART5 Tx(发送脚)的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;				  //选定哪个IO口 现选定PC12
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;           //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		  //设定IO口的输出速度为50MHz
	GPIO_Init(GPIOC, &GPIO_InitStructure);    				  //初始化GPIOC

	//将UART5 Rx(接收脚)的GPIO配置为浮空输入模式															  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;				  //选定哪个IO口 现选定PD2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	  //浮空输入
	GPIO_Init(GPIOD, &GPIO_InitStructure);                    //初始化GPIOC
	  
	//配置UART5参数
	USART_InitStructure.USART_BaudRate = 2400;	                    //波特率设置:2400
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	    //数据位数设置:8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1; 	        //停止位设置: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(UART5, &USART_InitStructure);                       //初始化UART5

	//打开发送中断和接收中断(如果需要中断)
	//USART_ITConfig(UART5, USART_IT_TXE, ENABLE);  // 使能指定的UART4发送中断
  	USART_ITConfig(UART5, USART_IT_RXNE, ENABLE); // 使能指定的UART4接收中断

	//使能 UART5, 配置完毕
	USART_Cmd(UART5, ENABLE);                             // UART5使能

	//如下语句解决第1个字节无法正确发送出去的问题 */
    USART_ClearFlag(UART5, USART_FLAG_TC);                //清串口5发送标志
}

反复接收串口2数据

void USART2_IRQHandler(void){
   if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断有效,若接收数据寄存器满
     {
      Temp[counter] = USART_ReceiveData(USART2);   //接收数据
      //网购给的程序
      //if(counter == 0 && Re_buf[0] != 0x55) return;      //第 0 号数据不是帧头,跳过
	  if(counter == 0 && Temp[0] != 0x55) return;      //第 0 号数据不是帧头,跳过
      counter++; 
      if(counter==11) //接收到 11 个数据
      { 
         memcpy(Re_buf,Temp,11);
         counter=0; //重新赋值,准备下一帧数据的接收
         sign=1;//缓冲区Re_buf是否有数据标志
      }    
   }
}

反复查询缓冲区是否存在数据,存在并取走

   while (1)
   {
      if(sign)
      {  
         memcpy(Temp,Re_buf,11);
         sign=0;
         if(Re_buf[0]==0x55)       //检查帧头
         {  
            switch(Re_buf[1])
            {
               case 0x51: //标识这个包是加速度包
                  a[0] = ((short)(Temp[3]<<8 | Temp[2]))/32768.0*16;      //X轴加速度
                  a[1] = ((short)(Temp[5]<<8 | Temp[4]))/32768.0*16;      //Y轴加速度
                  a[2] = ((short)(Temp[7]<<8 | Temp[6]))/32768.0*16;      //Z轴加速度
                  T    = ((short)(Temp[9]<<8 | Temp[8]))/340.0+36.25;      //温度
                  break;
               case 0x52: //标识这个包是角速度包
                  w[0] = ((short)(Temp[3]<<8| Temp[2]))/32768.0*2000;      //X轴角速度
                  w[1] = ((short)(Temp[5]<<8| Temp[4]))/32768.0*2000;      //Y轴角速度
                  w[2] = ((short)(Temp[7]<<8| Temp[6]))/32768.0*2000;      //Z轴角速度
                  T    = ((short)(Temp[9]<<8| Temp[8]))/340.0+36.25;      //温度
                  break;
               case 0x53: //标识这个包是角度包
                  angle[0] = ((short)(Temp[3]<<8| Temp[2]))/32768.0*180;   //X轴滚转角(x 轴)
                  angle[1] = ((short)(Temp[5]<<8| Temp[4]))/32768.0*180;   //Y轴俯仰角(y 轴)
                  angle[2] = ((short)(Temp[7]<<8| Temp[6]))/32768.0*180;   //Z轴偏航角(z 轴)
                  T        = ((short)(Temp[9]<<8| Temp[8]))/340.0+36.25;   //温度

                  //printf("X轴角度:%.2f   Y轴角度:%.2f   Z轴角度:%.2f\r\n",angle[0],angle[1],angle[2]);
                  break;
               default:  break;
            }
			printf("X角度:%.2f  Y角度:%.2f  Z角度:%.2f  X速度:%.2f  Y速度:%.2f  Z速度:%.2f\r\n",angle[0],angle[1],angle[2],w[0],w[1],w[2]);
         }
         
      }
      delay_ms(50);
   }
}


posted @ 2018-05-18 09:32  灰太狼的喜羊羊  阅读(3792)  评论(0编辑  收藏  举报