IIC通信链接
IIC通信
AT24C02(EEPROM)简介
总容量是256(2K/8)个字节。
接口:IIC
地址介绍
1、EEPROM由8位表示为存储地址
2、设备号+读写位
其中最低位是读写位,0表示读,1表示写
高7位表示设备地址(IIC通讯使用)
下面图中的设备地址只是占用了4位,A0-A2默认为0。
因此设备地址为1010(二进制)
3、内存地址
根据EEPROM的型号不同,其中设备地址占的位数有所不同,有的存储的地址单元超过8位。
例如AT24C04有512个地址,需要9位表示。24C08有1024个地址,需要10位表示。
为解决这个问题,A0-A2不仅可以表示原有设备号的地址数据,也可以存储内存地址高于8位的数据。
读时序
写时序
重点理解与掌握
1、掌握IIC通信的原理与IO模拟IIC时序的逻辑代码
2、对EEPROM设备地址A0-A2的理解
3、根据时序图写发送字节函数
4、对发送字节函数进行进一步封装,发送固定长度的数据,字符串等
代码
eeprom.c文件
#include<stdio.h>
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "i2c.h"
#include "eeprom.h"
/*
//eeprom--AT24
//u16 a;
//const u8 TEXT_Buffer[]={"2023年8月30日"};
//#define SIZE sizeof(TEXT_Buffer)
u8 data[SIZE];
// u8 value;
// AT24_write_byte(0,0x23); //发送数字
AT24CXX_Write(10,(u8*)TEXT_Buffer,SIZE);
// value=AT24_read_byte(0);
AT24CXX_Read(10,data,SIZE);
// printf("%x\n",value);
printf("%s\n",data);//显示读到的字符串
printf("\n");
delay_ms(100);
*/
void AT24_init()
{
i2c_init();
}
/*
按照AT24(读)时序图的先后顺序,进行顺序执行
*/
u8 AT24_read_byte(u16 readaddr)
{
u8 value;
iic_start();
if(EE_TYPE>AT24C16)
{
iic_send_byte(0XA0); //A是EEPROM在I2C的地址(手册)
iic_wait_ack();
iic_send_byte(readaddr/256); //readaddr是EEPROM的内存地址(0~255)
iic_wait_ack();
}
else{
iic_send_byte(0XA0|(readaddr/256)<<1); //发送设备号和高于8位的内存地址
}
iic_wait_ack();
iic_send_byte(readaddr%256); //发送低于8位的内存地址
iic_wait_ack();
iic_start();
iic_send_byte(0xA1);
iic_wait_ack();
value = iic_read_byte(0);
iic_stop();
return value;
}
/*
按照AT24(写)时序图的先后顺序,进行顺序执行
*/
void AT24_write_byte(u16 writeaddr,u8 DataToWrite) //
{
iic_start();
if(EE_TYPE>AT24C16)
{
iic_send_byte(0XA0);
iic_wait_ack();
iic_send_byte(writeaddr/256);
iic_wait_ack();
}
else{
iic_send_byte(0XA0|(writeaddr/256)<<1);
}
iic_wait_ack();
iic_send_byte(writeaddr%256);
iic_wait_ack();
iic_send_byte(DataToWrite);
iic_wait_ack();
iic_stop();
delay_ms(10);
}
//---------------------------------------------------------------------------
//在AT24CXX里面的指定地址开始写入长度为Len的数据
//该函数用于写入16bit或者32bit的数据.
//WriteAddr :开始写入的地址
//DataToWrite:数据数组首地址
//Len :要写入数据的长度2,4
void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)
{
u8 t;
for(t=0;t<Len;t++)
{
AT24_write_byte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
}
}
//在AT24CXX里面的指定地址开始读出长度为Len的数据
//该函数用于读出16bit或者32bit的数据.
//ReadAddr :开始读出的地址
//返回值 :数据
//Len :要读出数据的长度2,4
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
{
u8 t;
u32 temp=0;
for(t=0;t<Len;t++)
{
temp<<=8;
temp+=AT24_read_byte(ReadAddr+Len-t-1);
}
return temp;
}
//检查AT24CXX是否正常
//这里用了24XX的最后一个地址(255)来存储标志字.
//如果用其他24C系列,这个地址要修改
//返回1:检测失败
//返回0:检测成功
u8 AT24CXX_Check(void)
{
u8 temp;
temp=AT24_read_byte(255);//避免每次开机都写AT24CXX
if(temp==0X55)return 0;
else//排除第一次初始化的情况
{
AT24_write_byte(255,0X55);
temp=AT24_read_byte(255);
if(temp==0X55)return 0;
}
return 1;
}
//在AT24CXX里面的指定地址开始读出指定个数的数据
//读取ReadAddr地址的数据,放入pBuffer数组
//ReadAddr :开始读出的地址 对24c02为0~255
//pBuffer :数据数组首地址
//NumToRead:要读出数据的个数
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{
while(NumToRead)
{
*pBuffer++=AT24_read_byte(ReadAddr++);
NumToRead--;
}
}
//在AT24CXX里面的指定地址开始写入指定个数的数据
//将pBuffer数组的内容写入WriteAddr地址
//WriteAddr :开始写入的地址 对24c02为0~255
//pBuffer :数据数组首地址
//NumToWrite:要写入数据的个数
//*pBuffer :读出来的数据保存在数组里
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
while(NumToWrite--)
{
AT24_write_byte(WriteAddr,*pBuffer);
WriteAddr++;
pBuffer++;
}
}
eeprom.h文件
#ifndef EEPROM_H
#define EEPROM_H
#include "stm32f10x.h"
#include "sys.h"
#define AT24C1 127
#define AT24C2 255
#define AT24C4 511
#define AT24C8 1023
#define AT24C16 2047
#define AT24C32 4095
#define AT24C64 8189
#define AT24C128 16383
#define AT24C256 32767
#define EE_TYPE AT24C2
void AT24_init(void);
u8 AT24_read_byte(u16 readaddr); //读一个字节(8位)的数据
void AT24_write_byte(u16 writeaddr,u8 DataToWrite); //写一个字节的数据
void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len); //写入Len长度位的数据
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len);
u8 AT24CXX_Check(void);
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead);
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite);
#endif