江协科技STM32学习- P35 硬件I2C读写MPU6050

[复制链接]
发表于 2025-12-30 14:20:22 | 显示全部楼层 |阅读模式
        🚀write in front🚀  
🔎各人好,我是黄桃罐头,盼望你看完之后,能对你有所资助,不敷请指正!共同砚习互换
🎁接待各位→点赞👍 + 收藏⭐️ + 留言📝​ 
  💬本系列哔哩哔哩江科大STM32的视频为主以及自己的总结梳理📚 
  
   🚀Projeet source code🚀   
  💾工程代码放在了本人的Gitee堆栈:iPickCan (iPickCan) - Gitee.com
  
引用:

STM32入门教程-2023版 过细讲授 中笔墨幕_哔哩哔哩_bilibili
Keil5 MDK版 下载与安装教程(STM32单片机编程软件)_mdk528-CSDN博客
STM32之Keil5 MDK的安装与下载_keil5下载步调到单片机stm32-CSDN博客
0. 江协科技/江科大-STM32入门教程-各章节详细条记-查阅传送门-STM32尺度库开发_江协科技stm32条记-CSDN博客
【STM32】江科大STM32学习条记汇总(已完结)_stm32江科大条记-CSDN博客
江科大STM32学习条记(上)_stm32博客-CSDN博客
STM32学习条记一(基于尺度库学习)_电平输出推免-CSDN博客
STM32 MCU学习资源-CSDN博客
stm32学习条记-作者: Vera工程师养成记
stem32江科大自学条记-CSDN博客

术语:

英文缩写形貌
GPIO:General Purpose Input Onuput通用输入输出
AFIO:Alternate Function Input Output复用输入输出
AO:Analog Output模仿输出
DO:Digital Output数字输出
内部时钟源 CK_INT:Clock Internal内部时钟源
外部时钟源 ETR:External Trigger 时钟源 External 触发
外部时钟源 ETR:External Trigger mode 1外部时钟源 External 触发 时钟模式1
外部时钟源 ETR:External Trigger mode 2外部时钟源 External 触发 时钟模式2
外部时钟源 ITRx:Internal Trigger inputs外部时钟源,ITRx (Internal trigger inputs)内部触发输入
外部时钟源 TIx:exTernal Input pin 外部时钟源 TIx (external input pin)外部输入引脚
CCR:Capture/Comapre Register捕捉/比力寄存器
OC:Output Compare输出比力
IC:Input Capture输入捕捉
TI1FP1:TI1 Filter Polarity 1Extern Input 1 Filter Polarity 1,外部输入1滤波极性1
TI1FP2:TI1 Filter Polarity 2Extern Input 1 Filter Polarity 2,外部输入1滤波极性2
DMA:Direct Memory Access直接存储器存取

正文:

0. 概述

从 2024/06/12 定下筹划开始学习下江协科技STM32课程,接下来将会按照哔站上江协科技STM32的教学视频来学习入门STM32 开发,本文是视频教程 P2 STM32简介一讲的条记。
1.🚚I2C硬件库函数

stm32中I2C库函数先容(stm32f10x_i2c.h) 
下面这些是关于I2C的库函数,这里我会挑选最常见的以及本期要用到的往复举行详细讲授。

1.初始化

在学过前面这么多布局体初始化的函数,对于布局体的初始化我们已经再属性不外了,下面是I2C外设的布局体初始化的函数。
  1. void I2C_DeInit(I2C_TypeDef* I2Cx);
  2. void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);
  3. void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);
复制代码
一样平常环境我们都是自己去界说设置布局体再初始化的,下面我们看一个界说好布局体初始化的示例:
  1. I2C_InitTypeDef I2C_initstruct;
  2.     I2C_initstruct.I2C_Mode = I2C_Mode_I2C; //选择模式,这里选定使用I2C模式
  3.     I2C_initstruct.I2C_ClockSpeed = 100000; //选择时钟的频率,不得大于400kHz
  4.     I2C_initstruct.I2C_DutyCycle = I2C_DutyCycle_2;//占空比选择,低电平:高电平,如果当前是标准速度的话,这个是没用的的,如果在快速时钟的时候,这个才会起作用
  5.     I2C_initstruct.I2C_Ack = I2C_Ack_Enable; //选择是否给应答
  6.     I2C_initstruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//stm32作为从机的时候的响应地址位数
  7.     I2C_initstruct.I2C_OwnAddress1 = 0x01;   //stm32作为从机的时候地址,我们这里是主机,所以这里随便设一个就行了
  8.     I2C_Init(I2C2, &I2C_initstruct);
