电路原理图
EEPROM为ATMEL公司的AT24C01A。单片机为ATMEL公司的AT89C51。
软件说明
C语言为Franklin C V3.2。将源程序另存为testi2c.c,用命令
C51 testi2c.c
L51 TESTI2C.OBJ
OHS51 TESTI2C
编译,连接,得到TESTI2C.HEX文件,即可由编程器读入并进行写片,实验。
3.源程序
#include <reg51.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int #define AddWr 0xa0 /*器件地址选择及写标志*/ #define AddRd 0xa1 /*器件地址选择及读标志*/ #define Hidden 0x0e /*显示器的消隐码*/ /*有关全局变量*/ sbit Sda = P3 ^ 7; /*串行数据*/ sbit Scl = P3 ^ 6; /*串行时钟*/ sbit WP = P3 ^ 5; /*硬件写保护*/ void mDelay(uchar j) { uint i; for (; j > 0; j--) { for (i = 0; i < 125; i--) {;} } } /*发送起始条件*/ void Start(void) /*起始条件*/ { Sda = 1; Scl = 1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); Sda = 0; _nop_ (); _nop_ (); _nop_ (); _nop_ (); } void Stop(void) /*停止条件*/ { Sda = 0; Scl = 1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); Sda = 1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); } void Ack(void) /*应答位*/ { Sda = 0; _nop_ (); _nop_ (); _nop_ (); _nop_ (); Scl = 1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); Scl = 0; } void NoAck(void) /*反向应答位*/ { Sda = 1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); Scl = 1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); Scl = 0; } void Send(uchar Data) /*发送数据子程序,Data为要求发送的数据*/ { uchar BitCounter = 8; /*位数控制*/ uchar temp; /*中间变量控制*/ do { temp = Data; Scl = 0; _nop_ (); _nop_ (); _nop_ (); _nop_ (); if ((temp & 0x80) == 0x80) /* 如果最高位是1*/ Sda = 1; else Sda = 0; Scl = 1; temp = Data << 1; /*RLC*/ Data = temp; BitCounter--; } while (BitCounter); Scl = 0; } uchar Read(void) /*读一个字节的数据,并返回该字节值*/ { uchar temp = 0; uchar temp1 = 0; uchar BitCounter = 8; Sda = 1; do { Scl = 0; _nop_ (); _nop_ (); _nop_ (); _nop_ (); Scl = 1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); if (Sda) /*如果Sda=1;*/ temp = temp | 0x01; /*temp的最低位置1*/ else temp = temp & 0xfe; /*否则temp的最低位清0*/ if (BitCounter - 1) { temp1 = temp << 1; temp = temp1; } BitCounter--; } while (BitCounter); return (temp); } void WrToROM(uchar Data[], uchar Address, uchar Num) { uchar i; uchar *PData; PData = Data; for (i = 0; i { Start(); /*发送启动信号*/ Send(0xa0); /*发送SLA+W*/ Ack(); Send(Address + i); /*发送地址*/ Ack(); Send(*(PData + i)); Ack(); Stop(); mDelay(20); } } void RdFromROM(uchar Data[], uchar Address, uchar Num) { uchar i; uchar *PData; PData = Data; for (i = 0; i { Start(); Send(0xa0); Ack(); Send(Address + i); Ack(); Start(); Send(0xa1); Ack(); * (PData + i) = Read(); Scl = 0; NoAck(); Stop(); } } void main() { uchar Number[4] = {1, 2, 3, 4}; WP = 1; WrToROM(Number, 4, 4); /*将初始化后的数值写入EEPROM*/ mDelay(20); Number[0] = 0; Number[1] = 0; Number[2] = 0; Number[3] = 0; /*将数组中的值清掉,以验证读出的数是否正确*/ RdFromROM(Number, 4, 4); }
问题:本程序中未采用块读写的方法,显得有点‘笨’,这是由于项目原因,现项目已完成,程序已写好,短时不会修改,也不会花上一定的精力去做,虽然理论上已很成熟,就这样写一下,未必不对,但与我的本栏目要求不符,所以就未做上去,如果以后我做了,将再补上。