stm32实现IIC读写

IIC.c

#include "Driver_I2C2.h"
#include "Delay.h"

#define I2C_DELAY Delay_us(10)


/**
 * @description: 初始化
 * @return {*}
 */
void Driver_I2C2_Init(void)
{
    /*
        PB10->SCL
        PB11->SDA
            开漏输出: 既可以用于输出也可以输入. 外界要有上拉电阻.
                    用于输入的时候,最好先输出一个1,把线的控制权交给外界.

            MODE=11 CNF=01

     */
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;

    GPIOB->CRH |= (GPIO_CRH_MODE10 | GPIO_CRH_MODE11 | GPIO_CRH_CNF10_0 | GPIO_CRH_CNF11_0);
    GPIOB->CRH &= ~(GPIO_CRH_CNF10_1 | GPIO_CRH_CNF11_1);
}

/**
 * @description: 起始信号
 * @return {*}
 */
void Driver_I2C2_Start(void)
{
    /* 1. 拉高sda和scl */
    SDA_HIGH;
    SCL_HIGH;
    /* 2. 延时 */
    I2C_DELAY;
    /* 3. 拉低sda */
    SDA_LOW;
    /* 4. 延时 */
    I2C_DELAY;
}

/**
 * @description: 停止信号
 * @return {*}
 */
void Driver_I2C2_Stop(void)
{
    /* 1. scl 拉高 sda拉低 */
    SCL_HIGH;
    SDA_LOW;
    /* 2. 延时 */
    I2C_DELAY;
    /* 3. 拉高sda */
    SDA_HIGH;
    /* 4.  延时 */
    I2C_DELAY;
}

/**
 * @description: 接收方产生应答信号
 */
void Driver_I2C2_Ack(void)
{
    /* 1. 拉高sda和拉低scl */
    SDA_HIGH;
    SCL_LOW;
    /* 2. 延时 */
    I2C_DELAY;
    /* 3. sda拉低 */
    SDA_LOW;
    /* 4. 延时 */
    I2C_DELAY;
    /* 5. scl拉高 */
    SCL_HIGH;
    /* 6. 延时 */
    I2C_DELAY;
    /* 7. scl拉低 */
    SCL_LOW;
    /* 8. 延时 */
    I2C_DELAY;
    /* 9. sda 拉高 */
    SDA_HIGH;
    /* 10. 延时 */
    I2C_DELAY;
}

/**
 * @description: 接收方产生非应答信号
 */
void Driver_I2C2_NAck(void)
{
    /* 1. 拉高sda和拉低scl */
    SDA_HIGH;
    SCL_LOW;
    /* 2. 延时 */
    I2C_DELAY;

    /* 3. scl拉高 */
    SCL_HIGH;

    /* 4. 延时 */
    I2C_DELAY;

    /* 5. scl拉低*/
    SCL_LOW;

    /* 6. 延时 */
    I2C_DELAY;
}

/**
 * @description: 等待接收方法的应答
 * @return {*} 应答或非应答
 */
uint8_t Driver_I2C2_WaitAck(void)
{
    /* 1. 把sda拉高, sda的主动权交给对方(e2prom芯片) */
    SDA_HIGH;

    /* 2. scl拉低  */
    SCL_LOW;
    /* 3. 延时 */
    I2C_DELAY;
    /* 4. 拉高scl */
    SCL_HIGH;
    /* 5. 延时 */
    I2C_DELAY;
    /* 6. 读取sda的电平 */
    uint8_t ack = ACK;
    if (READ_SDA)
    {
        ack = NACK;
    }
    /* 7. 拉低scl */
    SCL_LOW;

    /* 8. 延时 */
    I2C_DELAY;
    return ack;
}

/**
 * @description: 发送一个字节的数据
 * @param {uint8_t} byte 要发送的字节
 */
void Driver_I2C_SendByte(uint8_t byte)
{
    for (uint8_t i = 0; i < 8; i++)
    {
        /* 1. sda和scl 拉低 */
        SDA_LOW;
        SCL_LOW;

        I2C_DELAY;

        /* 2. 向sda写数据 */
        if (byte & 0x80)
        {
            SDA_HIGH;
        }
        else
        {
            SDA_LOW;
        }
        I2C_DELAY;

        /* 3. 时钟拉高 */
        SCL_HIGH;

        I2C_DELAY;

        /* 4. 时钟拉低 */
        SCL_LOW;

        I2C_DELAY;

        /* 5. 左移1位, 为下一次发送做准备 */
        byte <<= 1;
    }
}

