• I.MX6U-ALPHA开发板(SPI实验)


    一、SPI协议详解

    ​ 1、SPI相比I2C最大的优势有两点:一个是速度快,最高可以大几十M,甚至上百MHz,第二个就是SPI是个全双工。
    ​ 2、SPI接口和I2C一样,一个SPI接口可以连接多个SPI外设,SPI通过CS引脚/数据线,片选引脚来选择和哪个SPI外设通信。SPI通信前先将指定的SPI外设对应的CS引脚拉低来选中此设备。
    ​ 3、ALPHA开发板上通过ECSPI3接口连接了一个6轴传感器,引脚如下:
    ​ ECSPI3_SCLK : UART2_RX
    ​ ECSPI3_MOSI:UART2_CTS
    ​ ECSPI3_SS0:UART2_TXD
    ​ ECSPI3_MISO: UART2_RTS
    ​ 6ULL一个SPI主接口有4个硬件片选,分别为SS0~SS3。
    ​ 4、根据CPOL和CPHA可以设置四种工作模式,一般使用CPOL=0、CPHA=0。

    二、6ULL SPI接口详解

    ​ 1、6ULL的SPI接口叫做ECSPI,支持全双工、主丛可配置。
    ​ 2、4个硬件片选信号,可以使用软件片选,这样一个SPI接口所能连接的外设就无限制了。
    ​ 1、RXDATA寄存器为接收到的数据。
    ​ 2、TXDATA寄存器为发送数据寄存器。
    ​ 3、CONREG寄存器为配置寄存器,bit0置1,使能SPI。Bit3置1,表示当向TXFIFO写入数据以后马上开启SPI突发访问,也就是发送数据。Bit7:4设置SPI通道主从模式,bit7为通道3,bit4为通道0,我们使用到了SS0,也就是通道0,因此需要设置bit4为1。Bit19:18设置为00,我们使用到SS0,也就是通道0。Bit31:30设置突发访问长度,我们设置为7,也就是8bit突发长度,一个字节。
    ​ 4、CONFIGREG寄存器的bit0为PHA,设置为0,表示 串行时钟的第一个跳变沿开始采集数据。设置bit4为PO,设置为0,表示SCLK空闲的时候为低电平。Bit8设置0。Bit12设置 为0。Bit16设置为0,表示空闲的时候数据线为高。Bit20设置为0,表示SCLK空闲的时候为低。
    ​ 5、STATREG寄存器,bit0表示TXFIFO为空,我们在发送数据之前要等待TXFIFO为空,也就是等待bit0为1。Bit3表示RXFIFO是否有数据,为1的时候示RXFIFO至少有1个字的数据,我们在接收数据的时候要等到bit3为1。
    ​ 6、PERIODREG寄存器,bit14:0设置wait states时间,我们设置为0X2000。Bit15设置wait states的时钟源为SPI CLK,将此位设置0。Bit21:16表示片选信号的延时,可设置0-63,这里设置为0.
    ​ 7、SPI时钟设置!
    ​ SPI时钟源最终来源于pll3_sw_clk=480MHz/8=60MHz,设置CSCDR2寄存器的bit18为0,也就是ECSPI时钟源为60MHz。bit24:19设置为0,表示1分频,因此最终进入到SPI外设的时钟源为60MHz
    ​ ECSPI模块还需要对时钟进行两级分频,由ECSPI_CONREG寄存器设置。Bit15:12设置前级分频,可以设置00xf,表示116分频。Bit11:8设置2级分频,设置2^n分频,n=0~15.

    三、ICM20608简介

    ICM-20608 是 InvenSense 出品的一款 6 轴 MEMS 传感器,包括 3 轴加速度和 3 轴陀螺仪。

    ICM-20608 尺寸非常小,只有 3x3x0.75mm,采用 16P 的 LGA 封装。ICM-20608 内部有一个 512字节的 FIFO。陀螺仪的量程范围可以编程设置,可选择±250,±500,±1000 和±2000°/s,加速度的量程范围也可以编程设置,可选择±2g,±4g,±8g 和±16g。陀螺仪和加速度计都是 16 位的 ADC,并且支持 I2C 和 SPI 两种协议,使用 I2C 接口的话通信速度最高可以达到400KHz,使用 SPI 接口的话通信速度最高可达到 8MHz。I.MX6U-ALPHA 开发板上的 ICM-20608 通过 SPI 接口和 I.MX6U 连接在一起。ICM-20608 特性如下:

    ①、陀螺仪支持 X,Y 和 Z 三轴输出,内部集成 16 位 ADC,测量范围可设置:±250,±500,±1000 和±2000°/s。

    ②、加速度计支持 X,Y 和 Z 轴输出,内部集成 16 位 ADC,测量范围可设置:±2g,±4g, ±4g,±8g 和±16g。

    ③、用户可编程中断。

    ④、内部包含 512 字节的 FIFO。

    ⑤、内部包含一个数字温度传感器。

    ⑥、耐 10000g 的冲击。

    ⑦、支持快速 I2C,速度可达 400KHz。

    ⑧、支持 SPI,速度可达 8MHz。

    四、实验程序编写

    ​ 1、我们在使用浮点计算的时候程序卡死了,因为我们没有开始6UL的硬件浮点运算。我们在编译的时候没有使用浮点。解决此问题需要两点:
    ​ ①、开启6UL的硬件浮点单元
    ​ ②、编译的是时候指定硬件浮点。

    //bsp_spi.h
    #ifndef _BSP_SPI_H
    #define _BSP_SPI_H
    
    #include "imx6ul.h"
    
    /* 函数声明 */
    void spi_init(ECSPI_Type *base);
    unsigned char spich0_readwrite_byte(ECSPI_Type *base, unsigned char txdata);
    
    #endif
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    //bsp_spi.c
    #include "bsp_spi.h"
    #include "bsp_gpio.h"
    #include "stdio.h"
    
    //初始化SPI
    //base	: 要初始化的SPI
    void spi_init(ECSPI_Type *base)
    {
    	/* 配置CONREG寄存器
    	 * bit0 : 		1 	使能ECSPI
    	 * bit3 : 		1	当向TXFIFO写入数据以后立即开启SPI突发。
    	 * bit[7:4] : 	0001 SPI通道0主模式,根据实际情况选择,
    	 *            	   	开发板上的ICM-20608接在SS0上,所以设置通道0为主模式
    	 * bit[19:18]:	00 	选中通道0(其实不需要,因为片选信号我们我们自己控制)
    	 * bit[31:20]:	0x7	突发长度为8个bit。 
    	 */
    	base->CONREG = 0; /* 先清除控制寄存器 */
    	base->CONREG |= (1 << 0) | (1 << 3) | (1 << 4) | (7 << 20); /* 配置CONREG寄存器 */
    
    	/*
         * ECSPI通道0设置,即设置CONFIGREG寄存器
         * bit0:	0 通道0 PHA为0
         * bit4:	0 通道0 SCLK高电平有效
         * bit8: 	0 通道0片选信号 当SMC为1的时候此位无效
         * bit12:	0 通道0 POL为0
         * bit16:	0 通道0 数据线空闲时高电平
         * bit20:	0 通道0 时钟线空闲时低电平
    	 */
    	base->CONFIGREG = 0; 		/* 设置通道寄存器 */
    	
    	/*  
         * ECSPI通道0设置,设置采样周期
         * bit[14:0] :	0X2000  采样等待周期,比如当SPI时钟为10MHz的时候
         *  		    0X2000就等于1/10000 * 0X2000 = 0.8192ms,也就是连续
         *          	读取数据的时候每次之间间隔0.8ms
         * bit15	 :  0  采样时钟源为SPI CLK
         * bit[21:16]:  0  片选延时,可设置为0~63
    	 */
    	base->PERIODREG = 0X2000;		/* 设置采样周期寄存器 */
    
    	/*
         * ECSPI的SPI时钟配置,SPI的时钟源来源于pll3_sw_clk/8=480/8=60MHz
         * 通过设置CONREG寄存器的PER_DIVIDER(bit[11:8])和POST_DIVEDER(bit[15:12])来
         * 对SPI时钟源分频,获取到我们想要的SPI时钟:
         * SPI CLK = (SourceCLK / PER_DIVIDER) / (2^POST_DIVEDER)
         * 比如我们现在要设置SPI时钟为6MHz,那么PER_DIVEIDER和POST_DEIVIDER设置如下:
         * PER_DIVIDER = 0X9。
         * POST_DIVIDER = 0X0。
         * SPI CLK = 60000000/(0X9 + 1) = 60000000=6MHz
    	 */
    	base->CONREG &= ~((0XF << 12) | (0XF << 8));	/* 清除PER_DIVDER和POST_DIVEDER以前的设置 */
    	base->CONREG |= (0X9 << 12);					/* 设置SPI CLK = 6MHz */
    }
    
    //SPI通道0发送/接收一个字节的数据
    //base	: 要使用的SPI
    //txdata	: 要发送的数据
    unsigned char spich0_readwrite_byte(ECSPI_Type *base, unsigned char txdata)
    { 
    	uint32_t  spirxdata = 0;
    	uint32_t  spitxdata = txdata;
    
        /* 选择通道0 */
    	base->CONREG &= ~(3 << 18);
    	base->CONREG |= (0 << 18);
    
      	while((base->STATREG & (1 << 0)) == 0){} /* 等待发送FIFO为空 */
    		base->TXDATA = spitxdata;
    	
    	while((base->STATREG & (1 << 3)) == 0){} /* 等待接收FIFO有数据 */
    		spirxdata = base->RXDATA;
    	return spirxdata;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    //bsp_icm20608.h
    
    #ifndef _BSP_ICM20608_H
    #define _BSP_ICM20608_H
    
    #include "imx6ul.h"
    #include "bsp_gpio.h"
    
    
    /* 宏定义 */
    #define ICM20608_CSN(n)    (n ? gpio_pinwrite(GPIO1, 20, 1) : gpio_pinwrite(GPIO1, 20, 0))   /* SPI片选信号	 */
    
    #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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    //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设备 */
    
    //初始化ICM20608
    //返回0 初始化成功,其他值 初始化失败
    unsigned char icm20608_init(void)
    {	
    	unsigned char regvalue;
    	gpio_pin_config_t cs_config;
    
    	/* 1、ESPI3 IO初始化 
     	 * ECSPI3_SCLK 	-> UART2_RXD
     	 * ECSPI3_MISO 	-> UART2_RTS
     	 * ECSPI3_MOSI	-> UART2_CTS
     	 */
    	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);	
    
    	icm20608_write_reg(ICM20_PWR_MGMT_1, 0x80);		/* 复位,复位后为0x40,睡眠模式 			*/
    	delayms(50);
    	icm20608_write_reg(ICM20_PWR_MGMT_1, 0x01);		/* 关闭睡眠,自动选择时钟 					*/
    	delayms(50);
    
    	regvalue = icm20608_read_reg(ICM20_WHO_AM_I);
    	printf("icm20608 id = %#X\r\n", regvalue);
    	if(regvalue != ICM20608G_ID && regvalue != ICM20608D_ID)
    		return 1;
    		
    	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;
    }
    
    	
    //写ICM20608指定寄存器
    //reg  : 要读取的寄存器地址
    //value: 要写入的值
    void icm20608_write_reg(unsigned char reg, unsigned char value)
    {
    	/* ICM20608在使用SPI接口的时候寄存器地址
    	 * 只有低7位有效,寄存器地址最高位是读/写标志位
    	 * 读的时候要为1,写的时候要为0。
    	 */
    	reg &= ~0X80;	
    	
    	ICM20608_CSN(0);						/* 使能SPI传输			*/
    	spich0_readwrite_byte(ECSPI3, reg); 	/* 发送寄存器地址		*/ 
    	spich0_readwrite_byte(ECSPI3, value);	/* 发送要写入的值			*/
    	ICM20608_CSN(1);						/* 禁止SPI传输			*/
    }	
    
    //读取ICM20608寄存器值
    //reg	: 要读取的寄存器地址
    //返回读取到的寄存器值
    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);     		/* 发送寄存器地址  		*/ 
      	reg_val = spich0_readwrite_byte(ECSPI3, 0XFF);	/* 读取寄存器的值 			*/
     	ICM20608_CSN(1);                				/* 禁止SPI传输 			*/
      	return(reg_val);               	 				/* 返回读取到的寄存器值 */
    }
    
    //读取ICM20608连续多个寄存器
    //reg	: 要读取的寄存器地址
    //返回读取到的寄存器值
    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传输 			*/
    }
    
    //获取陀螺仪的分辨率
    //返回获取到的分辨率
    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;
    }
    
    //获取加速度计的分辨率
    //返回获取到的分辨率
    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;
    }
    
    
    //读取ICM20608的加速度、陀螺仪和温度原始值
    
    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();
    
    	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]);
    
    	/* 计算实际值 */
    	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;
    
    	icm20608_dev.temp_act = (((float)(icm20608_dev.temp_adc) - 25 ) / 326.8 + 25) * 100;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
  • 相关阅读:
    [Python急救站]基于Transformer Models模型完成GPT2的学生AIGC学习训练模型
    【测开求职】面试题:MySQL 吐血整理
    【Unity】在Unity 3D中使用Spine开发2D动画
    【系统设计系列】缓存
    从工厂到社会:探索如何应用设计模式工厂模式
    无刷驱动设计——浅谈MOS驱动电路
    【GPT‑4o】完整教程:LORA微调LLaMA3并结合RAG和Agent技术实现Text2SQL任务
    Linux数字运算的常用命令
    2 分钟,教你用 Serverless 每天给女朋友自动发土味情话
    使用Redis将单机登录改为分布式登录
  • 原文地址:https://blog.csdn.net/qq_61540355/article/details/126574727