📄 eeprom.c
字号:
/*
岁月催人老,2007-09-10
读写AT24C16的函数,用模拟方式读写任意地址的任意个数据(小于256)
输出以下两个函数,分别用于读写;
addr为16位的地址;取值0--2047
*s为放置写入(或读出)数据的缓冲区指针
count为一次写入的数量,最大为255
返回值表明读写是否成功;1--成功;0 -- 出错;
没有检测是否地址溢出,所以请使用时注意;
unsigned char write(unsigned int addr,unsigned char *s,unsigned char count);
unsigned char read(unsigned int addr,unsigned char *s,unsigned char count);
需要引入两个函数,这两个函数可以自己定义,也可以使用系统的,如下
void delay_xms(unsigned int x); 延时x毫秒
void delay_xus(unsigned int x); 延时x微秒
使用系统自带
#define F_CPU ??(你的晶振频率)
#include <util\delay.h>
#define delay_xms(a) _delay_ms(a)
#define delay_xus(a) _delay_us(a)
该程序针对ATMEGA64在AT24C16上应用;如果用其它的MCU,请更改端口设置
*/
#define PORT_EP PORTD
#define DDR_EP DDRD
#define PIN_EP PIND
#define SDA (1 << PD1)
#define SCL (1 << PD0)
#define PIN_SDA (PIN_EP & SDA)
#define I2CWAIT delay_xus(2)
#define SET_SDA PORTD |= SDA;I2CWAIT
#define CLR_SDA PORTD &= ~SDA;I2CWAIT
#define SET_SCL PORTD |= SCL;I2CWAIT
#define CLR_SCL PORTD &= ~SCL;I2CWAIT
#define SDA_IN DDRD &= ~SDA;delay_xus(1)
#define SDA_OUT DDRD |= SDA;delay_xus(1)
#define IF_SDA_H (PIND & SDA) == SDA
#define IF_SDA_L (PIND & SDA) == 0
// 在SCL为高的时间,SDA从高到低的跳变表明开始,从低到高的跳变表明结束
// SDA 在处理数据时,SCL必须在低状态,否则就表明开始或结束;
// SCL从低到高的跳变时输出或读入数据;
void i2cstart(void)
{
SDA_OUT;
SET_SDA;
delay_xus(10);
SET_SCL;
CLR_SDA;
CLR_SCL;
}
unsigned char i2cstop(void)
{
//SDA_OUT;
CLR_SDA;
SET_SCL;
SET_SDA;
SDA_IN;
if (IF_SDA_L)
{
SDA_OUT;
return 0;
}
else
{
SDA_OUT;
return 1;
}
}
unsigned char i2csendbyte(unsigned char temp12)
{
unsigned char i=8;
unsigned char flag2data;
CLR_SCL;
while (i--)
{
if (temp12&0x80)
{
SET_SDA;
}
else
{
CLR_SDA;
}
temp12<<=1;
SET_SCL;
CLR_SCL;
}
SDA_IN;
SET_SCL;
if (IF_SDA_H)
{
flag2data = 1;
}
else
{
flag2data = 0;
//disp_char(2,2,'5',0);
}
CLR_SCL;
SDA_OUT;
return flag2data;
}
unsigned char i2creceivebyte(unsigned char ac)
{
unsigned char i=8,temp12=0;
SDA_IN;
CLR_SCL;
while (i--)
{
SET_SCL;
temp12 <<= 1;
if (IF_SDA_H) temp12++;
CLR_SCL;
}
SDA_OUT;
if (ac)
{
SET_SDA;
}
else
{
CLR_SDA;
}
SET_SCL;
CLR_SCL;
return temp12;
}
unsigned char setaddr(unsigned char sla,unsigned char suba,unsigned char rw)
{
sla &= 0x07;
sla <<= 1;
if (rw)
sla |= 0xa1;
else
sla |= 0xa0;
i2cstart();
if (i2csendbyte(sla)) return 1;
if (!rw) return i2csendbyte(suba);
return 0;
}
unsigned char write(unsigned int addr,unsigned char *s,unsigned char count)
{
unsigned char i;
do
{
for (i=255;i>0;i--)
{
if (setaddr(addr >> 8,addr,0) == 0) break;
i2cstop();
if (i == 0) return 0;
}
i = ((unsigned char)addr) & 0x0f;
if (count == 0) return i2cstop();
do
{
if (i2csendbyte(*s))
{
i2cstop();
return 0;
}
s++;
addr++;
} while((--count) && ((++i) < 0x10));
i2cstop();
delay_xms(20);
} while(1);
}
unsigned char read(unsigned int addr,unsigned char *s,unsigned char count)
{
unsigned char mack;
if (count == 0) return 0;
if (setaddr(addr >> 8,addr,0))
{
i2cstop();
return 1;
}
do
{
if (setaddr(addr >> 8,addr,1))
{
i2cstop();
return 1;
}
for (;;)
{
mack = ((--count) && ((++addr) & 0xff));
*s = i2creceivebyte(!mack);
s++;
if (!mack) break;
}
}while(count);
return i2cstop();
}
void init_eeprom(void)
{
//unsigned char i;
DDR_EP |= SDA | SCL;
PORT_EP |= SDA | SCL;
TWCR= 0X00; //disable twi
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -