写在前面
备战2024电赛,使用到了TI开发板,型号MSPM0G3507,该开发板除文档外,网上资料稀少。
现在为大家提供spi连接icm20602陀螺仪的代码,以促共同进步。
该代码由逐飞seekfree仓库移植而来,如有侵权请私信联系我删除,谢谢。
代码亲测成功,如有bug欢迎评论区指正。
头文件
ICM20602.h
#ifndef ICM20602_H
#define ICM20602_H
#include "../COMMON.h"
#define ICM20602_DEV_ADDR (0x69)
#define ICM20602_SPI_W (0x00)
#define ICM20602_SPI_R (0x80)
#define ICM20602_XG_OFFS_TC_H (0x04)
#define ICM20602_XG_OFFS_TC_L (0x05)
#define ICM20602_YG_OFFS_TC_H (0x07)
#define ICM20602_YG_OFFS_TC_L (0x08)
#define ICM20602_ZG_OFFS_TC_H (0x0A)
#define ICM20602_ZG_OFFS_TC_L (0x0B)
#define ICM20602_SELF_TEST_X_ACCEL (0x0D)
#define ICM20602_SELF_TEST_Y_ACCEL (0x0E)
#define ICM20602_SELF_TEST_Z_ACCEL (0x0F)
#define ICM20602_XG_OFFS_USRH (0x13)
#define ICM20602_XG_OFFS_USRL (0x14)
#define ICM20602_YG_OFFS_USRH (0x15)
#define ICM20602_YG_OFFS_USRL (0x16)
#define ICM20602_ZG_OFFS_USRH (0x17)
#define ICM20602_ZG_OFFS_USRL (0x18)
#define ICM20602_SMPLRT_DIV (0x19)
#define ICM20602_CONFIG (0x1A)
#define ICM20602_GYRO_CONFIG (0x1B)
#define ICM20602_ACCEL_CONFIG (0x1C)
#define ICM20602_ACCEL_CONFIG_2 (0x1D)
#define ICM20602_LP_MODE_CFG (0x1E)
#define ICM20602_ACCEL_WOM_X_THR (0x20)
#define ICM20602_ACCEL_WOM_Y_THR (0x21)
#define ICM20602_ACCEL_WOM_Z_THR (0x22)
#define ICM20602_FIFO_EN (0x23)
#define ICM20602_FSYNC_INT (0x36)
#define ICM20602_INT_PIN_CFG (0x37)
#define ICM20602_INT_ENABLE (0x38)
#define ICM20602_FIFO_WM_INT_STATUS (0x39)
#define ICM20602_INT_STATUS (0x3A)
#define ICM20602_ACCEL_XOUT_H (0x3B)
#define ICM20602_ACCEL_XOUT_L (0x3C)
#define ICM20602_ACCEL_YOUT_H (0x3D)
#define ICM20602_ACCEL_YOUT_L (0x3E)
#define ICM20602_ACCEL_ZOUT_H (0x3F)
#define ICM20602_ACCEL_ZOUT_L (0x40)
#define ICM20602_TEMP_OUT_H (0x41)
#define ICM20602_TEMP_OUT_L (0x42)
#define ICM20602_GYRO_XOUT_H (0x43)
#define ICM20602_GYRO_XOUT_L (0x44)
#define ICM20602_GYRO_YOUT_H (0x45)
#define ICM20602_GYRO_YOUT_L (0x46)
#define ICM20602_GYRO_ZOUT_H (0x47)
#define ICM20602_GYRO_ZOUT_L (0x48)
#define ICM20602_SELF_TEST_X_GYRO (0x50)
#define ICM20602_SELF_TEST_Y_GYRO (0x51)
#define ICM20602_SELF_TEST_Z_GYRO (0x52)
#define ICM20602_FIFO_WM_TH1 (0x60)
#define ICM20602_FIFO_WM_TH2 (0x61)
#define ICM20602_SIGNAL_PATH_RESET (0x68)
#define ICM20602_ACCEL_INTEL_CTRL (0x69)
#define ICM20602_USER_CTRL (0x6A)
#define ICM20602_PWR_MGMT_1 (0x6B)
#define ICM20602_PWR_MGMT_2 (0x6C)
#define ICM20602_I2C_IF (0x70)
#define ICM20602_FIFO_COUNTH (0x72)
#define ICM20602_FIFO_COUNTL (0x73)
#define ICM20602_FIFO_R_W (0x74)
#define ICM20602_WHO_AM_I (0x75)
#define ICM20602_XA_OFFSET_H (0x77)
#define ICM20602_XA_OFFSET_L (0x78)
#define ICM20602_YA_OFFSET_H (0x7A)
#define ICM20602_YA_OFFSET_L (0x7B)
#define ICM20602_ZA_OFFSET_H (0x7D)
#define ICM20602_ZA_OFFSET_L (0x7E)
#define ICM20602_TIMEOUT_COUNT (0x00FF)
void icm20602_get_acc (void);
void icm20602_get_gyro (void);
uint8_t icm20602_init (void);
extern int16_t icm20602_gyro_x, icm20602_gyro_y, icm20602_gyro_z;
extern int16_t icm20602_acc_x, icm20602_acc_y, icm20602_acc_z;
extern float icm20602_transition_factor[2];
#define icm20602_acc_transition(acc_value) ((float)(acc_value) / icm20602_transition_factor[0])
#define icm20602_gyro_transition(gyro_value) ((float)(gyro_value) / icm20602_transition_factor[1])
#endif
源文件
1.ICM20602.c
#include "ICM20602.h"
int16_t icm20602_gyro_x = 0, icm20602_gyro_y = 0, icm20602_gyro_z = 0;
int16_t icm20602_acc_x = 0, icm20602_acc_y = 0, icm20602_acc_z = 0;
float icm20602_transition_factor[2] = {4096, 16.4};
#define ICM20602_CS(x) ((x) ? (DL_GPIO_setPins(OTHER_PORT,OTHER_ICM_CS_PIN)) : (DL_GPIO_clearPins(OTHER_PORT,OTHER_ICM_CS_PIN)))
void spi_write_8bit_register(uint8_t reg, uint8_t data){
DL_SPI_transmitData8(ICM_SPI_INST, reg);
while (DL_SPI_isBusy(ICM_SPI_INST));
DL_SPI_transmitData8(ICM_SPI_INST, data);
while (DL_SPI_isBusy(ICM_SPI_INST));
}
void spi_read_8bit_registers(uint8_t reg, uint8_t *data, uint32_t len){
DL_SPI_transmitData8(ICM_SPI_INST,reg);
while (DL_SPI_isBusy(ICM_SPI_INST));
for (int i = 0; i< len; i++) {
DL_SPI_transmitData8(ICM_SPI_INST,0);
while (DL_SPI_isBusy(ICM_SPI_INST));
while (!DL_SPI_isRXFIFOEmpty(ICM_SPI_INST))
data[i] = DL_SPI_receiveData8(ICM_SPI_INST);
}
}
uint8_t spi_read_8bit_register(uint8_t reg){
DL_SPI_transmitData8(ICM_SPI_INST,reg);
while (DL_SPI_isBusy(ICM_SPI_INST));
DL_SPI_transmitData8(ICM_SPI_INST,0);
while (DL_SPI_isBusy(ICM_SPI_INST));
uint8_t data = 0;
while (!DL_SPI_isRXFIFOEmpty(ICM_SPI_INST))
data = DL_SPI_receiveData8(ICM_SPI_INST);
return data;
}
static void icm20602_write_register(uint8_t reg, uint8_t data)
{
ICM20602_CS(0);
spi_write_8bit_register(reg | ICM20602_SPI_W, data);
ICM20602_CS(1);
}
static uint8_t icm20602_read_register(uint8_t reg)
{
uint8_t data = 0;
ICM20602_CS(0);
data = spi_read_8bit_register(reg | ICM20602_SPI_R);
ICM20602_CS(1);
return data;
}
static void icm20602_read_registers(uint8_t reg, uint8_t *data, uint32_t len)
{
ICM20602_CS(0);
spi_read_8bit_registers(reg | ICM20602_SPI_R, data, len);
ICM20602_CS(1);
}
uint8_t icm20602_self_check (void)
{
uint8_t dat = 0, return_state = 0;
uint16_t timeout_count = 0;
while(0x12 != dat)
{
if(ICM20602_TIMEOUT_COUNT < timeout_count ++)
{
return_state = 1;
break;
}
dat = icm20602_read_register(ICM20602_WHO_AM_I);
}
return return_state;
}
void icm20602_get_acc (void)
{
uint8_t dat[6];
icm20602_read_registers(ICM20602_ACCEL_XOUT_H, dat, 6);
icm20602_acc_x = (int16_t)(((uint16_t)dat[0] << 8 | dat[1]));
icm20602_acc_y = (int16_t)(((uint16_t)dat[2] << 8 | dat[3]));
icm20602_acc_z = (int16_t)(((uint16_t)dat[4] << 8 | dat[5]));
}
void icm20602_get_gyro (void)
{
uint8_t dat[6];
icm20602_read_registers(ICM20602_GYRO_XOUT_H, dat, 6);
icm20602_gyro_x = (int16_t)(((uint16_t)dat[0] << 8 | dat[1]));
icm20602_gyro_y = (int16_t)(((uint16_t)dat[2] << 8 | dat[3]));
icm20602_gyro_z = (int16_t)(((uint16_t)dat[4] << 8 | dat[5]));
}
uint8_t icm20602_init (void)
{
uint8_t val = 0x0, return_state = 0;
uint16_t timeout_count = 0;
system_delay_ms(10);
do
{
if(icm20602_self_check())
{
return_state = 1;
break;
}
icm20602_write_register(ICM20602_PWR_MGMT_1, 0x80); // 复位设备
system_delay_ms(2);
do
{ // 等待复位成功
val = icm20602_read_register(ICM20602_PWR_MGMT_1);
if(ICM20602_TIMEOUT_COUNT < timeout_count ++)
{
return_state = 2;
break;
}
}while(0x41 != val);
if(2 == return_state)
{
break;
}
icm20602_write_register(ICM20602_PWR_MGMT_1, 0x01);
icm20602_write_register(ICM20602_PWR_MGMT_2, 0x00);
icm20602_write_register(ICM20602_CONFIG, 0x01);
icm20602_write_register(ICM20602_SMPLRT_DIV, 0x07);
icm20602_write_register(ICM20602_ACCEL_CONFIG, 0x10);
icm20602_transition_factor[0] = 4096;
icm20602_write_register(ICM20602_GYRO_CONFIG, 0x18);
icm20602_transition_factor[1] = 16.4;
icm20602_write_register(ICM20602_ACCEL_CONFIG_2, 0x03);
}while(0);
return return_state;
}
2.测试代码
通过自行查看icm20602_init()的返回值
以及icm20602_gyro_x,icm20602_acc_x等值的大小来观察测试结果
#include "Library/COMMON.h"
int main(void)
{
SYSCFG_DL_init();
icm20602_init();
while (1) {
icm20602_get_gyro();
icm20602_get_acc();
system_delay_ms(1);
}
}
配置
一个SPI,命名为ICM_SPI
一个GPIO,端口命名为OTHER
一个PIN命名为ICM_CS
,设置为Output,默认高电平