ICM-20608驱动编写

bsp_icm20608.h

#ifndef _BSP_ICM20608_H
#define _BSP_ICM20608_H
/***************************************************************
文件名	: 	 bsp_icm20608.h
描述	   : ICM20608驱动文件。
***************************************************************/
#include "imx6ul.h"
#include "bsp_gpio.h"

/* 宏定义 */
#define ICM20608_CSN(n)    (n ? gpio_pinwrite(GPIO1, 20, 1) : gpio_pinwrite(GPIO1, 20, 0))   /* SPI片选信号	 */

//定义ID值,用于确认是否匹配,根据寄存器手册定义
#define ICM20608G_ID			0XAF	/* ID值 */
#define ICM20608D_ID			0XAE	/* ID值 */

/* ICM20608寄存器 
 *复位后所有寄存器地址都为0,除了
 *Register 107(0X6B) Power Management 1 	= 0x40
 *Register 117(0X75) WHO_AM_I 				= 0xAF或0xAE
 */
/* 陀螺仪和加速度自测(出产时设置,用于与用户的自检输出值比较) */
// 陀螺仪
#define	ICM20_SELF_TEST_X_GYRO		0x00
#define	ICM20_SELF_TEST_Y_GYRO		0x01
#define	ICM20_SELF_TEST_Z_GYRO		0x02
// 加速度
#define	ICM20_SELF_TEST_X_ACCEL		0x0D
#define	ICM20_SELF_TEST_Y_ACCEL		0x0E
#define	ICM20_SELF_TEST_Z_ACCEL		0x0F

/* 陀螺仪静态偏移 */
#define	ICM20_XG_OFFS_USRH			0x13
#define	ICM20_XG_OFFS_USRL			0x14
#define	ICM20_YG_OFFS_USRH			0x15
#define	ICM20_YG_OFFS_USRL			0x16
#define	ICM20_ZG_OFFS_USRH			0x17
#define	ICM20_ZG_OFFS_USRL			0x18

#define	ICM20_SMPLRT_DIV			0x19
#define	ICM20_CONFIG				0x1A
#define	ICM20_GYRO_CONFIG			0x1B
#define	ICM20_ACCEL_CONFIG			0x1C
#define	ICM20_ACCEL_CONFIG2			0x1D
#define	ICM20_LP_MODE_CFG			0x1E
#define	ICM20_ACCEL_WOM_THR			0x1F
#define	ICM20_FIFO_EN				0x23
#define	ICM20_FSYNC_INT				0x36
#define	ICM20_INT_PIN_CFG			0x37
#define	ICM20_INT_ENABLE			0x38
#define	ICM20_INT_STATUS			0x3A

/* 加速度输出 */
#define	ICM20_ACCEL_XOUT_H			0x3B
#define	ICM20_ACCEL_XOUT_L			0x3C
#define	ICM20_ACCEL_YOUT_H			0x3D
#define	ICM20_ACCEL_YOUT_L			0x3E
#define	ICM20_ACCEL_ZOUT_H			0x3F
#define	ICM20_ACCEL_ZOUT_L			0x40

/* 温度输出 */
#define	ICM20_TEMP_OUT_H			0x41
#define	ICM20_TEMP_OUT_L			0x42

/* 陀螺仪输出 */
#define	ICM20_GYRO_XOUT_H			0x43
#define	ICM20_GYRO_XOUT_L			0x44
#define	ICM20_GYRO_YOUT_H			0x45
#define	ICM20_GYRO_YOUT_L			0x46
#define	ICM20_GYRO_ZOUT_H			0x47
#define	ICM20_GYRO_ZOUT_L			0x48

#define	ICM20_SIGNAL_PATH_RESET		0x68
#define	ICM20_ACCEL_INTEL_CTRL 		0x69
#define	ICM20_USER_CTRL				0x6A
#define	ICM20_PWR_MGMT_1			0x6B
#define	ICM20_PWR_MGMT_2			0x6C
#define	ICM20_FIFO_COUNTH			0x72
#define	ICM20_FIFO_COUNTL			0x73
#define	ICM20_FIFO_R_W				0x74
#define	ICM20_WHO_AM_I 				0x75

/* 加速度静态偏移 */
#define	ICM20_XA_OFFSET_H			0x77
#define	ICM20_XA_OFFSET_L			0x78
#define	ICM20_YA_OFFSET_H			0x7A
#define	ICM20_YA_OFFSET_L			0x7B
#define	ICM20_ZA_OFFSET_H			0x7D
#define	ICM20_ZA_OFFSET_L 			0x7E