/**
 * @description: 读一个字节的数据
 * @param {uint8_t} byte 要发送的字节
 */
uint8_t Driver_I2C_ReadByte(void)
{
    uint8_t data = 0;
    for (uint8_t i = 0; i < 8; i++)
    {
        /* 1. 拉低scl */
        SCL_LOW;
        /* 2. 延时 */
        I2C_DELAY;
        /* 3. 拉高scl */
        SCL_HIGH;
        /* 4. 延时 */
        I2C_DELAY;
        /* 5. 读取sda */
        data <<= 1;
        if (READ_SDA)
        {
            data |= 0x01;
        }
        /* 6. 拉低scl */
        SCL_LOW;

        /* 7. 延时 */
        I2C_DELAY;
    }

    return data;
}

IIC.h

#ifndef __DRIVER_I2C2_H
#define __DRIVER_I2C2_H

#include "Delay.h"
#include "stm32f10x.h"
#include "Driver_USART.h"

#define ACK 0
#define NACK 1

#define SCL_HIGH  (GPIOB->ODR |= GPIO_ODR_ODR10)
#define SCL_LOW  (GPIOB->ODR &= ~GPIO_ODR_ODR10)

#define SDA_HIGH  (GPIOB->ODR |= GPIO_ODR_ODR11)
#define SDA_LOW  (GPIOB->ODR &= ~GPIO_ODR_ODR11)

#define READ_SDA (GPIOB->IDR & GPIO_IDR_IDR11)


void Driver_I2C2_Init(void);

void Driver_I2C2_Start(void);

void Driver_I2C2_Stop(void);

void Driver_I2C2_Ack(void);

void Driver_I2C2_NAck(void);

uint8_t Driver_I2C2_WaitAck(void);

void Driver_I2C_SendByte(uint8_t byte);

uint8_t Driver_I2C_ReadByte(void);

#endif


读写操作

Inf_W24C02.c

#include "Inf_W24C02.h"

void Inf_W24C02_Init(void)
{
    Driver_I2C2_Init();
}

void Inf_W24C02_WriteByte(uint8_t innerAddr, uint8_t byte)
{
    /* 1. 开始信号 */
    Driver_I2C2_Start();

    /* 2. 发送写地址 */
    Driver_I2C_SendByte(ADDR);
    /* 3. 等待响应 */
    uint8_t ack = Driver_I2C2_WaitAck();
    if (ack == ACK)
    {
        /* 4. 发送内部地址 */
        Driver_I2C_SendByte(innerAddr);
        /* 5. 等待响应 */
        Driver_I2C2_WaitAck();
        /* 6. 发送具体数据 */
        Driver_I2C_SendByte(byte);
        /* 7. 等待响应 */
        Driver_I2C2_WaitAck();
        /* 8. 停止信号 */
        Driver_I2C2_Stop();
    }
    Delay_ms(5);
}

uint8_t Inf_W24C02_ReadByte(uint8_t innerAddr)
{
    /* 1. 起始信号 */
    Driver_I2C2_Start();
    /* 2. 发送一个写地址   假写 */
    Driver_I2C_SendByte(ADDR);
    /* 3. 等待响应 */
    Driver_I2C2_WaitAck();
    /* 4. 发送内部地址 */
    Driver_I2C_SendByte(innerAddr);
    /* 5. 等待响应 */
    Driver_I2C2_WaitAck();
    /* 6. 起始信号 */
    Driver_I2C2_Start();
    /* 7. 发送读地址  真读 */
    Driver_I2C_SendByte(ADDR + 1);
    /* 8. 等待响应 */
    Driver_I2C2_WaitAck();
    /* 9. 读取一个字节 */
    uint8_t byte = Driver_I2C_ReadByte();

    /* 10. 给对方一个非应答 */
    Driver_I2C2_NAck();

    /* 11. 停止信号 */
    Driver_I2C2_Stop();
    return byte;
}

