首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带Atmega的lcd驱动问题:第二行没有字符

带Atmega的lcd驱动问题:第二行没有字符
EN

Stack Overflow用户
提问于 2021-06-22 12:19:23
回答 2查看 204关注 0票数 0

我有一个项目,其中一个8x2字符液晶显示器是由一个atmega8单片机控制。

lcd是一个dips082-hnled:https://eu.mouser.com/datasheet/2/127/dips082e-274871.pdf

由于控制非常容易,所以我编写了自己的函数来初始化它,并为它编写了一些文本。写一些文字是我真正需要的,对于这个项目.

问题如下:

虽然液晶显示器的第一行与我的程序非常好,但我无法得到任何东西显示在第二行在任何。

我检查了lcd数据表和lcd使用的驱动芯片的数据表,我不知道问题出在哪里。

我还检查了第二个,已知的好的相同类型的液晶显示器,我也有同样的问题,所以它不可能是一个错误的液晶显示器。

以下是我驾驶液晶显示器的所有代码:

代码语言:javascript
复制
#include <xc.h>

#include "pinmapping.h"
#include "main.h"

#include <util/delay.h>
//LCD:
//RS: HIGH=Screen Data, LOW=Command
//RW: HIGH=Read, LOW=Write
//E: FALLING EDGE=Execute Command/Write Data
//D0...D7: PORTD, 8-bit data lines

void toggleEnable(){
    
    //set pin low
    PORTB = PORTB & (~LCD_E);
    //wait for 3 ms so the lcd has time to execute the instruction
    _delay_ms(3);
    //set pin high again
    PORTB = PORTB | LCD_E;
    //allow for a minimal high time
    _delay_ms(3);
    
}

void initLCD(){
    
    //Wait until internal LCD init complete
    _delay_ms(25);
    
    //Set RS and RW low
    PORTB = PORTB & (~(LCD_RS | LCD_RW));
    
    //Function Set (8-bit data, 2 lines, 5x8 font)
    PORTD = 0b00110000;
    toggleEnable();
    
    //Display ON/OFF (Display on, Cursor visible, Cursor blink)
    PORTD = 0b00001100;
    toggleEnable();
    
    //Clear Display, Cursor Home
    PORTD = 0b00000001;
    toggleEnable();
    
    //Entry Mode set (Cursor auto-increment)
    PORTD = 0b00000110;
    toggleEnable();
    
    //Set RS and RW high again
    PORTB = PORTB | (LCD_RS | LCD_RW);
    
}

void testLCD(){
    
    char testchars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvxyz0123456789!?-+,. :;<=>*/()%&#$";
    
    //Set RS low and RW low
    PORTB = PORTB & (~LCD_RS);
    PORTB = PORTB & (~LCD_RW);
    
    //Clear Display, Cursor Home
    PORTD = 0b00000001;
    toggleEnable();
    
    //Set RS high and RW low
    PORTB = PORTB | LCD_RS;
    PORTB = PORTB & (~LCD_RW);
    
    //Write the array contents to the lcd - this should completely fill the DDRAM
    for(int i = 0; i < 80; i++){
        
        PORTD = testchars[i];
        toggleEnable();
        
    }
    
}

void writeLCD(char text[16]){
    
    //Set RS low and RW low
    PORTB = PORTB & (~LCD_RS);
    PORTB = PORTB & (~LCD_RW);
    
    //Clear Display, Cursor Home
    PORTD = 0b00000001;
    toggleEnable();
    
    //Set RS high and RW low
    PORTB = PORTB | LCD_RS;
    PORTB = PORTB & (~LCD_RW);
    
    //loop through string send it to lcd
    for(int i = 0; i < 16; i++){
        
        //We have a 16 char lcd so we need to jump to line 2 after 8 chars
        if(i == 8){
            
            //Set RS low and RW low
            PORTB = PORTB & (~LCD_RS);
            PORTB = PORTB & (~LCD_RW);

            //Set DD-RAM Address to 0x40 - the beginning of line 2
            PORTD = 0xC0;
            //and execute command
            toggleEnable();

            //Set RS high and RW low
            PORTB = PORTB | LCD_RS;
            PORTB = PORTB & (~LCD_RW);
            
        }
        
        //put the current char to data bus
        PORTD = text[i];
        
        //then toggle the enable pin to actually write it to the lcd
        toggleEnable();
        
    }
    
    //Set RS and RW low
    PORTB = PORTB & (~(LCD_RS | LCD_RW));
    
    //reset cursor to start
    PORTD = 0b00000010;
    toggleEnable();
    
    //Set RS and RW high again
    PORTB = PORTB | (LCD_RS | LCD_RW);
    
}

void commandLCD(char command){
    
    //Set RS and RW low
    PORTB = PORTB & (~(LCD_RS | LCD_RW));
    
    PORTD = command;
    toggleEnable();
    
    //Set RS and RW high again
    PORTB = PORTB | (LCD_RS | LCD_RW);
    
}

正如您所看到的,我编写了一个测试函数,它应该填充整个80字节的显示内存,lcd有。

我正在使用xc8编译器。

在初始化io-port之后,在主函数的开头调用initLCD函数。

然后,从程序的不同部分调用writeLCD函数.

H文件为所使用的不同引脚定义位掩码。(例如: LCD_RS)

液晶显示器的8条数据线连接到atmega的D端口,与其位相匹配(如:液晶D0与avr D0,液晶D1与avr D1等)。

也许我忽略了什么,或者我做错了什么,但我不知道是什么导致了问题.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-26 15:16:01

所以我终于想出来了!

基本上一切都是正确的,但很明显,您需要执行两次函数设置命令,才能将显示设置为8位数据模式和2行显示。

无论是在用于显示的数据表还是用于所使用的控制器的数据表中,都没有提到这一点。

因此,这是经过修改的initLCD函数,使其工作。(是的,我在测试时翻转了字体的位,但是根据数据表,这在2行显示中被忽略了)

代码语言:javascript
复制
void initLCD(){
    
    //Wait until internal LCD init complete
    _delay_ms(25);
    
    //Set RS and RW low
    PORTB = PORTB & (~(LCD_RS | LCD_RW));
    
    //Function Set (8-bit data, 2 lines, 5x8 font)
    PORTD = 0b00111100;
    toggleEnable();
    
    //Apparently this has to be done twice, to get 2 lines to work
    PORTD = 0b00111100;
    toggleEnable();
    
    //Display ON/OFF (Display on, Cursor visible, Cursor blink)
    PORTD = 0b00001100;
    toggleEnable();
    
    //Clear Display, Cursor Home
    PORTD = 0b00000001;
    toggleEnable();
    
    //Entry Mode set (Cursor auto-increment)
    PORTD = 0b00000110;
    toggleEnable();
    
    //Set RS and RW high again
    PORTB = PORTB | (LCD_RS | LCD_RW);
    
}

如数据表所示,第2行从地址40开始。

没有地址81号。写超过80个字符只是重写了第一个字符。它在80之后被包装,所以如果你给它写了81个字符,最后一个字符就会覆盖第一个字符。

票数 0
EN

Stack Overflow用户

发布于 2021-08-29 20:58:40

我想你会在第一行结束后找到第2行,这是40个字符,不管你的显示器的实际字符数是多少。

所以,如果你到第1行的第41位,你应该开始写到第2行。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68083429

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档