2. 基于软件模拟的I2C对开发板上的AT24C02(EEPROM)进行读写,实现按字节写和指定地址读的函数
时间: 2024-02-27 10:53:36 浏览: 85
10_I2C_EEPROM.rar
好的,针对你的问题,我可以给你一个基本的思路和代码示例。
首先,你需要了解一下 AT24C02 EEPROM 的寄存器地址和读写方式。AT24C02 EEPROM 内部有256个字节,每个字节有一个唯一的地址,地址范围为0x00到0xFF。它有两个主要的寄存器,地址寄存器和数据寄存器。写操作时,先向地址寄存器写入要写入的地址,再向数据寄存器写入要写入的数据。读操作时,向地址寄存器写入要读取的地址,然后从数据寄存器读取数据。
接下来,我们可以编写一个基于软件模拟的 I2C 函数,用来实现按字节写和指定地址读的操作。这里我们假设使用GPIO口模拟I2C,SDA使用GPIO1,SCL使用GPIO2,如果你的开发板上的GPIO口不一样,可以根据实际情况修改代码。
```c
#include "stdio.h"
#include "stdlib.h"
#include "stdint.h"
#include "stdbool.h"
#include "gpio.h"
#include "delay.h"
#define SDA_PIN 1 // SDA使用GPIO1
#define SCL_PIN 2 // SCL使用GPIO2
// I2C起始信号
void i2c_start(void)
{
gpio_set_direction(SDA_PIN, GPIO_OUTPUT); // SDA设置为输出
gpio_write(SDA_PIN, true); // SDA拉高
gpio_write(SCL_PIN, true); // SCL拉高
delay_us(5); // 延时
gpio_write(SDA_PIN, false); // SDA拉低
delay_us(5); // 延时
gpio_write(SCL_PIN, false); // SCL拉低
}
// I2C停止信号
void i2c_stop(void)
{
gpio_set_direction(SDA_PIN, GPIO_OUTPUT); // SDA设置为输出
gpio_write(SDA_PIN, false); // SDA拉低
gpio_write(SCL_PIN, true); // SCL拉高
delay_us(5); // 延时
gpio_write(SDA_PIN, true); // SDA拉高
delay_us(5); // 延时
}
// I2C发送一个字节
bool i2c_send_byte(uint8_t data)
{
uint8_t i;
bool ack;
gpio_set_direction(SDA_PIN, GPIO_OUTPUT); // SDA设置为输出
for (i = 0; i < 8; i++) {
gpio_write(SCL_PIN, false); // SCL拉低
delay_us(5); // 延时
gpio_write(SDA_PIN, (data & 0x80) ? true : false); // 发送数据
data <<= 1;
gpio_write(SCL_PIN, true); // SCL拉高
delay_us(5); // 延时
}
gpio_write(SCL_PIN, false); // SCL拉低
gpio_set_direction(SDA_PIN, GPIO_INPUT); // SDA设置为输入
delay_us(5); // 延时
ack = !gpio_read(SDA_PIN); // 接收ACK信号
gpio_write(SCL_PIN, true); // SCL拉高
delay_us(5); // 延时
gpio_write(SCL_PIN, false); // SCL拉低
return ack;
}
// I2C接收一个字节
uint8_t i2c_receive_byte(bool ack)
{
uint8_t i, data = 0;
gpio_set_direction(SDA_PIN, GPIO_INPUT); // SDA设置为输入
for (i = 0; i < 8; i++) {
gpio_write(SCL_PIN, true); // SCL拉高
delay_us(5); // 延时
data = (data << 1) | gpio_read(SDA_PIN); // 接收数据
gpio_write(SCL_PIN, false); // SCL拉低
}
gpio_set_direction(SDA_PIN, GPIO_OUTPUT); // SDA设置为输出
gpio_write(SDA_PIN, ack ? false : true); // 发送ACK信号
gpio_write(SCL_PIN, true); // SCL拉高
delay_us(5); // 延时
gpio_write(SCL_PIN, false); // SCL拉低
return data;
}
// 按字节写数据到AT24C02
void at24c02_write_byte(uint8_t data, uint8_t addr)
{
i2c_start(); // 发送起始信号
i2c_send_byte(0xA0); // 发送写地址
i2c_send_byte(addr); // 发送写地址的低位
i2c_send_byte(data); // 发送要写入的数据
i2c_stop(); // 发送停止信号
}
// 指定地址读取AT24C02的数据
uint8_t at24c02_read_byte(uint8_t addr)
{
uint8_t data;
i2c_start(); // 发送起始信号
i2c_send_byte(0xA0); // 发送写地址
i2c_send_byte(addr); // 发送写地址的低位
i2c_start(); // 发送起始信号
i2c_send_byte(0xA1); // 发送读地址
data = i2c_receive_byte(false); // 读取数据
i2c_stop(); // 发送停止信号
return data;
}
```
上面的代码中,我们使用了 GPIO 库和延时库,如果你的开发板上没有这些库,需要自己实现相应的函数。此外,我们假设你已经将 AT24C02 连接到了开发板上,并正确配置了相应的 GPIO 引脚。
现在,你可以在你的程序中调用 `at24c02_write_byte()` 函数来按字节写入数据,调用 `at24c02_read_byte()` 函数来指定地址读取数据了。
阅读全文