/**
 * @description: 页写入.一次写入多个字节
 * @param {uint8_t} innerAddr
 * @param {uint8_t} *bytes
 * @param {uint8_t} len
 * @return {*}
 */
void Inf_W24C02_WriteBytes(uint8_t innerAddr, uint8_t *bytes, uint8_t len)
{
    /* 1. 开始信号 */
    Driver_I2C2_Start();

    /* 2. 发送写地址 */
    Driver_I2C_SendByte(ADDR);
    /* 3. 等待响应 */
    uint8_t ack = Driver_I2C2_WaitAck();
    if (ack == ACK)
    {
        /* 4. 发送内部地址 */
        Driver_I2C_SendByte(innerAddr);
        /* 5. 等待响应 */
        Driver_I2C2_WaitAck();

        for (uint8_t i = 0; i < len; i++)
        {
            /* 6. 发送具体数据 */
            Driver_I2C_SendByte(bytes[i]);
            /* 7. 等待响应 */
            Driver_I2C2_WaitAck();
        }
        /* 8. 停止信号 */
        Driver_I2C2_Stop();
    }
    Delay_ms(5);
}

/**
 * @description: 一次性读取多个字节的数据
 * @param {uint8_t} innerAddr 起始位置
 * @param {uint8_t} *bytes 存储读到的数据
 * @param {uint8_t} len 读取的字节数
 * @return {*}
 */
void Inf_W24C02_ReadBytes(uint8_t innerAddr, uint8_t *bytes, uint8_t len)
{

    /* 1. 起始信号 */
    Driver_I2C2_Start();
    /* 2. 发送一个写地址   假写 */
    Driver_I2C_SendByte(ADDR);
    /* 3. 等待响应 */
    Driver_I2C2_WaitAck();
    /* 4. 发送内部地址 */
    Driver_I2C_SendByte(innerAddr);
    /* 5. 等待响应 */
    Driver_I2C2_WaitAck();
    /* 6. 起始信号 */
    Driver_I2C2_Start();
    /* 7. 发送读地址  真读 */
    Driver_I2C_SendByte(ADDR + 1);
    /* 8. 等待响应 */
    Driver_I2C2_WaitAck();

    for (uint8_t i = 0; i < len; i++)
    {
        /* 9. 读取一个字节 */
        bytes[i] = Driver_I2C_ReadByte();
        if (i < len - 1)
        {
            Driver_I2C2_Ack();
        }
        else
        {
            Driver_I2C2_NAck();
        }
    }
    /* 11. 停止信号 */
    Driver_I2C2_Stop();
}

void Inf_W24C02_WriteBytesAutoPage(uint8_t innerAddr, uint8_t *bytes, uint8_t len)
{
    // 不需要自动换页
    if ((innerAddr % 16) + len <= 16)
    {
        Inf_W24C02_ReadBytes(innerAddr, bytes, len);
        return;
    }
    // 需要换页处理
    //uint8_t apge = (len - innerAddr % 16) / 16 + 1  ;// 一共需要page页

}


Inf_W24C02.h

#ifndef __INF_W24C02_H
#define __INF_W24C02_H

#include "Driver_I2C2.h"
#include "string.h"

#define ADDR 0xA0
void Inf_W24C02_Init(void);
void Inf_W24C02_WriteByte(uint8_t innerAddr, uint8_t byte);

uint8_t Inf_W24C02_ReadByte(uint8_t innerAddr);

void Inf_W24C02_WriteBytes(uint8_t innerAddr, uint8_t *bytes, uint8_t len);

void Inf_W24C02_ReadBytes(uint8_t innerAddr, uint8_t *bytes, uint8_t len);

#endif



相关推荐

  1. stm32实现IIC

    2024-07-10 22:02:06       31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 22:02:06       100 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 22:02:06       107 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 22:02:06       90 阅读
  4. Python语言-面向对象

    2024-07-10 22:02:06       98 阅读

热门阅读

  1. 中小企业和数智化的距离,只差一块华为IdeaHub

    2024-07-10 22:02:06       30 阅读
  2. C# —— Directory类

    2024-07-10 22:02:06       23 阅读
  3. 在Ubuntu 22.04上安装Docker最新版本

    2024-07-10 22:02:06       24 阅读