[方案相关]

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

[复制链接]
2161|20
手机看帖
扫描二维码
随时随地手机跟帖
qsrg51|  楼主 | 2024-5-31 14:26 | 显示全部楼层 |阅读模式
使用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)。
根据具体应用场景调整时序和延时。

使用特权

评论回复
学到了,小华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设备,需要看看时钟周期能否适应,尤其是把程序移植到不同的工作主频的单片机的时候。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

50

主题

364

帖子

1

粉丝