复制代码
2.使能利用

我们本期不须要用DMA到使能,以是这里就不外多讲授。
  1. void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
复制代码
3.天生起始位和竣事位标记

  1. void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
  2. void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
复制代码
手册表明如下:

4.发送I2C从机地点

下面这个函数实在就是前面学习软件I2C的“点名”利用,硬件也是一样的,同样都是须要举行点名指定的I2C从机来举行通讯。假如有多个从机,主机遇实行下面这个函数后会给每一个从机发送Address的数据,然后从机汲取到了后就对比自己的IP数据,假如一样的话那么就开始跟主机通讯,其他从机保持缄默沉静。
  1. void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
复制代码

5.发送数据和汲取数据

下面这个是发送数据:
  1. void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
复制代码
下面可以看到把数据放入到数据寄存器DR的利用后,然后剩下就是进入到发送数据的流程。 

下面这个是继承数据:
  1. uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
复制代码
我们可以看到这个函数的返回值是DR寄存器内里的数据。 

6.发送应答位

下面这个函数是用来发送应答位的,当主机汲取到了数据之后会向从机发送应答环境,假如应答位是ENABLE表现汲取完成返回一个应答反之就是无应答返回 ,手册表明如下

  1. void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);
复制代码

7.状态检测

下面这个函数是用来检测每次利用一个步调之后的状态的,比如发送了一个字节后的数据,然后就会进入一个EVx的状态,这里就须要去实行这个状态是否完成,然后再实行下一步,这是一种缓冲机制以包管数据收发的正确性。在上一期我们也是详细讲授过了这个过程了的。
  1. ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT);
复制代码
下面是这个函数的干系参数: 

2.🚚硬件I2C读取MPU6050

实验征象如下,实在跟前面软件I2C读取MPU6050征象是一样的,只是方法差异。(软件I2C读取MPU6050链接:stm32入门-----软件I2C读写MPU6050-CSDN博客)

1.电路连线图


查STM32F102T8C6引脚界说表,看到I2C1 PB6, PB7引脚已经给 OLED液晶表现屏利用,本节我们利用I2C2的PB10,PB11引脚。



2.紧张工程文件 
紧张工程文件如下,这里我们就没有像软件那部门一样须要创建一个MyI2C的文件往复实行收发数据的底层,这里我们是利用硬件外设设置库函数往复实现I2C通讯的,底层是由硬件来主动实行的,以是就不须要MyI2C这个文件了。


此中MPU6050.c文件是用来设置I2C外设以及MPU6050干系模块的文件,MPU6050_reg.h文件是存放MPU6050干系寄存器数据的文件

 MPU6050_reg.h文件数据如下:
  1. #ifndef __MP6050_REG_H__
  2. #define __MP6050_REG_H__
  3. #define MP6050_SMPLRT_DIV                0x19
  4. #define MP6050_CONFIG                        0x1A
  5. #define MP6050_GYRO_CONFIG                0x1B
  6. #define MP6050_ACCEL_CONFIG                0x1C
  7. #define MP6050_ACCEL_XOUT_H                0x3B
  8. #define MP6050_ACCEL_XOUT_L                0x3C
  9. #define MP6050_ACCEL_YOUT_H                0x3D       
  10. #define MP6050_ACCEL_YOUT_L                0x3E
  11. #define MP6050_ACCEL_ZOUT_H                0x3F
  12. #define MP6050_ACCEL_ZOUT_L                0x40
  13. #define MP6050_TEMP_OUT_H                0x41
  14. #define MP6050_TEMP_OUT_L                0x42
  15. #define MP6050_GYRO_XOUT_H                0x43
  16. #define MP6050_GYRO_XOUT_L                0x44
  17. #define MP6050_GYRO_YOUT_H                0x45
  18. #define MP6050_GYRO_YOUT_L                0x46
  19. #define MP6050_GYRO_ZOUT_H                0x47
  20. #define MP6050_GYRO_ZOUT_L                0x48
  21. #define MP6050_PWM_MGMT_1                0x6B
  22. #define MP6050_PWM_MGMT_2                0x6C
  23. #define MP6050_WHO_AM_I                        0x75
  24. #endif
复制代码
这里我们紧张去讲授MPU6050.c这个文件内里的内容,这个是设置I2C外设的紧张文件。
3.MPU6050.c代码分析

(1)检测步调超时利用

