STM32F407软件模拟I2C实现MPU6050通讯(CUBEIDE)(上)

简介: STM32F407软件模拟I2C实现MPU6050通讯(CUBEIDE)

代码工程

https://download.csdn.net/download/weixin_52849254/87886797

模拟I2C读写的实现

mpu6050_iic.c

/**
 ****************************************************************************************************
 * @file        mpu6050_iic.c
 * @version     V1.0
 * @date        2022-06-21
 *
 ****************************************************************************************************
 */
#include "mpu6050_iic.h"
#include "main.h"
/**
 * @brief       IIC接口延时函数,用于控制IIC读写速度
 * @param       无
 * @retval      无
 */
static inline void mpu6050_iic_delay(void)
{
    delay_us(2);
}
/**
 * @brief       产生IIC起始信号
 * @param       无
 * @retval      无
 */
void mpu6050_iic_start(void)
{
    MPU6050_IIC_SDA(1);
    MPU6050_IIC_SCL(1);
    mpu6050_iic_delay();
    MPU6050_IIC_SDA(0);
    mpu6050_iic_delay();
    MPU6050_IIC_SCL(0);
    mpu6050_iic_delay();
}
/**
 * @brief       产生IIC停止信号
 * @param       无
 * @retval      无
 */
void mpu6050_iic_stop(void)
{
    MPU6050_IIC_SDA(0);
    mpu6050_iic_delay();
    MPU6050_IIC_SCL(1);
    mpu6050_iic_delay();
    MPU6050_IIC_SDA(1);
    mpu6050_iic_delay();
}
/**
 * @brief       等待IIC应答信号
 * @param       无
 * @retval      0: 应答信号接收成功
 *              1: 应答信号接收失败
 */
uint8_t mpu6050_iic_wait_ack(void)
{
    uint8_t waittime = 0;
    uint8_t rack = 0;
    MPU6050_IIC_SDA(1);
    mpu6050_iic_delay();
    MPU6050_IIC_SCL(1);
    mpu6050_iic_delay();
    while (MPU6050_IIC_READ_SDA())
    {
        waittime++;
        if (waittime > 250)
        {
            mpu6050_iic_stop();
            rack = 1;
            break;
        }
    }
    MPU6050_IIC_SCL(0);
    mpu6050_iic_delay();
    return rack;
}
/**
 * @brief       产生ACK应答信号
 * @param       无
 * @retval      无
 */
void mpu6050_iic_ack(void)
{
    MPU6050_IIC_SDA(0);
    mpu6050_iic_delay();
    MPU6050_IIC_SCL(1);
    mpu6050_iic_delay();
    MPU6050_IIC_SCL(0);
    mpu6050_iic_delay();
    MPU6050_IIC_SDA(1);
    mpu6050_iic_delay();
}
/**
 * @brief       不产生ACK应答信号
 * @param       无
 * @retval      无
 */
void mpu6050_iic_nack(void)
{
    MPU6050_IIC_SDA(1);
    mpu6050_iic_delay();
    MPU6050_IIC_SCL(1);
    mpu6050_iic_delay();
    MPU6050_IIC_SCL(0);
    mpu6050_iic_delay();
}
/**
 * @brief       IIC发送一个字节
 * @param       dat: 要发送的数据
 * @retval      无
 */
void mpu6050_iic_send_byte(uint8_t dat)
{
    uint8_t t;
    for (t=0; t<8; t++)
    {
        MPU6050_IIC_SDA((dat & 0x80) >> 7);
        mpu6050_iic_delay();
        MPU6050_IIC_SCL(1);
        mpu6050_iic_delay();
        MPU6050_IIC_SCL(0);
        dat <<= 1;
    }
    MPU6050_IIC_SDA(1);
}
/**
 * @brief       IIC接收一个字节
 * @param       ack: ack=1时,发送ack; ack=0时,发送nack
 * @retval      接收到的数据
 */
uint8_t mpu6050_iic_read_byte(uint8_t ack)
{
    uint8_t i;
    uint8_t dat = 0;
    for (i = 0; i < 8; i++ )
    {
        dat <<= 1;
        MPU6050_IIC_SCL(1);
        mpu6050_iic_delay();
        if (MPU6050_IIC_READ_SDA())
        {
            dat++;
        }
        MPU6050_IIC_SCL(0);
        mpu6050_iic_delay();
    }
    if (ack == 0)
    {
        mpu6050_iic_nack();
    }
    else
    {
        mpu6050_iic_ack();
    }
    return dat;
}
/**
 * @brief       初始化IIC接口
 * @param       无
 * @retval      无
 */
void mpu6050_iic_init(void)
{
    GPIO_InitTypeDef gpio_init_struct = {0};
    /* 使能SCL、SDA引脚GPIO的时钟 */
    MPU6050_IIC_SCL_GPIO_CLK_ENABLE();
    MPU6050_IIC_SDA_GPIO_CLK_ENABLE();
    /* 初始化SCL引脚 */
    gpio_init_struct.Pin    = MPU6050_IIC_SCL_GPIO_PIN;  /* SCL引脚 */
    gpio_init_struct.Mode   = GPIO_MODE_OUTPUT_PP;          /* 推挽输出 */
    gpio_init_struct.Pull   = GPIO_PULLUP;                  /* 上拉 */
    gpio_init_struct.Speed  = GPIO_SPEED_FREQ_HIGH;         /* 高速 */
    HAL_GPIO_Init(MPU6050_IIC_SCL_GPIO_PORT, &gpio_init_struct);
    /* 初始化SDA引脚 */
    gpio_init_struct.Pin    = MPU6050_IIC_SDA_GPIO_PIN;  /* SDA引脚 */
    gpio_init_struct.Mode   = GPIO_MODE_OUTPUT_OD;          /* 开漏输出 */
    HAL_GPIO_Init(MPU6050_IIC_SDA_GPIO_PORT, &gpio_init_struct);
    mpu6050_iic_stop();
}

