OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8900|回复: 15

ICM-20608读取WHO AM I寄存器问题

[复制链接]

8

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
146
金钱
146
注册时间
2017-12-4
在线时间
24 小时
发表于 2018-1-24 20:28:21 | 显示全部楼层 |阅读模式
1金钱
ICM-20608为一6轴传感器与mpu6000差不多只不过功耗低一些,现在想读取WHO AM I寄存区中的0x75,然后由串口发到串口助手
以下是我的代码
int main(void)
{
        uint8_t a=0xF5;//访问 WHO AM I 寄存器的第一个字节0x75|0x80
        uint8_t b=0;
//                uint8_t rxdata=0;
//                uint8_t txdata =  0x6A;
//                uint8_t buf[2]={0};
//                buf[0] = txdata;buf[1]=0x10;


  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_UART7_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
       

               
                //HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_RESET);//CS拉低
               
    //if(HAL_SPI_Transmit(&hspi1,buf,2,500) != HAL_OK)
                        //return 0;
                //if(HAL_SPI_Receive(&hspi1,&rxdata,1,500) != HAL_OK)
                        //return 0;
               
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);//CS拉高
               
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_RESET);//CS拉低
    if(HAL_SPI_Transmit(&hspi1, &a, 1, 200)!=HAL_OK)//向WHO AM I 寄存器发送第一个字节
                        return 0;
                if(HAL_SPI_Receive(&hspi1, &b, 1, 200)!=HAL_OK)//接收WHO AM I 寄存器的数据
                   return 0;
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);//CS拉高
               
    HAL_Delay(300);
                HAL_UART_Transmit(&huart7, &b, 1, 200);//串口发送从寄存器得到的数据
               
       

  }

  /* USER CODE END 3 */

}

请大神指点

最佳答案

