[ZLG-MCU] 求助关于GPIO的IOPIN问题

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

本版积分规则

3

主题

7

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部

3

主题

7

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部