news 2026/5/1 7:19:41

江协科技10-4 I2C硬件通信

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
江协科技10-4 I2C硬件通信

第一点很好去理解,下面的不必在乎,目前用不到,直接看最后一点,可以根据引脚的图去看具体是哪个接口是这两条线

这个功能框图还是很好理解的吧,首先看上面的SDA,可知的是,比较器和帧错误校验这一块目前是不用的,这两块是STM32本身作为从机的时候进行校验地址位用的

省去不必要的结构,这是我们剩下的结构

=========================================================================

由于SMT32默认是从机状态,所以要先通过s=1,产生起始条件,变为主机状态,并且将s=1存储到控制寄存器中

然后执行EV5,读取控制器寄存器,得知了主机已经准备好了,写入从机地址然后将控制寄存器中的s=1清楚,先将地址写入到DR寄存器中,然后再进入移位寄存器中,然后再进入到I2C总线上去

然后执行A,从机自动响应是不是自己

EV6:ADDR=1的意思就是,从机已经收到地址,然后发了应答信号A,主机读到了这个信息,然后硬件自动将SR1和SR2清楚

EV8_1:首先TxE=1的意思就是状态寄存器表明数据寄存器空了,该往里面填写东西了,后面就很好理解了,开始往数据寄存器写东西了

EV8:由于上个时候,移位和数据都是空的,所以数据寄存器把东西移到了移位寄存器,但是此时移位寄存器还在运输数据,但是此时的数据寄存器已经空了,这里就是TxE=1的意思,继续往数据寄存器写入数据,此时硬件会自动将状态寄存器中的TxE=1给清楚了

A:选择继续发送还是不发送了

EV8:然后继续,移位寄存器在传送,但是此时数据寄存器空了,状态寄存器置1,表示快发数据,然后被硬件自动清楚

EV8_2:很简单就是说在TxE=1和BTF=1,就是说移位寄存器在工作,数据寄存器是空的,然后结束传送,然后状态寄存器中的TxE=1和BTF=1被硬件自动清除

=========================================================================

①:开启I2C外设以及开启对应的GPIO时钟

②:把 I2C 外设对应的 GPIO 口初始化为复用开漏模

③:使用结构体,对整个 I2C 进行配置

④:通过 I2C_Cmd 函数,使能 I2C 外设

================所需要的函数===============================================

=========================================================================main.c

#include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "MPU6050.h" uint8_t ID; int16_t AX, AY, AZ, GX, GY, GZ; int main(void) { OLED_Init(); MPU6050_Init(); OLED_ShowString(1, 1, "ID:"); ID = MPU6050_GetID(); OLED_ShowHexNum(1, 4, ID, 2); while (1) { MPU6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ); OLED_ShowSignedNum(2, 1, AX, 5); OLED_ShowSignedNum(3, 1, AY, 5); OLED_ShowSignedNum(4, 1, AZ, 5); OLED_ShowSignedNum(2, 8, GX, 5); OLED_ShowSignedNum(3, 8, GY, 5); OLED_ShowSignedNum(4, 8, GZ, 5); } }

MPU6050.c

#include "stm32f10x.h" // Device header #include "MPU6050_Reg.h" #define MPU6050_ADDRESS 0xD0 void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT) { uint32_t Timeout; Timeout = 10000; while (I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS) { Timeout --; if (Timeout == 0) { break; } } } //这里重新封装了一下,防止意外卡死 void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data) { I2C_GenerateSTART(I2C2, ENABLE); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); I2C_SendData(I2C2, RegAddress); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING); I2C_SendData(I2C2, Data); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED); I2C_GenerateSTOP(I2C2, ENABLE); } uint8_t MPU6050_ReadReg(uint8_t RegAddress) { uint8_t Data; I2C_GenerateSTART(I2C2, ENABLE); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); I2C_SendData(I2C2, RegAddress); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED); I2C_GenerateSTART(I2C2, ENABLE); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); I2C_AcknowledgeConfig(I2C2, DISABLE); I2C_GenerateSTOP(I2C2, ENABLE); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED); Data = I2C_ReceiveData(I2C2); I2C_AcknowledgeConfig(I2C2, ENABLE); return Data; } void MPU6050_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_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); I2C_InitTypeDef I2C_InitStructure; I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_ClockSpeed = 50000; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//应答功能开启 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_OwnAddress1 = 0x00; //这两行都是stm32作为从机的时候,所需要配置的 I2C_Init(I2C2, &I2C_InitStructure); I2C_Cmd(I2C2, ENABLE); MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01); MPU6050_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_t MPU6050_GetID(void) { return MPU6050_ReadReg(MPU6050_WHO_AM_I); } void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ) { uint8_t DataH, DataL; DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H); DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L); *AccX = (DataH << 8) | DataL; DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H); DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L); *AccY = (DataH << 8) | DataL; DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H); DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L); *AccZ = (DataH << 8) | DataL; DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H); DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L); *GyroX = (DataH << 8) | DataL; DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H); DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L); *GyroY = (DataH << 8) | DataL; DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H); DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L); *GyroZ = (DataH << 8) | DataL; }