查看完整内容[请看2#楼]

楼主你修改spi的模式 设置POL=0 PHA=0就可以读到0xAE或者0XAF了,0xAE和0xAF的不同是因为模块版本不同(模块的后缀),但是数据手册上的时序图应该是POL=1 PHA=1,这个按照数据手册配置就GG了,感觉是手册的问题,然后 操作寄存器的时候需要先复位,我是搞阿尔法的时候发现的这个问题的,太坑了
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
124
金钱
124
注册时间
2019-10-14
在线时间
24 小时
发表于 2018-1-24 20:28:22 | 显示全部楼层
楼主你修改spi的模式 设置POL=0 PHA=0就可以读到0xAE或者0XAF了,0xAE和0xAF的不同是因为模块版本不同(模块的后缀),但是数据手册上的时序图应该是POL=1 PHA=1,这个按照数据手册配置就GG了,感觉是手册的问题,然后 操作寄存器的时候需要先复位,我是搞阿尔法的时候发现的这个问题的,太坑了
回复

使用道具 举报

8

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
146
金钱
146
注册时间
2017-12-4
在线时间
24 小时
 楼主| 发表于 2018-1-24 20:31:52 | 显示全部楼层
我得到的一直是00,数据手册上写的应该是0XAF,上边问题中写错了,0x75是who am i 的地址
回复

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
906
金钱
906
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-1-24 21:32:56 | 显示全部楼层
问题1:你是否正确的设置了SPI的连线呢?
问题2:为什么要操作0x75|0x80?

请核实。
回复

使用道具 举报

8

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
146
金钱
146
注册时间
2017-12-4
在线时间
24 小时
 楼主| 发表于 2018-1-25 16:51:10 | 显示全部楼层
a496298685 发表于 2018-1-24 21:32
问题1:你是否正确的设置了SPI的连线呢?
问题2:为什么要操作0x75|0x80?

1.SPI连线没问题
2. 因为数据手册说SPI读写操作在16个或更多时钟周期(两个或多个字节)内完成。 第一个字节包含SPI地址,以及后面的字节包含SPI数据。 第一个字节的第一位包含读/写位并指示读取(1)或写入(0)操作。
回复

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
906
金钱
906
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-1-25 17:27:07 | 显示全部楼层
志存高远 发表于 2018-1-25 16:51
1.SPI连线没问题
2. 因为数据手册说SPI读写操作在16个或更多时钟周期(两个或多个字节)内完成。 第一个 ...

TIM截图20180125170309.png

我验证了一下,
我的MPU-6050可以收到115=0x73。
我的MPU-6050收到了104=0x68。

你的ICM-20608其他功能都好用吗?总线上的其他SPI设备好用吗?
回复

使用道具 举报

8

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
146
金钱
146
注册时间
2017-12-4
在线时间
24 小时
 楼主| 发表于 2018-1-25 17:35:14 | 显示全部楼层
a496298685 发表于 2018-1-25 17:27
我验证了一下,
我的MPU-6050可以收到115=0x73。
我的MPU-6050收到了104=0x68。

老哥可以进一步交流吗QQ:861688675
回复

使用道具 举报

8

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
146
金钱
146
注册时间
2017-12-4
在线时间
24 小时
 楼主| 发表于 2018-1-25 17:36:50 | 显示全部楼层
a496298685 发表于 2018-1-25 17:27
我验证了一下,
我的MPU-6050可以收到115=0x73。
我的MPU-6050收到了104=0x68。

或者代码共享一下
回复

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
906
金钱
906
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-1-25 17:38:33 | 显示全部楼层

我使用的是IIC接口,基于STM32 HAL库的,确定需要吗?
回复

使用道具 举报

8

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
146
金钱
146
注册时间
2017-12-4
在线时间
24 小时
 楼主| 发表于 2018-1-25 17:40:11 | 显示全部楼层
a496298685 发表于 2018-1-25 17:38
我使用的是IIC接口,基于STM32 HAL库的,确定需要吗?

我也是这个库不过是SPI,发过来看看吧
回复

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
906
金钱
906
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-1-25 17:49:10 | 显示全部楼层
志存高远 发表于 2018-1-25 17:40
我也是这个库不过是SPI,发过来看看吧

[mw_shl_code=c,false]#ifndef __MPU_6050_H
#define __MPU_6050_H

extern HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
extern I2C_HandleTypeDef hi2c1;


#define MPU_6050_Addr 0xD0
#define MPU_6050_AddR 0xD1



uint8_t MPU_Init(void);                                                                 //初始化MPU6050
uint8_t MPU_Write_Len(uint8_t reg,uint8_t len,uint8_t *buf);//IIC连续写
uint8_t MPU_Read_Len(uint8_t reg,uint8_t len,uint8_t *buf); //IIC连续读
uint8_t MPU_Write_Byte(uint8_t reg,uint8_t data);                                //IIC写一个字节
uint8_t MPU_Read_Byte(uint8_t reg);                                                //IIC读一个字节

uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr);
uint8_t MPU_Set_Accel_Fsr(uint8_t fsr);
uint8_t MPU_Set_LPF(int16_t lpf);
uint8_t MPU_Set_Rate(int16_t rate);
uint8_t MPU_Set_Fifo(uint8_t sens);

int16_t MPU_Get_Temperature(void);
uint8_t MPU_Get_Gyroscope(int16_t *gx,int16_t *gy,int16_t *gz);
uint8_t MPU_Get_Accelerometer(int16_t *ax,int16_t *ay,int16_t *az);

