NXP S32K146 FLEXI2C底层驱动 IAM-20680(一) 在上一篇文章的基础上,写IAM-20680年的接口层与上一篇相似,os任务分为初始化和正常运行,以下是基于IAM-30680寄存器写初始化相关代码。
- REGISTER 117 – WHO AM I
WHO AM I寄存器 只读地址位为0x该寄存器用于验证设备的身份。WHOAMI内容为8位设备ID。该寄存器的默认值为0xA9。这与应用程序处理器的从属性有关I2C控制器上看到的设备I2C地址不同。IAM-20680的I2C地址是0x68或0x这取决于原因AD0引脚驱动值。我们是low即0x68
BOOLEAN hw_IAM_20680_check(void) {
i2c_data_t IMU_data; INT8U buf[1] = {
0}; IMU_data.regaddr = IMU_Reg_WHO_AM_I; IMU_data.len = 1; IMU_data.devaddr = IMU_Reg_DEV_ADDR; IMU_data.data = buf; if(TRUE == hal_flexio_i2c_read(&IMU_data)) {
if (IMU_20680_ID==IMU_data.data) {
return APL_OK; } } return APL_FAIL; }
- REGISTER 107 – POWER MANAGEMENT 1 传感器的初始化和基本配置 IAM-20680年的基本配置包括以下步骤: ①要初始化传感器,请执行复位并让步IAM-20680通过寄存器PWR_MGMT1(地址0x6B)设置为0x选择选择最佳时钟源(见第9.寄存器地址027节x6B,可读可写。
第七:设置为1时,所有寄存器均为缺省值。 第六:设置为1时进入睡眠模式,默认为1,我们写0. 第五:设置为1时开启循环,我们写0 第四:设置为1时打开待机模式,我们写0 第三:设置为1时关闭温度传感器,我们写0 CLKSEL[2:0]默认值为000。CLKSEL[2:0]设置为001,以实现陀螺仪的完整性能。寄存器写0x81。
连续写三个寄存器。106-108
BOOLEAN hw_IAM_20680_Config(void) {
i2c_data_t IMU_data; INT8U buf[3] = {
0}; IMU_data.regaddr = IMU_Reg_Config;//0x6A-x6C
IMU_data.len = 3;
IMU_data.devaddr = IMU_Reg_DEV_ADDR;
buf[2]=0x80;//REGISTER 108 – POWER MANAGEMENT 2
buf[1]=0x81;//REGISTER 107 – POWER MANAGEMENT 1
buf[0]=0x45;//REGISTER 106 – USER CONTROL
IMU_data.data = buf;
if(TRUE == hal_flexio_i2c_write(&IMU_data))
{
return APL_OK;
}
return APL_FAIL;
}
- REGISTER 25 – SAMPLE RATE DIVIDER
- REGISTER 26 – CONFIGURATION
- REGISTER 27 – GYROSCOPE CONFIGURATION
- REGISTER 28 – ACCELEROMETER CONFIGURATION
- REGISTER 29 – ACCELEROMETER CONFIGURATION 2 我愚蠢了兄弟们,官网上边有软件例程,解读一下例程吧,我还一个个小函数敲呢,愚蠢了。 官网例程eMD-SmartMotion-IAM20680-1.5.0 1.doc文档:Software User Guide 软件指南 2.EMD-APP:这个应用项目演示如何使用低级驱动程序控制和检索IAM设备的数据。它通过UART接口发送数据,并在主机控制台上显示。该应用程序使用核心库来生成一个可加载的二进制文件。目录包含平台依赖的功能和示例代码,以接口驱动程序配置传感器和流式数据等。 2.1 ASF 用的ATSAMG55,这个文件夹是系统文件底层的,interrupt之类的。 2.2 config 底层配置的头文件。 2.3 IAM-20680 就正常使用IAM的接口 2.3.1 example -raw 一个演示原始加速度计和原始陀螺仪数据流的例子。默认配置为低噪声模式,ODR配置为50Hz。 2.3.2 example -selftest 一个执行accel和gyro自我测试的例子,并提供PASS/失败结果以及陀螺仪/accel低噪声/低功率偏差的例子。 2.3.3 example -wom 一个示例演示了WOM(动态唤醒)特性的配置和使用,以及在接收到WOM中断时完整的FIFO读取。默认配置为低功耗,ODR配置为500Hz。IAM20680HP/IAM20680HT的默认FIFO大小设置为4KB。对于IAM20680HT,本示例还展示了如何启用INT2引脚 剩下的基本上都是如何实现IAM通讯的接口文件。它是以PIC芯片为基础写的,可以把接口层直接拿过来用,具体每个人的平台不同底层文件不同。
int inv_iam20680_init(struct inv_iam20680 * dev)
{
int status = 0;
/* Reset device */
status |= inv_iam20680_device_reset(dev);
/* Wake up device */
status |= inv_iam20680_wr_pwr_mgmt_1_sleep(dev,IAM20680_PWR_MGMT_1_SLEEP_awake);
//status |= iam20680_reg_readandwrite(dev,MPUREG_PWR_MGMT_1,BIT_SLEEP_MASK,IAM20680_PWR_MGMT_1_SLEEP_awake,1);
/* Setup CLKSEL */
status |= inv_iam20680_wr_pwr_mgmt_1_clksel(CLK_SEL);
/* Disable Accel and Gyro all axes */
status |= inv_iam20680_wr_pwr_mgmt_2_accel_stby((uint8_t)IAM20680_PWR_MGMT_2_XA_disable | (uint8_t)IAM20680_PWR_MGMT_2_YA_disable | (uint8_t)IAM20680_PWR_MGMT_2_ZA_disable);
status |= inv_iam20680_wr_pwr_mgmt_2_gyro_stby((uint8_t)IAM20680_PWR_MGMT_2_XG_disable | (uint8_t)IAM20680_PWR_MGMT_2_YG_disable | (uint8_t)IAM20680_PWR_MGMT_2_ZG_disable);
/* Set default full scale range */
status |= inv_iam20680_wr_accel_config_accel_fs_sel((uint8_t)IAM20680_ACCEL_CONFIG_FS_SEL_4g);
status |= inv_iam20680_wr_gyro_config_fs_sel((uint8_t)IAM20680_GYRO_CONFIG_FS_SEL_2000dps);
/* Set default bandwidth */
status |= inv_iam20680_wr_accel_config2_a_dlpf_cfg((uint8_t) IAM20680_ACCEL_CONFIG2_A_DLPF_CFG_420);
status |= inv_iam20680_wr_config_dlpf_cfg((uint8_t)IAM20680_CONFIG_DLPF_CFG_176);
/* Set default averaging filter */
status |= inv_iam20680_wr_accel_config2_dec2_cfg((uint8_t)IAM20680_ACCEL_CONFIG2_DEC2_CFG_4x);
status |= inv_iam20680_wr_lp_mode_cfg_g_avgcfg((uint8_t)IAM20680_LP_MODE_CFG_G_AVGCFG_1x);
/* Initial sampling rate to 100Hz*/
status |= inv_iam20680_wr_smplrt_div((uint8_t)SAMPLE_RATE_DIVIDER);
/* make sure FIFO is disabled */
status |= inv_iam20680_wr_user_ctrl_fifo_en((uint8_t)IAM20680_USER_CTRL_FIFO_EN_disable);
status |= inv_iam20680_wr_fifo_en_gyro_fifo_en((uint8_t)IAM20680_FIFO_EN_GYRO_FIFO_EN_disable);
status |= inv_iam20680_wr_fifo_en_accel_fifo_en((uint8_t)IAM20680_FIFO_EN_ACCEL_FIFO_EN_disable);
status |= inv_iam20680_wr_fifo_en_temp_fifo_en((uint8_t)IAM20680_FIFO_EN_TEMP_FIFO_EN_disable);
/* Configure FIFO: - FIFO stream mode i.e over write the data when the FIFO overflows */
status |= inv_iam20680_wr_config_fifo_mode((uint8_t)IAM20680_CONFIG_FIFO_MODE_STREAM);
/* Enable Data Ready Interrupt */
status |= inv_iam20680_wr_int_enable_data_rdy_int_en((uint8_t)IAM20680_INT_ENABLE_DATA_RDY_INT_EN_enable);
return status;
}
int SetupInvDevice(BOOLEAN (*read_reg)(i2c_data_t *data),BOOLEAN (*write_reg)(i2c_data_t *data))
{
int rc = 0;
uint8_t who_am_i;
struct hal_iam20680_i2c iam20680_config;
iam20680_config.read_reg = (*read_reg);
iam20680_config.write_reg = (*write_reg);
iam20680_config.max_read = 64;
iam20680_config.max_write = 64;
memset(&icm_device, 0, sizeof(icm_device));
icm_device.config = iam20680_config;
rc = hw_IAM_20680_check();
if(rc!= TRUE )
rc = hw_IAM_20680_check();
if(rc != TRUE)
return rc;
rc = inv_iam20680_init(&icm_device);
return rc;
}
实现了IAM模块的初始化
int iam20680_init(void)
{
SetupInvDevice(hal_flexio_i2c_read,hal_flexio_i2c_write);
dev_config.enable_accel = (uint8_t)ENABLE_ACCEL;
dev_config.enable_gyro = (uint8_t)ENABLE_GYRO;
dev_config.set_low_noise_mode = (uint8_t)LOW_NOISE_MODE;
dev_config.acc_fsr_g = FSR_ACC_G;
dev_config.gyr_fsr_dps = FSR_GYR_DPS;
dev_config.odr_us = ODR_US;
ConfigureInvDevice(&dev_config);
eGyro_State=GYRO_WORKING;
}
实现了从FIFO中读取数据
int iam20680_GetDataFromFIFO(inv_dev_config_t* device_config)
{
int rc = 0;
uint8_t int_status = 0;
int16_t raw_acc[3], raw_gyro[3];
uint16_t packet_count = 0, packet_count_i = 0;
uint16_t packet_size = 0;
uint32_t timestamp = 0;
if(device_config->enable_accel)
packet_size += ACCEL_DATA_SIZE;
if(device_config->enable_gyro)
packet_size += GYRO_DATA_SIZE;
rc = inv_iam20680_rd_int_status( &int_status);
if(!rc)
return rc;
if(int_status & BIT_DATA_RDY_INT_MASK)
{
uint8_t fifo_count[2];
inv_iam20680_rd_fifo_count( fifo_count);
packet_count = (fifo_count[0] << 8) | fifo_count[1];
packet_count /= packet_size; /* FIFO byte mode */
if(int_status & BIT_FIFO_OVERFLOW_MASK)
{
inv_iam20680_wr_user_ctrl_fifo_rst();
//clear_irq();在这里清中断吗?!!!!
return false;
}
else if(packet_count>0)
{
for (packet_count_i=0; packet_count_i<packet_count; packet_count_i++)
{
uint8_t data[ACCEL_DATA_SIZE + GYRO_DATA_SIZE];
if(!(rc = inv_iam20680_rd_fifo(packet_size, data))) //读取失败
{
inv_iam20680_wr_user_ctrl_fifo_rst();
}
//timestamp = timer_get_irq_timestamp_us(); 读时间戳不读不行?
if(device_config->enable_accel && device_config->enable_gyro) {
raw_acc[0] = (data[0] << 8) | data[1];
raw_acc[1] = (data[2] << 8) | data[3];
raw_acc[2] = (data[4] << 8) | data[5];
raw_gyro[0] = (data[6] << 8) | data[7];
raw_gyro[1] = (data[8] << 8) | data[9];
raw_gyro[2] = (data[10] << 8)| data[11];
}
else if(device_config->enable_accel && !device_config->enable_gyro) {
raw_acc[0] = (data[0] << 8) | data[1];
raw_acc[1] = (data[2] << 8) | data[3];
raw_acc[2] = (data[4] << 8) | data[5];
}
else if(!device_config->enable_accel && device_config->enable_gyro) {
raw_gyro[0] = (data[0] << 8) | data[1];
raw_gyro[1] = (data[2] << 8) | data[3];
raw_gyro[2] = (data[4] << 8) | data[5];
}
}
}
}
return TRUE;
}
以上代码未经验证,到目前为主是以S32K146为平台实现了FIFO读取IMU的数据,下一步则是使用卡尔曼滤波及MATLAB仿真IMU的姿态!!!