ba7lnn 发表于 2023-6-22 13:21:51

ST8A8K, 汇编驱LCD1602问题, 4线制的

各位老师好, 学习8051汇编, 写的一段STC8A8K汇编, 不能正常工作,请教下问题出在那?

代码如下:



p4 data 0c0h

lcd_db4 equ p4.1
lcd_db5 equ p3.7
lcd_db6 equ p3.6
lcd_db7 equ p3.5

lcd_en equ p2.0
lcd_rs equ p4.2
//rw equ p1.6

org 00h
acall lcd_init
acall lcd_cls

mov a, #'H'
lcall write_text
mov a, #'E'
lcall write_text
mov a, #'L'
lcall write_text
mov a, #'L'
lcall write_text
mov a, #'O'
lcall write_text

loop: sjmp loop


write_text:
setb lcd_rs
lcall lcd_b
ret

lcd_init:
mov a, #30h
acall lcd_b
mov a, #030h
acall lcd_b
mov a, #030h
acall lcd_b
mov a, #020h
acall lcd_b
mov a, #028h
acall lcd_b
mov a, #0Ch
acall lcd_b
ret

lcd_cls:
mov a, 0x01
acall lcd_b
ret

lcd_cur:
mov a, 0x0c
acall lcd_b
ret


lcd_b:
clr lcd_en                ;lcd en = 0
clr lcd_rs               ;rs=0, write cmd
clr c
rlc a
mov lcd_db4, c
rlc a
mov lcd_db5, c
rlc a
mov lcd_db6, c
rlc a
mov lcd_db7, c

setb lcd_en                        ;lcd en = 1
acall delay1
clr lcd_en

rlc a
mov lcd_db4, c
rlc a
mov lcd_db5, c
rlc a
mov lcd_db6, c
rlc a
mov lcd_db7, c

setb lcd_en
acall delay2
clr lcd_en
ret                                                ;return

;delay(182)
delay1:
mov r0, #182
delay_loop1: djnz r0, delay_loop1
ret

;delay(30)
delay2:
mov r0, #30
delay_loop2: djnz r0,delay_loop2


end

算是这个https://www.stcaimcu.com/forum.php?mod=viewthread&tid=2224贴子的延伸哈

神农鼎 发表于 2023-6-22 14:55:43



虽然是 C, 但是看看思路和设置,I/O口要初始化的





下面这个这 STC15实验箱的程序,找到1个汇编的 LCD1602,
但是 STC8A8K64D4你要设置 I/O的工作模式


ba7lnn 发表于 2023-6-24 15:23:42

设置了I/O工作模式,也对比了这个C,还是不行

神农鼎 发表于 2023-6-24 17:09:48

你参考如下 STC15 的汇编,但I/O口要现初始化成 准双向口
https://www.stcaimcu.com/data/attachment/forum/202306/22/145544ykasaqekqspe9zxa.png

=========================================
;*************功能说明    **************

;驱动LCD1602字符屏.


;显示效果为: LCD显示时间.

;******************************************

Fosc_KHZ    EQU 11059   ;11059KHZ

STACK_POIRTER   EQU   0D0H    ;堆栈开始地质

;*******************************************************************
;*******************************************************************

P4      DATA 0C0H
P5      DATA 0C8H

P0M1    DATA    0x93    ; P0M1.n,P0M0.n   =00--->Standard,    01--->push-pull
P0M0    DATA    0x94    ;                   =10--->pure input,11--->open drain
P1M1    DATA    0x91    ; P1M1.n,P1M0.n   =00--->Standard,    01--->push-pull
P1M0    DATA    0x92    ;                   =10--->pure input,11--->open drain
P2M1    DATA    0x95    ; P2M1.n,P2M0.n   =00--->Standard,    01--->push-pull
P2M0    DATA    0x96    ;                   =10--->pure input,11--->open drain
P3M1    DATA    0xB1    ; P3M1.n,P3M0.n   =00--->Standard,    01--->push-pull
P3M0    DATA    0xB2    ;                   =10--->pure input,11--->open drain
P4M1    DATA    0xB3    ; P4M1.n,P4M0.n   =00--->Standard,    01--->push-pull
P4M0    DATA    0xB4    ;                   =10--->pure input,11--->open drain
P5M1    DATA    0xC9    ; P5M1.n,P5M0.n   =00--->Standard,    01--->push-pull
P5M0    DATA    0xCA    ;                   =10--->pure input,11--->open drain
P6M1    DATA    0xCB    ; P6M1.n,P6M0.n   =00--->Standard,    01--->push-pull
P6M0    DATA    0xCC    ;                   =10--->pure input,11--->open drain
P7M1    DATA    0xE1    ;
P7M0    DATA    0xE2    ;