uint8_t MPU_Write_Byte(uint8_t Addr,uint8_t Data)
{
        #define MPU_SELF_TESTX_REG                0X0D        //自检寄存器X
        #define MPU_SELF_TESTY_REG                0X0E        //自检寄存器Y
        #define MPU_SELF_TESTZ_REG                0X0F        //自检寄存器Z
        #define MPU_SELF_TESTA_REG                0X10        //自检寄存器A
        #define MPU_SAMPLE_RATE_REG                0X19        //采样频率分频器
        #define MPU_CFG_REG                                    0X1A        //配置寄存器
        #define MPU_GYRO_CFG_REG                  0X1B        //陀螺仪配置寄存器
        #define MPU_ACCEL_CFG_REG                  0X1C        //加速度计配置寄存器
        #define MPU_MOTION_DET_REG                0X1F        //运动检测阀值设置寄存器
        #define MPU_FIFO_EN_REG                          0X23        //FIFO使能寄存器
        #define MPU_I2CMST_CTRL_REG                0X24        //IIC主机控制寄存器
        #define MPU_I2CSLV0_ADDR_REG        0X25        //IIC从机0器件地址寄存器
        #define MPU_I2CSLV0_REG                          0X26        //IIC从机0数据地址寄存器
        #define MPU_I2CSLV0_CTRL_REG        0X27        //IIC从机0控制寄存器
        #define MPU_I2CSLV1_ADDR_REG        0X28        //IIC从机1器件地址寄存器
        #define MPU_I2CSLV1_REG                          0X29        //IIC从机1数据地址寄存器
        #define MPU_I2CSLV1_CTRL_REG        0X2A        //IIC从机1控制寄存器
        #define MPU_I2CSLV2_ADDR_REG        0X2B        //IIC从机2器件地址寄存器
        #define MPU_I2CSLV2_REG                          0X2C        //IIC从机2数据地址寄存器
        #define MPU_I2CSLV2_CTRL_REG        0X2D        //IIC从机2控制寄存器
        #define MPU_I2CSLV3_ADDR_REG        0X2E        //IIC从机3器件地址寄存器
        #define MPU_I2CSLV3_REG                          0X2F        //IIC从机3数据地址寄存器
        #define MPU_I2CSLV3_CTRL_REG        0X30        //IIC从机3控制寄存器
        #define MPU_I2CSLV4_ADDR_REG        0X31        //IIC从机4器件地址寄存器
        #define MPU_I2CSLV4_REG                          0X32        //IIC从机4数据地址寄存器
        #define MPU_I2CSLV4_DO_REG                0X33        //IIC从机4写数据寄存器
        #define MPU_I2CSLV4_CTRL_REG        0X34        //IIC从机4控制寄存器
        #define MPU_I2CSLV4_DI_REG                0X35        //IIC从机4读数据寄存器
        #define MPU_I2CMST_STA_REG                0X36        //IIC主机状态寄存器
        #define MPU_INTBP_CFG_REG                  0X37        //中断/旁路设置寄存器
        #define MPU_INT_EN_REG                          0X38        //中断使能寄存器
        #define MPU_INT_STA_REG                          0X3A        //中断状态寄存器

        #define MPU_ACCEL_XOUTH_REG                0X3B        //加速度值,X轴高8位寄存器
        #define MPU_ACCEL_XOUTL_REG                0X3C        //加速度值,X轴低8位寄存器
        #define MPU_ACCEL_YOUTH_REG                0X3D        //加速度值,Y轴高8位寄存器
        #define MPU_ACCEL_YOUTL_REG                0X3E        //加速度值,Y轴低8位寄存器
        #define MPU_ACCEL_ZOUTH_REG                0X3F        //加速度值,Z轴高8位寄存器
        #define MPU_ACCEL_ZOUTL_REG                0X40        //加速度值,Z轴低8位寄存器

        #define MPU_TEMP_OUTH_REG                  0X41        //温度值高八位寄存器
        #define MPU_TEMP_OUTL_REG                  0X42        //温度值低8位寄存器

        #define MPU_GYRO_XOUTH_REG                0X43        //陀螺仪值,X轴高8位寄存器
        #define MPU_GYRO_XOUTL_REG                0X44        //陀螺仪值,X轴低8位寄存器
        #define MPU_GYRO_YOUTH_REG                0X45        //陀螺仪值,Y轴高8位寄存器
        #define MPU_GYRO_YOUTL_REG                0X46        //陀螺仪值,Y轴低8位寄存器
        #define MPU_GYRO_ZOUTH_REG                0X47        //陀螺仪值,Z轴高8位寄存器
        #define MPU_GYRO_ZOUTL_REG                0X48        //陀螺仪值,Z轴低8位寄存器

        #define MPU_I2CSLV0_DO_REG                0X63        //IIC从机0数据寄存器
        #define MPU_I2CSLV1_DO_REG                0X64        //IIC从机1数据寄存器
        #define MPU_I2CSLV2_DO_REG                0X65        //IIC从机2数据寄存器
        #define MPU_I2CSLV3_DO_REG                0X66        //IIC从机3数据寄存器

        #define MPU_I2CMST_DELAY_REG        0X67        //IIC主机延时管理寄存器
        #define MPU_SIGPATH_RST_REG                0X68        //信号通道复位寄存器
        #define MPU_MDETECT_CTRL_REG        0X69        //运动检测控制寄存器
        #define MPU_USER_CTRL_REG                  0X6A        //用户控制寄存器
        #define MPU_PWR_MGMT1_REG                  0X6B        //电源管理寄存器1
        #define MPU_PWR_MGMT2_REG                  0X6C        //电源管理寄存器2
        #define MPU_FIFO_CNTH_REG                  0X72        //FIFO计数寄存器高八位
        #define MPU_FIFO_CNTL_REG                  0X73        //FIFO计数寄存器低八位
        #define MPU_FIFO_RW_REG                          0X74        //FIFO读写寄存器
        #define MPU_DEVICE_ID_REG                  0X75        //器件ID寄存器
        return (uint8_t)HAL_I2C_Mem_Write(&hi2c1,MPU_6050_Addr,Addr,1,&Data,1,10);
}
uint8_t MPU_Read_Byte(uint8_t Addr)
{
        uint8_t Data=0;
        HAL_I2C_Mem_Read(&hi2c1,MPU_6050_AddR,Addr,1,&Data,1,10);
        return Data;
}
//IIC连续写
//reg:寄存器地址
//len:写入长度
//buf:数据区
//返回值:0,正常
//其他,错误代码
uint8_t MPU_Write_Len(uint8_t Addr,uint8_t Length,uint8_t *Buffer)
{
        return (uint8_t)HAL_I2C_Mem_Write(&hi2c1,MPU_6050_Addr,Addr,1,Buffer,Length,10);       
}
//IIC连续读
//reg:要读取的寄存器地址
//len:要读取的长度
//buf:读取到的数据存储区
//返回值:0,正常
//其他,错误代码
uint8_t MPU_Read_Len(uint8_t Addr,uint8_t Length,uint8_t *Buffer)
{
        return (uint8_t)HAL_I2C_Mem_Read(&hi2c1,MPU_6050_AddR,Addr,1,Buffer,Length,10);       
}
//初始化MPU6050
//返回值:0,成功
//    其他,错误代码
uint8_t MPU_Init(void)
{
        uint8_t res;
        MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);        //复位MPU6050
  HAL_Delay(100);
        MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);        //唤醒MPU6050
        MPU_Set_Gyro_Fsr(3);                                        //陀螺仪传感器,±2000dps
        MPU_Set_Accel_Fsr(0);                                        //加速度传感器,±2g
        MPU_Set_Rate(50);                                                //设置采样率50Hz
        MPU_Write_Byte(MPU_INT_EN_REG,0X00);        //关闭所有中断
        MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);        //I2C主模式关闭
        MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);        //关闭FIFO
        MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80);        //INT引脚低电平有效
        res=MPU_Read_Byte(MPU_DEVICE_ID_REG);
        MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);        //设置CLKSEL,PLL X轴为参考
        MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);        //加速度与陀螺仪都工作
        MPU_Set_Rate(50);                                                //设置采样率为50Hz
        return res==104?1:0;
}
//设置MPU6050陀螺仪传感器满量程范围
//fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//返回值:0,设置成功
//其他,设置失败
uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr)
{
        return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围  
}
//设置MPU6050加速度传感器满量程范围
//fsr:0,±2g;1,±4g;2,±8g;3,±16g
//返回值:0,设置成功
//其他,设置失败
uint8_t MPU_Set_Accel_Fsr(uint8_t fsr)
{
        return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围  
}
//设置MPU6050的数字低通滤波器
//lpf:数字低通滤波频率(Hz)
//返回值:0,设置成功
//其他,设置失败
uint8_t MPU_Set_LPF(int16_t lpf)
{
        uint8_t data=0;
        if(lpf>=188)data=1;
        else if(lpf>=98)data=2;
        else if(lpf>=42)data=3;
        else if(lpf>=20)data=4;
        else if(lpf>=10)data=5;
        else data=6;
        return MPU_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器  
}
//设置MPU6050的采样率(假定Fs=1KHz)
//rate:4~1000(Hz)
//返回值:0,设置成功
//其他,设置失败
uint8_t MPU_Set_Rate(int16_t rate)
{
        uint8_t data;
        if(rate>1000)rate=1000;
        if(rate<4)rate=4;
        data=1000/rate-1;
        data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data);        //设置数字低通滤波器
        return MPU_Set_LPF(rate/2);        //自动设置LPF为采样率的一半
}

