[STM32F4] STM32F4_MPU6050六轴传感器详解

[复制链接]
 楼主| kqh11a 发表于 2023-6-29 18:53 | 显示全部楼层
MyMPU6050.c

  1. #include "stm32f4xx.h"               
  2. #include "MyMPU6050.h"
  3. #include "delay.h"
  4. #include "usart.h"


  5. //初始化MPU6050
  6. //返回值:0,成功
  7. //    其他,错误代码
  8. u8 MPU6050_Init(void)
  9. {
  10.         //该步骤严格按读取MPU6050姿态的步骤进行
  11.         u8 res;
  12.         IIC_Init();
  13.     //#define MPU_PWR_MGMT1_REG                0X6B        //电源管理寄存器1
  14.         MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X80);        //复位MPU6050  通过对电源管理寄存器1的位7写1来实现
  15.     //位7 DEVICE_RESET:该位设置1,重启内部寄存器到默认值。复位完成后该位自动清0。
  16.     delay_ms(100);
  17.         MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X00);        //唤醒MPU6050  通过使电源管理寄存器1清0,进入正常工作模式
  18.     //设置角速度传感器(陀螺仪)和加速度传感器的满量程范围
  19.     //设置两个传感器的满量程范围(FSR),分别通过陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置。
  20.     //我们一般设置陀螺仪的满量程范围为2000dps,加速度传感器的满量程范围为2g。
  21.         MPU6050_Set_Gyro_Fsr(3);                                        //陀螺仪传感器,±2000dps
  22.         MPU6050_Set_Accel_Fsr(0);                                        //加速度传感器,±2g
  23.         MPU6050_Set_Rate(50);                                                //设置采样率50Hz
  24.     //设置其他参数,其中包括关闭中断、关闭AUX IIC接口、禁止FIFO、设置陀螺仪采样率和设置数字低通滤波器(DLPF)
  25.         MPU6050_Write_Byte(MPU_INT_EN_REG,0X00);        //关闭所有中断  将中断使能寄存器的所有位写入0,关闭所有中断
  26.         MPU6050_Write_Byte(MPU_USER_CTRL_REG,0X00);        //I2C主模式关闭 也就是MPU6050充当主机,通过IIC和磁力传感器进行通讯,实现九轴传感器
  27.         MPU6050_Write_Byte(MPU_FIFO_EN_REG,0X00);        //关闭FIFO  将FIFO使能寄存器的所有位写入0,来关闭FIFO
  28.         MPU6050_Write_Byte(MPU_INTBP_CFG_REG,0X80);        //INT引脚低电平有效
  29.         res=MPU6050_Read_Byte(MPU_DEVICE_ID_REG);   //通过读取WHO_AM_I寄存器获取MPU6050的ID
  30.         if(res==MPU_Address)//器件ID正确   //判断ID是否是0X68
  31.         {
  32.         //配置系统时钟源并使能角速度传感器和加速度传感器
  33.                 MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X01);        //设置CLKSEL,PLL X轴为参考 通过设置电源管理寄存器1的最低位,设置系统时钟为001
  34.                 MPU6050_Write_Byte(MPU_PWR_MGMT2_REG,0X00);        //加速度与陀螺仪都工作  通过设置电源管理寄存器2的所有位为0来使能加速度计和陀螺仪,设置为1则加速度计和陀螺仪的X,Y,Z轴进入待机模式
  35.                 MPU6050_Set_Rate(50);                                                //设置采样率为50Hz
  36.         }
  37.     else
  38.         return 1; //ID错误
  39.         return 0;
  40. }
  41. //设置MPU6050的陀螺仪传感器满量程范围
  42. //FS_SEL:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
  43. //返回值:0,设置成功
  44. //                其他,设置失败
  45. u8 MPU6050_Set_Gyro_Fsr(u8 FS_SEL)
  46. {
  47.         return MPU6050_Write_Byte(MPU_GYRO_CFG_REG,FS_SEL<<3); //设置陀螺仪配置寄存器的位3和位4,这里选择量程3,±2000dps,所以配置为3即可
  48. }
  49. //设置MPU6050加速度传感器满量程范围
  50. //AFS_SEL::0,±2g;1,±4g;2,±8g;3,±16g
  51. //返回值:0,设置成功
  52. //    其他,设置失败
  53. u8 MPU6050_Set_Accel_Fsr(u8 AFS_SEL)
  54. {
  55.         return MPU6050_Write_Byte(MPU_ACCEL_CFG_REG,AFS_SEL<<3); //配置加速度传感器配置寄存器的位3和位4,所以需要左移三位,这里设置0,±2g;
  56. }
  57. //设置MPU6050的数字低通滤波器
  58. //PinLv:数字低通滤波频率
  59. //返回值:0,设置成功
  60. //    其他,设置失败
  61. u8 MPU6050_Set_LPF(u16 PinLv)
  62. {
  63.         u8 Data=0;
  64.         if(PinLv>=188)  //这里解释一下,为什么分别设置数字低通滤波频率为188 98 42 20 10 并且得到的低通滤波频率为1 2 3 4 5 6
  65.                                         //首先设置MPU6050的数字低通滤波器其实质是设置配置寄存器的低3位,根据官方MPU6050寄存器手册
  66.                 Data=1;     //当设置的数字低通滤波器频率大于188Hz时,配置寄存器的低三位写入001,也就是1
  67.         else if(PinLv>=98)
  68.                 Data=2;                //当设置的数字低通滤波器频率大于98Hz时,配置寄存器的低三位写入010,也就是2
  69.         else if(PinLv>=42)
  70.                 Data=3;                //当设置的数字低通滤波器频率大于42Hz时,配置寄存器的低三位写入011,也就是3
  71.         else if(PinLv>=20)
  72.                 Data=4;                //当设置的数字低通滤波器频率大于20Hz时,配置寄存器的低三位写入100,也就是4
  73.         else if(PinLv>=10)
  74.                 Data=5;                //当设置的数字低通滤波器频率大于10Hz时,配置寄存器的低三位写入101,也就是5
  75.         else
  76.                 Data=6;                //其他情况下均写入111,表示6
  77.         return MPU6050_Write_Byte(MPU_CFG_REG,Data);  //通过写配置寄存器的第三位即可设置数字低通滤波器
  78.     //#define MPU_CFG_REG                                0X1A        //配置寄存器
  79. }
  80. //设置MPU6050采样率
  81. //Rate:4~1000Hz
  82. //返回值:0,设置成功
  83. //    其他,设置失败
  84. u8 MPU6050_Set_Rate(u16 Rate) //这里一定要假设MPU6050的输出频率为1Khz,输出频率可以是1Khz或者8Khz,其值和数字低通滤波器的设置有关,当数字低通滤波器的低三位写入0或者7时,为8Khz,其余均是1Khz
  85. {
  86.         u8 Data;  //定义Data是采样率分频寄存器写入的8位数值
  87.         if(Rate>1000) //设置范围
  88.                 Rate=1000;
  89.         if(Rate<4)    //设置范围
  90.                 Rate=4;
  91.         Data=1000/Rate-1;  //采样频率 = 陀螺仪输出频率 / (1+SMPLRT_DIV)  其中SMPLRT_DIV就是Data,寄存器中写入的值
  92.         //采样频率 = 陀螺仪输出频率 / (1+Data) 其中输出频率是1Khz
  93.         Data=MPU6050_Write_Byte(MPU_SAMPLE_RATE_REG,Data); //设置数字低通滤波器
  94.         return MPU6050_Set_LPF(Rate/2); //自动设置数字低通滤波器为采样频率的一半
  95. }
  96. //得到温度值
  97. //返回值:温度值(扩大了100倍)
  98. short MPU6050_Get_Temperature(void)
  99. {
  100.         u8 Buffer[2]; //温度的值是由两个八位寄存器读取的,所以定义一个存储两字节大小的数组
  101.         short raw;  //短整型16位
  102.         float temperature;
  103.         MPU6050_Read_Len(MPU_Address,MPU_TEMP_OUTH_REG,2,Buffer);
  104.         raw=((u16)Buffer[0]<<8)|Buffer[1]; //16位温度值需要两个8位进行或运算
  105.         temperature=36.53+((double)raw)/340; //Temperature = 36.53 + regval/340 ,计算温度的公式 其中regval是从0X41和0X42寄存器读出的值
  106.         return temperature*100;
  107. }
  108. //得到陀螺仪原始值
  109. //GX,GY,GZ:陀螺仪X,Y,Z轴的原始读数
  110. //返回值:0,成功
  111. //    其他,错误代码
  112. u8 MPU6050_Get_Gyroscope(short *GX,short *GY,short *GZ)
  113. {
  114.         u8 Buffer[6];
  115.         u8 res;
  116.         res=MPU6050_Read_Len(MPU_Address,MPU_GYRO_XOUTH_REG,6,Buffer);//读陀螺仪的原始值是通过读6个陀螺仪数据输出寄存器,这些寄存器都是8位的,每两个寄存器拼接成一个16位的原始数据
  117.         if(res==0)//返回值为0,表示读成功
  118.         {
  119.                 *GX=((u16)Buffer[0]<<8)|Buffer[1];//因为先读的是寄存器的高8位
  120.                 *GY=((u16)Buffer[2]<<8)|Buffer[3];
  121.                 *GZ=((u16)Buffer[4]<<8)|Buffer[5];
  122.         }
  123.         return res;
  124. }
  125. //得到加速度计原始值
  126. //AX,AY,AZ:加速度计X,Y,Z轴的原始读数
  127. //返回值:0,成功
  128. //    其他,错误代码
  129. u8 MPU6050_Get_Accelerometer(short *AX,short *AY,short *AZ)
  130. {
  131.         u8 Buffer[6];
  132.         u8 res;
  133.         res=MPU6050_Read_Len(MPU_Address,MPU_ACCEL_XOUTH_REG,6,Buffer);//读加速度计的原始值是通过读6个加速度数据输出寄存器,这些寄存器都是8位的,每两个寄存器拼接成一个16位的原始数据
  134.         if(res==0)//返回值为0,表示读成功
  135.         {
  136.                 *AX=((u16)Buffer[0]<<8)|Buffer[1];//因为先读的是寄存器高8位
  137.                 *AY=((u16)Buffer[2]<<8)|Buffer[3];
  138.                 *AZ=((u16)Buffer[4]<<8)|Buffer[5];
  139.         }
  140.         return res;
  141. }
  142. //IIC连续写
  143. //Address:器件地址
  144. //Register:寄存器地址
  145. //Length:要写入的长度
  146. //Buffer:数据区
  147. //返回值:0,正常
  148. //                其他,错误代码
  149. u8 MPU6050_Write_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer)
  150. {
  151.         u8 i;
  152.         IIC_Start(); //发送起始信号
  153.         IIC_Send_Byte((Address<<1)|0); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯,地址最低位是读写位
  154.         //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|0表示左移一位再把最低位置0,也就表示主机写数据到从机
  155.         if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
  156.         {
  157.                 IIC_Stop();
  158.                 return 1;
  159.         }
  160.         IIC_Send_Byte(Register); //跳过if判断语句就意味着从机接收到了主机的信号,主机发送寄存器地址
  161.         IIC_Wait_Ack(); //等待从机应答
  162.         for(i=0;i<Length;i++)
  163.         {
  164.                 IIC_Send_Byte(Buffer[i]);//通过循环一位一位的发送数据,发送Length字节长的数据
  165.                 if(IIC_Wait_Ack())//IIC时序规定每发送一位,从机都要应答一次
  166.                 {
  167.                         IIC_Stop();
  168.                         return 1;
  169.                 }
  170.         }
  171.         IIC_Stop(); //发送完毕,IIC通讯结束
  172.         return 0;
  173. }
  174. //IIC连续读
  175. //Address:器件地址
  176. //Register:要读取的寄存器地址
  177. //Length:要读取的长度
  178. //Buffer:读取到的数据存储区
  179. //返回值:0,正常
  180. //                其他,错误代码
  181. u8 MPU6050_Read_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer)
  182. {
  183.         IIC_Start(); //发送起始信号
  184.         IIC_Send_Byte((Address<<1)|0); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯
  185.         //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|0表示左移一位再把最低位置0,也就表示主机写数据到从机
  186.         if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
  187.         {
  188.                 IIC_Stop();
  189.                 return 1;
  190.         }
  191.         IIC_Send_Byte(Register); //跳过if判断语句就意味着从机接收到了主机的信号,主机发送寄存器地址
  192.         IIC_Wait_Ack(); //等待从机应答
  193.         IIC_Start(); //发送起始信号
  194.         IIC_Send_Byte((Address<<1)|1); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯
  195.         //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|1表示左移一位再把最低位置1,也就表示主机从从机中读数据
  196.         IIC_Wait_Ack(); //等待从机应答
  197.         while(Length)
  198.         {
  199.                 if(Length==1)//如果只写入了一个节长的数据,那么发送NAck
  200.                 {
  201.                         *Buffer=IIC_Read_Byte(0); //不产生应答
  202.                 }
  203.                 else
  204.                         *Buffer=IIC_Read_Byte(1);//产生应答
  205.                 Length--;
  206.                 Buffer++;
  207.         }
  208.         IIC_Stop();
  209.         return 0;
  210. }
  211. //IIC写一个字节
  212. //Register:寄存器地址
  213. //Data:数据
  214. //返回值:0,正常
  215. //                其他,错误代码
  216. u8 MPU6050_Write_Byte(u8 Register,u8 Data)
  217. {
  218.         IIC_Start();
  219.         IIC_Send_Byte((MPU_Address<<1)|0); //注意写一位写字节时,发送的是从机IIC的地址
  220.         if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
  221.         {
  222.                 IIC_Stop();
  223.                 return 1;
  224.         }
  225.         IIC_Send_Byte(Register);
  226.         IIC_Wait_Ack();
  227.         IIC_Send_Byte(Data);
  228.         if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
  229.         {
  230.                 IIC_Stop();
  231.                 return 1;
  232.         }
  233.         IIC_Stop();
  234.         return 0;
  235. }
  236. //IIC读一个字节
  237. //Register:寄存器地址
  238. //返回值:读到的数据
  239. u8 MPU6050_Read_Byte(u8 Register)
  240. {
  241.         u8 res;
  242.         IIC_Start();
  243.         IIC_Send_Byte((MPU_Address<<1)|0);
  244.         IIC_Wait_Ack();
  245.         IIC_Send_Byte(Register);
  246.         IIC_Wait_Ack();
  247.         IIC_Start();
  248.         IIC_Send_Byte((MPU_Address<<1)|1);
  249.         IIC_Wait_Ack();
  250.         res=IIC_Read_Byte(0);
  251.         IIC_Stop();
  252.         return res;
  253. }

 楼主| kqh11a 发表于 2023-6-29 18:53 | 显示全部楼层