P_HC595_SER   BIT P4.0;   //pin 14    SER   data input
P_HC595_RCLKBIT P5.4;   //pin 12    RCLk    store (latch) clock
P_HC595_SRCLK BIT P4.3;   //pin 11    SRCLK   Shift data clock


hour    DATA    0x30
minuteDATA    0x31
secondDATA    0x32


;*******************************************************************
;*******************************************************************
      ORG   0000H               ;reset
      LJMP    F_Main


TestString1:    DB "---Clock demo---", 0x00

;******************** 主程序 **************************/
      ORG   0100H       ;reset
F_Main:
    CLR   A
    MOV   P0M1, A   ;设置为准双向口
    MOV   P0M0, A
    MOV   P1M1, A   ;设置为准双向口
    MOV   P1M0, A
    MOV   P2M1, A   ;设置为准双向口
    MOV   P2M0, A
    MOV   P3M1, A   ;设置为准双向口
    MOV   P3M0, A
    MOV   P4M1, A   ;设置为准双向口
    MOV   P4M0, A
    MOV   P5M1, A   ;设置为准双向口
    MOV   P5M0, A
    MOV   P6M1, A   ;设置为准双向口
    MOV   P6M0, A
    MOV   P7M1, A   ;设置为准双向口
    MOV   P7M0, A


    MOV   SP, #STACK_POIRTER
    MOV   PSW, #0
    USING   0       ;选择第0组R0~R7

;================= 用户初始化程序 ====================================

    LCALL   F_Initialize_LCD
    MOV   A, #0
    LCALL   F_ClearLine
    MOV   A, #1
    LCALL   F_ClearLine

    ANL   P2M1, #NOT (1 SHL 4)    ;P2.4设置为推挽输出
    ORL   P2M0, #    (1 SHL 4)
    SETB    P2.4                ;开背光
    LCALL   F_DisableHC595      ;禁止掉学习板上的HC595显示,省电

    MOV   R2, #0;第0行
    MOV   R3, #0;第0个字符
    MOV   DPTR, #TestString1
    LCALL   F_PutString

    MOV   hour, #12   ;初始化时间值
    MOV   minute, #0
    MOV   second, #0
    LCALL   F_DisplayRTC

    LCALL   F_DisableHC595;禁止掉学习板上的HC595显示,省电

;=================== 主循环 ==================================
L_MainLoop:
    MOV   A, #250         ;延时250 ms
    LCALL   F_delay_ms
    MOV   A, #250         ;延时250 ms
    LCALL   F_delay_ms
    MOV   A, #250         ;延时250 ms
    LCALL   F_delay_ms
    MOV   A, #250         ;延时250 ms
    LCALL   F_delay_ms

    LCALL   F_RTC
    LCALL   F_DisplayRTC
    LJMP    L_MainLoop

;*******************************************************************
;*******************************************************************



;========================================================================
; 函数: F_DisableHC595
; 描述: 禁止HC595显示.
; 参数: none.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
; 备注: 所用到的通用寄存器都入栈保护, 退出时恢复原来数据不改变.
;========================================================================
F_DisableHC595:
    PUSH    AR7
    SETB    P_HC595_SER
    MOV   R7, #20
L_DisableHC595_Loop:
    SETB    P_HC595_SRCLK
    NOP
    CLR   P_HC595_SRCLK
    NOP
    DJNZ    R7, L_DisableHC595_Loop
    SETB    P_HC595_RCLK = 1;
    NOP
    CLR   P_HC595_RCLK = 0;                           //锁存输出数据
    SETB    P_HC595_RCLK = 1;
    NOP
    CLR   P_HC595_RCLK = 0;                           //锁存输出数据
    POP   AR7
    RET


;========================================================================
; 函数: F_delay_ms
; 描述: 延时子程序。
; 参数: ACC: 延时ms数.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
; 备注: 除了ACCC和PSW外, 所用到的通用寄存器都入栈保护, 退出时恢复原来数据不改变.
;========================================================================
F_delay_ms:
    PUSH    AR2   ;入栈R2
    PUSH    AR3   ;入栈R3
    PUSH    AR4   ;入栈R4

    MOV   R2,A