/*
 * ICM20608结构体
 */
struct icm20608_dev_struc
{
    
    
	signed int gyro_x_adc;		/* 陀螺仪X轴原始值 			*/
	signed int gyro_y_adc;		/* 陀螺仪Y轴原始值 			*/
	signed int gyro_z_adc;		/* 陀螺仪Z轴原始值 			*/
	signed int accel_x_adc;		/* 加速度计X轴原始值 			*/
	signed int accel_y_adc;		/* 加速度计Y轴原始值 			*/
	signed int accel_z_adc;		/* 加速度计Z轴原始值 			*/
	signed int temp_adc;		/* 温度原始值 				*/

	/* 下面是计算得到的实际值,扩大100倍 */
	signed int gyro_x_act;		/* 陀螺仪X轴实际值 			*/
	signed int gyro_y_act;		/* 陀螺仪Y轴实际值 			*/
	signed int gyro_z_act;		/* 陀螺仪Z轴实际值 			*/
	signed int accel_x_act;		/* 加速度计X轴实际值 			*/
	signed int accel_y_act;		/* 加速度计Y轴实际值 			*/
	signed int accel_z_act;		/* 加速度计Z轴实际值 			*/
	signed int temp_act;		/* 温度实际值 				*/
};

struct icm20608_dev_struc icm20608_dev;	/* icm20608设备 */


/* 函数声明 */
unsigned char icm20608_init(void);
void icm20608_write_reg(unsigned char reg, unsigned char value);
unsigned char icm20608_read_reg(unsigned char reg);
void icm20608_read_len(unsigned char reg, unsigned char *buf, unsigned char len);
void icm20608_getdata(void);


#endif



bsp_icm20608.c

#include "bsp_icm20608.h"
#include "bsp_delay.h"
#include "bsp_spi.h"
#include "stdio.h"
struct icm20608_dev_struc icm20608_dev;	/* icm20608设备 */
/*
 * @description	: 初始化ICM20608
 * @param		: 无
 * @return 		: 0 初始化成功,其他值 初始化失败
 */
unsigned char icm20608_init(void)
{
    
    	
	unsigned char regvalue;
	gpio_pin_config_t cs_config;

	/* 1、ESPI3 IO初始化 
	  ALPHA开发板上通过ECSPI13接口连接了一个六轴传感器
 	 * ECSPI3_SCLK 	-> UART2_RXD
 	 * ECSPI3_MISO 	-> UART2_RTS
 	 * ECSPI3_MOSI	-> UART2_CTS
 	 * ECSPI3_SSO	-> UART2_TXD
 	 */
	IOMUXC_SetPinMux(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK, 0);
	IOMUXC_SetPinMux(IOMUXC_UART2_CTS_B_ECSPI3_MOSI, 0);
	IOMUXC_SetPinMux(IOMUXC_UART2_RTS_B_ECSPI3_MISO, 0);
	
	/* 配置SPI   SCLK MISO MOSI IO属性	
	 *bit 16: 0 HYS关闭
	 *bit [15:14]: 00 默认100K下拉
	 *bit [13]: 0 keeper功能
	 *bit [12]: 1 pull/keeper使能 
	 *bit [11]: 0 关闭开路输出
 	 *bit [7:6]: 10 速度100Mhz
 	 *bit [5:3]: 110 驱动能力为R0/6
	 *bit [0]: 1 高转换率
 	 */
	IOMUXC_SetPinConfig(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK, 0x10B1);
	IOMUXC_SetPinConfig(IOMUXC_UART2_CTS_B_ECSPI3_MOSI, 0x10B1);
	IOMUXC_SetPinConfig(IOMUXC_UART2_RTS_B_ECSPI3_MISO, 0x10B1);

	/*初始化片选引脚*/
	IOMUXC_SetPinMux(IOMUXC_UART2_TX_DATA_GPIO1_IO20, 0);
	IOMUXC_SetPinConfig(IOMUXC_UART2_TX_DATA_GPIO1_IO20, 0X10B0);
	cs_config.direction = kGPIO_DigitalOutput;
	cs_config.outputLogic = 0;
	gpio_init(GPIO1, 20, &cs_config);
	
	/* 2、初始化SPI */
	spi_init(ECSPI3);	
    /* 3、初始化IMC20608 */
    //icm20608默认在睡眠模式下,读就出问题了,必须先复位,复位以后,关闭睡眠模式
	icm20608_write_reg(ICM20_PWR_MGMT_1, 0x80);		/* 复位,复位后为0x40,睡眠模式 			*/
	delayms(50);
	icm20608_write_reg(ICM20_PWR_MGMT_1, 0x01);		/* 关闭睡眠,自动选择时钟 					*/
	delayms(50);
    /* 4、ID匹配 */
	regvalue = icm20608_read_reg(ICM20_WHO_AM_I);
	printf("icm20608 id = %#X\r\n", regvalue);
	if(regvalue != ICM20608G_ID && regvalue != ICM20608D_ID)
		return 1;
	/* 3、IMC20608初始化代码,查看寄存器手册 */	
	icm20608_write_reg(ICM20_SMPLRT_DIV, 0x00); 	/* 输出速率是内部采样率					*/
	icm20608_write_reg(ICM20_GYRO_CONFIG, 0x18); 	/* 陀螺仪±2000dps量程 				*/
	icm20608_write_reg(ICM20_ACCEL_CONFIG, 0x18); 	/* 加速度计±16G量程 					*/
	icm20608_write_reg(ICM20_CONFIG, 0x04); 		/* 陀螺仪低通滤波BW=20Hz 				*/
	icm20608_write_reg(ICM20_ACCEL_CONFIG2, 0x04); 	/* 加速度计低通滤波BW=21.2Hz 			*/
	icm20608_write_reg(ICM20_PWR_MGMT_2, 0x00); 	/* 打开加速度计和陀螺仪所有轴 				*/
	icm20608_write_reg(ICM20_LP_MODE_CFG, 0x00); 	/* 关闭低功耗 						*/
	icm20608_write_reg(ICM20_FIFO_EN, 0x00);		/* 关闭FIFO						*/
	return 0;
}
/*
 * @description	: 读取ICM20608寄存器值,SPI接口写数据
 * @param - reg	: 要读取的寄存器地址
 * @return 		: 读取到的寄存器值
 */