//得到温度值
//返回值:温度值(扩大了100倍)
int16_t MPU_Get_Temperature(void)
{
    uint8_t buf[2];
    int16_t raw;
                float temp;
                MPU_Read_Len(MPU_TEMP_OUTH_REG,2,buf);
    raw=((int16_t)buf[0]<<8)|buf[1];  
    temp=36.53+((double)raw)/340;  
    return temp*100;
}
//得到陀螺仪值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//其他,错误代码
uint8_t MPU_Get_Gyroscope(int16_t *gx,int16_t *gy,int16_t *gz)
{
    uint8_t buf[6],res;  
                res=MPU_Read_Len(MPU_GYRO_XOUTH_REG,6,buf);
                if(res==0)
                {
                        *gx=((int16_t)buf[0]<<8)|buf[1];  
                        *gy=((int16_t)buf[2]<<8)|buf[3];  
                        *gz=((int16_t)buf[4]<<8)|buf[5];
                }
    return res;
}
//得到加速度值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//其他,错误代码
uint8_t MPU_Get_Accelerometer(int16_t *ax,int16_t *ay,int16_t *az)
{
    uint8_t buf[6],res;  
        res=MPU_Read_Len(MPU_ACCEL_XOUTH_REG,6,buf);
        if(res==0)
        {
                *ax=((int16_t)buf[0]<<8)|buf[1];  
                *ay=((int16_t)buf[2]<<8)|buf[3];  
                *az=((int16_t)buf[4]<<8)|buf[5];
        }        
    return res;
}