mpu6050_iic.h

#ifndef __MPU6050_IIC_H
#define __MPU6050_IIC_H
#include "main.h"
/* 引脚定义 */
#define MPU6050_IIC_SCL_GPIO_PORT            GPIOB
#define MPU6050_IIC_SCL_GPIO_PIN             GPIO_PIN_8
#define MPU6050_IIC_SCL_GPIO_CLK_ENABLE()    do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)
#define MPU6050_IIC_SDA_GPIO_PORT            GPIOB
#define MPU6050_IIC_SDA_GPIO_PIN             GPIO_PIN_9
#define MPU6050_IIC_SDA_GPIO_CLK_ENABLE()    do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)
/* IO操作 */
#define MPU6050_IIC_SCL(x)                   do{ x ?                                                                                             \
                                                    HAL_GPIO_WritePin(MPU6050_IIC_SCL_GPIO_PORT, MPU6050_IIC_SCL_GPIO_PIN, GPIO_PIN_SET) :    \
                                                    HAL_GPIO_WritePin(MPU6050_IIC_SCL_GPIO_PORT, MPU6050_IIC_SCL_GPIO_PIN, GPIO_PIN_RESET);   \
                                                }while(0)
#define MPU6050_IIC_SDA(x)                   do{ x ?                                                                                             \
                                                    HAL_GPIO_WritePin(MPU6050_IIC_SDA_GPIO_PORT, MPU6050_IIC_SDA_GPIO_PIN, GPIO_PIN_SET) :    \
                                                    HAL_GPIO_WritePin(MPU6050_IIC_SDA_GPIO_PORT, MPU6050_IIC_SDA_GPIO_PIN, GPIO_PIN_RESET);   \
                                                }while(0)
#define MPU6050_IIC_READ_SDA()               HAL_GPIO_ReadPin(MPU6050_IIC_SDA_GPIO_PORT, MPU6050_IIC_SDA_GPIO_PIN)
/* 操作函数 */
void mpu6050_iic_start(void);                /* 产生IIC起始信号 */
void mpu6050_iic_stop(void);                 /* 产生IIC停止信号 */
uint8_t mpu6050_iic_wait_ack(void);          /* 等待IIC应答信号 */
void mpu6050_iic_ack(void);                  /* 产生ACK应答信号 */
void mpu6050_iic_nack(void);                 /* 不产生ACK应答信号 */
void mpu6050_iic_send_byte(uint8_t dat);     /* IIC发送一个字节 */
uint8_t mpu6050_iic_read_byte(uint8_t ack);  /* IIC接收一个字节 */
void mpu6050_iic_init(void);                 /* 初始化IIC接口 */
#endif

代码分析

这段代码是用于驱动MPU6050模块的IIC接口的代码。主要功能包括产生起始信号、停止信号、等待应答信号、产生应答信号、发送字节和接收字节等操作。

具体代码功能如下:

mpu6050_iic_delay():用于控制IIC读写速度的延时函数。

mpu6050_iic_start():产生IIC起始信号。

mpu6050_iic_stop():产生IIC停止信号。

mpu6050_iic_wait_ack():等待IIC应答信号,返回值表示应答信号是否接收成功。

mpu6050_iic_ack():产生ACK应答信号。

mpu6050_iic_nack():不产生ACK应答信号。

mpu6050_iic_send_byte():发送一个字节。

mpu6050_iic_read_byte():接收一个字节,参数ack表示是否发送ACK应答信号。

mpu6050_iic_init():初始化IIC接口,配置SCL和SDA引脚的GPIO模式、上拉和输出类型。

这些函数一起完成了对MPU6050模块的IIC接口进行初始化和操作的功能。这些函数可以根据具体的硬件配置和需求进行修改和适应。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
传感器
【STM32】I2C练习,SHT3X温度传感器的数据读取
【STM32】I2C练习,SHT3X温度传感器的数据读取
231 0
|
传感器 算法
【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪
【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪
1007 0
STM32CubeMX mpu6050驱动
STM32CubeMX mpu6050驱动
206 10
|
传感器
【经典案例】STM32F407使用HAL库配置I2C详解
STM32F407是一个强大的微控制器,广泛应用于嵌入式系统中。在许多应用中,我们需要使用I2C总线来与传感器、EEPROM、显示屏等外设进行通信。本文将详细介绍如何使用STM32 HAL库来配置和使用I2C接口。
1930 2
|
传感器 存储 缓存
stm32f407探索者开发板(十三)——JLINK在线调试_软件调试_方法与技巧
stm32f407探索者开发板(十三)——JLINK在线调试_软件调试_方法与技巧
803 0
|
传感器 存储 缓存
STM32--MPU6050与I2C外设
STM32--MPU6050与I2C外设
384 1
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
1230 2
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
1569 0