L_Delay_Nms_Loop1:
    MOV   R3, #HIGH (Fosc_KHZ / 14)
    MOV   R4, #LOW(Fosc_KHZ / 14)

L_Delay_Nms_Loop2:
    MOV   A, R4   ; 1T
    CLR   C       ; 1T
    SUBB    A, #1   ; 2T
    MOV   R4, A   ; 1T
    MOV   A, R3   ; 1T
    SUBB    A, #0   ; 2T
    MOV   R3, A   ; 1T
    ORL   A, R4   ; 1T
    JNZ   L_Delay_Nms_Loop2   ; 4T

    DJNZ    R2, L_Delay_Nms_Loop1

    POP   AR4   ;出栈R2
    POP   AR3   ;出栈R3
    POP   AR2   ;出栈R4
    RET



;========================================================================
; 函数: F_DisplayRTC
; 描述: 显示时钟函数
; 参数: none.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_DisplayRTC:
    MOV   R2, #1;第2行
    MOV   R3, #4;第4个字符
    MOV   A, hour
    MOV   B, #10
    DIV   AB
    ADD   A, #'0'         ;(2,5,hour / 10 + '0')
    LCALL   F_WriteChar
    INC   R3      ;第5个字符
    MOV   A, B
    ADD   A, #'0'         ;(2,6,hour % 10 +'0')
    LCALL   F_WriteChar
    INC   R3      ;第6个字符
    MOV   A, #'-'         ;(2,7,'-')
    LCALL   F_WriteChar

    INC   R3      ;第7个字符
    MOV   A, minute
    MOV   B, #10
    DIV   AB
    ADD   A, #'0'         ;(2,8,minute / 10 + '0')
    LCALL   F_WriteChar
    INC   R3      ;第8个字符
    MOV   A, B
    ADD   A, #'0'         ;(2,9,minute % 10 +'0')
    LCALL   F_WriteChar
    INC   R3      ;第9个字符
    MOV   A, #'-'         ;(2,10,'-')
    LCALL   F_WriteChar

    INC   R3      ;第10个字符
    MOV   A, second
    MOV   B, #10
    DIV   AB
    ADD   A, #'0'         ;(2,8,second / 10 + '0')
    LCALL   F_WriteChar
    INC   R3      ;第11个字符
    MOV   A, B
    ADD   A, #'0'         ;(2,9,second % 10 +'0')
    LCALL   F_WriteChar
    RET

;========================================================================
; 函数: F_RTC
; 描述: RTC演示函数
; 参数: none.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_RTC:
    INC   second
    MOV   A, second
    CLR   C
    SUBB    A, #60
    JNC   $+3
    RET
    MOV   second, #0

    INC   minute
    MOV   A, minute
    CLR   C
    SUBB    A, #60
    JNC   $+3
    RET
    MOV   minute, #0

    INC   hour
    MOV   A, hour
    CLR   C
    SUBB    A, #24
    JNC   $+3
    RET
    MOV   hour, #0
    RET


;************* LCD1602相关程序*****************************************************/
;8位数据访问方式    LCD1602   标准程序    梁工编写    2014-2-21

LineLengthEQU 16      ;16x2

/*************Pin define*****************************************************/

LCD_BUS   DATA 0x80   ;P0--0x80, P1--0x90, P2--0xA0, P3--0xB0

LCD_B7BIT LCD_BUS.7   ;D7 -- Pin 14       LED- -- Pin 16
LCD_B6BIT LCD_BUS.6   ;D6 -- Pin 13       LED+ -- Pin 15
LCD_B5BIT LCD_BUS.5   ;D5 -- Pin 12       Vo   -- Pin 3
LCD_B4BIT LCD_BUS.4   ;D4 -- Pin 11       VDD-- Pin 2
LCD_B3BIT LCD_BUS.3   ;D3 -- Pin 10       VSS-- Pin 1
LCD_B2BIT LCD_BUS.2   ;D2 -- Pin9
LCD_B1BIT LCD_BUS.1   ;D1 -- Pin8
LCD_B0BIT LCD_BUS.0   ;D0 -- Pin7

