news 2026/6/10 23:51:55

[STM32]Day10-Part2硬件I2C读写MPU6050

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[STM32]Day10-Part2硬件I2C读写MPU6050

I2C外设简介

STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,减轻CPU的负担。

支持多主机模型。支持7位/10位地址模式。

支持不同的通讯速度,标准速度(高达100kHz),快速(高达400kHz)。

支持DMA

兼容SMBus协议

STM32F103C8T6硬件I2C资源:I2C1、I2C2

I2C框图

DATA REGISTER和数据移位寄存器是数据收发的核心部分。往SDA写数据时,把一个字节数据到DR,当移位寄存器没有数据正在移位时,数据从DR转运到移位寄存器同时置状态寄存器TXE为1,DR可以写入新值等待发送。从SDA读取数据时,数据逐位存进移位寄存器,收到完整一个字节数据后转运到DR,同时置标志位RXNE为1,等待读取数据。

I2C基本结构

使用硬件I2C时,SDA和SCL对应的GPIO口设置为复用开漏输出模式。复用是指GPIO的状态是由片上外设控制的。

主机发送与接收时序

主机发送时序

主机接收时序

软件/硬件波形图对比

硬件I2C读写MPU6050

在软件I2C基础上实现硬件I2C整体思路:配置I2C外设,对I2C2外设进行初始化 -> 控制外设电路,实现指定地址写的时序 -> 控制外设电路,实现指定地址读的时序

I2C2初始化:开启I2C2和GPIO时钟 -> 配置GPIO为复用开漏输出模式 -> 配置I2C -> 开启I2C

使用到的函数

// 产生开始信号和停止信号voidI2C_GenerateSTART(I2C_TypeDef*I2Cx,FunctionalState NewState);voidI2C_GenerateSTOP(I2C_TypeDef*I2Cx,FunctionalState NewState);// 配置收到一个字节后主机是否应答voidI2C_AcknowledgeConfig(I2C_TypeDef*I2Cx,FunctionalState NewState);// 发送一个字节和接收一个字节voidI2C_SendData(I2C_TypeDef*I2Cx,uint8_tData);uint8_tI2C_ReceiveData(I2C_TypeDef*I2Cx);// 发送7位地址voidI2C_Send7bitAddress(I2C_TypeDef*I2Cx,uint8_tAddress,uint8_tI2C_Direction);// 检查EVx是否发生ErrorStatusI2C_CheckEvent(I2C_TypeDef*I2Cx,uint32_tI2C_EVENT);

代码

// MPU6050.c#include"stm32f10x.h"// Device header#include"MPU6050_Reg.h"#defineMPU6050_ADDRESS0xD0// 指定地址写voidMPU6050_WriteReg(uint8_tRegAddress,uint8_tData){I2C_GenerateSTART(I2C2,ENABLE);while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Transmitter);while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);I2C_SendData(I2C2,RegAddress);while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING)!=SUCCESS);I2C_SendData(I2C2,Data);while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);I2C_GenerateSTOP(I2C2,ENABLE);}// 指定地址读uint8_tMPU_6050_ReadReg(uint8_tRegAddress){uint8_tData;uint32_tTimeOut;TimeOut=10000;I2C_GenerateSTART(I2C2,ENABLE);while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS){TimeOut--;if(TimeOut==0){break;}}I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Transmitter);while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);I2C_SendData(I2C2,RegAddress);while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);I2C_GenerateSTART(I2C2,ENABLE);while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Receiver);while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)!=SUCCESS);I2C_AcknowledgeConfig(I2C2,DISABLE);I2C_GenerateSTOP(I2C2,ENABLE);while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED)!=SUCCESS);Data=I2C_ReceiveData(I2C2);I2C_AcknowledgeConfig(I2C2,ENABLE);returnData;}voidMPU6050_Init(void){// 开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);// 配置GPIOGPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_OD;// 复用开漏模式GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);// 配置I2CI2C_InitTypeDef I2C_InitStructure;I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;I2C_InitStructure.I2C_ClockSpeed=50000;// 时钟频率I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;// 时钟频率大于100kHz下才有用I2C_InitStructure.I2C_Ack=I2C_Ack_Enable;// 应答位配置I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;// STM32作为从机时地址位数I2C_InitStructure.I2C_OwnAddress1=0x00;// 设置作为从机时的地址I2C_Init(I2C2,&I2C_InitStructure);// 开启I2CI2C_Cmd(I2C2,ENABLE);// 配置电源管理寄存器1,解除睡眠模式MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0x01);// 配置电源管理寄存器2MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0x00);// 配置采样率分频MPU6050_WriteReg(MPU6050_SMPLRT_DIV,0x09);// 配置寄存器MPU6050_WriteReg(MPU6050_CONFIG,0x06);// 陀螺仪配置寄存器MPU6050_WriteReg(MPU6050_GYRO_CONFIG,0x18);// 加速度计配置寄存器MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0x18);}uint8_tMPU6050_GetID(void){returnMPU_6050_ReadReg(MPU6050_WHO_AM_I);}voidMPU6050_GetData(int16_t*AccX,int16_t*AccY,int16_t*AccZ,int16_t*GyroX,int16_t*GyroY,int16_t*GyroZ){uint8_tDataH,DataL;DataH=MPU_6050_ReadReg(MPU6050_ACCEL_XOUT_H);DataL=MPU_6050_ReadReg(MPU6050_ACCEL_XOUT_L);*AccX=(DataH<<8)|DataL;DataH=MPU_6050_ReadReg(MPU6050_ACCEL_YOUT_H);DataL=MPU_6050_ReadReg(MPU6050_ACCEL_YOUT_L);*AccY=(DataH<<8)|DataL;DataH=MPU_6050_ReadReg(MPU6050_ACCEL_ZOUT_H);DataL=MPU_6050_ReadReg(MPU6050_ACCEL_ZOUT_L);*AccZ=(DataH<<8)|DataL;DataH=MPU_6050_ReadReg(MPU6050_GYRO_XOUT_H);DataL=MPU_6050_ReadReg(MPU6050_GYRO_XOUT_L);*GyroX=(DataH<<8)|DataL;DataH=MPU_6050_ReadReg(MPU6050_GYRO_YOUT_H);DataL=MPU_6050_ReadReg(MPU6050_GYRO_YOUT_L);*GyroY=(DataH<<8)|DataL;DataH=MPU_6050_ReadReg(MPU6050_GYRO_ZOUT_H);DataL=MPU_6050_ReadReg(MPU6050_GYRO_ZOUT_L);*GyroZ=(DataH<<8)|DataL;}// main.c#include"stm32f10x.h"// Device header#include"OLED_Hardware.h"#include"MPU6050.h"int16_tAX,AY,AZ,GX,GY,GZ;intmain(void){OLED_Init_H();MPU6050_Init();OLED_ShowString_H(1,1,"ID:");OLED_ShowNum_H(1,4,MPU6050_GetID(),2);while(1){MPU6050_GetData(&AX,&AY,&AZ,&GX,&GY,&GZ);OLED_ShowSignedNum_H(2,1,AX,5);OLED_ShowSignedNum_H(3,1,AY,5);OLED_ShowSignedNum_H(4,1,AZ,5);OLED_ShowSignedNum_H(2,8,GX,5);OLED_ShowSignedNum_H(3,8,GX,5);OLED_ShowSignedNum_H(4,8,GX,5);}}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 23:50:03

