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