|
HOLTEK 从I2C的程序
; 芯片: HT46R47 ; 频率: 3.5795454M 赫兹
;--------------------------- ; IO口 Input / Output 定义 ;--------------------------- SCL EQU PA.0 ; IO PSCL EQU PAC.0 ; IO<-> 0-> 1<- SDA EQU PA.5 ; SDA 接到#INT PSDA EQU PAC.5 ; IO<-> 0-> 1<-
;--------------------------- ; I2C Slave Int 外部中断 ;--------------------------- I2CSlave: SNZ SCL ; while SCL=1 SDA=0 Start RETI NULL_Instruction ; 保留部分,用于程序改变 NULL_Instruction ; 保留部分,用于程序改变 MOV Tmp2ACC,A ;保存累加器 MOV A,status ;保存状态寄存器 MOV Tmp2PSW,A ; MOV A,MP MOV Tmp2MP,A ; Save MP MOV A,08h ; MOV I2CTOver,A ; CLR EEI ; 除能外部中断 I2CSlave05: SNZ SCL ; While SCL 1 JMP I2CSlave10 ; SCL 1->0 SNZ SDA ; SDA 0->1 JMP I2CSlave05 ; SDA=0,Wait SCL->0 SNZ SCL ; SCL=1 SDA=1 最后需要跳出 JMP I2CSlave10 ; SCL=0 防止错判为Stop SDZ I2CTOver ; JMP I2CSlave05 ; while SCL=1 SDA=1 Stop JMP I2CSlave99 ; I2CSlave10: NULL_Instruction ; 保留部分,用于程序改变 NULL_Instruction ; 保留部分,用于程序改变 MOV A,0FFh ; MOV I2CTOver,A ; MOV A,8 MOV BitCnt,A CLR ACC
;-- 接收地址+RW 字节 ---- I2CSlave12: RL ACC ; Data 先高后低 I2CSlave16: SNZ SCL ; Wait SCL 0->1 JMP I2CSlave16 ; SCL=0, Wait SZ SDA ; if SDA=0 ADD A,01 ; if SDA=1,Data+1 I2CSlave18: SNZ SCL ; wait SCL 1->0 JMP I2CSlave20 ; SCL=1 SDZ I2CTOver ; JMP I2CSlave18 ; JMP I2CSlave99 ; Jump Exit
I2CSlave20: SDZ BitCnt ; JMP I2CSlave12 ; Next MOV I2CRWFlag,A ; XOR A,MyADDr ; CLR ACC.0 ; SZ ACC ; JMP I2CSlave99 ; ADDress Not EQU ,Exit ;-- 发送ACK信号 ------------ CLR PSDA ; SDA -> OUTPUT CLR SDA ; (ACK) SDA = 0 I2CSlave22: SNZ SCL ; While SCL 0->1 JMP I2CSlave22 ; Wait SCL=0
CLR PSDA ; SDA -> OUTPUT CLR SDA ; (ACK) SDA = 0 I2CSlave30: SNZ SCL ; Wait SCL=1 JMP I2CSlave32 ; While SCL 1->0 SDZ I2CTOver ; JMP I2CSlave30 ; JMP I2CSlave99 ; I2CSlave32: SET PSDA ; SDA -> INPUT SET SDA ; SDA = 1 SZ I2CRWFlag.0 ; JMP I2CSlaveRD ; ===Read JMP
;-- 接收数据ADDr -------- I2CSlave40: NULL_Instruction ; 保留部分,用于程序改变 NULL_Instruction ; 保留部分,用于程序改变 MOV A,8 MOV BitCnt,A ; CLR ACC ; I2CSlave42: RL ACC ; Data 先高后低 I2CSlave46: SNZ SCL ; Wait SCL 0->1 JMP I2CSlave46 ; SZ SDA ; if SDA=0 ADD A,01 ; I2CSlave48: SNZ SCL ; wait SCL 1->0 JMP I2CSlave50 ; Wait SCL 1->0 SDZ I2CTOver ; While SCL=1 JMP I2CSlave48 ; JMP I2CSlave99 ; Jump Exit
I2CSlave50: SDZ BitCnt JMP I2CSlave42 ; Next MOV I2CADDr,A ; ->I2CADDr
;-- 发送ACK信号 ------------ CLR PSDA ; SDA -> OUTPUT CLR SDA ; (ACK) SDA = 0 I2CSlave52: SNZ SCL ; While SCL 0->1 JMP I2CSlave52 ; Wait SCL=0 MOV A,0ffh ; MOV I2CTOver,A ; I2CSlave55: SNZ SCL ; Wait SCL=1 JMP I2CSlave58 ; While SCL 1->0 SDZ I2CTOver ; JMP I2CSlave55 ; JMP I2CSlave99 ; Jump Exit I2CSlave58: SET PSDA ; SDA -> INPUT SET SDA ; SDA = 1 MOV A,I2CADDr ; MOV MP,A ; Point 初始化
;-- 继续接收数据Data -------- I2CSlave6L: NULL_Instruction ; 保留部分,用于程序改变 NULL_Instruction ; 保留部分,用于程序改变 MOV A,8 MOV BitCnt,A CLR ACC
;-- 接收数据Data -------- I2CSlave60: ; RL ACC ; Data 先高后低 I2CSlave62: SNZ SCL ; While SCL 0->1 JMP I2CSlave62 ; Wait SCL=1
SNZ SDA ; SDA=1 JMP I2CSlave66 ; if SDA=0 ?Stop ;-- SCL=1,SDA=1 判启动 -------- I2CSlave64: SNZ SCL ; SCL=1 JMP I2CSlave68 ; while SCL 1->0 SNZ SDA ; JMP I2CSlave80 ; Start == SDA 1->0 SDZ I2CTOver ; While SCL=1 JMP I2CSlave64 ; SDA=1 不变 JMP I2CSlave99 ; Jump Exit
;-- SCL=1,SDA=0 判结束-------- I2CSlave66: SNZ SCL ; SCL=1 JMP I2CSlave70 ; While SCL 1->0 SZ SDA JMP I2CSlave88 ; Stop == SDA 0->1 SDZ I2CTOver ; While SCL=1 JMP I2CSlave66 ; SDA=0 不变 JMP I2CSlave99 ; Jump Exit
I2CSlave68: ADD A,01 ; Data Bit=1 I2CSlave70: SDZ BitCnt JMP I2CSlave60 ; Next MOV IAR,A ; ->I2CADDr INC MP ;
;-- 发送ACK信号 ------------ CLR PSDA ; SDA -> OUTPUT CLR SDA ; (ACK) SDA = 0 I2CSlave72: SNZ SCL ; While SCL 0->1 JMP I2CSlave72 ; Wait SCL=0 I2CSlave74: SNZ SCL ; Wait SCL=1 JMP I2CSlave76 ; While SCL 1->0 SDZ I2CTOver ; JMP I2CSlave74 ; JMP I2CSlave76 ; Jump Exit I2CSlave76: SET PSDA ; SDA -> INPUT SET SDA ; SDA = 1 MOV A,0ffh ; MOV I2CTOver,A ; JMP I2CSlave6L ;
;-- Read Data ------------ I2CSlave80: NULL_Instruction ; 保留部分,用于程序改变 NULL_Instruction ; 保留部分,用于程序改变 SNZ SCL ; Wait SCL 1 JMP I2CSlave82 ; SCL 1->0 SNZ SDA ; SDA 0->1 JMP I2CSlave80 ; JMP I2CSlave99 ; I2CSlave82: MOV A,8 MOV BitCnt,A CLR ACC
;-- 接收地址+RW 字节 ---- I2CSlave84: RL ACC ; Data 先高后低 I2CSlave86: SNZ SCL ; Wait SCL 0->1 JMP I2CSlave86 ; SCL=0, Wait SZ SDA ; if SDA=0 ADD A,01 ; if SDA=1,Data+1 I2CSlave87: SNZ SCL ; wait SCL=1 JMP I2CSlave89 ; While SCL 1->0 SDZ I2CTOver ; JMP I2CSlave87 ; JMP I2CSlave99 ; Jump Exit
I2CSlave89: SDZ BitCnt ; JMP I2CSlave84 ; Next MOV I2CRWFlag,A ; XOR A,MyADDr ; CLR ACC.0 ; SZ ACC ; JMP I2CSlave99 ; ADDress Not EQU ,Exit SNZ I2CRWFlag.0 ; if Read -> JMP I2CSlave99 ; W Exit
;-- 发送ACK信号 ------------ CLR PSDA ; SDA -> OUTPUT CLR SDA ; (ACK) SDA = 0 I2CSlave90: SNZ SCL ; While SCL 0->1 JMP I2CSlave90 ; Wait SCL=0 MOV A,I2CADDr ; MOV MP,A ;
;-- 发送Data数据 -------- I2CSlave92: CLR PSDA MOV A,8 MOV BitCnt,A ; MOV A,0FFH MOV I2CTOver,A ; MOV A,IAR ;
I2CSlave94: SNZ SCL ; Wait SCL=1 JMP I2CSlave96 ; While SCL 1->0 SDZ I2CTOver ; JMP I2CSlave94 ; JMP I2CSlave88 ; I2CSlave96: SNZ ACC.MSB ; =1 JMP I2CSlave97 ; =0 SET SDA ; SDA = 1 JMP I2CSlave98 ; I2CSlave97: CLR SDA ; SDA=0 I2CSlave98: SNZ SCL ; While SCL 0->1 JMP I2CSlave98 ; Wait SCL=0 RL ACC ; SDZ BitCnt ; 8位数据 JMP I2CSlave94 ; 继续
;-- 接收ACK 数据 -------- I2CSlave9A: SNZ SCL ; Wait SCL=1 JMP I2CSlave9B ; While SCL 1->0 SDZ I2CTOver ; JMP I2CSlave9A ; I2CSlave9B: SET PSDA ; 读取ACK前置方向为输入 SET SDA ; I2CSlave9C: SNZ SCL ; While SCL 0->1 JMP I2CSlave9C ; Wait SCL=0 SZ SDA ; SDA=0 ACK JMP I2CSlave88 ; SDA=1 NO ACK RETurn INC MP ; Point + 1 JMP I2CSlave92 ; 继续
;-- 读取当前数据 -------- I2CSlaveRD: NULL_Instruction ; 保留部分,用于程序改变 NULL_Instruction ; 保留部分,用于程序改变 MOV A,I2CADDr ; MOV MP,A ; MOV A,8 MOV BitCnt,A ; MOV A,0FFH MOV I2CTOver,A ; MOV A,IAR ; JMP I2CSlave94 ; ;-- 退出前保存地址 -------- I2CSlave88: MOV A,MP ; MOV I2CADDr,A ; SET PSDA ; SDA -> INPUT SET SDA ; SDA = 1
;-- 退出的入口,恢复数据 ---- I2CSlave99: NULL_Instruction ; 保留部分,用于程序改变 NULL_Instruction ; 保留部分,用于程序改变 SET EEI ; 使能外部中断 MOV A,Tmp2MP MOV MP,A ; MOV A,Tmp2PSW MOV status,A ;恢复状态寄存器 MOV A,Tmp2ACC ;恢复累加器 CLR EIF ; 防止再次进入中断 RETI
|