stm32 mpu6050 模拟i2c实例实现

发布者:静逸闲云最新更新时间:2019-08-09 来源: eefocus关键字:stm32  mpu6050  模拟i2c 手机看文章 扫描二维码
随时随地手机看文章

    最近准备一个比赛,所以正在加紧学习stm32,这篇文章就结合mpu6050分析一下利用i2c实现芯片之间的通信。


    首先可以在原有的LED文件或显示屏(OLED)的文件基础上,新建一个HANDWARE,在其中加入mpu6050.c和mpu6050.h(名字自定)。

    首先是在C文件中加入基本的I2C通信函数


    1.I2C的GPIO端口初始化SDA、SCL设置为推挽输出。


    2.然后是i2c_start();i2c_stop();函数,根据时序图设置SCL、SDA的高低电平变化。


    3.之后加入主机ack的响应函数和ack的等待响应函数i2c_wait_ack();i2c_ack();i2c_waitack();。


    4.最后加入IIC_Send_Byte();和IIC_Read_Byte();


    具体实现可以参考其他文章,这里重点讲解mpu6050的通信实现。


    上面部分的一个难点在于GPIO口的模式转化,因为SDA的输入输出在变化,所以可以使用寄存器操作的宏定义来改变IO口的模式,使用位操作来控制SDA、SCL的高低电平。其中在wait_ack中设置SDA为输入,可以通过SDA_w的设置达到输入的上拉、下拉的设置,具体参考下面的端口位配置表。


#define SDA_IN()  {GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=8<<0;}

#define SDA_OUT() {GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=3<<0;}

 

//IO操作函数  

#define SCL    PBout(9) //SCL

#define SDA_w    PBout(8) //SDA  

#define SDA_r  PBin(8) //输入SDA 

       完成上面的I2C函数,就可以根据I2C函数完成mpu6050函数的编写了。对于具体芯片,有具体的时序分析。这部分也可以参考其他文章,这里列出实例。


u8 MPU_Write_Byte(u8 reg,u8 data)  

    i2c_start(); 

IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令

if(i2c_wait_ack()) //等待应答

{

i2c_stop();  

return 1;

}

    IIC_Send_Byte(reg); //写寄存器地址

    i2c_wait_ack(); //等待应答 

IIC_Send_Byte(data);//发送数据

if(i2c_wait_ack()) //等待ACK

{

i2c_stop();  

return 1;  

}  

    i2c_stop();  

return 0;

}

u8 MPU_Read_Byte(u8 reg)

{

u8 res;

    i2c_start(); 

IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令

i2c_wait_ack(); //等待应答 

    IIC_Send_Byte(reg); //写寄存器地址

    i2c_wait_ack(); //等待应答

    i2c_start();

IIC_Send_Byte((MPU_ADDR<<1)|1);//发送器件地址+读命令

    i2c_wait_ack(); //等待应答 

res=IIC_Read_Byte(0);//读取数据,发送nACK 

    i2c_stop(); //产生一个停止条件 

return res;

}

    


  1.针对mpu6050写出具体的字节发送、读取函数,mpu6050主要用到了MPU_Read_Byte,MPU_Write_Byte,MPU_Read_Len(连续读函数)。


    2.mpu6050的初始化函数MPU_Init(),其中会向芯片的指定寄存器传入参数,所以可以在.h文件中加入寄存器的宏定义。


    3.根据需要定义向指定寄存器读取数值的函数,mpu6050可以读取陀螺仪值、加速度值、温度值。


    其中加速度计通过重力加速度分解(利用atan2)可以得到倾角,而陀螺仪则可以测得角速度。但是这两类数据都不准确,需要数据融合。


这里给出一个互补滤波的算法。


    Angle = (0.98) * (Angle + gyro * dt) + (0.02) *(acc); 


    利用这个算法可以得到较精确的值。

关键字:stm32  mpu6050  模拟i2c 引用地址:stm32 mpu6050 模拟i2c实例实现

上一篇:STM32(五)IIC通信原理及IO口软件模拟编程
下一篇:STM32(五)IIC通信原理及IO口软件模拟编程

推荐阅读最新更新时间:2024-11-17 05:41

