我想用lpc2114来模拟I2C总线(虽然lpc2114有自带的接口,不过这种模拟还是有普遍意义). LPC2114的GPIO在应用中要么是输入,要么是输出,同时既是输入又是输出是不能的. 这就遇到一个问题,I2C中有应答机制,也就是说SDA是双向的,它同时发送信号,又要接收来自器件的应答信号,这怎么模拟? 我的想法是: 发送数据是设置模拟的SDA端口(比如P0.24)为GPIO,方向为输出; 在接收数据或判断应答信号时把SDA端口(比如P0.24)的方向设置为输入,读取IOPIN. 是不是要这样来回切换I/O口的方向. 还有一个问题就是对IOPIN寄存器的理解.手册中是这么说的, IOPIN:GPIO引脚寄存器,不管方向和模式如何设定,引脚的当前状态都可以从该寄存器中读数. 如果果真是这样的话,我引脚设置成输出,外面输入信号,我不用切换状态,直接从IOPIN读端口状态不就可以拉吗? 如果这样的话,端口不是能拉双向的拉吗,同时既是输入又是输出. 希望大家帮我解惑,谢谢
下面是我模拟I2C的关键程序,运行发现出错. #define SDA 1<<24 //p0.24 作为输出 #define SDA1 0x00000000 //p0.24 作为输出 #define SCL 1<<25 //p0.25 作为输出
void Delay1(uint16 x) { for(;x>0;x--); }
void Start_I2c() { IO0SET=SDA; /*发送起始条件的数据信号*/ IO0SET=SCL; Delay1(1000); /*起始条件建立时间大于4.7us,延时*/ IO0CLR=SDA; /*发送起始信号*/ Delay1(1000); /* 起始条件锁定时间大于4μs*/ IO0CLR=SCL; /*钳住I2C总线,准备发送或接收数据 */ Delay1(1000); }
void Stop_I2c() { IO0CLR=SDA; IO0CLR=SCL; /*发送结束条件的数据信号*/ Delay1(1000); /*发送结束条件的时钟信号*/ IO0SET=SCL; /*结束条件建立时间大于4μs*/ Delay1(1000); IO0SET=SDA; /*发送I2C总线结束信号*/ Delay1(1000); } /******************************************************************* 字节数据传送函数 函数原型: void SendByte(uint8 c); 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对 此状态位进行操作.(不应答或非应答都使ack=0 假) 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。 ********************************************************************/ void SendByte(uint8 c) { uint8 BitCnt; uint32 i; char s[40]; for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/ { if((c<<BitCnt)&0x80)IO0SET=SDA; /*判断发送位*/ else IO0CLR=SDA; Delay1(1000); IO0SET=SCL; /*置时钟线为高,通知被控器开始接收数据位*/ Delay1(1000); /*保证时钟高电平周期大于4μs*/ IO0CLR=SCL; /*保证时钟低电平周期大于4.7μs*/ Delay1(1000); } IO0SET=SDA; /*8位发送完后释放数据线,准备接收应答位*/ Delay1(1000); IO0SET=SCL; //产生第9个时钟 IO0DIR=SDA1|SCL; //切换SDA方向 while(IO0PIN&SDA) { i++; if(i>2000) break; } if(i>2000) {sprintf(s,"NO ACK!,ERROR!"); SendPCStr(40,20,s,0x30);ack=0; } else {sprintf(s,"OK!"); SendPCStr(40,20,s,0x30);ack=1;} /*判断是否接收到应答信号*/ IO0CLR=SCL; IO0DIR=SDA|SCL; Delay1(1000); } uint8 ISendByte(uint8 sla,uint8 c) { Start_I2c(); /*启动总线*/ SendByte(sla); /*发送器件地址*/ if(ack==0)return(0); SendByte(c); /*发送数据*/ if(ack==0)return(0); Stop_I2c(); /*结束总线*/ return(1); } main函数初始化后运行ISendByte(0xa0,0x55),发现总是显示NO ACK!ERROR!说明程序有问题.fclk=4*11.0592;Delay1(1000)这个延迟肯定是大于4.7us的.不知道什么问题,时序我看拉没问题啊. |