目录
IIC总线原理图
图来源:CT117E-M4产品手册.pdf
SCL:时钟信号线(双方通信的基础 )
SDA:数据线(传送地址 或 数据)
VCC/GND 电源和地 (用高电平或低电平 或高变低 低变高 来表示某种通信状态 )
A0/A1/A2 编写地址(可以是设备的地址 写入字节的地址)
WP 读写操作(有1位标识确定 0是写 1是读)
通信方式: 同步通信 串行通信
为什么有地址线?
SCL 和 SDA可以挂载多个外设 区分就需要地址线(找到AT24C02)
IIC总线连接EEPROM——可编程可擦除的内存空间(ROM一般不可擦除)
实用价值:让用户修改指定代码
概念引入:一些嵌入式设备在出厂的时候 内部代码已经完整的烧录进去 用户不可修改,也许我们有这样的需求,那就是留下一部分可配置的可编程的空间 来满足不同人的需求。这样慢慢的 EEPROM的技术就出现了......
要想实现EEPROM的功能 你必须要了解一个芯片,那就是图中标注的 "24C02"
在比赛官方包的芯片资料里有这样的一个文档 AT24C02.pdf 里面介绍了芯片的电气特性 IIC的通信原理 地址信息 SCL:时钟信号线
SDA:数据线设置参考图(待会我们要到时序图) 等等... 如果想研究深入一点手册是必看的。
建立IIC的通信模块也是相当的繁琐 好在比赛官方 已经为我们准备好了有关IIC的库文件 。老样子 我们拿过来直接用就好了,,,
添加IIC库文件
.c 文件复制到 \src目录 .h文件复制到 \inc目录
keil5双击Application/User 添加 .c文件
记得在main.c中添加i2c的头文件
#include "i2c_hal.h"
模块添加完了还不能够使用 因为它只给最基本的函数 像I2CStart I2CWaitAck... 我们需要编写一个函数
向EEPROM里的某个地址写入 多少位的字节。
编写EEPROM读写函数
编写写函数 请参考AT24C02
static void delay(unsigned int n)
{
uint32_t i;
for ( i = 0; i < n; ++i);
}
void EEPROM_write(unsigned char *EEPROM, unsigned char addr, unsigned char num)
{
I2CStart();
I2CSendByte(0xa0); //为什么是A0 请看图figure 7 a0就是 1010 0000 最后一位0代表写
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
while(num--)
{
I2CSendByte(*EEPROM++);//按照字节循环写入 循环次数就是写入的字节数
I2CWaitAck(); //等待对方ACK
}
I2CStop();
delay(500); //延时等待发送完毕
}
再来看看 是不是觉得这个函数不用记忆了
读函数 同样参考AT24C02
void EEPROM_read(unsigned char *EEPROM, unsigned char addr, unsigned char num)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
while(num--)
{
*EEPROM++ = I2CReceiveByte();
if(num)
I2CSendAck(); //循环读数据 如果读完了就发送no ack 代表不往后读数据了
else
I2CSendNotAck();
}
I2CStop();
}
初始化配置调用
//可擦除EEPROM 模拟初始化值
I2CInit();
unsigned char EEPROM_String_1[4] = {33,14,10,66};
EEPROM_write(EEPROM_String_1, 0, 4);
用lcd测试读出数据
void eeprom_fun(void)
{
if(uwTick-uwTick_EEPROM<300) return;
uwTick_EEPROM=uwTick;
unsigned char EEPROM_redString[4] = {0};
EEPROM_read(EEPROM_redString, 0, 4);
sprintf((char *)&uart_string[0],"EEPROM:%d %d %d %d",EEPROM_redString[0],EEPROM_redString[1],EEPROM_redString[2],EEPROM_redString[3]);
LCD_DisplayStringLine(Line5,(unsigned char *)&uart_string[0]);
}