一. 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传感器的陀螺仪与加速度计的值都没有打印。原因在于我们没有做硬件浮点支持的操作。下一篇学习开启硬件浮点支持的操作。
串口打印如下: