評:驅動程序對于所有的鐵電系列I2C FRAM都是適用的,只是容量、電平(3V和5V)的不同,驅動程序是針對51MCU的,但對其他MCU只要稍微修改就可使用。
在存貯數據量不大,而且讀寫次數頻繁時,可選擇I2C FRAM。
//THIS CODE WAS DESIGNED TO DEMONSTRATE HOW THE FM24C04/FM24C04A SERIAL FRAM COULD
//BE INTERFACED TO THE 8051 MICROCONTROLLER. THE INTERFACE USES 2 LINES
//FROM PORT 2 (P2.7 AND P2.6) TO COMMUNICATE.
//THE CODE SHOWN DEMONSTRATES A 'RANDOM READ' AND 'BYTE WRITE'. THE OTHER *
//MODES OF OPERATION CAN BE CREATED BY EXPANDING UPON THESE ROUTINES.
//the first date writed:2003-11-20
//email:gaoqiang@huazhoucn.com
//by:tiger
//=============================
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define IIC_READ 0XA1 //定義讀指令
#define IIC_WRITE 0XA0 //定義寫指令
#define NOP _nop_()
//#define SDA INT0
//#define SCL T0
//==============================
uchar idata buff[32]; //save the byte read out form iic device in test operation
uchar idata readbuff[32];//測試數組,暫存寫入讀出數據
//uchar writebuff[32];
//===============================
sbit SDA=P1^4;//P2^7; //THE SDA BIT IS PORT 2 BIT 7
sbit SCL=P1^7;//P2^6; //THE SCL BIT IS PORT 2 BIT 6
//sbit WP=P2^5;
//sbit test=P1^0;
//===============================
//define a bit_operation byte to use in shift operation
//use this mode can achieve high operation speed
uchar bdata bbyte;//定義位操作用數組,采用此方法可提高位操作速度
sbit a0=bbyte^0;
sbit a1=bbyte^1;
sbit a2=bbyte^2;
sbit a3=bbyte^3;
sbit a4=bbyte^4;
sbit a5=bbyte^5;
sbit a6=bbyte^6;
sbit a7=bbyte^7;
//========================================
bit IFACK; //record the SDA state to confirn if ACK has happened
bit NO_ACK; //no ack flag
bit BUS_FAULT; //bus fault flag
//========================================
//FUNCTION:ROUTES TO PROVIDE A START SIGNAL
void start(void)
{
SCL=0;SDA=1;SCL=1;SDA=0;SCL=0;
}
//=======================================
//FUNCTION:ROUTES TO PROVIDE A STOP SIGNAL
void stop(void)
{
SCL=0;SDA=0;SCL=1;SDA=1;SCL=0;
}
//=====================================
//FUNCTION:ROUTES TO PROVIDE ACK SINGAL
void ack(void)
{
SCL=0;SDA=0;SCL=1;SCL=0;
}
//=====================================
//FUNCTION:ROUTES TO RELEASE THE SDA TO RECEIVE A ACK SIGNAL
// OR TO PROVIDE A NO_ACK SIGNAL
//type=1等待應答信號
//type=0 產生無應答信號
void nack(uchar type)
{
SCL=0;SDA=1;SCL=1;IFACK=SDA; SCL=0;
if(type)
{
if(IFACK)//如果無應答信號,則置標志位NO_ACK,程序中止
{
NO_ACK=1;//用戶可以加入自己的異常處理程序
//while(1);
}
else NO_ACK=0;
}
}
//=======================================================
//FUNCTION:THE IIC DEVICE SHIFT OUT A BYTE TO THE MASTER
uchar inbyte(void) {//從IIC器件中讀出數據
SDA=1;
SCL=1;a7=SDA;SCL=0;
SCL=1;a6=SDA;SCL=0;
SCL=1;a5=SDA;SCL=0;
SCL=1;a4=SDA;SCL=0;
SCL=1;a3=SDA;SCL=0;
SCL=1;a2=SDA;SCL=0;
SCL=1;a1=SDA;SCL=0;
SCL=1;a0=SDA;SCL=0;
return(bbyte);
}
//=======================================================
//FUNCTION:THE IIC DEVICE SHIFT IN A BYTE FROM THE MASTER
void outbyte(uchar outdata) {//將數據寫放IIC器件
bbyte=outdata;
SDA=a7;SCL=1;SCL=0;
SDA=a6;SCL=1;SCL=0;
SDA=a5;SCL=1;SCL=0;
SDA=a4;SCL=1;SCL=0;
SDA=a3;SCL=1;SCL=0;
SDA=a2;SCL=1;SCL=0;
SDA=a1;SCL=1;SCL=0;
SDA=a0;SCL=1;SCL=0;
}
//======================================================
//FUNCTION:BYTE WRITE. 'add' THE WRITE ADDRESS, 'wbyte' THE DATA WANT TO WRITE
void writebyte(uint add,uchar wbyte)//add為寫入地址,wbyte為寫入數據
{
uchar temph,templ;
temph=(uchar)(add/256);
templ=(uchar)(add%256);
start(); //開始信號
outbyte(IIC_WRITE); //寫命令
nack(1); //等待應答
outbyte(temph); //寫地址
nack(1); //等待應答
outbyte(templ); //寫地址
nack(1);
outbyte(wbyte); //寫數據
nack(1); //等待應答
stop(); //停止信號
}
//=====================================================
//FUNCTION:RANDOM READ.'add' IS THE ADDRESS WANT TO READ
uchar readbyte (uint add)//add為讀地址
{
uchar temp,temph,templ;
temph=(uchar)(add/256);
templ=(uchar)(add%256);
start(); //開始信號
outbyte(IIC_WRITE); //寫命令
nack(1); //等待應答
outbyte(temph); //寫地址
nack(1); //等待應答
outbyte(templ); //寫地址
nack(1);
start(); //開始信號
outbyte(IIC_READ); //讀命令
nack(1); //等待應答
temp=inbyte(); //讀數據
nack(0); //無應答
stop(); //停止信號
return(temp);
}
//=================================================
//連寫函數
//add為讀起始地址,ptr數據保存指針,writelen為寫入數據長度
void writebyteseq(uint add,uchar *ptr,uint writelen)
{
//uchar temp;
uchar temph,templ;
uint i;
temph=(uchar)(add/256);
templ=(uchar)(add%256);
start();
outbyte(IIC_WRITE);
nack(1);
outbyte(temph);
nack(1);
outbyte(templ);
nack(1);
for(i=0;i<writelen;i++)
{
outbyte(*(ptr+i));
nack(1);
}
stop();
}
//=================================================
//連讀函數
//add為讀起始地址,ptr數據保存指針,writelen為讀出數據長度
void readbyteseq(uint add,uchar *ptr,uint readlen)
{
uchar temph,templ;
uint i;
temph=(uchar)(add/256);
templ=(uchar)(add%256);
start();
outbyte(IIC_WRITE);
nack(1);
outbyte(temph);
nack(1);
outbyte(templ);
nack(1);
start();
outbyte(IIC_READ);
nack(1);
for(i=0;i<readlen-1;i++)
{
*(ptr+i)=inbyte();
ack();
}
*(ptr+readlen-1)=inbyte();
nack(0);
stop();
}
//=======================================================
//THIS IS A TEST OPERATION
void main(void)
{
uchar i;
uchar j=0;
//WP=0;
while(1)
{
if(j++>255){j=0;}
for(i=0;i<32;i++) readbuff[i]=j;
writebyteseq(0, readbuff, 32);
for(i=0;i<32;i++) readbuff[i]=0;
readbyteseq(0,readbuff,32);
//for(i=0;i<32;i++)
//writebyte(i,i);
for(i=0;i<32;i++)
buff[i]=readbyte(i);
i=0;
}
}