(1)硬件原理图
图中选用的并口脚都是比较通用的接法,当然也存在使用其他并口脚的情况。图中的每个PIN脚都接了反向器。
(2)如下是一个并口软件IIC调试工具的若干子函数,这些子函数的实现与上图的接法并不对应,下面使用的是并口2作SCL,并口3作SDA。
#define SCL_H 0x01
#define SDA_H 0x02 //使用的并口号
#define SCL_L 0x00
#define SDA_L 0x00 //使用的并口号
#define SDA_OE_L 0x00
#define SDA_I 0x80 //读应答或者读数据
#define SDA_DIR 0x04
#define SDA_OE_H SDA_DIR
void IICDelay(int t)
{
::Sleep(t);
}
void IICStart(void)
{
WritePptByte(validPpt, SDA_H|SCL_H|SDA_OE_L);//SCL = 1; SDA = 1
IICDelay(DELAY_TIME);
WritePptByte(validPpt, SDA_L|SCL_H|SDA_OE_L);//when SCL = 1, SDA 1->0 transition , this is start condition
IICDelay(DELAY_TIME);
WritePptByte(validPpt, SDA_L|SCL_L|SDA_OE_L);//SCL = 0; SDA = 0
IICDelay(DELAY_TIME);
}
void IICStop(void)
{
WritePptByte(validPpt, SDA_L|SCL_L|SDA_OE_L);//SCL = 0; SDA = 0
IICDelay(DELAY_TIME);
WritePptByte(validPpt, SDA_L|SCL_H|SDA_OE_L);//SCL = H; SDA = 0
IICDelay(DELAY_TIME);
WritePptByte(validPpt, SDA_H|SCL_H|SDA_OE_L);//when SCL = 1; SDA 0->1 transtion, this is stop condition
IICDelay(DELAY_TIME);
}
int IICWriteByte(BYTE dat)
{
int i;
for(i = 0; i < 8; i++)
{
WritePptByte(validPpt, ((dat & 0x80)?SDA_H:SDA_L) | SCL_L | SDA_OE_L);//SCL = 0; DATA Ready
IICDelay(DELAY_TIME);
WritePptByte(validPpt, ((dat & 0x80)?SDA_H:SDA_L) | SCL_H | SDA_OE_L);//SCL = 0->1; OUTPUT DATA
IICDelay(DELAY_TIME);
dat <<= 1;
}
WritePptByte(validPpt, ((dat & 0x80)?SDA_H:SDA_L)|SCL_L|SDA_OE_H);//SCL = 0; SDA = 1,此时dat 已为0
IICDelay(DELAY_TIME);
WritePptByte(validPpt, ((dat & 0x80)?SDA_H:SDA_L)|SCL_H|SDA_OE_H);//SCL 0->1 ,we will read the ACK
IICDelay(DELAY_TIME);
if (~ ReadPptByte(validPpt+1) & SDA_I) //读并口的状态寄存器。读取的是反向后的值
i = 0;//no ack
else
i = 1;//ack
IICDelay(DELAY_TIME);
WritePptByte(validPpt, SCL_L|SDA_OE_L);//SCL = 0; SDA = 0 //回复默认,一个操作结束
IICDelay(DELAY_TIME);
return i;
}
BYTE IICReadByte(void)
{
int i;
BYTE dat = 0;
for(i = 0; i < 8; i++)
{
WritePptByte(validPpt, SDA_H|SCL_L|SDA_OE_H);//SCL = 0; SDA = 1,注意后面并不是从SDA上读的值
IICDelay(DELAY_TIME);
WritePptByte(validPpt, SDA_H|SCL_H|SDA_OE_H);//SCL 0->1 ,we will read the Data bit
IICDelay(DELAY_TIME);
if(~ ReadPptByte(validPpt+1) & 0x80) //反向的值,所以要加取反
{
dat <<= 1;
dat |= 1;
}
else
dat <<= 1;
IICDelay(DELAY_TIME);
}
WritePptByte(validPpt, SDA_L|SCL_L|SDA_OE_L);//SCL = 0; SDA = 0
IICDelay(DELAY_TIME);
WritePptByte(validPpt, SDA_L|SCL_H|SDA_OE_L);//SCL 0->1 ,we will send the ACK to device
return dat;
}
void IICSendAck(int ack)
{
if(ack)
{//if need ack
WritePptByte(validPpt, SDA_L|SCL_L|SDA_OE_L);//SCL = 0; SDA = 0
IICDelay(DELAY_TIME);
WritePptByte(validPpt, SDA_L|SCL_H|SDA_OE_L);//SCL 0->1 ,we will send the ACK to device
}//if need ack
else
{//no ack
WritePptByte(validPpt, SDA_H|SCL_L|SDA_OE_L);//SCL = 0; SDA = 1
IICDelay(DELAY_TIME);
WritePptByte(validPpt, SDA_H|SCL_H|SDA_OE_L);//SCL 0->1 ,we will send the NO ACK to device
}//no ack
IICDelay(DELAY_TIME);
}