生日布置aaaaaaa

布置区域电视墙横幅&#xff1a;我(生)三(日)岁(快)啦(乐)&#xff0c;或者反过来&#xff1a;生(我)日(三)快(岁)乐(啦)&#xff0c;这个用艺术字制作&#xff0c;然后A4打印&#xff0c;每个子一张&#xff0c;共8张&#xff0c;挂到绳子上。视频&#xff1a;精选她从出生到现…

作者头像 李华
网站建设 2026/6/10 23:47:54

计算机毕业设计之基于o2o 模式的外卖点餐系统

伴随着社会以及科学技术的发展&#xff0c;互联网已经渗透在人们的身边&#xff0c;网络慢慢的变成了人们的生活必不可少的一部分&#xff0c;紧接着网络飞速的发展&#xff0c;系统管理这一名词已不陌生&#xff0c;越来越多的商家等机构都会定制一款属于自己个性化的管理系统…

作者头像 李华
网站建设 2026/6/10 23:44:38

Claude Code 代码库迁移评估流程:目录扫描、依赖分析和风险清单

这篇文章不讨论“Claude Code 能不能替你重构整个项目”。生产项目里这么做风险太高。更可落地的方式&#xff0c;是把 Claude Code 放进迁移评估流程&#xff1a;先读懂代码库&#xff0c;再生成依赖分析、风险清单和分阶段迁移建议。 Anthropic 官方把 Claude Code 定位为能读…

作者头像 李华
网站建设 2026/6/10 23:44:37

全国地下水位深度数据集

地下水是一个地区重要的自然资源&#xff0c;地下水位数据可以为研究地下水的长期变化提供总要参考资料。 地下水位数据反映了地下水资源的状况&#xff0c;‌对于水资源管理和保护具有重要意义。地下水水位的变动受到多种因素的影响&#xff0c;‌包括人为因素和自然因素。该数…

作者头像 李华
网站建设 2026/6/10 23:42:40

描述符(Descriptors)‌

1. 什么是描述符&#xff1f; 描述符是 Python 面向对象编程中一个底层但极其强大的机制。简单来说&#xff0c;‌描述符是一个实现了特定协议&#xff08;__get__, __set__, __delete__&#xff09;的类‌。当你把一个描述符类的实例赋值给另一个类的‌类属性‌时&#xff0c;…

作者头像 李华
网站建设 2026/6/10 23:41:46

臭氧层空洞是否正在悄悄逼近你的头顶? - 蓝色星球

当我们谈论“蓝天保卫战”时&#xff0c;大家脑海里浮现的往往是雾霾散去后那抹罕见的湛蓝&#xff0c;或者是空气净化器滤芯更换时那声沉重的叹息。很少有人会把目光投向平流层&#xff0c;去关注那里那层薄薄的、看不见的“保护伞”是否正在修补。 但在昨天&#xff0c;生态环…

作者头像 李华