前言
消失了几天的我在哪?对,没错,就在实验室默默的调试代码。
折磨我几天的MPU终于弄好了(虽然只是弄好一半,但是也是值得令人开心的)
本节介绍
本节主要介绍关于stm32使用IIC来读取mpu数据的过程,准确来说是模拟IIC读取mpu6050以及9250的相关过程
一、IIC通讯
1.1 IIC通讯简介
简单来说IIC是一种通讯方式,一般的连线方式是这样的。
也就是说IIC需要三根线对外设进行通讯。SCL、SDA以及GND。在使用模块的时候可能会有其他的要求,比方说接5V,或者接地,这部分在开发的时候再进一步叙述。因为版权问题,IIC在STM32中设计的比较复杂(这部分看杨桃的IIC代码就明白了),最然说直接用就行了,但是还需要稍微懂一些。所以我们一般使用模拟IIC实现IIC的通讯功能。模拟IIC这里不给出代码,但是会解释有哪些步骤
1.2 模拟IIC
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号
这是模拟IIC实现函数,有些代码中可能有一些延时,没得关系。
实际使用的使用还有一些坑:
- 1模拟IIC虽然不是真正的IIC,但是仍然也需要在原来的IIC端口上面才能开模拟IIC(我是这样觉得的)
- 2一定要注意你的芯片IIC端口,和你代码的IIC端口要一致(比方说下面的代码就是PC12、PC11端口)连线更不能错。
//IO方向设置
#define SDA_IN() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}
#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}
//IO操作函数
#define IIC_SCL PCout(12) //SCL
#define IIC_SDA PCout(11) //SDA
#define READ_SDA PCin(11) //输入SDA
关于IO端口方向问题,建议看这位博主的介绍:(59条消息) GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=(u32)8<<12;(学习笔记)_gpiob->crh_浦子哥的博客-优快云博客
1.3 mpu外设
这一块直接介绍两个外设:mpu6050以及9250,因为还不做开发,所以先说一下模块:
IIC连接上面四根线就行了(9250连线也是这样)
6050主要是三轴陀螺仪与三轴加速度计组成
9250是6500(类似6050)结合磁力计组成
在设计过程中6050可以使用IIC,9250不仅可以使用IIC还可以使用spi(通讯方式)
DMP是MPU模块中官方设计的一个固件装置,这个装置对于新手比较友好,比方说能够固件滤波。9250固件库甚至有直接换成算四元素的封装函数。但是,即使优点那么多,我们还是需要使用原始数据的。(因为我们要实现更加准确的滤波算法)后面会实现位姿准换以及滤波实现。
模拟IIC对于MPU设定的ID和实际地址:
9250:
#define MPU9250_ADDR 0X68 //MPU6500的器件IIC地址
磁力计的ID地址比较复杂
6050:
//如果AD0脚(9脚)接地,IIC地址为0X68(不包含最低位).
//如果接V3.3,则IIC地址为0X69(不包含最低位).
#define MPU_ADDR 0X68
二、实现
实现模拟IIC读取MPU的逻辑:
STM32采用IIC对MPU建立通讯,然后使用USART串口实现调试(也可以使用LCD显示屏)
2.1 代码实现
实际代码初始化MPU以及模拟IIC(模拟IIC可以放在MPU中初始化)然后在mpu的驱动函数中直接找出读取的数据然后放在主函数定义的数据里面就行了,具体说就是
MPU_Get_Accelerometer()
MPU_Get_Gyroscope()
printf()打印给串口调试工具就行了
2.2 BUG
可能出现的bug问题:
- 一定要注意:你是否成功初始化了MPU以及模拟IIC两部分,是否能够运行到while(1)循环(因为你器件的问题就不会初始化结束卡住了),建议在while里面放一个LED0=!LED0来提示系统正在运行。
- 你的模拟IIC定义的引脚还有MPU模块连线是否有问题,很大有可能复制别人模块忘记调端口了,导致芯片的IIC端口不对,或者设置的端口就不是你连接的端口
- 你的器件模块一旦AD0接线了那你的MPU的ID地址就不对了
- IIC端口设置为开漏输出(不一定有用)。正点官方是推挽输出。之前看了别人的博客说是需要设定为开漏输出,也就是这里:
void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; //RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11; //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//开漏输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); IIC_SCL=1; IIC_SDA=1; }
上述是仅仅从模拟IIC与MPU建立通讯的角度来谈的,后面博客还会进一步就滤波还有频率问题仔细的研究。代码因为涉及版权就不放出来了。
三、感谢
感谢这些博主还有官网的支持
正点原子
杨桃电子
(59条消息) STM32 软件模拟IIC_stm32模拟iic_一个旅者的博客-优快云博客
【快速入门】MPU6050工作原理及应用_哔哩哔哩_bilibili