stm32实现IIC读写

IIC.c

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

c 复制代码
#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

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

c 复制代码
#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
相关推荐
jjjxxxhhh1231 小时前
FPGA,使用场景,相比于单片机的优势
单片机·嵌入式硬件·fpga开发
无敌最俊朗@1 小时前
stm32学习之路——八种GPIO口工作模式
c语言·stm32·单片机·学习
EterNity_TiMe_2 小时前
【论文复现】STM32设计的物联网智能鱼缸
stm32·单片机·嵌入式硬件·物联网·学习·性能优化
changingshow3 小时前
Arduino IDE Windows 系统 离线安装 esp32 开发板 亲测好用。
单片机·嵌入式硬件
7yewh5 小时前
嵌入式硬件杂谈(一)-推挽 开漏 高阻态 上拉电阻
驱动开发·stm32·嵌入式硬件·mcu·物联网·硬件架构·pcb工艺
Chervin12 小时前
Windows,虚拟机Ubuntu和开发板三者之间的NFS服务器搭建
linux·单片机·ubuntu·arm
TeYiToKu13 小时前
笔记整理—linux驱动开发部分(8)framebuffer类设备
linux·驱动开发·笔记·嵌入式硬件·arm
电子工程师UP学堂15 小时前
STM32 设计的较为复杂的物联网项目,包括智能家居控制系统,涵盖了硬件和软件的详细设计。
stm32
7yewh15 小时前
嵌入式硬件电子电路设计(五)MOS管详解(NMOS、PMOS、三极管跟mos管的区别)
stm32·嵌入式硬件·mcu·物联网·硬件架构·硬件工程·pcb工艺
电子工程师UP学堂15 小时前
用单片机MSP430设计一个太阳能实战项目,能够详细的设计出它的硬件和软件系统
单片机