MPU6050.h

#ifndef __MPU6050_H #define __MPU6050_H void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data); uint8_t MPU6050_ReadReg(uint8_t RegAddress); void MPU6050_Init(void); uint8_t MPU6050_GetID(void); void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ); #endif
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 7:19:28

永磁同步电机三矢量模型预测电流控制探索

永磁同步电机三矢量模型预测电流控制(有参考文献&#xff09; [1]参考文献&#xff1a;《永磁同步电机三矢量模型预测电流控制_徐艳平》 (1)采用id0 &#xff0c;速度环 PI 控制器的输出作为q轴电流的给定。 在核心模块 TV-MPCC 中&#xff0c;首先根据电流给定值和反馈值计算三…

作者头像 李华
网站建设 2026/4/30 13:05:13

wazero嵌入式部署实战:5个关键步骤解决物联网设备计算瓶颈

wazero嵌入式部署实战&#xff1a;5个关键步骤解决物联网设备计算瓶颈 【免费下载链接】AI_NovelGenerator 使用ai生成多章节的长篇小说&#xff0c;自动衔接上下文、伏笔 项目地址: https://gitcode.com/GitHub_Trending/ai/AI_NovelGenerator 面对物联网设备日益复杂的…

作者头像 李华
网站建设 2026/4/23 12:53:24

程序员技术学习路径完整指南:从入门到精通的5大阶段

程序员技术学习路径完整指南&#xff1a;从入门到精通的5大阶段 【免费下载链接】Best-websites-a-programmer-should-visit-zh 程序员应该访问的最佳网站中文版 项目地址: https://gitcode.com/gh_mirrors/be/Best-websites-a-programmer-should-visit-zh 在当今快速发…

作者头像 李华
网站建设 2026/4/17 15:25:49

SpringBoot 集成 XXL-JOB

这篇文章面向后端工程师和运维同学&#xff0c;手把手教你把 XXL-JOB 无缝集成到 Spring Boot 项目中&#xff1b;包含完整源码示例、配置项说明、常见问题与排查、最佳实践与运维建议&#xff0c;复制即可发布到技术博客。目录 背景与适用场景准备工作&#xff08;XXL-JOB 管理…

作者头像 李华
网站建设 2026/4/30 19:37:24

SpringBoot+Vue3+MySQL集群 开发健康体检双系统

随着全民健康意识的提升&#xff0c;健康体检系统正面临着前所未有的流量洪峰。从每年的“体检季”预约高峰&#xff0c;到企业团检的集中涌入&#xff0c;瞬时的高并发访问足以让传统的单体应用架构瞬间崩溃。如何构建一个既能承载海量用户、又能保证数据安全与业务连续性的高…

作者头像 李华
网站建设 2026/5/1 6:09:20

AutoDock-Vina分子对接终极教程:Windows环境高效配置与实战解析

AutoDock-Vina分子对接终极教程&#xff1a;Windows环境高效配置与实战解析 【免费下载链接】AutoDock-Vina AutoDock Vina 项目地址: https://gitcode.com/gh_mirrors/au/AutoDock-Vina 还在为分子对接实验的复杂配置而苦恼吗&#xff1f;AutoDock-Vina作为药物研发领域…

作者头像 李华