本帖最后由 chuandaoxy 于 2014-2-9 17:43 编辑
我在编写一个驱动程序,汇编版十分成功,但是C语言版本老是不能顺利通过,于是产生了,用C调用汇编的办法,因为时序控制,用汇编更精准,由于CPU管脚少,很少使用液晶模块,我在网上发现用2根线,驱动8574再驱动1602,因为C调用汇编要传递参数,(就是要显示的字符串),下面是我的汇编代码,希望那位热心朋友改成C的版本,谢谢(晶振110592)
SDA BIT P2.1 ; I2C DATA
SCL BIT P2.0 ; I2C CLOCK
DATA_I2C EQU 2FH ;Bit addressing DATA buffer for I2C bus
ADDR_I2C EQU 30H ;Address buffer for I2C bus
ADDR_A3A0 EQU 34H ;REAL ADDRESS FROM 0-7 OF I2C
I2C_ACK BIT PSW.5 ;I2C Acknowledge Flag 0= Not acknowledge
I2C_ALL BIT PSW.1 ;If send data complete this falg will be = 1
//EN_LCD BIT DATA_I2C.3 ;BIT 3 of DATA_I2C
//RS_LCD BIT DATA_I2C.2 ;BIT 2 OF DATA_I2C
EN_LCD BIT DATA_I2C.1 ;BIT 3 of DATA_I2C
RS_LCD BIT DATA_I2C.3 ;BIT 2 OF DATA_I2C
;******************************************************************************
; MAIN PROGRAM
;******************************************************************************
; LCD is CONNECT TO PCF8754 at address 7EHS
; 4 BIT INTERFACE
MAIN: MOV SP,#128-24
ACALL INIT_LCD
MOV A,#01H ;CLEAR LCD
ACALL WR_INS_LCD
MOV A,#00H ;Start address at 00
ACALL SET_DDRAM
MOV DPTR,#MESSAGE
ACALL WR_L_LCD
MOV A,#40H
ACALL SET_DDRAM
MOV DPTR,#MESSAGE1
ACALL WR_L_LCD
MESSAGE: DB 'Test20lineLCDby..I2C',020H
MESSAGE1: DB 'www.mcu.cz',020H
NUMBER_TAB: DB 030H,031H,032H,033H,034H,035H,036H,037H,038H,039H
;******************************************************************************
; LCDC Routines
;******************************************************************************
; INITIAL LCD
INIT_LCD: MOV A,#33H
ACALL WR_INS_LCD
MOV A,#32H
ACALL WR_INS_LCD
MOV A,#28H ;FUNCTION SET
ACALL WR_INS_LCD
MOV A,#06H ;ENTRY MODE
ACALL WR_INS_LCD
MOV A,#01H ;CLEAR DISPLAY
ACALL WR_INS_LCD
ACALL I2C_DELAY
MOV A,#01H ;CLEAR DISPLAY
ACALL WR_INS_LCD
ACALL I2C_DELAY
ACALL I2C_DELAY
MOV A,#0CH ;08H Display OFF ,no cursor and not blink (0Ch for ON)
ACALL WR_INS_LCD ;If 0fH then blink and show cursor
RET
; SET ADDRESS OF DDRAM
; INPUT = A
SET_DDRAM: SETB ACC.7
ACALL WR_INS_LCD
RET
; SET ADDRESS OF CGRAM
; INPUT = A
SET_CGRAM: CLR ACC.7
SETB ACC.6
ACALL WR_INS_LCD
RET
; WRITE LINE LCD DIGIT=20
; INPUT = DPTR
; REG = R5 A , DPTR
WR_L_LCD: PUSH 05H ;PUSH R5
MOV R5,#00 ;NUMBER OF DIGIT
CLR A ;CLEAR A
WR_LINE_1: MOVC A,@A+DPTR
ACALL WR_CH_LCD
INC R5
MOV A,R5
CJNE A,#20,WR_LINE_1 ;CHECK FOR 20 DIGIT COMPLETE
POP 05H ;POP R5
MOV A,#01H ;CLEAR DISPLAY
ACALL WR_INS_LCD
ACALL I2C_DELAY
ACALL I2C_DELAY
ACALL I2C_DELAY
RET
; write DATA to DDRAM
; REG = ACC
; INPUT = ACC
WR_CH_LCD: PUSH ACC
ANL A,#0F0H
MOV ADDR_A3A0,#07H
MOV DATA_I2C,A
SETB RS_LCD
ACALL WR_8574
ACALL ENABLE_LCD
POP ACC
SWAP A
ANL A,#0F0H
MOV DATA_I2C,A
SETB RS_LCD
ACALL WR_8574
ACALL ENABLE_LCD
RET
; WRITE instruction to LCD USE PCF8574 at address 7EH
; REG = A
; INPUT = A
WR_INS_LCD: PUSH ACC ;Keep A
ANL A,#0F0H
MOV ADDR_A3A0,#07H ;Select address of PCF 8574 to LCD
MOV DATA_I2C,A
ACALL WR_8574
ACALL ENABLE_LCD
POP ACC
SWAP A
ANL A,#0F0H
MOV DATA_I2C,A
ACALL WR_8574
; ENABLE PULSE FOR LCD INPUT = A
ENABLE_LCD: SETB EN_LCD
ACALL WR_8574
CLR EN_LCD
ACALL WR_8574
RET
;******************************************************************************
; I2C Routines
;******************************************************************************
; Write Data to PCF8574A,PCF8574AP
; I/P = DATA_I2C , ADDR_A3A0
; *ADDR_CH can has value 0-7
//WR_8574: MOV ADDR_I2C,#70H
WR_8574: MOV ADDR_I2C,#4EH
ACALL ADJ_ADDR
START_WR: ACALL I2C_CONN ;START WRITE DATA TO I2C DEVICE
START_WR_1: ACALL I2C_D_WR
ACALL I2C_STOP
RET
; ADJUST ADDRESS OF I2C FOR 7 BIT ADDRESSING
; I/P = ADDR_A0A3
; O/P = ADDR_I2C
; REG = ACC
; Example:
; ADDR_I2C: 0100 1110
; ADDR_A3A0: 0000 0011
ADJ_ADDR: PUSH ACC
ANL ADDR_I2C,#0F1H ;YYYY 000Y
MOV A,ADDR_A3A0
ANL A,#07H ;0000 0XXX
RL A ;0000 XXX0
ANL A,#0EH ;0000 XXX0
ADD A,ADDR_I2C
MOV ADDR_I2C,A ;YYYY XXXY
POP ACC
RET
; WRITE DATA TO I2C PHERIFERAL
; REG = R4 , ACC ,CARRY FLAG
; INPUT = DATA_I2C
I2C_D_WR: PUSH ACC
MOV A,DATA_I2C
SJMP I2C_SEND
; Connect and Send data to I2C Device
; I/P = ADDR_I2C
; O/P = I2C_ACK
; REG = R5 ACC
I2C_CONN: PUSH ACC ;Addressing to I2C Device
MOV A,ADDR_I2C
ACALL I2C_START ;Start connect
;SEND Data to I2C
I2C_SEND: PUSH 05H ;PUSH R5
MOV R5,#08
I2C_SEND_1: RLC A ;MOV BIT to Carry FLAG
MOV SDA,C
ACALL I2C_CLK ;CLOCK TO SEND ONE BIT
DJNZ R5,I2C_SEND_1 ;Decrease R5 BY ONE
SETB SDA ;Complete Send Eight Bit
ACALL I2C_DELAY
SETB SCL
ACALL I2C_DELAY
JB SDA,I2C_SEND_2 ;Jump if Device not Acknowledge
SETB I2C_ACK ;Device Acknowledge
I2C_SEND_2: CLR SCL
POP 05H
POP ACC
RET
; I2C Start Condition
; O/P = I2C_ALL
I2C_START: SETB SDA
SETB SCL
CLR I2C_ALL
ACALL I2C_DELAY
CLR SDA
ACALL I2C_DELAY
CLR SCL
RET
; I2C Stop Condition
; O/P = I2C_ALL
I2C_STOP: CLR SDA
SETB SCL
ACALL I2C_DELAY
SETB SDA
SETB I2C_ALL
RET
; Clock pulse for I2C
I2C_CLK: SETB SCL
ACALL I2C_DELAY
CLR SCL
RET
; Delay time at system clock 12 MHz
I2C_DELAY: PUSH 02H
MOV R2,#0FFH
DJNZ R2,$
POP 02H
RET
END
|