本实验为IIC总线通信协议,以友善之臂mini2440为实验平台,对其开发板上的AT24c08a指定位置写入字符串“hello”,并指定位置读出该位置的内容。
初始工作,首先需要配置GPE14、15管脚分别为IICSLC、IICSDA,并禁止上拉功能。然后设置IIC时钟频率,使能应答信号,并使IIC中断使能,禁止IIC中断屏蔽寄存器。
应答中断处理函数为清除中断标志位,清除中断标记flag。
指定内存写函数的实现为:首先设置主设备发送模式,写入从设备地址,清除中断标记,然后等待应答,写入设备内存地址,等待到应答后开始连续发送数据,存入指定空间。发送结束发出停止命令,结束本次通讯,让IIC状态改为开始状态,准备下一次读写操作。
指定内存读函数,首先配置设备为发送模式,写入要读的设备地址,写入要读的设备内存,设置为主机接收模式,发送接收设备地址,此后从设备会返回一个要读的内存地址,读取该地址抛弃后,连续读取指定内存数据,读到最后一个数据不再产生应答,停止接收,改为准备状态。
AT24C08 的地址格式为: 1 0 1 0 A2 P1 P0 W/R
A2为设备地址位、P1,P0为片内页寻址 LSB=0 写 LSB=1 读
其中mini2440读写位为自动标记无需配置。
/*51实验24: I2C存储卡读写实验*/
#include
#include
#define cp8155 XBYTE[0xff20]
#define pa8155 XBYTE[0xff21]
#define pb8155 XBYTE[0xff22]
#define pc8155 XBYTE[0xff23]
#define dataadr 0x4000
//*********************************************
//MON51必须用到的
code unsigned char stop[3] _at_ 0x3b;
unsigned char code DISPB[]={0x0C0,0x0F9,0x0A4,0x0B0,0x99,0x92,0x82,0x0F8,0x80,0x90,
0x088,0x83,0x0C6,0x0A1,0x86,0x8E,0xFF,0x0C,0xDE,0x0F3,0x08F};
unsigned char ledbuf[6];
sbit SCL=P3^0;
sbit SDA=P3^1;
sbit INS=P1^0;
sbit WRS=P1^1;
sbit RDS=P1^2;
bit ack; //是否应答
void disp(void);
void delay(unsigned char dl);
void Start_I2c(void);
void Stop_I2c(void);
void SendByte(unsigned char c);
unsigned char RcvByte();
bit ISendByte(unsigned char sla,unsigned char c);
bit IRcvByte(unsigned char sla,unsigned char *c);
void main(void)
{
unsigned char tmp1,tmp2;
bit wrok,wrst; //读写正常,读写状态
//SP=0x60;
SP=0x53;
tmp2=0x50;
wrok=1; wrst=0;
cp8155=0x43;
while(1)
{
while(INS);
delay(1);
if (INS==0) break;
}
while(1)
{
if (wrst==0)
{//写数据到卡
for (tmp1=0;tmp1<0x80;tmp1++)
{
WRS=!WRS;
if (ISendByte(tmp1,tmp2)==0) {wrok=0; break;}
tmp2++;
}
Stop_I2c();
}
else
{//从卡读数据
for (tmp1=0;tmp1<0x80;tmp1++)
{
RDS=!RDS;
if (IRcvByte(tmp1,&tmp2)==0) {wrok=0; break;}
XBYTE[dataadr+tmp1]=tmp2; //读取数据
}
Stop_I2c();
}
if (wrok==0)
{//读写错误
ledbuf[0]=0x01; ledbuf[1]=0x0c; ledbuf[2]=0x10;
ledbuf[3]=0x0E; ledbuf[4]=0x14; ledbuf[5]=0x14;//IC-ERR
while(1) disp();
}
if (wrst==0) wrst=1; //向卡写数据完成后,读取数据
else
{//IC卡读写正确
ledbuf[0]=0x01; ledbuf[1]=0x0c; ledbuf[2]=0x09;
ledbuf[3]=0x00; ledbuf[4]=0x00; ledbuf[5]=0x0d;//ICgood
while(1) disp();
}
}
}
void disp(void)
{
unsigned char i;
unsigned int ledwz=0x20;
for (i=0;i<6;i++)
{
pb8155=DISPB[ledbuf[i]];
pa8155=~(ledwz>>i);
delay(8);
}
}
void delay(unsigned char dl)
{
unsigned char ii1,ii2;
for (ii1=0;ii1
// for (ii2=0;ii2<0xA;ii2++);
for (ii2=0;ii2<0x0f;ii2++);
}
//发送开始
void Start_I2c(void)
{
SDA=1; delay(1);
SCL=1; delay(1);
SDA=0; delay(1);
SCL=0; delay(1);
}
//发送停止
void Stop_I2c(void)
{
SCL=0; delay(1);
SDA=0; delay(1);
SCL=1; delay(1);
SDA=1; delay(1);
}
//发送数据C可以是地址,也可以是数据,发完后等待应答,并置状态位ack=1(ok)
void SendByte(unsigned char c)
{
unsigned char BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
{
SCL=0;
if((c<
else SDA=0;
delay(1);
SCL=1; delay(1); //置时钟线为高,通知被控器开始接收数据位
}
SCL=0; delay(1);
SCL=1; delay(1);
if(SDA==1) ack=0;
else ack=1; //*判断是否接收到应答信号
}
//发送字节数据函数
bit ISendByte(unsigned char sla,unsigned char c)
{
Stop_I2c(); delay(1); //结束总线
Start_I2c(); //启动总线
SendByte(0xA0); //WR2401
if(ack==0) return(0);
SendByte(sla); //地址
SCL=0; delay(1);
if(ack==0) return(0);
SendByte(c); //写数据
if (ack==0) return(0);
Stop_I2c(); delay(3);
return(1);
}
//读字节数据函数从器件地址sla,返回值在c. 返回1(OK)
bit IRcvByte(unsigned char sla,unsigned char *c)
{
Stop_I2c(); delay(1); //结束总线
Start_I2c(); //启动总线
SendByte(0xA0); //WR2401
if(ack==0) return(0);
SendByte(sla); //地址
SCL=0; delay(1);
if(ack==0) return(0);
Start_I2c(); //启动总线
SendByte(0xA1); //设备地址00
if(ack==0) return(0);
*c=RcvByte(); //读取数据
if (ack==0) return(0);
Stop_I2c();
return(1);
}
//接收从器件传来的数据,并判断总线错误(不发应答信号),
unsigned char RcvByte()
{
unsigned char retc;
unsigned char BitCnt;
retc=0;
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SCL=0; delay(1); //置时钟线为低,准备接收数据位
SCL=1; delay(1); //置时钟线为高使数据线上数据有效
retc=retc<<1;
if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中
delay(1);
}
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』