qsrg51 发表于 2024-5-31 14:26

如何在HC32F460上实现模拟I2C并与24CXX EEPROM进行通信

使用HC32F460进行模拟IIC驱动24CXX系列EEPROM,需要实现I2C通信协议并进行数据读写操作。以下是一个简要的示例代码,展示如何在HC32F460上实现模拟I2C并与24CXX EEPROM进行通信:

c

#include "hc32f460.h"

// 定义I2C相关的引脚(假设使用GPIOB的PIN6和PIN7)
#define I2C_SCL_PIN      GPIO_PIN_6
#define I2C_SDA_PIN      GPIO_PIN_7
#define I2C_PORT         GPIO_PORT_B

// I2C延时函数(根据需要调整)
void I2C_Delay(void) {
    for (volatile uint32_t i = 0; i < 500; i++);
}

// 设置SDA为输出模式
void SDA_Output(void) {
    GPIO_SetMode(I2C_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_PP);
}

// 设置SDA为输入模式
void SDA_Input(void) {
    GPIO_SetMode(I2C_PORT, I2C_SDA_PIN, GPIO_MODE_IN_FLOATING);
}

// I2C起始信号
void I2C_Start(void) {
    SDA_Output();
    GPIO_ResetBits(I2C_PORT, I2C_SDA_PIN);
    I2C_Delay();
    GPIO_ResetBits(I2C_PORT, I2C_SCL_PIN);
    I2C_Delay();
}

// I2C停止信号
void I2C_Stop(void) {
    SDA_Output();
    GPIO_ResetBits(I2C_PORT, I2C_SDA_PIN);
    I2C_Delay();
    GPIO_SetBits(I2C_PORT, I2C_SCL_PIN);
    I2C_Delay();
    GPIO_SetBits(I2C_PORT, I2C_SDA_PIN);
    I2C_Delay();
}

// 发送I2C一个字节
void I2C_SendByte(uint8_t data) {
    SDA_Output();
    for (uint8_t i = 0; i < 8; i++) {
      if (data & 0x80)
            GPIO_SetBits(I2C_PORT, I2C_SDA_PIN);
      else
            GPIO_ResetBits(I2C_PORT, I2C_SDA_PIN);
      I2C_Delay();
      GPIO_SetBits(I2C_PORT, I2C_SCL_PIN);
      I2C_Delay();
      GPIO_ResetBits(I2C_PORT, I2C_SCL_PIN);
      data <<= 1;
    }
}

// 读取I2C一个字节
uint8_t I2C_ReadByte(void) {
    uint8_t data = 0;
    SDA_Input();
    for (uint8_t i = 0; i < 8; i++) {
      GPIO_SetBits(I2C_PORT, I2C_SCL_PIN);
      I2C_Delay();
      data <<= 1;
      if (GPIO_ReadInputDataBit(I2C_PORT, I2C_SDA_PIN))
            data |= 0x01;
      GPIO_ResetBits(I2C_PORT, I2C_SCL_PIN);
      I2C_Delay();
    }
    return data;
}

// 发送ACK
void I2C_Ack(void) {
    SDA_Output();
    GPIO_ResetBits(I2C_PORT, I2C_SDA_PIN);
    I2C_Delay();
    GPIO_SetBits(I2C_PORT, I2C_SCL_PIN);
    I2C_Delay();
    GPIO_ResetBits(I2C_PORT, I2C_SCL_PIN);
}

// 发送NACK
void I2C_NAck(void) {
    SDA_Output();
    GPIO_SetBits(I2C_PORT, I2C_SDA_PIN);
    I2C_Delay();
    GPIO_SetBits(I2C_PORT, I2C_SCL_PIN);
    I2C_Delay();
    GPIO_ResetBits(I2C_PORT, I2C_SCL_PIN);
}

// 写入24CXX一个字节数据
void EEPROM_WriteByte(uint8_t devAddr, uint8_t memAddr, uint8_t data) {
    I2C_Start();
    I2C_SendByte(devAddr);
    I2C_Ack();
    I2C_SendByte(memAddr);
    I2C_Ack();
    I2C_SendByte(data);
    I2C_Ack();
    I2C_Stop();
}

// 从24CXX读取一个字节数据
uint8_t EEPROM_ReadByte(uint8_t devAddr, uint8_t memAddr) {
    uint8_t data;
    I2C_Start();
    I2C_SendByte(devAddr);
    I2C_Ack();
    I2C_SendByte(memAddr);
    I2C_Ack();
    I2C_Start();
    I2C_SendByte(devAddr | 0x01);// 读操作
    I2C_Ack();
    data = I2C_ReadByte();
    I2C_NAck();
    I2C_Stop();
    return data;
}

int main(void) {
    // 初始化GPIO等
    // ...

    // 示例:写入和读取EEPROM
    EEPROM_WriteByte(0xA0, 0x00, 0x55);// 向地址0x00写入0x55
    uint8_t readData = EEPROM_ReadByte(0xA0, 0x00);// 从地址0x00读取数据

    while (1) {
      // 主循环
    }
}



qsrg51 发表于 2024-5-31 14:26

这个示例展示了如何使用GPIO引脚模拟I2C通信协议,与24CXX系列EEPROM进行数据读写。你需要根据实际的硬件配置修改GPIO端口和引脚定义。同时,可能需要调整延时函数以适应不同的硬件速度。

qsrg51 发表于 2024-5-31 14:27

注意事项:

确保正确连接HC32F460和24CXX EEPROM的SCL和SDA引脚。
可能需要根据具体型号调整设备地址(devAddr)。
根据具体应用场景调整时序和延时。

HDSC小华MCU代理 发表于 2024-6-3 16:03

学到了,小华MCU全系列产品,超低功耗、通用控制、电机控制、汽车电子。提货请联系18256013035 微信同号

caigang13 发表于 2024-6-3 19:20

模拟IIC很好实现,下一个别人写的代码,改一下就能用了

chenjun89 发表于 2024-6-4 08:03

有硬件IIC还是用硬件接口吧,软件模拟效率太低了。

b5z1giu 发表于 2024-6-18 12:43

模拟I2C的话不就是时序的事儿么,网上有很多模拟I2C的操作,你看看就好了

g0d5xs 发表于 2024-6-18 13:56

其实你用硬件I2C效果和速度之类的都是更好的吧

suw12q 发表于 2024-6-18 15:06

这种模拟I2C不是很成熟了么,只要delay弄准确了就可以

p0gon9y 发表于 2024-6-18 16:12

你这个弄得挺好的,但是我觉得模拟不太行在哪儿,就是时序依照每个芯片都要调整

lamanius 发表于 2024-6-18 17:20

看着还不错,这I2C模拟是不是没啥意义,毕竟HC32F460的接口那么多,不用模拟也可以吧

cen9ce 发表于 2024-6-18 18:26

你的延时函数用的是定时器吗?

y1n9an 发表于 2024-6-19 07:35

其实你这个最重要的是I2C_Delay()吧

d1ng2x 发表于 2024-6-19 08:46

我觉得模拟I2C还是不错的,主要是模拟之后移植方便了

kaif2n9j 发表于 2024-6-19 10:37

是不是之前都用模拟I2C都是为了ST的那个I2C效果不好吧

lix1yr 发表于 2024-6-19 12:08

现在用24Cxx都不如直接用MCU的内置flash了

亚瑟 发表于 2024-6-28 19:13

用内部的flash就挺不错的

CarterERO 发表于 2024-6-28 22:50

外置的主要是方便移植吧

suncat0504 发表于 2024-6-29 10:18

以模拟方式处理I2C,最主要的就是时钟周期的适配。

suncat0504 发表于 2024-6-29 10:20

不同的I2C设备,需要看看时钟周期能否适应,尤其是把程序移植到不同的工作主频的单片机的时候。
页: [1] 2
查看完整版本: 如何在HC32F460上实现模拟I2C并与24CXX EEPROM进行通信