LCD_ENA BIT P2.7    ;Pin 6
LCD_RWBIT P2.6    ;Pin 5   LCD_RS    R/W   DB7--DB0      FOUNCTION
LCD_RSBIT P2.5    ;Pin 4      0       0   INPUT      write the command to LCD model
                  ;         0       1   OUTPUT   read BF and AC pointer from LCD model
                  ;         1       0   INPUT      write the data to LCDmodel
                  ;         1       1   OUTPUT   read the data from LCD model

;total 2 lines, 16x2= 32
;first line address:0~15
;second line address: 64~79


C_CLEAR         EQU 0x01    ;clear LCD
C_HOME          EQU 0x02    ;cursor go home
C_CUR_L         EQU 0x04    ;cursor shift left after input
C_RIGHT         EQU 0x05    ;picture shift right after input
C_CUR_R         EQU 0x06    ;cursor shift right after input
C_LEFT          EQU 0x07    ;picture shift left after input
C_OFF         EQU 0x08    ;turn off LCD
C_ON            EQU 0x0C    ;turn onLCD
C_FLASH         EQU 0x0D    ;turn onLCD, flash
C_CURSOR      EQU 0x0E    ;turn onLCD and cursor
C_FLASH_ALL   EQU 0x0F    ;turn onLCD and cursor, flash
C_CURSOR_LEFT   EQU 0x10    ;single cursor shift left
C_CURSOR_RIGHTEQU 0x10    ;single cursor shift right
C_PICTURE_LEFTEQU 0x10    ;single picture shift left
C_PICTURE_RIGHT EQU 0x10    ;single picture shift right
C_BIT8          EQU 0x30    ;set the data is 8 bits
C_BIT4          EQU 0x20    ;set the data is 4 bits
C_L1DOT7      EQU 0x30    ;8 bits,one line 5*7dots
C_L1DOT10       EQU 0x34    ;8 bits,one line 5*10 dots
C_L2DOT7      EQU 0x38    ;8 bits,tow lines 5*7 dots
C_4bitL2DOT7    EQU 0x28    ;4 bits,tow lines 5*7 dots
C_CGADDRESS0    EQU 0x40    ;CGRAM address0 (addr=40H+x)
C_DDADDRESS0    EQU 0x80    ;DDRAM address0 (addr=80H+x)


;========================================================================
; 函数: F_LCD_DelayNop
; 描述: 延时函数
; 参数: none.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_LCD_DelayNop:
    NOP         ;NOP(15)
    NOP
    NOP
    NOP
    NOP
    NOP
    NOP
    RET

;========================================================================
; 函数: F_CheckBusy
; 描述: 检测忙
; 参数: none.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_CheckBusy:            ;check the LCD busy or not. With time out
    PUSH    ACC
    PUSH    AR2
    PUSH    AR3
    MOV   R2, #HIGH 10000
    MOV   R3, #LOW10000

L_CheckBusyLoop:
    JNB   LCD_B7, L_QuitCheckBusy ; 5T
    MOV   A, R3   ; 1T
    CLR   C       ; 1T
    SUBB    A, #1   ; 2T
    MOV   R3, A   ; 1T
    MOV   A, R2   ; 1T
    SUBB    A, #0   ; 2T
    MOV   R2, A   ; 1T
    ORL   A, R3   ; 1T
    JNZ   L_CheckBusyLoop ; 4T
L_QuitCheckBusy:
    POP   AR3
    POP   AR2
    POP   ACC

;   JB      LCD_B7, $   ;check the LCD busy or not. Without time out
    RET


;========================================================================
; 函数: F_IniSendCMD
; 描述: 初始化写命令(不检测忙)
; 参数: ACC: 要写的命令.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_IniSendCMD:
    CLR   LCD_RW
    MOV   LCD_BUS, A
    LCALL   F_LCD_DelayNop
    SETB    LCD_ENA
    LCALL   F_LCD_DelayNop
    CLR   LCD_ENA
    MOV   LCD_BUS, #0xff
    RET

;========================================================================
; 函数: F_Write_CMD
; 描述: 写命令(检测忙)
; 参数: ACC: 要写的命令.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_Write_CMD:
    CLR   LCD_RS
    SETB    LCD_RW
    MOV   LCD_BUS, #0xff
    LCALL   F_LCD_DelayNop
    SETB    LCD_ENA
    LCALL   F_CheckBusy   ;check the LCD busy or not.
    CLR   LCD_ENA
    CLR   LCD_RW

    MOV   LCD_BUS, A
    LCALL   F_LCD_DelayNop
    SETB    LCD_ENA
    LCALL   F_LCD_DelayNop
    CLR   LCD_ENA
    MOV   LCD_BUS, #0xff
    RET

