一.概述
93C46/56/66系列EEPROM产品采用Microware串行总线接口,读写、擦除速度快,寿命可达100万次以上擦写,掉电保存数据长达200年以上,可配置8位或16位存储结构,也是使用很广泛的EEPROM芯片。在速度上,比24C系列EEPROM占优势。
Microware串行总线接口是由美国国家半导体公司提出,总线采用三根信号线:时钟线、数据输入线和数据输出线,所以也叫“三线制串行总线”。51单片机本身不带三线制串行总线接口,所以要读写93C系列芯片也需要软件模拟三线制串行总线。
需要注意的是,93C46和93C56/66的驱动程序有点区别。93C46的地址字节是7位,而93C56/66的地址字节是9位,在编程作起始位、操作码和地址字节的合并时要据实处理。除此以外,其他的都是一样的。
二.电路设计
93C系列芯片的ORG管脚内部有1M欧姆的上拉电阻,悬空的时候带高电平,配置为16位存储结构。DO管脚需要接一个2K-4.7K欧姆的上拉电阻。
三.软件设计
/*****************************************************************
*程序名称:93C46驱动
*程序功能:写人8个数据,再读出来,放在P2口显示。
* MCU型号:AT89S52-24PU
*时钟频率:12MHZ
*****************************************************************/
#include<reg52.h>
unsigned char datacode[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//写入93C46的数据
sbit cs=P1^2;//片选,高电平有效
sbit sk=P1^3;//时钟
sbit din=P0^6;//数据输入
sbit dout=P0^7;//数据输出
sbit org=P1^1;//存储结构选择
//延时ms函数:
void Delayms(unsigned int t)
{
unsigned int x,y;
for(x=t;x>0;x--)
for(y=120;y>0;y--);
}
//写93c46操作码和地址函数(8位数据存储结构):
void Write93c46OpcAndAddr(unsigned char opcode,unsigned char addr)//
//注意:为了方便赋值,本函数把起始位和两位操作码作为一个字节的低三位进行赋值
{
unsigned char i;
unsigned int temp;
temp=opcode;
//把起始位、操作码和7位地址合成一个10位数置入int型数据
temp=(temp<<7)|addr;
//注意:93C56/66芯片地址是9位,合并以后是一个12位的int型数据
for(i=0;i<10;i++)
{
din=(temp&0x0200)?1:0;//从int型数据的第9位(0x0200)开始取数
//如果是12位数,从int型数据的第11位(0x0800)开始取数
sk=0;//产生时钟
sk=1;
temp<<=1;//取下一位
}
}
//读93C46数据函数(8位数据存储结构):
unsigned char Read93c46Data(unsigned char raddr)
{
unsigned char i,rdata=0;
cs=1;//选通
Write93c46OpcAndAddr(0x06,raddr);//写入读操作码和地址
for(i=0;i<8;i++)//读取8位数据
{
sk=0;//产生时钟
sk=1;
rdata<<=1;//存下一位
if(dout==1)rdata|=0x01;//逐位读取数据并处理
else rdata&=(~0x01);
}
cs=0;//选通禁止
return rdata;
}
//写93C46数据函数(8位数据存储结构):
void Write93c46Data(unsigned char waddr,unsigned char wdata)
{
unsigned char i;
cs=1;//选通
Write93c46OpcAndAddr(0x05,waddr);//写入写操作码和地址
for(i=0;i<8;i++)//写入8位数据
{
din=(wdata&0x80)?1:0;//逐位写入
sk=0;//产生时钟
sk=1;
wdata<<=1;//取下一位
}
cs=0;//选通禁止
cs=1;
while(!dout);//等待写完
cs=0;
}
//93C46写使能函数:
void WriteEnable93C46(void)
{
cs=1;//选通
Write93c46OpcAndAddr(0x04,0x60);//使能写允许
cs=0;//选通禁止
}
//擦除93C46某地址数据函数:
void EraseOneData93C46(unsigned char eraseaddr)
{
cs=1;//选通
Write93c46OpcAndAddr(0x07,eraseaddr);//擦除一个数据
cs=0;//选通禁止
cs=1;
while(!dout);//等待擦除完成
cs=0;
}
//擦除93C46所有数据函数:
void EraseAllData93C46(void)
{
cs=1;//选通
Write93c46OpcAndAddr(0x04,0x40);//擦除芯片的所有数据
cs=0;//选通禁止
cs=1;
while(!dout);//等待擦除完成
cs=0;
}
//主函数:
int main(void)
{
unsigned char i;
org=0;//8位数据存储结构
WriteEnable93C46();//写允许
EraseAllData93C46();//擦除全部数据
for(i=0;i<8;i++)
Write93c46Data(i,datacode);//从0地址开始写入8个数据
while(1)
{
for(i=0;i<8;i++)
{
P2=Read93c46Data(i);//从0地址开始读出数据,点亮P2口的8个LED
Delayms(500);
}
}
return 0;
}