如何在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) {
// 主循环
}
}
这个示例展示了如何使用GPIO引脚模拟I2C通信协议,与24CXX系列EEPROM进行数据读写。你需要根据实际的硬件配置修改GPIO端口和引脚定义。同时,可能需要调整延时函数以适应不同的硬件速度。 注意事项:
确保正确连接HC32F460和24CXX EEPROM的SCL和SDA引脚。
可能需要根据具体型号调整设备地址(devAddr)。
根据具体应用场景调整时序和延时。 学到了,小华MCU全系列产品,超低功耗、通用控制、电机控制、汽车电子。提货请联系18256013035 微信同号 模拟IIC很好实现,下一个别人写的代码,改一下就能用了 有硬件IIC还是用硬件接口吧,软件模拟效率太低了。 模拟I2C的话不就是时序的事儿么,网上有很多模拟I2C的操作,你看看就好了 其实你用硬件I2C效果和速度之类的都是更好的吧 这种模拟I2C不是很成熟了么,只要delay弄准确了就可以 你这个弄得挺好的,但是我觉得模拟不太行在哪儿,就是时序依照每个芯片都要调整 看着还不错,这I2C模拟是不是没啥意义,毕竟HC32F460的接口那么多,不用模拟也可以吧 你的延时函数用的是定时器吗? 其实你这个最重要的是I2C_Delay()吧 我觉得模拟I2C还是不错的,主要是模拟之后移植方便了 是不是之前都用模拟I2C都是为了ST的那个I2C效果不好吧 现在用24Cxx都不如直接用MCU的内置flash了 用内部的flash就挺不错的 外置的主要是方便移植吧 以模拟方式处理I2C,最主要的就是时钟周期的适配。 不同的I2C设备,需要看看时钟周期能否适应,尤其是把程序移植到不同的工作主频的单片机的时候。
页:
[1]
2