STM32学习笔记-FLASH读写
STM32的FLASH除了可以烧写如程序外,还可以供给用户做存储器,存储参数用,但是要注意的是,FLSAH的擦写次数是有限制的,10万次。 STM32F1系列单片机内核是Cortext-M3系列的,其存储器的映射是按照Cortext-M3的标准设计的,如下图。 从上图可看出最下main的512M是分配给Code 即程序存储区. 其内部分配如下图。 从上图可以看到FLASH的起始地址是:0x0800 0000 到 0x0807 FFFF ,126M的FLASH空间。STM32按页来编程擦写FLASH,如我的 STM32F103RCT6 SRAM为48KB,FLASH有256K. 分页是2Kb一页来设计的,而又的小容量的单
[单片机]
<font color='red'>STM32</font>学习笔记-FLASH读写
STM32F103利用模拟I2C驱动ADS1115
ADS1115通过模拟I2C驱动:(部分代码借鉴了网络上的几个,并且根据引脚进行了配置,都没有运行成功,今天调了一天,终于在晚上调了出来) 注意:本部分代码需要只是ADS1115的部分程序(一些用到的数组在此没有写),模拟II2C的各程序并未给出,大家根据需要进行裁剪,代码完全开源,希望能帮到大家,也希望大家乐于分享。 调试时需特别注意I2C的通信问题,特别是应答信号的使用需要特别关注,本人的程序之前出错全是因为从机的应答信号的未使用造成。 如有其它问题,欢迎指正批评,第一次写博客,感谢! 收获:对于I2C通信协议的理解更加深刻,对ADS1115也能进行单通道的使用。I2C的开始、发送/读写、应答、结束等一定要
[单片机]
stm32 通用定时器与 PWM
通用定时器(以下以通用定时器3,通道3 为例): 第一步:开启时钟使能 RCC- APB1ENR:1 位 //开启定时器3 时钟使能 第二步:设置定时器分频与装载计数值(以一周期 1ms) TIM3- PSC = 7199; //系统时钟为 72M 经 (7199+1) 分频后,定时器时钟为 10k(一周期为0.1ms) TIM3- ARR = 9; //计数周期为 0.1ms * (9+1) = 1ms 第三步:使能定时器 TIM3- CR1:0 位 //开启计数器,开始计时 第四步:溢出中断使能 TIM3- DIER:0 位 //开启溢出中断 第五步: void TIM3_IRQHandler(void); 利用通用定时
[单片机]
STM32 USB学习笔记1
主机环境:Windows 7 SP1 开发环境:MDK5.14 目标板:STM32F103C8T6 开发库:STM32F1Cube库和STM32_USB_Device_Library 之前在STM32论坛里领取过一块STM32开发板,本来以为是带有USB模块接口的,最后发现NUCLEO里是没有把USB模块外接出来的,所以就自个儿掏钱买了一块单板,如下图所示: 单板很简单,单纯是为了学习一下STM32的USB模块,之所以选择这个是因为它便宜,而且ST官方有提供USB模块库方便开发。 USB开发博大精深,比之串口,SPI,I2C来说多了很多东西,一个很简单的例子就是串口,SPI,I2C都可以使用通用IO口来模
[单片机]
<font color='red'>STM32</font> USB学习笔记1
STM32学习笔记之USB数据接收和发送流程分析
既然学习了USB,那就必须的搞懂USB设备与USB主机数据是怎么通讯的。这里主要讲设备端,因为我们的代码是做USB设备用的。 我们需要必须要定义了USB中断。起始在STM32的中断向量表中给USB两个中断,我们可以在stm32f10x.h中找到这两个中断: USB_HP_CAN1_TX_IRQn = 19, /*! USB Device High Priority or CAN1 TX Interrupts */ USB_LP_CAN1_RX0_IRQn = 20, /*! USB Device Low Priority or CAN1 RX0 Interrupts */ 这两个中断是USB与CAN复用的中断,在做USB用时,
[单片机]
stm32的TIM2作为实例一步步配置成为定时器
下面以stm32的TIM2作为实例一步步配置成为定时器: 1:对定时器的基本配置 TIM_TimeBaseStructure.TIM_Period = 65535; //设置自动装载寄存器 TIM_TimeBaseStructure.TIM_Prescaler = 100; //分频计数 TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //选择向上计数 TIM_TimeBaseInit(TIM2, &TIM_TimeBase
[单片机]
STM32单片机的系统定时器初始化设置
正如之前文章所述,在使用外设功能时,都必须提前对其精心初始化才能使用其功能。 以下是系统定时器初始化的程序清单。 #include“stm32f10x_lib.h” unsigned char sys_nub;//系统定时器中断计数变量 //SysTick 设置 void SysTIck_Config(void) { //失能SysTIck定时器 SysTIck_CounterCmd(SysTIck_Counter_Disable); //失能SysTick中断 SysTick_ITConfig(DISABLE); //设置SysTick时钟源 SysTick_ClockSourceConfig(SysTick_Source_
[单片机]
<font color='red'>STM32</font>单片机的系统定时器初始化设置
STM32HAL库ADC实验(三)——中断查询法
(模式:连续模式 非扫描模式) 使能ADC全局中断 参考视频 【STM32】超简单的开发方法-基础篇(ADC模数转换) https://player.bilibili.com/player.html?aid=715022775 参考文章:https://blog.csdn.net/as480133937/article/details/99627062 设置定时 可以看我这篇文章 配置玩定时器之后 配置ADC 使能ADC中断 基本函数: • HAL_ADC_Start_IT(&hadcx);       //中断轮询模式开启ADC • HAL_ADC_Stop_IT() //中断轮询模式停
[单片机]
STM32HAL库ADC实验(三)——中断查询法
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved