assembly 使用“检查忙碌”标志在LCD上显示数据的汇编代码有什么问题

fcy6dtqo  于 2023-01-26  发布在  其他
关注(0)|答案(1)|浏览(154)

这是我第一次与液晶显示器,我试图让我的代码(见下文)写一个PIC 18f 458显示ASCII字符'N'和'O'的液晶显示器;使用“检查忙碌”标志而不是延迟来工作。
当我在MPLAB X IDE中调试代码时,它看起来像预期的那样执行,但是,当我使用Proteus测试它时,它只显示“O”字符(见图1)。

REGA    EQU 0x07            ; set aside registers for delay
REGB    EQU 0x08            ; subroutines
REGC    EQU 0x09
LCD_DATA EQU    PORTD           ; LCD data pins RD0-RD7
LCD_CTRL EQU    PORTC           ; LCD control pins
RS      EQU     RC0             ; RS pin of LCD
RW      EQU     RC1             ; R/W pin of LCD
EN      EQU     RC2             ; Enable pin of LCD 

        ORG     0000H           ; burn into ROM starting at 0
    
        CLRF    TRISD           ; make PORT D an output
        CLRF    TRISC           ; make PORTC an output
        BCF     LCD_CTRL,EN     ; enable idle low
        CALL    LDELAY          ; wait for initialisation
        MOVLW   0x38            ; init LCD 2 lines, 5x7 char    
        CALL    COMMAND         ; issue command
        CALL    LDELAY          ; initialisation hold
        MOVLW   0x0E            ; LCD on, cursor on
        CALL    COMMAND         ; issue command
        CALL    READY           ; is LCD ready?
        MOVLW   0x01            ; clear LCD command
        CALL    COMMAND         ; issue command
        CALL    READY           ; is LCD ready?
        MOVLW   0x06            ; shift cursor right
        CALL    COMMAND         ; issue command
        CALL    READY           ; is LCD ready?
        MOVLW   0x86            ; cursor: line 1, pos. 6
        CALL    COMMAND         ; issue command
        CALL    READY           ; is LCD ready?
        MOVLW   A'N'            ; display letter 'N'
        CALL    DATA_DISPLAY
        CALL    READY           ; is LCD ready?
        MOVLW   A'O'            ; display letter 'O'
        CALL    DATA_DISPLAY
        CALL    READY           ; is LCD ready?
HERE    BRA     HERE        
;------------------------------------------------------ 
COMMAND MOVWF   LCD_DATA        ; issue command code
        BCF     LCD_CTRL,RS     ; RS = 0 for command
        BCF     LCD_CTRL,RW     ; R/W = 0 for write
        BSF     LCD_CTRL,EN     ; E = 1 for high pulse
        CALL    SDELAY          ; make a wide En pulse
        BCF     LCD_CTRL,EN     ; E = 0 for H-to-L pulse
        RETURN
;-----------------------------------------------------  
DATA_DISPLAY 
        MOVWF   LCD_DATA        ; copy WREG to LCD DATA pin
        BSF     LCD_CTRL,RS     ; RS = 1 for data
        BCF     LCD_CTRL,RW     ; R/W = 0 for write
        BSF     LCD_CTRL,EN     ; E = 1 for high pulse
        CALL    SDELAY          ; make a wide En pulse
        BCF     LCD_CTRL,EN     ; E = 0 for H-to-L pulse    
        RETURN
;-----------------------------------------------------
; check busy flag   
READY   SETF    TRISD           ; make PORTD input port for LCD data
        BCF     LCD_CTRL,RS     ; RS = 0 access command reg
        BSF     LCD_CTRL,RW     ; R/W = 1 read command flag
; read command reg and check busy flag  
BACK    BSF     LCD_CTRL,EN     ; E = 0 for L-to-H pulse
        CALL    SDELAY          ; make a wide En pulse
        BCF     LCD_CTRL,EN     ; E = 1 for L-to-H pulse
        BTFSC   LCD_DATA,7      ; stay until busy flag = 0
        BRA     BACK
        CLRF    TRISD           ; make PORTD output port for LCD data
        RETURN