unsigned char icm20608_read_reg(unsigned char reg)
{
    
    
	unsigned char reg_val;	   	

	/* ICM20608在使用SPI接口的时候寄存器地址
	 * 只有低7位有效,寄存器地址最高位是读/写标志位
	 * 读的时候要为1,写的时候要为0。
	 */
	reg |= 0x80; //查看数据手册
	
   	ICM20608_CSN(0);               					/* 片选拉低,选中芯片,使能SPI传输*/
  	spich0_readwrite_byte(ECSPI3, reg);     		/* 发送寄存器地址,使用SPI接口*/ 
  	reg_val = spich0_readwrite_byte(ECSPI3, 0XFF);	/* 读取寄存器的值(从机返回的数据) ,0XFF无效值,使能时钟*/
 	ICM20608_CSN(1);                				/*片选拉高,禁止SPI传输 			*/
  	return(reg_val);               	 				/* 返回读取到的寄存器值 */
}
/*
 * @description  : 写ICM20608指定寄存器,SPI接口读数据
 * @param - reg  : 要读取的寄存器地址
 * @param - value: 要写入的值
 * @return		 : 无
 */
void icm20608_write_reg(unsigned char reg, unsigned char value)
{
    
    
	/* ICM20608在使用SPI接口的时候寄存器地址
	 * 只有低7位有效,寄存器地址最高位是读/写标志位
	 * 读的时候要为1,写的时候要为0。
	 */
	reg &= ~0X80;//根据数据手册编写,地址的bit7置0,表示写数据	
	
	ICM20608_CSN(0);						/* 片选拉低,使能SPI传输	*/
	spich0_readwrite_byte(ECSPI3, reg); 	/* 发送寄存器地址 */ 
	spich0_readwrite_byte(ECSPI3, value);	/* 发送要写入的值 */
	ICM20608_CSN(1);						/* 片选拉高,禁止SPI传输			*/
}	
/*
 * @description	: 读取ICM20608连续多个寄存器
 * @param - reg	: 要读取的寄存器地址
 * @return 		: 读取到的寄存器值
 */
