这是我第一次与液晶显示器,我试图让我的代码(见下文)写一个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++);
}
1条答案
按热度按时间ztmd8pv51#
HD44780 8位并行接口的忙碌标志仅在ENABLE处于高电平时有效。
实际上,当使用真实的的LCD字符模块时,在ENABLE被设置为低电平时,LCD输出的状态将保持在其最后的驱动状态一微秒左右。这在模拟中不会发生,因此在ENABLE被设置为低电平时,数据将无效。
您需要阅读并理解LCD模块数据手册中的信息。注意LCD读取周期的时序图。