; 1/4 SECOND DELAY
LDELAY  
        MOVLW   D'200'          ; load WREG with literal value 200
        MOVWF   REGA            ; copy to delay regA
L1      MOVLW   D'250'          ; load WREG with literal value 250
        MOVWF   REGB            ; copy to delay regB
L2      NOP                     ; waste soem time
        NOP
        DECF    REGB, F         ; decrement value in regB
        BNZ     L2              ; repeat until it equals to zero
        DECF    REGA, F         ; decrement value in regA
        BNZ     L1              ; repeat until it equals to zero
        RETURN
; Short DELAY
SDELAY  
        MOVLW   D'2'            ; load WREG with literal value 2
        MOVWF   REGC            ; copy to delay regE
S1      NOP
        DECF    REGC, F         ; decrement value in regE
        BNZ     S1              ; repeat until it equals to zero
        RETURN
        END

当我将代码末尾的无限循环改为循环加载和显示字符时,我可以看到两个字符都显示在循环中(见图2)。


所以,我的问题是,我的代码(如下)出了什么问题,导致它只显示一个字符,即最后一个字符?
请注意,当我使用延迟(在汇编代码中)而不是忙碌标志时,代码按预期工作。同样,使用“检查忙”标志的C版本(见下文)也按预期工作。因此,我留下了挠头可能是什么问题。因此,任何人可以提供的见解将非常感谢。

#define ldata PORTD                     // PORTD = LCD data pins
#define rs PORTCbits.RC0                // rs = PORTC.0
#define rw PORTCbits.RC1                // rw = PORTC.1
#define en PORTCbits.RC2                // en = PORTC.2
#define busy PORTDbits.RD7              // busy = PORTD.7

void lcdcmd(unsigned char value);
void lcddata(unsigned char value);
void lcdready(void);
void MSDelay(unsigned int itime);
 
void main()
  {
    TRISD = 0;                          // both ports B and D as output
    TRISB = 0;
    en = 0;                             // enable idle low      
    MSDelay(250);                       // long delay
    lcdcmd(0x38);                       // init. LCD 2  lines, 5x7 matrix
    MSDelay(250);                       // long delay
    lcdcmd(0x0E);                       // display on, cursor on
    lcdready();                         // check the LCD busy flag
    lcdcmd(0x01);                       // clear LCD
    lcdready();                         // check the LCD busy flag          
    lcdcmd(0x06);                       // shift cursor right
    lcdready();                         // check the LCD busy flag          
    lcdcmd(0x86);                       // line 1, position 6
    lcdready();                         // check the LCD busy flag          
    lcddata('N');                       // display letter 'N'
    lcdready();                         // check the LCD busy flag
    lcddata('O');                       // display letter 'O'  
  }
void lcdcmd(unsigned char value)
  {
    ldata = value;                      // put the value on the pins
    rs = 0;
    rw = 0;
    en = 1;                             // strobe the enable pin
    MSDelay(1);
    en = 0;
  }
void lcddata(unsigned char value)
  {
    ldata = value;                      // put the value on the pins
    rs = 1;
    rw = 0;
    en = 1;                             // strobe the enable pin
    MSDelay(1);
    en = 0;
  }

void lcdready()
  {
    TRISD = 0xFF;                       // make PORTD an input
    rs = 0;                  
    rw = 1;                   
    do                                  // wait here for busy flag
     {
        en = 1;                          // strobe the enable pin
       MSDelay(1);
       en = 0;
     }while(busy==1);
    TRISD = 0; 
   }
void MSDelay(unsigned int itime)
  {
    unsigned int i, j;
    for(i=0;i<itime;i++)
       for(j=0;j<135;j++);                
  }
ztmd8pv5

ztmd8pv51#

HD44780 8位并行接口的忙碌标志仅在ENABLE处于高电平时有效。
实际上,当使用真实的的LCD字符模块时,在ENABLE被设置为低电平时,LCD输出的状态将保持在其最后的驱动状态一微秒左右。这在模拟中不会发生,因此在ENABLE被设置为低电平时,数据将无效。
您需要阅读并理解LCD模块数据手册中的信息。注意LCD读取周期的时序图。

相关问题