#endif
[/mw_shl_code]
回复

使用道具 举报

8

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
146
金钱
146
注册时间
2017-12-4
在线时间
24 小时
 楼主| 发表于 2018-1-25 17:51:44 | 显示全部楼层
a496298685 发表于 2018-1-25 17:49
[mw_shl_code=c,false]#ifndef __MPU_6050_H
#define __MPU_6050_H

多谢!!!
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2017-11-27
在线时间
1 小时
发表于 2018-12-14 15:22:23 | 显示全部楼层
请问一下楼主,我在使用icm20948也是识别不了器件,如果可以,共享下你的代码可好527595943@qq.com谢谢!
回复

使用道具 举报

4

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
103
金钱
103
注册时间
2017-10-17
在线时间
18 小时
发表于 2019-3-6 17:26:21 | 显示全部楼层
楼主问题解决了吗?
回复

使用道具 举报

9

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
166
金钱
166
注册时间
2015-12-30
在线时间
32 小时
发表于 2019-7-30 18:07:23 | 显示全部楼层
本帖最后由 Talons 于 2019-7-30 23:23 编辑

你好,我和你的情况不太一样,WHO AM I读出来的是0xAE,不是手册说的0xAF,而且我用SPI,所以需要禁用IIC,但是写0x6A寄存器为0x10(I2C_DIS设置为1),但是再读0xFA(首位为1),却还是出来0x00,好像IIC没法正确禁止。SPI总线上其他设备正常,不知道这是我的芯片有问题还是大家的WHO AM I其实可以不一样。


试了一下午,发现上电后,必须给电源管理寄存器写操作进行复位,再操作其他寄存器才能正常。
回复

使用道具 举报

22

主题

66

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2017-3-18
在线时间
17 小时
发表于 2020-7-29 09:16:08 | 显示全部楼层
Talons 发表于 2019-7-30 18:07
你好,我和你的情况不太一样,WHO AM I读出来的是0xAE,不是手册说的0xAF,而且我用SPI,所以需要禁用IIC, ...

我使用的i2c,上电也软复位了,然后读出是id还是0xae,层主这个问题解决了吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-4-30 13:51

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表