本帖最后由 tyw 于 2014-2-10 14:03 编辑
检测到时钟边沿后适当延时(做几个nop空操作)再读写数据试试.下例是I/O口模拟的SCL,用于读写HT2201 E2Prom,供参考.
;**********************
;* ◆字节读出子程序◆ *
;* 出口: A←读出内容 *
;**********************
RBYTE: SET SCL ;时钟脚_/ ̄
SET SDA_C ;定义数据脚为输入口
MOV A,08H
MOV DATA_8,A ;设传输数据长度8
RBYTE1: SET SCL ;时钟脚_/ ̄
NOP
NOP
NOP
NOP
NOP ;延时
CLR SCL ;时钟脚 ̄\_
NOP
NOP
NOP
NOP
NOP ;延时
RL READ_OUT ;读出数据字节左环移一位,准备下一位数据
CLR READ_OUT.0 ;读入数据字节最低位←"0" (从低位到高位)
SZ SDA ;检查数据线状态,="0"?
SET READ_OUT.0 ;≠"0",则读入数据字节最低位←"1"
SDZ DATA_8 ;数据长度减一,并检查是否为"0"
JMP RBYTE1 ;≠"0",转RBYTE1循环
MOV A,READ_OUT ;A←读出内容
RET
;**********************
;* ◆字节写入子程序◆ *
;* 入口: A←待写内容 *
;**********************
WBYTE: MOV BYTE_DAT,A ;待写内容暂存于A
CLR SCL ;时钟脚 ̄\_
CLR SDA_C ;定义数据脚为输出口
MOV A,08H
MOV DATA_8,A ;预置写入数据长度计数器
WBYTE1: CLR SDA ;数据脚←"0"
SZ BYTE_DAT.7 ;检查待写内容最高位=?
SET SDA ;最高位≠"0",则数据脚←"1"
SET SCL ;时钟脚_/ ̄\_ ,发送当前数据位
CLR SCL
RL BYTE_DAT ;待写内容字节左环移一位,准备下一位数据
SDZ DATA_8 ;写入数据长度减一,并检查是否为"0"
JMP WBYTE1 ;≠"0",转WBYTE1循环
SET SDA_C ;定义数据脚为输入口
SET SCL ;时钟脚_/ ̄,CPU准备收2201的应答信号
WBYTE2: SZ SDA ;检查数据脚状态
JMP WBYTE2 ;≠"0",转WBYTE2,等待应答信号
RET
|