IMX6ULL裸机篇SPI实验-ICM20608测量值计算

一.  SPI 实验

SPI实验:学习如何使用 I.MX6U 的 SPI 接口来驱动 ICM-20608,读取 ICM-20608 的六轴数据。

ICM20608 传感器包括陀螺仪与加速度计,还有温度值。本篇文章来学习 通过ADC的值,来转换为实际的值。例如,通过陀螺仪的 X,Y,Z轴转化为角速度值。通过加速度计的 X,Y,Z值转换为 加速度计的加速度值。

二.    测试值计算

由于陀螺仪的角速度是浮点型数,所以,可能需要保存数据的小数点后一两位。所以,这里采取将数据扩大 100倍,取的小数点后的数据后,最后打印再缩小 100倍的方法。

新增或更新 bsp_icm20608.c文件的几个函数如下:

/*获取 ICM20608的内部数据*/
void icm20608_get_data(void)
{
    unsigned char buffer[15] = {0}; 
    unsigned short accel_scale = 0;
    float gyro_scale = 0.0;
   
    accel_scale = icm20608_accel_scaleget();
    gyro_scale = icm20608_gyro_scaleget();

    icm20608_read_len(ICM20_ACCEL_XOUT_H, buffer, 14);
    //ADC传感器数据
    icm20608_dev.accel_x_adc = (signed short)((buffer[0] << 8) | buffer[1]);
    icm20608_dev.accel_y_adc = (signed short)((buffer[2] << 8) |buffer[3]);
    icm20608_dev.accel_z_adc = (signed short)((buffer[4] << 8) | buffer[5]);
    icm20608_dev.temp_adc = (signed short)((buffer[6] << 8) | buffer[7]);
    icm20608_dev.gyro_x_adc = (signed short)((buffer[8] << 8) | buffer[9]);
    icm20608_dev.gyro_y_adc = (signed short)((buffer[10] << 8) |buffer[11]);
    icm20608_dev.gyro_z_adc = (signed short)((buffer[12] << 8) | buffer[13]);

    //计算实际值,实际数据扩大100倍(0.01扩大100后,为 1)
    icm20608_dev.accel_x_act = ((float)(icm20608_dev.accel_x_adc) / accel_scale) * 100;
    icm20608_dev.accel_y_act = ((float)(icm20608_dev.accel_y_adc) / accel_scale) * 100;
    icm20608_dev.accel_z_act = ((float)(icm20608_dev.accel_z_adc) / accel_scale) * 100;
    icm20608_dev.gyro_x_act = ((float)(icm20608_dev.gyro_x_adc) / gyro_scale) * 100;
    icm20608_dev.gyro_y_act = ((float)(icm20608_dev.gyro_y_adc) / gyro_scale) * 100;
    icm20608_dev.gyro_z_act = ((float)(icm20608_dev.gyro_z_adc) / gyro_scale) * 100;
    
    icm20608_dev.temp_act = (((float)(icm20608_dev.temp_adc) - 25 ) / 326.8 + 25) * 100;
}

/*获取陀螺仪的分辨率 */
float icm20608_gyro_scaleget(void)
{
	unsigned char data;
	float gyroscale;
	
	data = (icm20608_read_byte(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_byte(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;
}

 main.c 文件中,主函数代码如下:

#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_uart.h"
#include "bsp_rtc.h"
#include "stdio.h"
#include "bsp_i2c.h"
#include "bsp_ap3216c.h"
#include "bsp_spi.h"
#include "bsp_icm20608.h"

/*把扩大100倍的数据再缩小,显示原数据 */
void decimal_data_handle(signed int data, char* buffer)
{
    signed int tmp_data = data;
    signed int integ = 0; //整数部分
    signed int fract = 0; //小数部分

    if(data < 0)
    {
        tmp_data = -tmp_data;
    }

	integ = tmp_data / 100;
	fract = tmp_data % 100;

    if(data < 0)
    {
        sprintf(buffer,"-%d.%d", integ, fract);
    }
    else
    {
        sprintf(buffer, "%d.%d", integ, fract);
    }
}

int main(void)
{
	unsigned char state = OFF;
    char icm_buffer[20] = {0};

	int_init();       /* 初始化中断(一定要最先调用!) */
	imx6u_clkinit();  /* 初始化系统时钟 			*/
	delay_init();	  /* 初始化延时 			*/
	clk_enable();	  /* 使能所有的时钟 			*/
	led_init();		  /* 初始化led 			*/
	beep_init();      /* 初始化beep	 		*/
	uart_init();      /* 初始化串口,波特率115200 */		
    rtc_init();       /* RTC时钟初始化      */

    while(icm20608_spi_init()) /*SPI从设备ICM20608初始化  */
    {
        printf("---SPI--not check icm20608!!!\r\n");
    }

	while(1)				
	{
        icm20608_get_data();

        decimal_data_handle(icm20608_dev.accel_x_act, icm_buffer);
        printf("acce-x: %s\r\n", icm_buffer);
        decimal_data_handle(icm20608_dev.accel_y_act, icm_buffer);
        printf("acce-y: %s\r\n", icm_buffer);
        decimal_data_handle(icm20608_dev.accel_z_act, icm_buffer);
        printf("acce-z: %s\r\n", icm_buffer);
        decimal_data_handle(icm20608_dev.gyro_x_act, icm_buffer);
        printf("gyro-x: %s\r\n", icm_buffer);
        decimal_data_handle(icm20608_dev.gyro_y_act, icm_buffer);
        printf("gyro-y: %s\r\n", icm_buffer);
        decimal_data_handle(icm20608_dev.gyro_z_act, icm_buffer);
        printf("gyro-z: %s\r\n", icm_buffer);
        decimal_data_handle(icm20608_dev.temp_act, icm_buffer);
        printf("temperature: %s\r\n\n", icm_buffer);

		state = !state;
		led_switch(LED0, state);
		delayms(500);
	}

	return 0;
}

以上代码经过测试,串口打印会卡死,即只是打印了前面寄存器的数据,之后 ICM20608传感器的陀螺仪与加速度计的值都没有打印。原因在于我们没有做硬件浮点支持的操作。下一篇学习开启硬件浮点支持的操作。

串口打印如下:

IMX6ULL裸机篇SPI实验-ICM20608测量值计算_第1张图片

你可能感兴趣的:(嵌入式C开发,裸机开发,arm开发,linux)