为满足程序加载时,按用户的要求配置某IIC接口芯片配置寄存器,用STC单片机模拟24C02。
主模式的模拟很普遍,但该芯片复位后处于主模式,使得STC要配置它只能处于从模式状态,而IIC从模式的模拟却很少有现成的代码参考。下面是STC模拟被读一个字节的原代码,测试成功:
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
//#include<intrins.h>
//#include <serial.h>
#define ack 0
#define noack 1
#define false 0
#define ture 1
//#define EE_ADD 0x00
#define EE_BYTEADD 0x00////
#define EE_WRITE 0xa0
#define EE_READ 0xa1
sbit scl="P1"^7;////STC2052.PIN19-SPICLK-SPIC
sbit sda="P1"^5;////STC2052.PIN17-MOSI-SPID
//bit ack_flag=0;////局部定义产生重入
//void iic_sdelay(uchar);
bit iic_start_decide();
bit iic_stop_decide();
void iic_ack_send(bit);
bit iic_ack_decide();
//void iic_ack();
//void iic_noack();
bit iic_send(uchar);//reentrant;
bit EEPROM_Imitate(uchar *p);
//uchar iic_receive();//reentrant;/////////////////////////////////////////////////////////////////
//bit iic_writestr(uchar*,uchar,uchar);
//bit iic_writeabyte(uchar,uchar);
//bit iic_readstr(uchar*,uchar,uchar);
//bit iic_readabyte(void);
bit iic_start_decide()////iic开始判断
{
while(0==scl);////开始条件不满足
while((1==scl)&&(1==sda));////开始条件正在建立,则等待
if((1==scl)&&(0==sda))////开始
{
while(1==scl);////等待到时钟线开始跳变
return ture;
}
else
return false;
}
bit iic_stop_decide()
{
while(0==scl);////结束条件不满足
while((1==scl)&&(0==sda));////结束条件正在建立,则等待
if((1==scl)&&(1==sda))////结束
return ture;
else
return false;
}
void iic_ack_send(bit a)////回应ACK或NOACK
{
if(ack==a)
sda=0;
else
sda=1;
while(0==scl);////等待SCL低电平
while(1==scl);////时钟线高电平时保持
}
bit iic_ack_decide()
{
bit ack_flag;////局部变量
//////////////////////////////////////sda=1; ////8位发送完毕,释放数据线SDA,准备接收应答位
while(0==scl);////等待SCL变高电平
ack_flag=0;
if(0==sda)////sda==0说明有回应
ack_flag=1;////设置回应成功标志
else
ack_flag=0;
//scl=0; ////嵌住总线,准备发送或接收数据
//iic_sdelay(4);
while(1==scl);
return(ack_flag);
}
bit iic_send(uchar sdata) //reentrant
{uchar i;
for(i=0;i<8;i++)
{
sda=(bit)(sdata&0x80);
sdata=sdata<<1;
while(0==scl);
while(1==scl);////检测scl,高电平时数据保持,scl跳到低电平才改变数据
}
return(iic_ack_decide());////判断主机有无回应
}
uchar iic_receive() //reentrant
{uchar i;
uchar rdata="0";
sda=1;
for(i=0;i<8;i++)
{
rdata<<=1;
while(0==scl);////当时钟线为低时,数据无效,等待
if(1==sda)
rdata++;
while(1==scl);////防止在一个高电平时读8次
}
//iic_sdelay(4);
//scl=0; ////嵌住总线,准备发送或接收数据////这里使用的是从模式
//iic_sdelay(8);
return (rdata);
}
//bit EEPROM_Imitate(uchar *p,uchar num)
bit EEPROM_Imitate(uchar *p)
{
//uchar i;
uchar s;
while(!iic_start_decide());//等待IIC开始
s=iic_receive();////器件地址
//serial_send(s);
if(EE_WRITE==s)
{
iic_ack_send(ack); ////回应
//serial_send(s);
}
else
{
iic_ack_send(noack);
goto enderr;
}
s=iic_receive();////存储字节地址
//serial_send(s);
if(EE_BYTEADD==s)
iic_ack_send(ack); ////回应
else
{
iic_ack_send(noack);
goto enderr;
}
while(!iic_start_decide());//如果iic开始
s=iic_receive();////器件地址
//serial_send(s);
if(EE_READ==s) ////主机要读EE的数据
iic_ack_send(ack); ////回应
else
{
iic_ack_send(noack);
goto enderr;
}
while(iic_send(*p)){p++;};////判断有NOACK后停止发送,接着判断停止位
if(iic_stop_decide())
return ture;
enderr:
scl=sda=1;
return false;
} |