QMA6100P 姿态传感器的初始化程序
文章目录
前言
国产3轴加速度传感器QMA6100P 的初始化程序,HK32的MCU,整个工程,可以顺利读取3个轴的数据。
一、简述
使用HK32F030MF4U6作为测试单片机
使用模拟IIC通讯
QMA6100P 的ID地址是0x12或者0x13(取决AD0脚是否接地)
寄存器地址0x00是存储ID的地址,读取到的数据是0x90
二、使用步骤
1.IIC基本配置(iic.c文件)
代码如下():
#define IIC_SCL_Pin GPIO_Pin_6
#define IIC_SCL_Port GPIOC
#define IIC_SDA_Pin GPIO_Pin_5
#define IIC_SDA_Port GPIOC
#define SCL_H() GPIO_SetBits(IIC_SCL_Port, IIC_SCL_Pin)
#define SCL_L() GPIO_ResetBits(IIC_SCL_Port, IIC_SCL_Pin)
#define SDA_H() GPIO_SetBits(IIC_SDA_Port, IIC_SDA_Pin)
#define SDA_L() GPIO_ResetBits(IIC_SDA_Port, IIC_SDA_Pin)
#define READ_SDA GPIO_ReadInputDataBit(IIC_SDA_Port, IIC_SDA_Pin)
#define ACCE_READ_ID (0x12<<1)+1
#define ACCE_WRITE_ID (0x12<<1)+0
void I2cInit(void)
{
/* sEE_I2C_SCL_GPIO_CLK and sEE_I2C_SDA_GPIO_CLK Periph clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
/* sEE_I2C Periph clock enable */
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIO configuration */
/* Configure sEE_I2C pins: SCL */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure sEE_I2C pins: SDA */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIO configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIO configuration */
/* Configure sEE_I2C pins: SCL */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void delay_us(unsigned short us);
static void IIC_Start(void)
{
SDA_OUT();
SDA_H();
SCL_H();
delay_us(4);
SDA_L();
delay_us(4);
SCL_L();
}
static void IIC_Stop(void)
{
SDA_OUT();
SCL_L();
SDA_L();
delay_us(4);
SCL_H();
SDA_H();
delay_us(4);
}
static uint8_t IIC_Wait_Ack(void)
{
uint8_t ucErrTime=0;
SDA_OUT();
SDA_H();delay_us(1);
SCL_H();delay_us(1);
SDA_IN();
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
SCL_L();
return 0;
}
static void IIC_Ack(void)
{
SCL_L();
SDA_OUT();
SDA_L();
delay_us(2);
SCL_H();
delay_us(2);
SCL_L();
}
static void IIC_NAck(void)
{
SCL_L();
SDA_OUT();
SDA_H();
delay_us(2);
SCL_H();
delay_us(2);
SCL_L();
}
static void IIC_Send_Byte(uint8_t Data)
{
uint8_t t;
SDA_OUT();
SCL_L();
for(t=0;t<8;t++)
{
if((Data&0x80)>>7)
SDA_H();
else
SDA_L();
Data<<=1;
delay_us(2);
SCL_H();
delay_us(2);
SCL_L();
delay_us(2);
}
}
static uint8_t IIC_Read_Byte(uint8_t ack)
{
uint8_t i,receive=0;
SDA_IN();
for(i=0;i<8;i++ )
{
SCL_L();
delay_us(2);
SCL_H();
receive<<=1;
if(READ_SDA)
receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();
else
IIC_Ack();
return receive;
}
void Acce_Write_Byte(uint8_t addr, uint8_t data)
{
IIC_Start();
IIC_Send_Byte(ACCE_WRITE_ID);
IIC_Wait_Ack();
IIC_Send_Byte(addr);
IIC_Wait_Ack();
IIC_Send_Byte(data);
IIC_Wait_Ack();
IIC_Stop();
delay_us(2);
}
uint8_t Acce_Read_Byte(uint8_t addr)
{
uint8_t Read_Data;
IIC_Start();
IIC_Send_Byte(ACCE_WRITE_ID);
IIC_Wait_Ack();
IIC_Send_Byte(addr);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(ACCE_READ_ID);
IIC_Wait_Ack();
Read_Data = IIC_Read_Byte(0);
IIC_Stop();
return Read_Data;
}
2.QMA6110P的寄存器地址(qma6100p.h文件)
代码如下(示例):
void funQMA6100PInit(void);
void funQMA6100PCheck(void);
short funAcceDrvReadX(void);
short funAcceDrvReadY(void);
short funAcceDrvReadZ(void);
#define SLAVE_ADDR QMA6100P_ADDRESS
#define QMA6100P_ADDRESS 0x12
#define QMA6100P_DEVICE_ID 0x90
#define QMA6100P_REG_CHIP_ID 0x00
#define QMA6100P_REG_XOUTL 0x01
#define QMA6100P_REG_XOUTH 0x02
#define QMA6100P_REG_YOUTL 0x03
#define QMA6100P_REG_YOUTH 0x04
#define QMA6100P_REG_ZOUTL 0x05
#define QMA6100P_REG_ZOUTH 0x06
#define QMA6100P_REG_STEP_CNT_L 0x07
#define QMA6100P_REG_STEP_CNT_M 0x08
#define QMA6100P_REG_STEP_CNT_H 0x0d
#define QMA6100P_REG_INT_STATUS_0 0x09
#define QMA6100P_REG_INT_STATUS_1 0x0a
#define QMA6100P_REG_INT_STATUS_2 0x0b
#define QMA6100P_REG_INT_STATUS_3 0x0c
#define QMA6100P_REG_FIFO_STATE 0x0e
#define QMA6100P_REG_RANGE 0x0f
#define QMA6100P_REG_BW_ODR 0x10
#define QMA6100P_REG_POWER_MANAGE 0x11
#define QMA6100P_REG_STEP_SAMPLE_CNT 0x12
#define QMA6100P_REG_STEP_PRECISION 0x13
#define QMA6100P_REG_STEP_TIME_LOW 0x14
#define QMA6100P_REG_STEP_TIME_UP 0x15
#define QMA6100P_REG_INT_EN_0 0x16
#define QMA6100P_REG_INT_EN_1 0x17
#define QMA6100P_REG_INT_EN_2 0x18
#define QMA6100P_REG_INT1_MAP_0 0x19
#define QMA6100P_REG_INT1_MAP_1 0x1a
#define QMA6100P_REG_INT2_MAP_0 0x1b
#define QMA6100P_REG_INT2_MAP_1 0x1c
#define QMA6100P_REG_INTPIN_CFG 0x20
#define QMA6100P_REG_INT_CFG 0x21
#define QMA6100P_REG_OS_CUST_X 0x27
#define QMA6100P_REG_OS_CUST_Y 0x28
#define QMA6100P_REG_OS_CUST_Z 0x29
#define QMA6100P_REG_NVM 0x33
#define QMA6100P_REG_RESET 0x36
#define QMA6100P_REG_DRDY_BIT 0x10 // enable 1
#define QMA6100P_REG_AMD_X_BIT 0x01
#define QMA6100P_REG_AMD_Y_BIT 0x02
#define QMA6100P_REG_AMD_Z_BIT 0x04
typedef enum
{
QMA6100P_MAP_INT1,
QMA6100P_MAP_INT2,
QMA6100P_MAP_INT_NONE
}qma6100p_int_map;
typedef enum
{
QMA6100P_BW_100 = 0,
QMA6100P_BW_200 = 1,
QMA6100P_BW_400 = 2,
QMA6100P_BW_800 = 3,
QMA6100P_BW_1600 = 4,
QMA6100P_BW_50 = 5,
QMA6100P_BW_25 = 6,
QMA6100P_BW_12_5 = 7,
QMA6100P_BW_OTHER = 8
}qma6100p_bw;
typedef enum
{
QMA6100P_RANGE_2G = 0x01,
QMA6100P_RANGE_4G = 0x02,
QMA6100P_RANGE_8G = 0x04,
QMA6100P_RANGE_16G = 0x08,
QMA6100P_RANGE_32G = 0x0f
}qma6100p_range;
typedef enum
{
QMA6100P_LPF_OFF = (0x00<<5),
QMA6100P_LPF_1 = (0x04<<5),
QMA6100P_LPF_2 = (0x01<<5),
QMA6100P_LPF_4 = (0x02<<5),
QMA6100P_LPF_8 = (0x03<<5),
QMA6100P_LPF_RESERVED = 0xff
}qma6100p_nlpf;
typedef enum
{
QMA6100P_HPF_DIV_OFF = (0x00<<5),
QMA6100P_HPF_DIV_10 = (0x01<<5),
QMA6100P_HPF_DIV_25 = (0x02<<5),
QMA6100P_HPF_DIV_50 = (0x03<<5),
QMA6100P_HPF_DIV_100 = (0x04<<5),
QMA6100P_HPF_DIV_200 = (0x05<<5),
QMA6100P_HPF_DIV_400 = (0x06<<5),
QMA6100P_HPF_DIV_800 = (0x07<<5),
QMA6100P_HPF_RESERVED = 0xff
}qma6100p_nhpf;
typedef enum
{
QMA6100P_MODE_STANDBY = 0,
QMA6100P_MODE_ACTIVE = 1,
QMA6100P_MODE_MAX
}qma6100p_mode;
typedef enum
{
QMA6100P_MCLK_102_4K = 0x03,
QMA6100P_MCLK_51_2K = 0x04,
QMA6100P_MCLK_25_6K = 0x05,
QMA6100P_MCLK_12_8K = 0x06,
QMA6100P_MCLK_6_4K = 0x07,
QMA6100P_MCLK_RESERVED = 0xff
}qma6100p_mclk;
typedef enum
{
QMA6100P_STEP_LPF_0 = (0x00<<6),
QMA6100P_STEP_LPF_2 = (0x01<<6),
QMA6100P_STEP_LPF_4 = (0x02<<6),
QMA6100P_STEP_LPF_8 = (0x03<<6),
QMA6100P_STEP_LPF_RESERVED = 0xff
}qma6100p_step_lpf;
typedef enum
{
QMA6100P_STEP_AXIS_ALL = 0x00,
QMA6100P_STEP_AXIS_YZ = 0x01,
QMA6100P_STEP_AXIS_XZ = 0x02,
QMA6100P_STEP_AXIS_XY = 0x03,
QMA6100P_STEP_AXIS_RESERVED = 0xff
}qma6100p_step_axis;
typedef enum
{
QMA6100P_STEP_START_0 = 0x00,
QMA6100P_STEP_START_4 = 0x20,
QMA6100P_STEP_START_8 = 0x40,
QMA6100P_STEP_START_12 = 0x60,
QMA6100P_STEP_START_16 = 0x80,
QMA6100P_STEP_START_24 = 0xa0,
QMA6100P_STEP_START_32 = 0xc0,
QMA6100P_STEP_START_40 = 0xe0,
QMA6100P_STEP_START_RESERVED = 0xff
}qma6100p_step_start_cnt;
typedef enum
{
QMA6100P_FIFO_MODE_NONE,
QMA6100P_FIFO_MODE_FIFO,
QMA6100P_FIFO_MODE_STREAM,
QMA6100P_FIFO_MODE_BYPASS,
QMA6100P_FIFO_MODE_MAX
}qma6100p_fifo_mode;
typedef enum
{
QMA6100P_TAP_SINGLE = 0x80,
QMA6100P_TAP_DOUBLE = 0x20,
QMA6100P_TAP_TRIPLE = 0x10,
QMA6100P_TAP_QUARTER = 0x01,
QMA6100P_TAP_MAX = 0xff
}qma6100p_tap;
typedef enum
{
QMA6100P_SENSITITY_2G = 244,
QMA6100P_SENSITITY_4G = 488,
QMA6100P_SENSITITY_8G = 977,
QMA6100P_SENSITITY_16G = 1950,
QMA6100P_SENSITITY_32G = 3910
}qma6100p_sensitity;
typedef struct {
int temp;
int acc_x;
int acc_y;
int acc_z;
}QMA6100PRawData_t;
QMA6100P ID和数据的读取函数(qma6100p.c文件)
uint8_t chip_id=0;
void funQMA6100PCheck(void)
{
chip_id=Acce_Read_Byte(QMA6100P_REG_CHIP_ID);
}
void funQMA6100PInit(void)
{
Acce_Write_Byte(QMA6100P_REG_RESET,0xB6);
delay_us(5);
Acce_Write_Byte(QMA6100P_REG_RESET,0x00);
delay_us(10);
Acce_Write_Byte(0x11,0x80);
Acce_Write_Byte(0x11,0x84);
Acce_Write_Byte(0x4a,0x20);
Acce_Write_Byte(0x56,0x01);
Acce_Write_Byte(0x5f,0x80);
delay_us(2);
Acce_Write_Byte(0x5f,0x00);
delay_us(10);
//设置满量程刻度
Acce_Write_Byte(QMA6100P_REG_RANGE, QMA6100P_RANGE_8G);
//设置带宽
Acce_Write_Byte(QMA6100P_REG_BW_ODR, QMA6100P_BW_100);
//设置时钟和模式
Acce_Write_Byte(QMA6100P_REG_POWER_MANAGE, QMA6100P_MCLK_6_4K|0x80);
//设置中断
Acce_Write_Byte(0x21,0x03);
}
short funAcceDrvReadX(void)
{
short u16Temp;
float X;
u16Temp = Acce_Read_Byte(QMA6100P_REG_XOUTL) + \
(Acce_Read_Byte(QMA6100P_REG_XOUTH)<<8);
X = (u16Temp>>2)*QMA6100P_SENSITITY_8G/1000.0;
//return (short)X;
return (short)u16Temp;
}
short funAcceDrvReadY(void)
{
short u16Temp;
float X;
u16Temp = Acce_Read_Byte(QMA6100P_REG_YOUTL) + \
(Acce_Read_Byte(QMA6100P_REG_YOUTH)<<8);
X = (u16Temp>>2)*QMA6100P_SENSITITY_8G/1000.0;
//return X;
return (short)u16Temp;
}
short funAcceDrvReadZ(void)
{
short u16Temp;
float X;
u16Temp = Acce_Read_Byte(QMA6100P_REG_ZOUTL) + \
(Acce_Read_Byte(QMA6100P_REG_ZOUTH)<<8);
X = (u16Temp>>2)*QMA6100P_SENSITITY_8G/1000.0;
//return X;
return (short)u16Temp;
}
主程序
配置好IIC端口初始化,然后就可以先读取传感器的ID地址0x00了,如果返回0x90说明IIC配置没有问题,然后再进行QMA6100P的参数设置,然后进行数据采集。
int main(void)
{
SysTick_Config(SystemCoreClock/200);
I2cInit();
funTime1config();
delay_us(2000);
funQMA6100PCheck();
funQMA6100PInit();
while(1)
{
if(Flag10ms)
{
Flag10ms=0;
Cnt10ms++;
if(Cnt10ms>200)
{
Cnt10ms=0;
GPIO_Toggle(GPIOC,GPIO_Pin_4);
QMA6110Pxyz[0] = funAcceDrvReadX();
QMA6110Pxyz[1] = funAcceDrvReadY();
QMA6110Pxyz[2] = funAcceDrvReadZ();
}
}
}
}
工程有整体打包上传,请自取https://download.csdn.net/download/b801007/88529553。