在进入到检测状态的函数的时间,难免会出现不测超时的环境,这里我们就须要去对这个bug举行处理处罚,比如假如超时的环境就放弃这个字节读取或写入的利用。
  1. //检测事件后的超时操作
  2. void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT) {
  3.     uint32_t time_out = 100000;
  4.     while (I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS) {
  5.         time_out--;
  6.         if (!time_out) {
  7.             break;
  8.         }
  9.     }
  10. }
复制代码
(2)指定地点写

代码是对应下面这个序列图举行写的,序列图跟代码的步调是一样的,我们这里利用的是7位。

  1. void MP6050_WriteReg(uint8_t RegAddr, uint8_t data)
  2. {
  3.         //起始条件
  4.         I2C_GenerateSTART(I2C2, ENABLE);        //产生Start起始位
  5.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);        //等待EV5事件
  6.        
  7.         //发送I2C从机地址
  8.         I2C_Send7bitAddress(I2C2, MP6050_I2CADDR, I2C_Direction_Transmitter);
  9.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS); //等待EV6事件
  10.        
  11.         //发送寄存器地址
  12.         I2C_SendData(I2C2, RegAddr);
  13.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS); //等待EV8事件
  14.        
  15.         //发送数据
  16.         I2C_SendData(I2C2, data);
  17.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS); //等待EV8事件
  18.        
  19.         //发送停止位
  20.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS); //等待EV8_2事件
  21.         I2C_GenerateSTOP(I2C2, ENABLE);
  22. }
复制代码
(3)指定地点读


  1. uint8_t MP6050_ReadReg(uint8_t RegAddr)
  2. {
  3.         uint8_t data = 0;
  4.        
  5.         //起始条件
  6.         I2C_GenerateSTART(I2C2, ENABLE);        //产生Start起始位
  7.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);        //等待EV5事件
  8.        
  9.         //发送I2C从机地址
  10.         I2C_Send7bitAddress(I2C2, MP6050_I2CADDR, I2C_Direction_Transmitter);
  11.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS); //等待EV6事件
  12.        
  13.         //发送寄存器地址
  14.     //这里需要等待EV8_2事件等待数据传输完成,TRANSMITTED 而不是 TRANSMITTING 正在传输
  15.         I2C_SendData(I2C2, RegAddr);
  16.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS); //等待EV8_2事件
  17.        
  18.         //重复起始条件
  19.         I2C_GenerateSTART(I2C2, ENABLE);        //产生Start起始位
  20.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);        //等待EV5事件
  21.        
  22.         //发送I2C从机地址
  23.         I2C_Send7bitAddress(I2C2, MP6050_I2CADDR, I2C_Direction_Receiver);
  24.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS); //等待EV6事件
  25.        
  26.         //只接收一个字节必须在EV6事件之后清除ACK位和应答位
  27.         I2C_AcknowledgeConfig(I2C2, DISABLE);        //设置NACK非应答位
  28.         I2C_GenerateSTOP(I2C2, ENABLE);                        //停止条件
  29.        
  30.         //接收数据
  31.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS); //等待EV7事件
  32.         data = I2C_ReceiveData(I2C2);
  33.         //回复默认的ACK=1,方便连续接收
  34.         I2C_AcknowledgeConfig(I2C2, ENABLE);
  35.        
  36.         return data;
  37. }
复制代码
(4)初始化设置

(5)获取MPU6050寄存器数据

4.主函数代码