void icm20608_read_len(unsigned char reg, unsigned char *buf, unsigned char len)
{
    
      
	unsigned char i;
	
	/* ICM20608在使用SPI接口的时候寄存器地址,只有低7位有效,
	 * 寄存器地址最高位是读/写标志位读的时候要为1,写的时候要为0。
	 */
	reg |= 0x80; 
		
   	ICM20608_CSN(0);               				/* 使能SPI传输	 		*/
  	spich0_readwrite_byte(ECSPI3, reg);			/* 发送寄存器地址  		*/   	   
 	for(i = 0; i < len; i++)					/* 顺序读取寄存器的值 			*/
 	{
    
    
		buf[i] = spich0_readwrite_byte(ECSPI3, 0XFF);	
	}
 	ICM20608_CSN(1);                			/* 片选拉高,禁止SPI传输 */
}
/*
 * @description : 读取ICM20608的加速度、陀螺仪和温度原始值
 * @param 		: 无
 * @return		: 无
 */
void icm20608_getdata(void)
{
    
    
	//定义陀螺仪、加速度计分辨率变量
	float gyroscale;
	unsigned short accescale;
	unsigned char data[14];
	
	icm20608_read_len(ICM20_ACCEL_XOUT_H, data, 14);//起始地址、保存数据单元、长度
	
	gyroscale = icm20608_gyro_scaleget();
	accescale = icm20608_accel_scaleget();
	// ADC传感器数据
	icm20608_dev.accel_x_adc = (signed short)((data[0] << 8) | data[1]); 
	icm20608_dev.accel_y_adc = (signed short)((data[2] << 8) | data[3]); 
	icm20608_dev.accel_z_adc = (signed short)((data[4] << 8) | data[5]); 
	icm20608_dev.temp_adc    = (signed short)((data[6] << 8) | data[7]); 
	icm20608_dev.gyro_x_adc  = (signed short)((data[8] << 8) | data[9]); 
	icm20608_dev.gyro_y_adc  = (signed short)((data[10] << 8) | data[11]);
	icm20608_dev.gyro_z_adc  = (signed short)((data[12] << 8) | data[13]);

	// 计算实际值(实际数据扩大100倍,0.01扩大100=1)
	// 原因:串口不支持浮点数输出、扩大100倍,相当于将小数点后两位变为整型。
	icm20608_dev.gyro_x_act = ((float)(icm20608_dev.gyro_x_adc)  / gyroscale) * 100;
	icm20608_dev.gyro_y_act = ((float)(icm20608_dev.gyro_y_adc)  / gyroscale) * 100;
	icm20608_dev.gyro_z_act = ((float)(icm20608_dev.gyro_z_adc)  / gyroscale) * 100;

	icm20608_dev.accel_x_act = ((float)(icm20608_dev.accel_x_adc) / accescale) * 100;
	icm20608_dev.accel_y_act = ((float)(icm20608_dev.accel_y_adc) / accescale) * 100;
	icm20608_dev.accel_z_act = ((float)(icm20608_dev.accel_z_adc) / accescale) * 100;
    //用到温度的计算表达式:寄存器手册,搜索TEMP_degC
	icm20608_dev.temp_act = (((float)(icm20608_dev.temp_adc) - 25 ) / 326.8 + 25) * 100;
}
/*
 * @description : 获取陀螺仪的分辨率
 * @param		: 无
 * @return		: 获取到的分辨率
 */
float icm20608_gyro_scaleget(void)
{
    
    
	unsigned char data;
	float gyroscale;
	
	data = (icm20608_read_reg(ICM20_GYRO_CONFIG) >> 3) & 0X3;
	switch(data) {
    
    
		case 0: 
			gyroscale = 131;
			break;
		case 1:
			gyroscale = 65.5;
			break;
		case 2:
			gyroscale = 32.8;
			break;
		case 3:
			gyroscale = 16.4;
			break;
	}
	return gyroscale;
}

/*
 * @description : 获取加速度计的分辨率
 * @param		: 无
 * @return		: 获取到的分辨率
 */
unsigned short icm20608_accel_scaleget(void)
{
    
    
	unsigned char data;
	unsigned short accelscale;
	
	data = (icm20608_read_reg(ICM20_ACCEL_CONFIG) >> 3) & 0X3;
	switch(data) {
    
    
		case 0: 
			accelscale = 16384;
			break;
		case 1:
			accelscale = 8192;
			break;
		case 2:
			accelscale = 4096;
			break;
		case 3:
			accelscale = 2048;
			break;
	}
	return accelscale;
}

猜你喜欢

转载自blog.csdn.net/shouchen1/article/details/129631669