;========================================================================
; 函数: F_Write_DIS_Data
; 描述: 写显示数据
; 参数: ACC: 要写的数据.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_Write_DIS_Data:
    CLR   LCD_RS
    SETB    LCD_RW

    MOV   LCD_BUS, #0xff
    LCALL   F_LCD_DelayNop
    SETB    LCD_ENA
    LCALL   F_CheckBusy   ;check the LCD busy or not.
    CLR   LCD_ENA
    CLR   LCD_RW
    SETB    LCD_RS

    MOV   LCD_BUS, A
    LCALL   F_LCD_DelayNop
    SETB    LCD_ENA
    LCALL   F_LCD_DelayNop
    CLR   LCD_ENA
    MOV   LCD_BUS, #0xff
    RET


;========================================================================
; 函数: F_Initialize_LCD
; 描述: 初始化LCD函数
; 参数: none.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_Initialize_LCD:
    SETB    LCD_ENA = 0;
    SETB    LCD_RS= 0;
    SETB    LCD_RW= 0;

    MOV   A, #100
    LCALL   F_delay_ms
    MOV   A, #C_BIT8      ;set the data is 8 bits
    LCALL   F_IniSendCMD

    MOV   A, #10
    LCALL   F_delay_ms
    MOV   A, #C_L2DOT7    ;tow lines 5*7 dots
    LCALL   F_Write_CMD

    MOV   A, #10
    LCALL   F_delay_ms
    MOV   A, #C_CLEAR
    LCALL   F_Write_CMD
    MOV   A, #C_CUR_R   ;Curror Shift Right
    LCALL   F_Write_CMD
    MOV   A, #C_ON      ;turn onLCD
    LCALL   F_Write_CMD
    RET


;========================================================================
; 函数: F_ClearLine
; 描述: 清除1行
; 参数: ACC: 行(0或1)
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_ClearLine:
    MOV   C, ACC.0
    MOV   ACC.6, C
    ANL   A, #0x40
    ORL   A, #0x80
    LCALL   F_Write_CMD   ;Write_CMD(0x80)

    PUSH    AR2
    MOV   R2, #LineLength
L_ClearLine_Loop:
    MOV   A, #' '
    LCALL   F_Write_DIS_Data
    DJNZ    R2, L_ClearLine_Loop
    POP   AR2
    RET


;========================================================================
; 函数: F_WriteChar
; 描述: 指定行、列和字符, 写一个字符
; 参数: R2: 行(0或1),R3: 第几个字符(0~15),ACC: 要写的字符.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_WriteChar:
    PUSH    ACC

    MOV   A, R2
    MOV   C, ACC.0
    MOV   ACC.6, C
    ANL   A, #0x40
    ORL   A, #0x80
    ADD   A, R3
    LCALL   F_Write_CMD   ;Write_CMD(0x80)

    POP   ACC
    LCALL   F_Write_DIS_Data
    RET

;========================================================================
; 函数: F_PutString
; 描述: 写一个字符串,指定行、列和字符串首地址
; 参数: R2: 行(0或1),R3: 第几个字符(0~15),DPTR: 要写的字符串首地址.
; 返回: none.
; 版本: VER1.0
; 日期: 2013-4-1
;========================================================================
F_PutString:
    MOV   A, R2
    MOV   C, ACC.0
    MOV   ACC.6, C
    ANL   A, #0x40
    ORL   A, #0x80
    ADD   A, R3
    LCALL   F_Write_CMD   ;Write_CMD(0x80)
L_PutString_Loop:
    CLR   A
    MOVC    A, @A+DPTR
    JZ      L_QuitPutString   ;遇到停止符0结束
    LCALL   F_Write_DIS_Data
    INC   DPTR
    INC   R3
    MOV   A, R3
    CJNE    A, #LineLength, L_PutString_Loop
L_QuitPutString:
    RET

;******************** LCD20 Module END ***************************

    END



ba7lnn 发表于 2023-6-27 09:09:14

谢谢, 是不是差一个仿真器的原因呢{:sweat:}
页: [1]
查看完整版本: ST8A8K, 汇编驱LCD1602问题, 4线制的