STM32—驱动GY85-IMU模块
时间:2023-10-14 16:07:02
GY85是一个惯性测量模块,集成了三轴加速度计、三轴陀螺仪、电子罗盘、气压传感器等芯片,用于测量和报告设备的速度、方向和重力。模块可以整合加速度计、陀螺仪、电子罗盘等传感器的数据。
这里介绍一下STM32驱动GY85代码,模块和STM通信接口为32IIC协议,我们使用软件IO口模拟IIC通信时序,读取每个芯片的数据存储在全局变量中GY85的介绍和一些基本知识可以参考本博客:点击跳转
芯片说明:
- ADXL345:测量三轴加速度计Roll、Pitch(航偏角Yaw无法测量)
- L3G4200D:测量三轴陀螺仪Roll、Pitch、Yaw(用加速度计获得准确温度的三个角度)
- HMC5883L:测量与地磁北极的偏转角度的电子罗盘
- BMP085:气压传感器,测量大气压、温度
以下是所有驱动代码:
/******************************************************************************* * 函数功能:串口2发送数据 HMC5883L ADXL345 BMP085 L3G4200D(串口2在mian初始化完成) * 波特率:115200 * 时间:2020.7.12 * 修改注释:全部 *******************************************************************************/ /*芯片说明 *ADXL345:测量三轴加速度计Roll、Pitch(航偏角Yaw无法测量) *L3G4200D:测量三轴陀螺仪Roll、Pitch、Yaw(用加速度计获得准确温度的三个角度) *HMC5883L:测量与地磁北极的偏转角度的电子罗盘 *BMP085:气压传感器,测量大气压和温度 */ #include "IMU.h" GPIO_InitTypeDef GPIO_InitStructure; ErrorStatus HSEStartUpStatus; #define FALSE 0 #define TRUE 1 #define u8 unsigned char #define u32 unsigned int #define uchar unsigned char #define uint unsigned int #define OSS 0 // BMP085使用 //L3G4200D内部寄存器 #define CTRL_REG1 0x20 #define CTRL_REG2 0x21 #define CTRL_REG3 0x22 #define CTRL_REG4 0x23 #define CTRL_REG5 0x24 #define OUT_X_L 0x28 #define OUT_X_H 0x29 #define OUT_Y_L 0x2A #define OUT_Y_H 0x2B #define OUT_Z_L 0x2C #define OUT_Z_H 0x2D //定义器件在IIC根据总线的地址ALT ADDRESS不同修改地址引脚 #define HMC5883L_Addr 0x3C /// #define ADXL345_Addr 0xA6 ///加速度传感器 #define BMP085_Addr 0xee ///气压传感器地址 #define L3G4200_Addr 0xD2 //陀螺仪传感器地址 unsigned char BUF[8]; //接收数据缓存区,作用是暂时缓存寄存器的值,然后进行算法分析 char test=0; int x,y;
uchar ge,shi,bai,qian,wan,shiwan; //uart,显示变量
short T_X,T_Y,T_Z; //陀螺仪输出数据
float angle; //电子罗盘输出角度,与地磁北极的偏转角度
/* 加速度计ADXL345 数据 */
int A_X,A_Y,A_Z; //加速度计读取的寄存器数据
short data_xyz[3]; //加速度计合成数据
float Q,T,K; //加速度计x、y、z原始数据
float Roll,Pitch; //Roll,Pitch角度
/* BMP085使用的变量 */
short ac1;
short ac2;
short ac3;
unsigned short ac4;
unsigned short ac5;
unsigned short ac6;
short b1;
short b2;
short mb;
short mc;
short md;
long temperature; //温度
long pressure; //气压
//************************************++++++++++++++++++++++++++++++++
/*模拟IIC端口输出输入定义
*SDA:PB9
*SCL:PB8
*/
#define SCL_H GPIOB->BSRR = GPIO_Pin_8
#define SCL_L GPIOB->BRR = GPIO_Pin_8
#define SDA_H GPIOB->BSRR = GPIO_Pin_9
#define SDA_L GPIOB->BRR = GPIO_Pin_9
#define SCL_read GPIOB->IDR & GPIO_Pin_8
#define SDA_read GPIOB->IDR & GPIO_Pin_9
/* 转换数据 */
void conversion(long temp_data)
{
shiwan=temp_data/100000+0x30 ;
temp_data=temp_data%100000; //取余运算
wan=temp_data/10000+0x30 ;
temp_data=temp_data%10000; //取余运算
qian=temp_data/1000+0x30 ;
temp_data=temp_data%1000; //取余运算
bai=temp_data/100+0x30 ;
temp_data=temp_data%100; //取余运算
shi=temp_data/10+0x30 ;
temp_data=temp_data%10; //取余运算
ge=temp_data+0x30;
}
/******************************************************************************* * Function Name : I2C_GPIO_Config * Description : Configration Simulation IIC GPIO * Input : None * Output : None * Return : None ****************************************************************************** */
void I2C_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/******************************************************************************* * Function Name : I2C_delay * Description : Simulation IIC Timing series delay * Input : None * Output : None * Return : None ****************************************************************************** */
void I2C_delay(void)
{
u8 i=30; //这里可以优化速度 ,经测试最低到5还能写入
while(i)
{
i--;
}
}
void delay5ms(void)
{
int i=5000;
while(i)
{
i--;
}
}
/******************************************************************************* * Function Name : I2C_Start * Description : Master Start Simulation IIC Communication * Input : None * Output : None * Return : Wheather Start ****************************************************************************** */
uint8_t I2C_Start(void)
{
SDA_H;
SCL_H;
I2C_delay();
if(!SDA_read)return FALSE; //SDA线为低电平则总线忙,退出
SDA_L;
I2C_delay();
if(SDA_read) return FALSE; //SDA线为高电平则总线出错,退出
SDA_L;
I2C_delay();
return TRUE;
}
/******************************************************************************* * Function Name : I2C_Stop * Description : Master Stop Simulation IIC Communication * Input : None * Output : None * Return : None ****************************************************************************** */
void I2C_Stop(void)
{
SCL_L;
I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SDA_H;
I2C_delay();
}
/******************************************************************************* * Function Name : I2C_Ack * Description : Master Send Acknowledge Single * Input : None * Output : None * Return : None ****************************************************************************** */
void I2C_Ack(void)
{
SCL_L;
I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
/******************************************************************************* * Function Name : I2C_NoAck * Description : Master Send No Acknowledge Single * Input : None * Output : None * Return : None ****************************************************************************** */
void I2C_NoAck(void)
{
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
/******************************************************************************* * Function Name : I2C_WaitAck * Description : Master Reserive Slave Acknowledge Single * Input : None * Output : None * Return : Wheather Reserive Slave Acknowledge Single ****************************************************************************** */
uint8_t I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK
{
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
SCL_L;
I2C_delay();
return FALSE;
}
SCL_L;
I2C_delay();
return TRUE;
}
/******************************************************************************* * Function Name : I2C_SendByte * Description : Master Send a Byte to Slave * Input : Will Send Date * Output : None * Return : None ****************************************************************************** */
void I2C_SendByte(u8 SendByte) //数据从高位到低位//
{
u8 i=8;
while(i--)
{
SCL_L;
I2C_delay();
if(SendByte&0x80)
SDA_H;
else
SDA_L;
SendByte<<=1;
I2C_delay();
SCL_H;
I2C_delay();
}
SCL_L;
}
/******************************************************************************* * Function Name : I2C_RadeByte * Description : Master Reserive a Byte From Slave * Input : None * Output : None * Return : Date From Slave ****************************************************************************** */
unsigned char I2C_RadeByte(void) //数据从高位到低位//
{
u8 i=8;
u8 ReceiveByte=0;
SDA_H;
while(i--)
{
ReceiveByte<<=1;
SCL_L;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
ReceiveByte|=0x01;
}
}
SCL_L;
return ReceiveByte;
}
//ZRX
//单字节写入*******************************************
uint8_t Single_Write(unsigned char SlaveAddress,unsigned char REG_Address,unsigned char REG_data) //void
{
if(!I2C_Start())return FALSE;
I2C_SendByte(SlaveAddress); //发送设备地址+写信号//I2C_SendByte(((REG_Address & 0x0700) >>7) | SlaveAddress & 0xFFFE);//设置高起始地址+器件地址
if(!I2C_WaitAck()){
I2C_Stop(); return FALSE;}
I2C_SendByte(REG_Address ); //设置低起始地址
I2C_WaitAck();
I2C_SendByte(REG_data);
I2C_WaitAck();
I2C_Stop();
delay5ms();
return TRUE;
}
//单字节读取*****************************************
unsigned char Single_Read(unsigned char SlaveAddress,unsigned char REG_Address)
{
unsigned char REG_data;
if(!I2C_Start())return FALSE;
I2C_SendByte(SlaveAddress); //I2C_SendByte(((REG_Address & 0x0700) >>7) | REG_Address & 0xFFFE);//设置高起始地址+器件地址
if(!I2C_WaitAck()){
I2C_Stop();test=1; return FALSE;}
I2C_SendByte((u8) REG_Address); //设置低起始地址
I2C_WaitAck();
I2C_Start();
I2C_SendByte(SlaveAddress+1);
I2C_WaitAck();
REG_data= I2C_RadeByte();
I2C_NoAck();
I2C_Stop();
//return TRUE;
return REG_data;
}
/* ******************************************************************************** ** 函数名称 : Delay(vu32 nCount) ** 函数功能 : 延时函数 ** 输 入 : 无 ** 输 出 : 无 ** 返 回 : 无 ******************************************************************************** */
void Delay(u32 nCount)
{
for(; nCount != 0; nCount--);
}
/* ******************************************************************************** ** 函数名称 : void Delayms(vu32 m) ** 函数功能 : 长延时函数 m=1,延时1ms ** 输 入 : 无 ** 输 出 : 无 ** 返 回 : 无 ******************************************************************************** */
void Delayms(u32 m)
{
u32 i;
for(; m != 0; m--)
for (i=0; i<50000; i++);
}
//************************************************
void USART2_SendData(unsigned char SendData)
{
USART_SendData(USART2, SendData);
Delayms(1);
}
//********************************************************************
long bmp085ReadTemp(void)
{
short temp_ut;
Single_Write(BMP085_Addr,0xF4,0x2E);
Delayms(5); // max time is 4.5ms
temp_ut = Single_Read(BMP085_Addr,0xF6);
temp_ut = (temp_ut<<8)| Single_Read(BMP085_Addr,0xF7);
return (long) temp_ut ;
}
//*************************************************************
long bmp085ReadPressure(void)
{
long pressure = 0;
Single_Write(BMP085_Addr,0xF4,0x34);
Delayms(5); // max time is 4.5ms
pressure = Single_Read(BMP085_Addr,0xF6);
pressure = (pressure<<8)| Single_Read(BMP085_Addr,0xF7);
pressure &= 0x0000FFFF;
return pressure;
}
//******************
void Send_ADXL345_data(int dis_data)
{
float temp ;
if(dis_data>0x7fff)dis_data-=0xffff;
if(dis_data<0){
dis_data=-dis_data;
USART_SendData(USART1,'-');
Delayms(2);
}
else
{
USART_SendData(USART1,'+');
Delayms(2);
}
temp=(float)dis_data*3.9; //计算数据和显示,查考ADXL345快速入门第4页
conversion(temp); //转换出显示需要的数据
USART2_SendData(qian);
USART2_SendData('.');
USART2_SendData(bai);
USART2_SendData(shi);
USART2_SendData(ge);
USART2_SendData('g');
}
//***************************************
//******************
void Send_L3G420D_data(short dis_data)
{
float temp ;
if(dis_data<0){
dis_data=-dis_data;
USART_SendData(USART1,'-');
Delayms(2);
}
else
{
USART_SendData(USART1,'+');
Delayms(2);
}
temp=(float)dis_data*0.07; //计算数据和显示,查考ADXL345快速入门第4页
conversion(temp); //转换出显示需要的数据
USART2_SendData(bai);
USART2_SendData(shi);
USART2_SendData(ge);
}
//***************************************
void Send_HMC5883L(void)
{
USART2_SendData('H');
USART2_SendData('M');
USART2_SendData('C');
USART2_SendData('5');
USART2_SendData('8');
USART2_SendData('8');
USART2_SendData('3');
USART2_SendData('L');
USART2_SendData(':');
conversion(angle);
USART2_SendData(bai);
USART2_SendData(shi);
USART2_SendData(ge);
USART2_SendData('`');
USART2_SendData(0x0d);
USART2_SendData(0x0a);
}
//*************************************************
void Send_BMP085(void)
{
USART2_SendData('B');
USART2_SendData('M');
USART2_SendData('P');
USART2_SendData('0');
USART2_SendData('8');
USART2_SendData('5');
USART2_SendData(':');
USART2_SendData('t');
USART2_SendData('=');
conversion(temperature);
USART2_SendData(bai);
USART2_SendData(shi);
USART2_SendData('.');
USART2_SendData(ge);
USART2_SendData('`');
USART2_SendData('C');
USART2_SendData(' ');
USART2_SendData('p');
USART2_SendData('=');
conversion(pressure);
USART2_SendData(shiwan);
USART2_SendData(wan);
USART2_SendData(qian);
USART2_SendData('.');
USART2_SendData(bai);
USART2_SendData(shi);
USART2_SendData(ge);
USART2_SendData('K');
USART2_SendData('p');
USART2_SendData('a');
USART2_SendData(0x0d);
USART2_SendData(0x0a);
}
//*****************************************************
void Send_ADXL345(void)
{
USART2_SendData('A');
USART2_SendData('D');
USART2_SendData('X');
USART2_SendData('L');
USART2_SendData('3');
USART2_SendData('4');
USART2_SendData('5');
USART2_SendData(':');
USART2_SendData('X');
USART2_SendData