MyMPU6050.c
  1. #include "stm32f4xx.h"               
  2. #include "MyMPU6050.h"
  3. #include "delay.h"
  4. #include "usart.h"


  5. //初始化MPU6050
  6. //返回值:0,成功
  7. //    其他,错误代码
  8. u8 MPU6050_Init(void)
  9. {
  10.         //该步骤严格按读取MPU6050姿态的步骤进行
  11.         u8 res;
  12.         IIC_Init();
  13.     //#define MPU_PWR_MGMT1_REG                0X6B        //电源管理寄存器1
  14.         MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X80);        //复位MPU6050  通过对电源管理寄存器1的位7写1来实现
  15.     //位7 DEVICE_RESET:该位设置1,重启内部寄存器到默认值。复位完成后该位自动清0。
  16.     delay_ms(100);
  17.         MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X00);        //唤醒MPU6050  通过使电源管理寄存器1清0,进入正常工作模式
  18.     //设置角速度传感器(陀螺仪)和加速度传感器的满量程范围
  19.     //设置两个传感器的满量程范围(FSR),分别通过陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置。
  20.     //我们一般设置陀螺仪的满量程范围为2000dps,加速度传感器的满量程范围为2g。
  21.         MPU6050_Set_Gyro_Fsr(3);                                        //陀螺仪传感器,±2000dps
  22.         MPU6050_Set_Accel_Fsr(0);                                        //加速度传感器,±2g
  23.         MPU6050_Set_Rate(50);                                                //设置采样率50Hz
  24.     //设置其他参数,其中包括关闭中断、关闭AUX IIC接口、禁止FIFO、设置陀螺仪采样率和设置数字低通滤波器(DLPF)
  25.         MPU6050_Write_Byte(MPU_INT_EN_REG,0X00);        //关闭所有中断  将中断使能寄存器的所有位写入0,关闭所有中断
  26.         MPU6050_Write_Byte(MPU_USER_CTRL_REG,0X00);        //I2C主模式关闭 也就是MPU6050充当主机,通过IIC和磁力传感器进行通讯,实现九轴传感器
  27.         MPU6050_Write_Byte(MPU_FIFO_EN_REG,0X00);        //关闭FIFO  将FIFO使能寄存器的所有位写入0,来关闭FIFO
  28.         MPU6050_Write_Byte(MPU_INTBP_CFG_REG,0X80);        //INT引脚低电平有效
  29.         res=MPU6050_Read_Byte(MPU_DEVICE_ID_REG);   //通过读取WHO_AM_I寄存器获取MPU6050的ID
  30.         if(res==MPU_Address)//器件ID正确   //判断ID是否是0X68
  31.         {
  32.         //配置系统时钟源并使能角速度传感器和加速度传感器
  33.                 MPU6050_Write_Byte(MPU_PWR_MGMT1_REG,0X01);        //设置CLKSEL,PLL X轴为参考 通过设置电源管理寄存器1的最低位,设置系统时钟为001
  34.                 MPU6050_Write_Byte(MPU_PWR_MGMT2_REG,0X00);        //加速度与陀螺仪都工作  通过设置电源管理寄存器2的所有位为0来使能加速度计和陀螺仪,设置为1则加速度计和陀螺仪的X,Y,Z轴进入待机模式
  35.                 MPU6050_Set_Rate(50);                                                //设置采样率为50Hz
  36.         }
  37.     else
  38.         return 1; //ID错误
  39.         return 0;
  40. }
  41. //设置MPU6050的陀螺仪传感器满量程范围
  42. //FS_SEL:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
  43. //返回值:0,设置成功
  44. //                其他,设置失败
  45. u8 MPU6050_Set_Gyro_Fsr(u8 FS_SEL)
  46. {
  47.         return MPU6050_Write_Byte(MPU_GYRO_CFG_REG,FS_SEL<<3); //设置陀螺仪配置寄存器的位3和位4,这里选择量程3,±2000dps,所以配置为3即可
  48. }
  49. //设置MPU6050加速度传感器满量程范围
  50. //AFS_SEL::0,±2g;1,±4g;2,±8g;3,±16g
  51. //返回值:0,设置成功
  52. //    其他,设置失败
  53. u8 MPU6050_Set_Accel_Fsr(u8 AFS_SEL)
  54. {
  55.         return MPU6050_Write_Byte(MPU_ACCEL_CFG_REG,AFS_SEL<<3); //配置加速度传感器配置寄存器的位3和位4,所以需要左移三位,这里设置0,±2g;
  56. }
  57. //设置MPU6050的数字低通滤波器
  58. //PinLv:数字低通滤波频率
  59. //返回值:0,设置成功
  60. //    其他,设置失败
  61. u8 MPU6050_Set_LPF(u16 PinLv)
  62. {
  63.         u8 Data=0;
  64.         if(PinLv>=188)  //这里解释一下,为什么分别设置数字低通滤波频率为188 98 42 20 10 并且得到的低通滤波频率为1 2 3 4 5 6
  65.                                         //首先设置MPU6050的数字低通滤波器其实质是设置配置寄存器的低3位,根据官方MPU6050寄存器手册
  66.                 Data=1;     //当设置的数字低通滤波器频率大于188Hz时,配置寄存器的低三位写入001,也就是1
  67.         else if(PinLv>=98)
  68.                 Data=2;                //当设置的数字低通滤波器频率大于98Hz时,配置寄存器的低三位写入010,也就是2
  69.         else if(PinLv>=42)
  70.                 Data=3;                //当设置的数字低通滤波器频率大于42Hz时,配置寄存器的低三位写入011,也就是3
  71.         else if(PinLv>=20)
  72.                 Data=4;                //当设置的数字低通滤波器频率大于20Hz时,配置寄存器的低三位写入100,也就是4
  73.         else if(PinLv>=10)
  74.                 Data=5;                //当设置的数字低通滤波器频率大于10Hz时,配置寄存器的低三位写入101,也就是5
  75.         else
  76.                 Data=6;                //其他情况下均写入111,表示6
  77.         return MPU6050_Write_Byte(MPU_CFG_REG,Data);  //通过写配置寄存器的第三位即可设置数字低通滤波器
  78.     //#define MPU_CFG_REG                                0X1A        //配置寄存器
  79. }
  80. //设置MPU6050采样率
  81. //Rate:4~1000Hz
  82. //返回值:0,设置成功
  83. //    其他,设置失败
  84. u8 MPU6050_Set_Rate(u16 Rate) //这里一定要假设MPU6050的输出频率为1Khz,输出频率可以是1Khz或者8Khz,其值和数字低通滤波器的设置有关,当数字低通滤波器的低三位写入0或者7时,为8Khz,其余均是1Khz
  85. {
  86.         u8 Data;  //定义Data是采样率分频寄存器写入的8位数值
  87.         if(Rate>1000) //设置范围
  88.                 Rate=1000;
  89.         if(Rate<4)    //设置范围
  90.                 Rate=4;
  91.         Data=1000/Rate-1;  //采样频率 = 陀螺仪输出频率 / (1+SMPLRT_DIV)  其中SMPLRT_DIV就是Data,寄存器中写入的值
  92.         //采样频率 = 陀螺仪输出频率 / (1+Data) 其中输出频率是1Khz
  93.         Data=MPU6050_Write_Byte(MPU_SAMPLE_RATE_REG,Data); //设置数字低通滤波器
  94.         return MPU6050_Set_LPF(Rate/2); //自动设置数字低通滤波器为采样频率的一半
  95. }
  96. //得到温度值
  97. //返回值:温度值(扩大了100倍)
  98. short MPU6050_Get_Temperature(void)
  99. {
  100.         u8 Buffer[2]; //温度的值是由两个八位寄存器读取的,所以定义一个存储两字节大小的数组
  101.         short raw;  //短整型16位
  102.         float temperature;
  103.         MPU6050_Read_Len(MPU_Address,MPU_TEMP_OUTH_REG,2,Buffer);
  104.         raw=((u16)Buffer[0]<<8)|Buffer[1]; //16位温度值需要两个8位进行或运算
  105.         temperature=36.53+((double)raw)/340; //Temperature = 36.53 + regval/340 ,计算温度的公式 其中regval是从0X41和0X42寄存器读出的值
  106.         return temperature*100;
  107. }
  108. //得到陀螺仪原始值
  109. //GX,GY,GZ:陀螺仪X,Y,Z轴的原始读数
  110. //返回值:0,成功
  111. //    其他,错误代码
  112. u8 MPU6050_Get_Gyroscope(short *GX,short *GY,short *GZ)
  113. {
  114.         u8 Buffer[6];
  115.         u8 res;
  116.         res=MPU6050_Read_Len(MPU_Address,MPU_GYRO_XOUTH_REG,6,Buffer);//读陀螺仪的原始值是通过读6个陀螺仪数据输出寄存器,这些寄存器都是8位的,每两个寄存器拼接成一个16位的原始数据
  117.         if(res==0)//返回值为0,表示读成功
  118.         {
  119.                 *GX=((u16)Buffer[0]<<8)|Buffer[1];//因为先读的是寄存器的高8位
  120.                 *GY=((u16)Buffer[2]<<8)|Buffer[3];
  121.                 *GZ=((u16)Buffer[4]<<8)|Buffer[5];
  122.         }
  123.         return res;
  124. }
  125. //得到加速度计原始值
  126. //AX,AY,AZ:加速度计X,Y,Z轴的原始读数
  127. //返回值:0,成功
  128. //    其他,错误代码
  129. u8 MPU6050_Get_Accelerometer(short *AX,short *AY,short *AZ)
  130. {
  131.         u8 Buffer[6];
  132.         u8 res;
  133.         res=MPU6050_Read_Len(MPU_Address,MPU_ACCEL_XOUTH_REG,6,Buffer);//读加速度计的原始值是通过读6个加速度数据输出寄存器,这些寄存器都是8位的,每两个寄存器拼接成一个16位的原始数据
  134.         if(res==0)//返回值为0,表示读成功
  135.         {
  136.                 *AX=((u16)Buffer[0]<<8)|Buffer[1];//因为先读的是寄存器高8位
  137.                 *AY=((u16)Buffer[2]<<8)|Buffer[3];
  138.                 *AZ=((u16)Buffer[4]<<8)|Buffer[5];
  139.         }
  140.         return res;
  141. }
  142. //IIC连续写
  143. //Address:器件地址
  144. //Register:寄存器地址
  145. //Length:要写入的长度
  146. //Buffer:数据区
  147. //返回值:0,正常
  148. //                其他,错误代码
  149. u8 MPU6050_Write_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer)
  150. {
  151.         u8 i;
  152.         IIC_Start(); //发送起始信号
  153.         IIC_Send_Byte((Address<<1)|0); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯,地址最低位是读写位
  154.         //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|0表示左移一位再把最低位置0,也就表示主机写数据到从机
  155.         if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
  156.         {
  157.                 IIC_Stop();
  158.                 return 1;
  159.         }
  160.         IIC_Send_Byte(Register); //跳过if判断语句就意味着从机接收到了主机的信号,主机发送寄存器地址
  161.         IIC_Wait_Ack(); //等待从机应答
  162.         for(i=0;i<Length;i++)
  163.         {
  164.                 IIC_Send_Byte(Buffer[i]);//通过循环一位一位的发送数据,发送Length字节长的数据
  165.                 if(IIC_Wait_Ack())//IIC时序规定每发送一位,从机都要应答一次
  166.                 {
  167.                         IIC_Stop();
  168.                         return 1;
  169.                 }
  170.         }
  171.         IIC_Stop(); //发送完毕,IIC通讯结束
  172.         return 0;
  173. }
  174. //IIC连续读
  175. //Address:器件地址
  176. //Register:要读取的寄存器地址
  177. //Length:要读取的长度
  178. //Buffer:读取到的数据存储区
  179. //返回值:0,正常
  180. //                其他,错误代码
  181. u8 MPU6050_Read_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer)
  182. {
  183.         IIC_Start(); //发送起始信号
  184.         IIC_Send_Byte((Address<<1)|0); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯
  185.         //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|0表示左移一位再把最低位置0,也就表示主机写数据到从机
  186.         if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
  187.         {
  188.                 IIC_Stop();
  189.                 return 1;
  190.         }
  191.         IIC_Send_Byte(Register); //跳过if判断语句就意味着从机接收到了主机的信号,主机发送寄存器地址
  192.         IIC_Wait_Ack(); //等待从机应答
  193.         IIC_Start(); //发送起始信号
  194.         IIC_Send_Byte((Address<<1)|1); //主机向从机发送器件地址,也就是主机想要和从机的哪块地址进行通讯
  195.         //IIC发送的从机地址是7位,最低位是R/W:主从写方向位,(Address<<1)|1表示左移一位再把最低位置1,也就表示主机从从机中读数据
  196.         IIC_Wait_Ack(); //等待从机应答
  197.         while(Length)
  198.         {
  199.                 if(Length==1)//如果只写入了一个节长的数据,那么发送NAck
  200.                 {
  201.                         *Buffer=IIC_Read_Byte(0); //不产生应答
  202.                 }
  203.                 else
  204.                         *Buffer=IIC_Read_Byte(1);//产生应答
  205.                 Length--;
  206.                 Buffer++;
  207.         }
  208.         IIC_Stop();
  209.         return 0;
  210. }
  211. //IIC写一个字节
  212. //Register:寄存器地址
  213. //Data:数据
  214. //返回值:0,正常
  215. //                其他,错误代码
  216. u8 MPU6050_Write_Byte(u8 Register,u8 Data)
  217. {
  218.         IIC_Start();
  219.         IIC_Send_Byte((MPU_Address<<1)|0); //注意写一位写字节时,发送的是从机IIC的地址
  220.         if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
  221.         {
  222.                 IIC_Stop();
  223.                 return 1;
  224.         }
  225.         IIC_Send_Byte(Register);
  226.         IIC_Wait_Ack();
  227.         IIC_Send_Byte(Data);
  228.         if(IIC_Wait_Ack()) //等待从机应答,IIC_Wait_Ack该函数的返回值若为1,则表示没有接收到从机的应答信号,IIC通讯结束
  229.         {
  230.                 IIC_Stop();
  231.                 return 1;
  232.         }
  233.         IIC_Stop();
  234.         return 0;
  235. }
  236. //IIC读一个字节
  237. //Register:寄存器地址
  238. //返回值:读到的数据
  239. u8 MPU6050_Read_Byte(u8 Register)
  240. {
  241.         u8 res;
  242.         IIC_Start();
  243.         IIC_Send_Byte((MPU_Address<<1)|0);
  244.         IIC_Wait_Ack();
  245.         IIC_Send_Byte(Register);
  246.         IIC_Wait_Ack();
  247.         IIC_Start();
  248.         IIC_Send_Byte((MPU_Address<<1)|1);
  249.         IIC_Wait_Ack();
  250.         res=IIC_Read_Byte(0);
  251.         IIC_Stop();
  252.         return res;
  253. }

 楼主| kqh11a 发表于 2023-6-29 18:55 | 显示全部楼层
MyMPU6050.h

  1. #ifndef _MYMPU6050__H_
  2. #define _MYMPU6050__H_
  3. #include "sys.h"
  4. #include "MyI2C.h"

  5. /
  6. //MyMPU6050.h头文件的寄存器地址宏定义均来源于MPU6050寄存器手册。如果想要了解每一种寄存器对应位的具体功能,请查阅MPU6050寄存器手册。
  7. #define MPU_SELF_TESTX_REG                0X0D        //自检寄存器X
  8. #define MPU_SELF_TESTY_REG                0X0E        //自检寄存器Y
  9. #define MPU_SELF_TESTZ_REG                0X0F        //自检寄存器Z
  10. #define MPU_SELF_TESTA_REG                0X10        //自检寄存器A
  11. #define MPU_SAMPLE_RATE_REG                0X19        //采样频率分频器
  12. #define MPU_CFG_REG                                0X1A        //配置寄存器
  13. #define MPU_GYRO_CFG_REG                0X1B        //陀螺仪配置寄存器
  14. #define MPU_ACCEL_CFG_REG                0X1C        //加速度计配置寄存器
  15. #define MPU_MOTION_DET_REG                0X1F        //运动检测阀值设置寄存器
  16. #define MPU_FIFO_EN_REG                        0X23        //FIFO使能寄存器
  17. #define MPU_I2CMST_CTRL_REG                0X24        //IIC主机控制寄存器
  18. #define MPU_I2CSLV0_ADDR_REG        0X25        //IIC从机0器件地址寄存器
  19. #define MPU_I2CSLV0_REG                        0X26        //IIC从机0数据地址寄存器
  20. #define MPU_I2CSLV0_CTRL_REG        0X27        //IIC从机0控制寄存器
  21. #define MPU_I2CSLV1_ADDR_REG        0X28        //IIC从机1器件地址寄存器
  22. #define MPU_I2CSLV1_REG                        0X29        //IIC从机1数据地址寄存器
  23. #define MPU_I2CSLV1_CTRL_REG        0X2A        //IIC从机1控制寄存器
  24. #define MPU_I2CSLV2_ADDR_REG        0X2B        //IIC从机2器件地址寄存器
  25. #define MPU_I2CSLV2_REG                        0X2C        //IIC从机2数据地址寄存器
  26. #define MPU_I2CSLV2_CTRL_REG        0X2D        //IIC从机2控制寄存器
  27. #define MPU_I2CSLV3_ADDR_REG        0X2E        //IIC从机3器件地址寄存器
  28. #define MPU_I2CSLV3_REG                        0X2F        //IIC从机3数据地址寄存器
  29. #define MPU_I2CSLV3_CTRL_REG        0X30        //IIC从机3控制寄存器
  30. #define MPU_I2CSLV4_ADDR_REG        0X31        //IIC从机4器件地址寄存器
  31. #define MPU_I2CSLV4_REG                        0X32        //IIC从机4数据地址寄存器
  32. #define MPU_I2CSLV4_DO_REG                0X33        //IIC从机4写数据寄存器
  33. #define MPU_I2CSLV4_CTRL_REG        0X34        //IIC从机4控制寄存器
  34. #define MPU_I2CSLV4_DI_REG                0X35        //IIC从机4读数据寄存器

  35. #define MPU_I2CMST_STA_REG                0X36        //IIC主机状态寄存器
  36. #define MPU_INTBP_CFG_REG                0X37        //中断/旁路设置寄存器
  37. #define MPU_INT_EN_REG                        0X38        //中断使能寄存器
  38. #define MPU_INT_STA_REG                        0X3A        //中断状态寄存器

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

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

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

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

  57. #define MPU_I2CMST_DELAY_REG        0X67        //IIC主机延时管理寄存器
  58. #define MPU_SIGPATH_RST_REG                0X68        //信号通道复位寄存器
  59. #define MPU_MDETECT_CTRL_REG        0X69        //运动检测控制寄存器
  60. #define MPU_USER_CTRL_REG                0X6A        //用户控制寄存器
  61. #define MPU_PWR_MGMT1_REG                0X6B        //电源管理寄存器1
  62. #define MPU_PWR_MGMT2_REG                0X6C        //电源管理寄存器2
  63. #define MPU_FIFO_CNTH_REG                0X72        //FIFO计数寄存器高八位
  64. #define MPU_FIFO_CNTL_REG                0X73        //FIFO计数寄存器低八位
  65. #define MPU_FIFO_RW_REG                        0X74        //FIFO读写寄存器
  66. #define MPU_DEVICE_ID_REG                0X75        //器件ID寄存器

  67. //如果MPU6050芯片的引脚A0接地,IIC地址为0X68
  68. //如果MPU6050芯片的引脚A0接电源3.3V,则IIC的地址为0X69
  69. #define MPU_Address 0X68



  70. u8 MPU6050_Init(void);
  71. u8 MPU6050_Set_Gyro_Fsr(u8 FS_SEL);
  72. u8 MPU6050_Set_Accel_Fsr(u8 AFS_SEL);
  73. u8 MPU6050_Set_LPF(u16 PinLv);
  74. u8 MPU6050_Set_Rate(u16 Rate);
  75. short MPU6050_Get_Temperature(void);
  76. u8 MPU6050_Get_Gyroscope(short *GX,short *GY,short *GZ);
  77. u8 MPU6050_Get_Accelerometer(short *AX,short *AY,short *AZ);
  78. u8 MPU6050_Write_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer);
  79. u8 MPU6050_Read_Len(u8 Address,u8 Register,u8 Length,u8 *Buffer);
  80. u8 MPU6050_Write_Byte(u8 Register,u8 Data);
  81. u8 MPU6050_Read_Byte(u8 Register);


  82. #endif

Bblythe 发表于 2023-12-1 07:14 | 显示全部楼层

减小检测部分与电压误差或电流放大器敏感的输入端之间的连接而引入的噪声
周半梅 发表于 2023-12-1 09:10 | 显示全部楼层

引线越长,它能接收和传送的干扰信号频率就越低
Pulitzer 发表于 2023-12-1 10:13 | 显示全部楼层

输入电压端上测得的值比它实际
童雨竹 发表于 2023-12-1 12:09 | 显示全部楼层

引线的长和宽影响它的电阻和电感量
Wordsworth 发表于 2023-12-1 13:12 | 显示全部楼层

它们的放置要尽可能靠近
Clyde011 发表于 2023-12-1 14:15 | 显示全部楼层

大地的地会通过散热器(用绝缘体与漏极隔开)从这些节点获取能量
万图 发表于 2023-12-1 16:11 | 显示全部楼层

输入电源电流环路
Uriah 发表于 2023-12-1 17:14 | 显示全部楼层

交流节点会引起特有的问题
帛灿灿 发表于 2023-12-1 19:10 | 显示全部楼层

输入和输出电流环路连接的位置只能是相应的输入 输出电容的接线端
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部