我用汇编编了个时钟程序.可是在读连续时间时有时回出现错误,有时又对了.不知道是什么原因.清高手指教.<br /><br />我是用伟福模拟的,看内存单元.我实际也用液晶显示过,一样.<br /><br /><br />;I2C总线说明:<br />;I2_SDA =1时,即总线空闲<br />;I2_SDA =0时,即总线忙,即正在使用<br />; 本程序集在I2_SDA =0时, 使I2_SCL=0,<br />;此时即可改变I2_SDA 的数据,或接受I2_SDA 数据的改变<br />;I2_SCL=0时, 数据是可以改变的<br />;I2_SCL=1时, 数据的改变视为控制信号,如0到1则为停止控制<br />;如1到0则为启动控制<br /><br />;I2C总线(PFC8563)驱动子程序集<br />I2_SCL EQU P2.6<br />I2_SDA EQU P2.7<br />I2ADDRW EQU 0A2H<br />I2ADDRR EQU 0A3H<br />I2TIMER EQU 02H<br />I2TIMERN EQU 07H<br /> ORG 0000H<br /> JMP MAIN<br /> ORG 0030H<br />MAIN:<br /> MOV SP,#80H<br /> MOV R0,#20H<br /> CALL I2_WRTIME ;写时间初始值<br />ED: MOV R0,#28H<br /> CALL I2_RDTIME ;读时间值<br /> JMP ED<br />;========================================================== 开始I2CU总线子程序<br />I2_START: SETB I2_SDA<br /> NOP<br /> SETB I2_SCL<br /> NOP ;建立起始条件的时间大于4.7us<br /><br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> CLR I2_SDA ;起始条件<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> CLR I2_SCL ;钳隹总线<br /> NOP<br /> RET<br />;===================================================结束I2CU总线子程序<br />I2_STOP: CLR I2_SDA<br /> NOP<br /> SETB I2_SCL ;结束总线时间大于4us<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> SETB I2_SDA ;结束总线<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> RET<br />;=============================================发送应答信号子程序:即发送0<br />I2_SDACK: CLR I2_SDA<br /> NOP<br /> NOP<br /> SETB I2_SCL<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> CLR I2_SCL<br /> SETB I2_SDA<br /> NOP<br /> NOP<br /> RET<br />;===========================================发送非应答信号子程序, 即发送1<br />I2_SDNACK: SETB I2_SDA<br /> NOP<br /> NOP<br /> SETB I2_SCL<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> CLR I2_SCL<br /> CLR I2_SDA<br /> NOP<br /> NOP<br /> RET<br />;====================================================<br />;检查应答子程序,即读应答信号:若读出结果 为0<br />;证明有应答,即总线上有器件响应,否则可能无器件或器件坏<br /><br />;出口参数:<br />;FO=O有应答<br /><br />I2_CHKACK: SETB I2_SDA<br /> NOP<br /> NOP<br /> SETB I2_SCL<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> CLR F0<br /> MOV C, I2_SDA<br /> JNC CEND<br /> SETB F0<br /><br />CEND: CLR I2_SCL<br /> RET<br /><br />;=============================================发送字节子程序<br /><br />;入口参数<br />;A: 被发送数<br /><br />;占用资源:<br />;R2<br /><br />;说明:每写一字节要调用一次I2_CHKACK取应答位<br /><br />I2_WRBYTE: MOV R2, #08H<br />I2_WRBYTELP1: RLC A<br /> MOV I2_SDA, C<br /> NOP<br /> SETB I2_SCL<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> CLR I2_SCL<br /> DJNZ R2, I2_WRBYTELP1<br /> NOP<br /> NOP<br /> RET<br /><br />;==================================================读取字节子程序<br /><br />;出口参数:<br />;A: 读出的数<br /><br />;占用资源<br />;R2<br /><br />;说明: 每读取一字节要发送一应答/非应答位<br /><br />I2_RDBYTE: MOV R2, #08H<br />I2_RDLP: SETB I2_SDA<br /> NOP<br /> SETB I2_SCL<br /> NOP<br /> NOP<br /> MOV C, I2_SDA<br /> NOP<br /> CLR I2_SCL<br /> RLC A<br /> NOP<br /> NOP<br /> NOP<br /> NOP<br /> DJNZ R2, I2_RDLP<br /> RET<br /><br /><br /><br />;===================================BCD码转二进制子程序<br /><br />;入口参数:<br />;A: BCD码<br /><br />;出口参数<br />;A: 二进制数<br /><br />;占用资源:<br />;A<br />;R2<br />;R3<br /><br />BCD2BIN: MOV R3, A<br /> ANL A, #0F0H<br /> RR A<br /> MOV R2, A<br /> RR A<br /> RR A<br /> ADD A, R2<br /> MOV R2, A<br /> MOV A, R3<br /> ANL A, #0FH<br /> ADD A, R2<br /> RET<br /><br /><br />;========================================写8563万年历子程序<br /><br />;入口参数:<br />;R0: 参数区首址: 参数区格式(秒分钟小时日星期月年,BCD码表示)<br /><br />;占用资源:<br />;A<br />;R0<br />;R2<br />;R3<br /><br /><br />I2_WRTIME: CALL I2_START ;发送起始条件<br /><br /> MOV A, #I2ADDRW<br /> CALL I2_WRBYTE ;发送8563地址<br /> CALL I2_CHKACK ;检查应答<br /> JB F0,I2_WRTIME<br /> MOV A, #I2TIMER ;发送8563时间寄存器地址<br /> CALL I2_WRBYTE<br /> CALL I2_CHKACK<br /> JB F0,I2_WRTIME<br /> MOV R3, #I2TIMERN<br />I2_WRTIMELP1: MOV A, @R0<br /> CALL I2_WRBYTE ;向8563写时间<br /> CALL I2_CHKACK<br /> JB F0,I2_WRTIME<br /> INC R0<br /> DJNZ R3, I2_WRTIMELP1<br /><br /> CALL I2_STOP ;发送停止条件<br /> RET<br /><br /><br />;===================================读8563万年历子程序<br /><br />;入口参数:<br />;R0: 参数区首址(格式同上)<br /><br />;出口参数:参数区存放万年历数据(二进制)<br /><br />;占用资源:<br />;A<br />;R0<br />;R2<br />;R3<br /><br />I2_RDTIME: CALL I2_START ;发送起始条件<br /><br /> MOV A, #I2ADDRW ;发送8563写地址<br /> CALL I2_WRBYTE<br /> CALL I2_CHKACK<br /> JB F0,I2_RDTIME<br /> MOV A, #I2TIMER ;发送8563时间寄存器首址<br /> CALL I2_WRBYTE<br /> CALL I2_CHKACK<br /> JB F0,I2_RDTIME<br /> CALL I2_START ;发送起始条件<br /> MOV A, #I2ADDRR ;发送8563读地址<br /> CALL I2_WRBYTE<br /> CALL I2_CHKACK<br /> JB F0,I2_RDTIME<br /> MOV R3, #I2TIMERN-1<br />I2_RDTIMELP1: CALL I2_RDBYTE ;读取8563万年历数据<br /> MOV @R0, A<br /> CALL I2_SDACK ;发送应答信号<br /> INC R0<br /> DJNZ R3, I2_RDTIMELP1<br /> CALL I2_RDBYTE ;读取8563万年历年数据<br /> MOV @R0, A<br /> CALL I2_SDNACK ;发送非应答信号<br /> CALL I2_STOP ;发送停止条件<br /> RET<br /><br /><br /><br /><br /><br /><br /><br /><br /> |
|