如需要绘制PCB,设计电路可以和我联系。sunhenu@163.com.
分类: LINUX
2012-05-04 15:01:51
今天简单介绍一下ADuC842的IIC接口。
ADUC842有专门的IIC接口,我们不需要使用IO去模拟IIC主机了,先看看IIC的寄存器
这里我说明一下,我们下面把使用IO模拟IIC的程序,和使用其自带的IIC接口程序进行比较,所以我具体说一下这几个位的意思;
MDO是数据输出位,就是说IIC输出高电平还是低电平,就是MD0=1或者0.
MDE是数据输出使能位,如果MDE=1,SDATA管脚就是用来输出,MDE=0,SDATA管脚是用作输入,
MDI就是SDATA管脚作为输入时,其输入的电平值。
这里说的,估计有点晕乎,也许吧,确实是的,我们在使用IO模拟IIC的时候,不需要考虑SDATA管脚的输入还是输出,只要pin=1;或者pin==1,就是设置其输出和检测其输入。但是这个IIC接口需要设置SDATA管脚的输入和输出功能。就是说SDATA要输出数据,首先MDE=1;SDATA要接受数据,首先要MDE=0;这个一定要记住,不然器件返回的应答信号收不到。
MCO和I2CM位简单,没有特殊的,按照说明设置就好了。
电路连线很简单,就是通过IIC接口设置芯片使得芯片输出口为低电平和高电平交替变换,PCA9554的资料网络上很多,不多说了。如图。
下面直接看程序,根据程序来说比较方便,这些都是子函数,主要的修改也就在子函数中,IO口模拟IIC程序就是后缀没有-temp的函数,有后缀的函数,就是我依据其改造的函数,是基于ADUC842IIC接口的函数。
void I2C_Delay()
{ char i;
for(i=0;i<50;i++);
}
/******************
start I2C, send I2C start bit
*******************/
void StartBit()
{
SDA = High; //send start bit
_nop_();
SCL = High;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA = Low;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = Low; //hold the I2C bus ,ready to send the data
_nop_();
_nop_();
}
void StartBit_temp()
{
MDE=1;
MDO=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
MCO=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
MDO=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
MCO=0;
_nop_();
_nop_();
}
/******************
send the stop bit to end an I2C communication
*******************/
void StopBit()
{
SDA = Low;
_nop_();
_nop_();
SCL = High;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA = High;
_nop_();
_nop_();
_nop_();
}
void StopBit_temp()
{
MDE=1;
MDO = Low;
_nop_();
_nop_();
MCO = High;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
MDE=1;
MDO = High;
_nop_();
_nop_();
_nop_();
}
/*****************
send 8-bits byte to the slave
******************/
void SendByte(unsigned char c)
{
unsigned BitCnt; //8 bits in a byte
//start to send bit, 8 rounds
for(BitCnt=0;BitCnt<8;BitCnt++)
{
if((c<
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0;
}
_nop_();
_nop_();
SDA = 1;
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
if(SDA)b_ACK = 0;
else b_ACK = 1;
SCL = 0;
_nop_();
_nop_();
}
void SendByte_temp(unsigned char c)
{
unsigned BitCnt; //8 bits in a byte
//start to send bit, 8 rounds
for(BitCnt=0;BitCnt<8;BitCnt++)
{
MDE=1;
if((c<
_nop_();
_nop_();
MCO=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
MCO = 0;
}
_nop_();
_nop_();
MDE=1;
MDO = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
MCO = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
MDE=0;
if(MDI)b_ACK = 0;
else b_ACK = 1;
MCO = 0;
_nop_();
_nop_();
}
我只说蓝色和红色的代码,其他的就很容易了,看见了吧,在这之前MDE=1,就是说SDATA脚都是输出,现在要检测ACK信号,要把SDATA脚设置为输入,所以MDE=0;和蓝色代码对比必须在if(MDI)之前加上MDE=0;这里有个小建议啊,就是为了避免出错,建议MDE和MDO,MDI配套使用就是说出现MDO,或者MDI之前都加一句MDE。
bit ISendByte(unsigned char sla,unsigned char c,unsigned char d)
{
// StartBit();
// SendByte(sla);
// if(!b_ACK)return(0);
// SendByte(c);
// if(!b_ACK)return(0);
// SendByte(d);
// if(!b_ACK)return(0);
// StopBit();
// return(1);
StartBit_temp();
SendByte_temp(sla);
if(!b_ACK)return(0);
SendByte_temp(c);
if(!b_ACK)return(0);
SendByte_temp(d);
if(!b_ACK)return(0);
StopBit_temp();
return(1);
}
主函数里面的一些设置,我直接复制代码,诸位自己分析了,很简单的。
I2CM=1;
MDE=1;
MDI=1;
SPE = 0; //Disable the SPI function in order to enable T2C function.
I2CCON = 0xA8; //set Master Mode, disables the output drivers on SDATA
//SCLOCK float high;
SPIM=1;
CPOL=1;
CPHA=1;
StopBit();
MCO=1;
for(i=0;i<100;i++);
ISendByte(0x40,0x03,0x00); //config valve I2C as output
ISendByte(0x40,0x01,0x00); //close all valve output
这段时间,有些事情,我需要处理,估计会很久都不再整理这个ADIMCU的开发,请见谅,以后有机会我会继续上传一些设计心得。