|
本程序已經(jīng)穩(wěn)定使用很長一段時(shí)間了,如果非要追根求源,應(yīng)該追溹到1998年,由于本系統(tǒng)是基于IIC EEPROM的,故對(duì)2401的讀寫采用了阻塞的方式,讀不到數(shù)據(jù)或?qū)懖蝗霐?shù)據(jù)就不退出。 本程序是基于447的,也在163上運(yùn)行過,不過IO的初始化操作需要作些修改,其他可以完全不用修改。 程序開頭的幾行ADD A,@0xFF是非常有用的,在以后的文章中會(huì)有描述。 程序如下: ;SYSTEM CLOCK 4MHz ;IO port define SDA == 4 SCL == 3 MSDA == 0 MSCL == 1 MCS == 2 MRST == 5 ;Register define TREG == 0X10 TCNT == 0X11 GCNT == 0X12 IICADDR == 0X1E IICBUF == 0X28 IICDAT0 == 0X28 IICDAT1 == 0X29 IICDAT2 == 0X2A IICDAT3 == 0X2B IICDAT4 == 0X2C IICDAT5 == 0X2D IICDAT6 == 0X2E IICDAT7 == 0X2F INCLUDE "EM78P447S.H" ORG 0X000 ADD A,@0XFF ADD A,@0XFF ADD A,@0XFF ADD A,@0XFF ADD A,@0XFF START: DISI SET P6 P7 PULL UP EN CONTR MOV TREG,A BC TREG,7 MOV A,TREG CONTW SET SCL SDA OUTPUT HIGH MOV A,@0XFF MOV TREG,A BC TREG,SCL SCL OUTPUT BC TREG,SDA SDA OUTPUT MOV A,TREG IOW IOC6 BS R6,SCL SCL HIGH BS R6,SDA SDA HIGH ;******************************************************************** ;讀入的測(cè)試程序,讀取2401的0x00~0x07地址內(nèi)容 READ_2401: MOV A,@0X00 MOV IICADDR,A CALL IIC_R8BYT RET ;******************************************************************** ;寫入的測(cè)試程序,向2401的0x00~0x07地址寫入0x00 WRITE_2401: MOV A,@0X00 MOV IICADDR,A CLR IICDAT CLR IICDAT CLR IICDAT CLR IICDAT CLR IICDAT CLR IICDAT CLR IICDAT CLR IICDAT CALL IIC_W8BYT RET ;******************************************************************** ;與Microchip的2401接口程序 ;******************************************************************** ;IIC_W8BYT,向2401的指定地址寫入8個(gè)字節(jié)數(shù)據(jù) ;地址由IICADDR指定,數(shù)據(jù)存在IICDAT0~I(xiàn)ICDAT7 IIC_W8BYT: CALL IIC_START MOV A,@0XA0 CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_W8BYT MOV A,IICADDR CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_W8BYT WRITE 8 BYTES TO 24C01 MOV A,@IICBUF MOV R4,A MOV A,@8 MOV GCNT,A IIC_W8BYT1: MOV A,R0 INC R4 CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_W8BYT DJZ GCNT JMP IIC_W8BYT1 CALL IIC_STOP RET ;******************************************************************** ;IIC_W1BYT,向2401的指定地址寫入1個(gè)字節(jié)數(shù)據(jù) ;地址由IICADDR指定,數(shù)據(jù)存在IICDAT0 IIC_W1BYT: CALL IIC_START MOV A,@0XA0 CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_W1BYT MOV A,IICADDR CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_W1BYT WRITE 1 BYTES TO 24C01 MOV A,@IICBUF MOV A,IICDAT0 CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_W1BYT1 CALL IIC_STOP RET ;******************************************************************** ;IIC_R8BYT,從2401的指定地址(IICADDR)讀入8個(gè)字節(jié)數(shù)據(jù) IIC_R8BYT: CALL IIC_START MOV A,@0XA0 CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_R8BYT MOV A,IICADDR CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_R8BYT CALL IIC_START MOV A,@0XA1 CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_R8BYT READ 8 BYTES FROM 24C01 MOV A,@IICBUF MOV R4,A MOV A,@7 MOV GCNT,A IIC_R8BYT1: CALL IIC_RBYT MOV R0,A INC R4 CALL IIC_SACK DJZ GCNT JMP IIC_R8BYT1 CALL IIC_RBYT MOV R0,A CALL IIC_SNACK CALL IIC_STOP RET ;******************************************************************** ;IIC_R1BYT,向2401的指定地址讀出1個(gè)字節(jié)數(shù)據(jù) ;地址由IICADDR指定,數(shù)據(jù)存在IICDAT0 IIC_R1BYT: CALL IIC_START MOV A,@0XA0 CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_R1BYT MOV A,IICADDR CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_R1BYT CALL IIC_START MOV A,@0XA1 CALL IIC_WBYT CALL IIC_CACK JBC R3,GP IF GP=1 OPTION AGAIN JMP IIC_R1BYT READ 1 BYTES FROM 24C01 CALL IIC_RBYT MOV IICDAT0,A CALL IIC_SNACK CALL IIC_STOP RET ;******************************************************************** ;IIC_START IIC_START: BS R6,SCL SCL=1 BS R6,SDA SDA=1 CALL IIC_DELAY BC R6,SDA SDA=0 CALL IIC_DELAY RET ;******************************************************************** ;IIC_STOP IIC_STOP: BS R6,SCL SCL=1 BC R6,SDA SDA=0 CALL IIC_DELAY BS R6,SDA SDA=1 CALL IIC_DELAY RET ;******************************************************************** ;IIC_CACK IF ACK,FIIC=0 IIC_CACK: SET SDA INPUT IOR IOC6 MOV TREG,A BS TREG,SDA MOV A,TREG IOW IOC6 BS R6,SCL SCL=1 BC R3,GP JBC R6,SDA BS R3,GP BC R6,SCL SCL=0 SET SDA OUTPUT IOR IOC6 MOV TREG,A BC TREG,SDA MOV A,TREG IOW IOC6 RET ;******************************************************************** ;IIC_SACK IIC_SACK: BC R6,SDA SDA=0 NOP BS R6,SCL SCL=1 CALL IIC_DELAY BC R6,SCL SCL=0 CALL IIC_DELAY RET ;******************************************************************** ;IIC_SNACK IIC_SNACK: BS R6,SDA SDA=1 NOP BS R6,SCL SCL=1 CALL IIC_DELAY BC R6,SCL SCL=0 CALL IIC_DELAY RET ;******************************************************************** ;IIC_WBYT IIC_WBYT: MOV TREG,A MOV A,@8 MOV TCNT,A IIC_WBYT1: BC R6,SCL SCL=0 JBC TREG,7 JMP IIC_WBIT1 JMP IIC_WBIT0 IIC_WBIT1: BS R6,SDA JMP IIC_WBYT2 IIC_WBIT0: BC R6,SDA SDA=X JMP IIC_WBYT2 IIC_WBYT2: RLC TREG CALL IIC_DELAY BS R6,SCL SCL=1 CALL IIC_DELAY DJZ TCNT JMP IIC_WBYT1 BC R6,SCL SCL=0 CALL IIC_DELAY RET ;******************************************************************** ;IIC_RBYT IIC_RBYT: MOV A,@8 MOV TCNT,A SET SDA INPUT IOR IOC6 OR A,@0X10 IOW IOC6 IIC_RBYT1: BS R6,SCL SCL=1 JBC R6,SDA JMP IIC_RBIT1 JMP IIC_RBIT0 IIC_RBIT1: BS TREG,0 JMP IIC_RBYT2 IIC_RBIT0: BC TREG,0 SDA=X JMP IIC_RBYT2 IIC_RBYT2: RLC TREG BC R6,SCL SCL=0 CALL IIC_DELAY DJZ TCNT JMP IIC_RBYT1 STORE READ RESULT RRC TREG MOV A,TREG MOV TCNT,A SET SDA OUTPUT IOR IOC6 AND A,@0XEF IOW IOC6 RESTORE READ RESULT MOV A,TCNT RET ;******************************************************************** ; IIC_DELAY: NOP NOP RET ORG 0XFFF JMP START |