这部门实在跟软件I2C读写MPU6050的是一样的。
MP6050.c
  1. #include "stm32f10x.h"                  // Device header#include "MP6050.h"#include "MyI2C.h"#include "Delay.h"#include "MP6050_Reg.h"#include "OLED.h"#define MP6050_I2CADDR                 (0x68 << 1)#define MP6050_I2CRead_DIR        0x01#define MP6050_I2CWrit_DIR        0x00void MP6050_Init(void){        //使能RCC外设时钟        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                //设置GPIO        GPIO_InitTypeDef gpioInitStructure;        gpioInitStructure.GPIO_Mode = GPIO_Mode_AF_OD;                        //复用开漏输出模式        gpioInitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;        //利用GPIOB_Pin10, Pin11        gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz;        GPIO_Init(GPIOB, &gpioInitStructure);                //设置I2C外设        I2C_InitTypeDef I2C_InitStruct;        I2C_StructInit(&I2C_InitStruct);                I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;                                //I2C工作方式        I2C_InitStruct.I2C_ClockSpeed = 100*1000;                        //I2C时钟频率,不凌驾400KHz        I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_16_9;        //I2C时钟占空比        I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;                        //I2C应答        I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;        //I2C从机7位模式        I2C_InitStruct.I2C_OwnAddress1 = 0x01;                                //I2C从机模式利用,自身地点寄存器        I2C_Init(I2C2, &I2C_InitStruct);                //使能I2C外设        I2C_Cmd(I2C2, ENABLE);                        MP6050_WriteReg(MP6050_PWM_MGMT_1, 0x01);        //关闭MP6050就寝模式,采样时钟选择内部GyroX轴时钟        MP6050_WriteReg(MP6050_PWM_MGMT_2, 0x00);        //MP6050 6轴都使能,不利用Wakeup模式        MP6050_WriteReg(MP6050_SMPLRT_DIV, 0x09);        //MP6050采样分频值10分频,实际采样频率=时钟频率/(分频值+1)        MP6050_WriteReg(MP6050_CONFIG, 0x06);                //MP6050不利用FSYNC,DLPF数字低通滤波器选择6最平滑滤波        MP6050_WriteReg(MP6050_GYRO_CONFIG, 0x18);        //陀螺仪量程选择最大量程        MP6050_WriteReg(MP6050_ACCEL_CONFIG, 0x18);        //加速率计量程选择最大量程,不利用高通滤波        MP6050_ReadReg(MP6050_WHO_AM_I);                }void MP6050_WriteReg(uint8_t RegAddr, uint8_t data)
  2. {
  3.         //起始条件
  4.         I2C_GenerateSTART(I2C2, ENABLE);        //产生Start起始位
  5.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);        //等待EV5事件
  6.        
  7.         //发送I2C从机地址
  8.         I2C_Send7bitAddress(I2C2, MP6050_I2CADDR, I2C_Direction_Transmitter);
  9.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS); //等待EV6事件
  10.        
  11.         //发送寄存器地址
  12.         I2C_SendData(I2C2, RegAddr);
  13.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS); //等待EV8事件
  14.        
  15.         //发送数据
  16.         I2C_SendData(I2C2, data);
  17.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS); //等待EV8事件
  18.        
  19.         //发送停止位
  20.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS); //等待EV8_2事件
  21.         I2C_GenerateSTOP(I2C2, ENABLE);
  22. }uint8_t MP6050_ReadReg(uint8_t RegAddr)
  23. {
  24.         uint8_t data = 0;
  25.        
  26.         //起始条件
  27.         I2C_GenerateSTART(I2C2, ENABLE);        //产生Start起始位
  28.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);        //等待EV5事件
  29.        
  30.         //发送I2C从机地址
  31.         I2C_Send7bitAddress(I2C2, MP6050_I2CADDR, I2C_Direction_Transmitter);
  32.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS); //等待EV6事件
  33.        
  34.         //发送寄存器地址
  35.     //这里需要等待EV8_2事件等待数据传输完成,TRANSMITTED 而不是 TRANSMITTING 正在传输
  36.         I2C_SendData(I2C2, RegAddr);
  37.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS); //等待EV8_2事件
  38.        
  39.         //重复起始条件
  40.         I2C_GenerateSTART(I2C2, ENABLE);        //产生Start起始位
  41.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);        //等待EV5事件
  42.        
  43.         //发送I2C从机地址
  44.         I2C_Send7bitAddress(I2C2, MP6050_I2CADDR, I2C_Direction_Receiver);
  45.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS); //等待EV6事件
  46.        
  47.         //只接收一个字节必须在EV6事件之后清除ACK位和应答位
  48.         I2C_AcknowledgeConfig(I2C2, DISABLE);        //设置NACK非应答位
  49.         I2C_GenerateSTOP(I2C2, ENABLE);                        //停止条件
  50.        
  51.         //接收数据
  52.         while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS); //等待EV7事件
  53.         data = I2C_ReceiveData(I2C2);
  54.         //回复默认的ACK=1,方便连续接收
  55.         I2C_AcknowledgeConfig(I2C2, ENABLE);
  56.        
  57.         return data;
  58. }
  59. void MP6050_GetData(struct MP6050_Data_ParaOut *MP6050ParaOut){        uint8_t Data_H = 0;        uint8_t Data_L = 0;                Data_H = MP6050_ReadReg(MP6050_ACCEL_XOUT_H);        Data_L = MP6050_ReadReg(MP6050_ACCEL_XOUT_L);        MP6050ParaOut->AccelX = (Data_H << 8) | Data_L;                //MP6050加速率计X轴                        Data_H = MP6050_ReadReg(MP6050_ACCEL_YOUT_H);        Data_L = MP6050_ReadReg(MP6050_ACCEL_YOUT_L);        MP6050ParaOut->AccelY = (Data_H << 8) | Data_L;                //MP6050加速率计Y轴                Data_H = MP6050_ReadReg(MP6050_ACCEL_ZOUT_H);        Data_L = MP6050_ReadReg(MP6050_ACCEL_ZOUT_L);        MP6050ParaOut->AccelZ = (Data_H << 8) | Data_L;                //MP6050加速率计Z轴                        Data_H = MP6050_ReadReg(MP6050_GYRO_XOUT_H);        Data_L = MP6050_ReadReg(MP6050_GYRO_XOUT_L);        MP6050ParaOut->GyroX = (Data_H << 8) | Data_L;                //MP6050角速率计X轴                Data_H = MP6050_ReadReg(MP6050_GYRO_YOUT_H);        Data_L = MP6050_ReadReg(MP6050_GYRO_YOUT_L);        MP6050ParaOut->GyroY = (Data_H << 8) | Data_L;                //MP6050角速率计X轴                Data_H = MP6050_ReadReg(MP6050_GYRO_ZOUT_H);        Data_L = MP6050_ReadReg(MP6050_GYRO_ZOUT_L);        MP6050ParaOut->GyroZ = (Data_H << 8) | Data_L;                //MP6050角速率计X轴}
复制代码
Main.c
  1. #include "stm32f10x.h"                  // Device header
  2. #include "oled.h"
  3. #include "Countersensor.h"
  4. #include "Encoder.h"
  5. #include "Timer.h"
  6. #include "AD.h"
  7. #include "Delay.h"
  8. #include "MyDMA.h"
  9. #include "UART.h"
  10. #include <stdio.h>
  11. #include "Key.h"
  12. #include "String.h"
  13. #include "LED.h"
  14. #include "MyI2C.h"
  15. #include "MP6050.h"
  16. #include "MP6050_Reg.h"
  17. #define MP6050_REG_ID                0x75
  18. #define MP6050_REG_PWRMNG2        0x6B
  19. #define MP6050_REG_SIMPDIV        0x19
  20. int main(int argc, char *argv[])
  21. {
  22.         uint8_t AckBit = 0;
  23.         uint8_t MP6050Id;
  24.         uint8_t RegVal = 0;
  25.         struct MP6050_Data_ParaOut MP6050Data = {0};
  26.        
  27.         OLED_Init();
  28.         MP6050_Init();
  29.         while(1)                                                                                 
  30.         {
  31.                 MP6050_GetData(&MP6050Data);
  32.                 OLED_ShowSignedNum(1, 1, MP6050Data.AccelX ,5);
  33.                 OLED_ShowSignedNum(1, 8, MP6050Data.AccelY ,5);
  34.                 OLED_ShowSignedNum(2, 1, MP6050Data.AccelZ ,5);
  35.                 OLED_ShowSignedNum(3, 1, MP6050Data.GyroX ,5);
  36.                 OLED_ShowSignedNum(3, 8, MP6050Data.GyroY ,5);
  37.                 OLED_ShowSignedNum(4, 1, MP6050Data.GyroZ ,5);
  38.                 Delay_ms(100);
  39.         }
  40.        
  41.         return 1;
  42. }
复制代码
实验效果:

利用淘宝购买的19块钱的24MHz 8通过逻辑分析仪抓取下硬件I2C读取时的通讯时序。
   可以看到硬件I2C的时序,SCLK时钟特别规整,SDA的变革也紧跟着SCK的降落沿。
  


3🚚实验标题记载和履历分享

   本节硬件I2C实验碰到了一个标题,就是I2C_ReceiveData()读取出来的数据总是固定的值 '0xD',反复排查才发现是由于在读取I2C DR汲取寄存器之前没有期待EV7变乱。假如不期待EV7变乱就直接读取I2C DR寄存器,根据STM32的主汲取时序此时DR寄存器的值还是上一次的值,I2C数据还没有开始汲取,以是此时立即读I2C DR寄存器就总是读取到的上一次值。
  正确的做法是,汲取时先期待EV7变乱确认I2C 已经汲取到数据,再读取I2C DR寄存器,此时读取到的才是正确的汲取数据。
  


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表