LSM6DS3姿态芯片和LIS2MD磁力计芯片数据读取(stm32)
上代码
main.c 代码示例
#include "lsm6ds3.h"
#include "lis2md.h"
int16_t Acc[3] = {0}, GYO[3] = {0},Mag[3] = {0};
int main(void)
{
I2C_GPIO_Config(); //配置IIC使用端口
Delayms(500); //延时
Lsm6ds3_Init( ); //姿态芯片初始化
LIS2MDL_Init(); //磁力计初始化
}
while(1)
{
read_Ang_rate(&GYO[0], &GYO[1],&GYO[2]); //陀螺仪
read_Acc_data(&Acc[0], &Acc[1],&Acc[2]); //加速度
LIS2MDL_Read_XYZ(&Mag[0], &Mag[1], &Mag[2]); //地磁;
//printf("打印读到数据");
}
lsm6ds3.h
#ifndef __lsm6ds3_H
#define __lsm6ds3_H#define LSM6DS3TR_C_WHO_AM_I 0x6A //是否为0x6A#define LSM_ADDR 0xD6 // 0xD6#define ACC_ODR_1_6hz 0xB0
#define ACC_ODR_12_5hz 0x10
#define ACC_ODR_26hz 0x20
#define ACC_ODR_52hz 0x30
#define ACC_ODR_104hz 0x40
#define ACC_ODR_208hz 0x50
#define ACC_ODR_416hz 0x60
#define ACC_ODR_833hz 0x70
#define ACC_ODR_1_66khz 0x80
#define ACC_ODR_3_33khz 0x90
#define ACC_ODR_6_66khz 0xA0
#define ACC_DISABLE 0X00#define ACC_CALE_2G 0X00 //加速度量程
#define ACC_CALE_16G 0X01
#define ACC_CALE_4G 0X02
#define ACC_CALE_8G 0X03#define ANG_ODR_12_5hz 0x10 //角速度采样速度
#define ANG_ODR_26hz 0x20
#define ANG_ODR_52hz 0x30
#define ANG_ODR_104hz 0x40
#define ANG_ODR_208hz 0x50
#define ANG_ODR_416hz 0x60
#define ANG_ODR_833hz 0x70
#define ANG_ODR_1_66khz 0x80
#define ANG_ODR_3_33khz 0x90
#define ANG_ODR_6_66khz 0xA0
#define ANG_DISABLE 0x00#define ANG_CALE_245 0X00 //角速度量程
#define ANG_CALE_500 0X04
#define ANG_CALE_1000 0X08
#define ANG_CALE_2000 0X0c // 2000度/s
/*********************************************寄存器**********************************************/#define LSM6DS3_WHO_AM_I 0x0f //#define CTRL1_XL 0X10
#define CTRL2_G 0X11
#define CTRL3_C 0X12
#define CTRL4_C 0X13
#define CTRL5_C 0X14
#define CTRL6_C 0X15
#define CTRL7_G 0X16
#define CTRL8_XL 0X17
#define CTRL9_XL 0X18
#define CTRL10_C 0X19#define OUTX_L_G 0X22 //角速度相关
#define OUTX_H_G 0X23
#define OUTY_L_G 0X24
#define OUTY_H_G 0X25
#define OUTZ_L_G 0X26
#define OUTZ_H_G 0X27#define OUTX_L_XL 0X28 //加速度相关
#define OUTX_H_XL 0X29
#define OUTY_L_XL 0X2A
#define OUTY_H_XL 0X2B
#define OUTZ_L_XL 0X2C
#define OUTZ_H_XL 0X2D#define TAP_CFG 0X58
#define WAKE_UP_THS 0X5B
#define WAKE_UP_DUR 0X5C
#define MD1_CFG 0X5E
#define TAP_THS_6D 0X59
#define D6D_SRC 0x1dvoid Reset_LSM6D(void);
void lsm6ds3tr_c_device_id_get(uint8_t *buff); //读who_am_i
void SetAccelerateRate_LSM6D(void);
void SetAccelerateFullScale_LSM6D(void);
void SetAngleSpeedRate_LSM6D(void);
void SetAngleSpeedFullScale_LSM6D(void);
void SetAcceleratemeterBW_LSM6d(void);
void Set_gyro_band_pass(void); //设置陀螺仪过滤器
bool Init_LSM6D(void);
void read_Ang_rate(int16_t* ps16X, int16_t* ps16Y, int16_t* ps16Z);
void read_Acc_data(int16_t* ps16X, int16_t* ps16Y, int16_t* ps16Z);#endif
lsm6ds3.c
#include <stm32f10x.h>#include "I2C.h"
#include "lsm6ds3.h"
#include "delay.h"void Lsm6ds3_Init(void)
{
// unsigned char temp;//while(Lsm6ds3_ReadByte(LSM6DS3_WHO_AM_I)!=0x69); //检测地址是否正确 Lsm6ds3_WriteByte(CTRL1_XL,ACC_ODR_104hz|ACC_CALE_8G); //加速采样频率及量程Lsm6ds3_WriteByte(CTRL2_G,ANG_ODR_104hz|ANG_CALE_2000);//陀螺仪样频率及量程Lsm6ds3_WriteByte(CTRL3_C,0X20); //中断输出低电平//使能陀螺仪x,y,z轴Lsm6ds3_WriteByte(CTRL10_C,0x38);//WAKE_UP INTERRUPT ConfigurationLsm6ds3_WriteByte(TAP_CFG,0x90);Lsm6ds3_WriteByte(WAKE_UP_DUR,0x08);Lsm6ds3_WriteByte(WAKE_UP_THS,0x08); //唤醒阈值Lsm6ds3_WriteByte(MD1_CFG,0x20); //中断1唤醒使能//6D Orientation ConfigurationLsm6ds3_WriteByte(TAP_THS_6D,0x40);Lsm6ds3_WriteByte(CTRL8_XL,0x01);}/*//[函数名称]SetAccelerateRate_LSM6D
//[函数功能]设置加速度数据输出速率#define RATE_208Hz 0x50
void SetAccelerateRate_LSM6D(void)
{uint8_t buf[1] = {0};IIC_Read(CTRL1_XL, buf, 1); //读取CTRL1_XL寄存器值buf[0] |= RATE_208Hz; //设置加速度计的数据输出速率为218HzIIC_Send(CTRL1_XL, buf, 1); //
}//[函数名称]SetAccelerateFullScale_LSM6D
//[函数功能]设置加速度计的满量程//#define ACC_FSXL_4G 0x08
void SetAccelerateFullScale_LSM6D(void)
{uint8_t buf[1] = {0};IIC_Read(CTRL1_XL, buf, 1); //读取CTRL1_XL寄存器配置buf[0] |= ACC_CALE_8G; //设置加速度计的满量程IIC_Send(CTRL1_XL, buf, 1);
}//[函数名称]SetAngleSpeedRate_LSM6D
//[函数功能]设置陀螺仪数据输出速率void SetAngleSpeedRate_LSM6D(void)
{uint8_t buf[1] = {0};IIC_Read(CTRL2_G, buf, 1); //读取CTRL2_G寄存器的配置buf[0] |= RATE_208Hz; //设置加速度计的数据采样率为208HzIIC_Send(CTRL2_G, buf, 1);
}//[函数名称]SetAngleSpeedFullScale_LSM6D
//[函数功能]设置陀螺仪满量程#define GYR_FSG_500 0x04
void SetAngleSpeedFullScale_LSM6D(void)
{uint8_t buf[1] = {0};IIC_Read(CTRL2_G, buf, 1);buf[0] |= ANG_CALE_2000; //设置陀螺仪计的最大量程IIC_Send(CTRL2_G, buf, 1);
}//[函数名称]SetAcceleratemeterBW_LSM6d
//[函数功能]设置加速度计带宽选择#define LSM6DS3TRC_ACC_BW0XL_400HZ 0x01 //加速度计模拟带宽
#define LSM6DS3TRC_ACC_LOW_PASS_ODR_50 0x88 //低通滤波器
void SetAcceleratemeterBW_LSM6d(void)
{uint8_t buf[1] = {0};IIC_Read(CTRL1_XL, buf, 1);buf[0] |= LSM6DS3TRC_ACC_BW0XL_400HZ;IIC_Send(CTRL1_XL, buf, 1);IIC_Read(CTRL8_XL, buf, 1);buf[0] |= LSM6DS3TRC_ACC_LOW_PASS_ODR_50;IIC_Send(CTRL8_XL, buf, 1);
}#define LSM6DS3TR_C_HP_260mHz_LP1_STRONG 0xA8
void Set_gyro_band_pass(void) //设置陀螺仪过滤器
{} *///获取角速度void read_Ang_rate(int16_t* ps16X, int16_t* ps16Y, int16_t* ps16Z)
{u8 valueL;u8 valueH;valueL= Lsm6ds3_ReadByte(0x22);valueH= Lsm6ds3_ReadByte(0x23);*ps16X=valueH*256+valueL;*ps16X=*ps16X/16.4;valueL=Lsm6ds3_ReadByte(0x24);valueH=Lsm6ds3_ReadByte(0x25);*ps16Y=valueH*256+valueL;*ps16Y=*ps16Y/16.4;valueL=Lsm6ds3_ReadByte(0x26);valueH=Lsm6ds3_ReadByte(0x27);*ps16Z=valueH*256+valueL;*ps16Z=*ps16Z/16.4;
} //获取加速度void read_Acc_data(int16_t* ps16X, int16_t* ps16Y, int16_t* ps16Z)
{u8 valueL;u8 valueH;valueL=Lsm6ds3_ReadByte(0x28);valueH=Lsm6ds3_ReadByte(0x29);* ps16X=valueH*256+valueL;valueL=Lsm6ds3_ReadByte(0x2a);valueH=Lsm6ds3_ReadByte(0x2b);* ps16Y=valueH*256+valueL;valueL=Lsm6ds3_ReadByte(0x2c);valueH=Lsm6ds3_ReadByte(0x2d);* ps16Z=valueH*256+valueL;
}
lis2md.h
#ifndef __lis2md_H
#define __lis2md_H#define LIS2MDL_ADDR_WRITE 0x3C
#define LIS2MDL_ADDR_READ 0x3C // 0x3D
#define LIS2MDL_CFG_A 0x60 //idle DM1,DM0为00
#define LIS2MDL_CFG_B 0x61
#define LIS2MDL_CFG_C 0x62
#define LIS2MDL_REG_WHO_AM_I 0x4F#define LIS2MDL_ADDR_INTCRTL 0x63
#define LIS2MDL_ADDR_INTSOURCE 0x64
#define LIS2MDL_ADDR_INTTHSL 0x65
#define LIS2MDL_ADDR_INTTHSH 0x66
#define LIS2MDL_ADDR_STATUS 0x67#define LIS2MDL_ADDR_XOUTL 0x68
#define LIS2MDL_ADDR_XOUTH 0x69
#define LIS2MDL_ADDR_YOUTL 0x6A
#define LIS2MDL_ADDR_YOUTH 0x6B
#define LIS2MDL_ADDR_ZOUTL 0x6C
#define LIS2MDL_ADDR_ZOUTH 0x6D#define LIS2MDL_ADDR_TEMPL 0x6E
#define LIS2MDL_ADDR_TEMPH 0x6F#define LIS2MDL_ADDR_OFFSETX_L 0x45
#define LIS2MDL_ADDR_OFFSETX_H 0x46
#define LIS2MDL_ADDR_OFFSETY_L 0x47
#define LIS2MDL_ADDR_OFFSETY_H 0x48
#define LIS2MDL_ADDR_OFFSETZ_L 0x49
#define LIS2MDL_ADDR_OFFSETZ_H 0x4A#define LIS2MDL_ADDR_CHIPID 0x4Fvoid LIS2MDL_Init(void);
int Get_WHO_AM_I_LIS2MDL(void);
void LIS2MDL_Soft_Reset(void); //磁力计复位
void LIS2MDL_Read_XYZ(int16_t* ps16X, int16_t* ps16Y, int16_t* ps16Z);#endif
lis2md.c
#include <stm32f10x.h>#include "I2C.h"
#include "lis2md.h"
#include "delay.h"//Startup sequence
void LIS2MDL_Init(void)
{uint8_t dat;dat=0x80;lis2md_WriteByte(LIS2MDL_CFG_A,dat);dat=0x10;lis2md_WriteByte(LIS2MDL_CFG_C,dat);}int Get_WHO_AM_I_LIS2MDL(void)
{return lis2md_ReadByte(LIS2MDL_REG_WHO_AM_I); }#define LIS2MDL_CFGA_SOFT_RST (1 << 5)
#define LIS2MDL_CFGA_REBOOT (1 << 6)
void LIS2MDL_Soft_Reset(void) //磁力计复位
{uint8_t dat;dat=LIS2MDL_CFGA_SOFT_RST;lis2md_WriteByte(LIS2MDL_CFG_A, dat);Delay_ms(1); //HAL_Delay(15); //HAL_Delay(2);dat=LIS2MDL_CFGA_REBOOT;lis2md_WriteByte(LIS2MDL_CFG_A, dat);Delay_ms(1); //HAL_Delay(15); //HAL_Delay(20);
}#define LIS2MDL_ADDR_READ 0x3D
void LIS2MDL_Read_XYZ(int16_t* ps16X, int16_t* ps16Y, int16_t* ps16Z)
{u8 valueL;u8 valueH;valueL=lis2md_ReadByte(LIS2MDL_ADDR_XOUTL);valueH=lis2md_ReadByte(LIS2MDL_ADDR_XOUTH);* ps16X=valueH*256+valueL;valueL=lis2md_ReadByte(LIS2MDL_ADDR_YOUTL);valueH=lis2md_ReadByte(LIS2MDL_ADDR_YOUTH);* ps16Y=valueH*256+valueL;valueL=lis2md_ReadByte(LIS2MDL_ADDR_ZOUTL);valueH=lis2md_ReadByte(LIS2MDL_ADDR_ZOUTH);* ps16Z=valueH*256+valueL;
}
i2c.h
#ifndef _I2C_H
#define _I2C_Htypedef enum {FALSE=0,TRUE=1} bool;void I2C_GPIO_Config(void); //mpu9250 输入定义
void I2C_delay(void);
void delay5ms(void);
bool I2C_Start(void);
void I2C_Stop(void);
void I2C_Ack(void);
void I2C_NoAck(void);
bool I2C_WaitAck(void);
void I2C_SendByte(u8 SendByte); //数据从高位到低位//
unsigned char I2C_RadeByte(void); //数据从高位到低位//
bool Single_Write(unsigned char SlaveAddress,unsigned char REG_Address,unsigned char REG_data);
unsigned char Single_Read(unsigned char SlaveAddress,unsigned char REG_Address);
void WWDG_Configuration(void);
void WWDG_IRQHandler(void);u8 Lsm6ds3_ReadByte(u8 Reg);
u8 Lsm6ds3_WriteByte(u8 WriteAddr, u8 Data);u8 lis2md_ReadByte(u8 Reg);
u8 lis2md_WriteByte(u8 WriteAddr, u8 Data) ;
#endif
i2c.c
#include "stm32f10x.h"
#include "i2c.h"
#include "lsm6ds3.h"#include "lis2md.h"char test=0; //IIC//************************************
/*模拟IIC端口输出输入定义*/
#define SCL_H GPIOB->BSRR = GPIO_Pin_6
#define SCL_L GPIOB->BRR = GPIO_Pin_6 #define SDA_H GPIOB->BSRR = GPIO_Pin_7
#define SDA_L GPIOB->BRR = GPIO_Pin_7#define SCL_read GPIOB->IDR & GPIO_Pin_6
#define SDA_read GPIOB->IDR & GPIO_Pin_7/*******************************************************************************
* Function Name : I2C_GPIO_Config
* Description : Configration Simulation IIC GPIO
* Input : None
* Output : None
* Return : None
****************************************************************************** */
void I2C_GPIO_Config(void) //mpu9250 输入定义
{GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //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=6; // 30 这里可以优化速度 ,经测试最低到5还能写入while(i) { i--; }
}void delay5ms(void)
{int i=1000; while(i) { i--; }
}
/*******************************************************************************
* Function Name : I2C_Start
* Description : Master Start Simulation IIC Communication
* Input : None
* Output : None
* Return : Wheather Start
****************************************************************************** */
bool 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
****************************************************************************** */
bool 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
//?????*******************************************bool 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;} //自己改写的两个读写函数u8 Lsm6ds3_ReadByte(u8 Reg)
{unsigned char REG_data; REG_data=Single_Read(LSM_ADDR,Reg);return REG_data;
}u8 Lsm6ds3_WriteByte(u8 WriteAddr, u8 Data)
{
Single_Write(LSM_ADDR,WriteAddr ,Data);
return 0;
}u8 lis2md_ReadByte(u8 Reg)
{unsigned char REG_data; REG_data=Single_Read(LIS2MDL_ADDR_READ,Reg);return REG_data;
}u8 lis2md_WriteByte(u8 WriteAddr, u8 Data)
{
Single_Write(LIS2MDL_ADDR_WRITE,WriteAddr ,Data);
return 0;
}/*
********************************************************************************
** 函数名称 : WWDG_Configuration(void)
** 函数功能 : 看门狗初始化
** 输 入 : 无
** 输 出 : 无
** 返 回 : 无
********************************************************************************
*/
void WWDG_Configuration(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); WWDG_SetPrescaler(WWDG_Prescaler_8); // WWDG clock counter = (PCLK1/4096)/8 = 244 Hz (~4 ms) WWDG_SetWindowValue(0x41); // Set Window value to 0x41WWDG_Enable(0x50); // Enable WWDG and set counter value to 0x7F, WWDG timeout = ~4 ms * 64 = 262 ms WWDG_ClearFlag(); // Clear EWI flagWWDG_EnableIT(); // Enable EW interrupt
}/*
********************************************************************************
** 函数名称 : WWDG_IRQHandler(void)
** 函数功能 : 窗口提前唤醒中断
** 输 入 : 无
** 输 出 : 无
** 返 回 : 无
********************************************************************************
*/ void WWDG_IRQHandler(void)
{/* Update WWDG counter */WWDG_SetCounter(0x50);/* Clear EWI flag */WWDG_ClearFlag();
}//************************************************