LCD1602液晶显示模块深入详解之软件篇(AVR)

LCD1602液晶显示模块的驱动虽然比七段数码管之类的显示要复杂一些,但实际上也并不是很难,最主要的还是初始化,为什么这么说呢?我们在调试一块新液晶屏的时候,都会先初始化看看有没有光标在闪,没有光标前是一番努力(PROTEUS上也是这么做的),光标出来之后就相对很容易了。

那初始化的流程是怎么样的呢?我们还是看看HD44780的数据手册吧,如下图所示:

可以看到,初始化的主要步骤如下:

(1)上电:这特么也算是一个步骤么?是的!如果你用的是其它液晶模块,比如LCD12864,会发现有一个复位引脚,LCD1602是没有复位引脚的,HD44780本身已经有内部复位逻辑。上电后复位其实会做很多事情的,主要如下:

a. 清除屏幕数据

b.设置8位并行通讯方式,1行显示,5X8点阵显示

c.显示关,关标关,光标闪烁关

d.地址自动加1,没有屏移

从复位所做的事情来看,初始化该做的都已经做了,要看到光标只需要两条指令:打开显示,再开启光标显示即可。但是为了充分保证初始化的成功率(有可能LCD1602由于外部电气特性条件没达到而没有成功初始化),一般还是会用指令显式重新进行初始化(况且有些时候默认的初始化可能还达不到我们的要求),后面的几条语句其实就是重复上电后做的那些事,我们看看

(2)功能设置(Function Set ):其实就是b点

(3)显示打开/关闭(Display On/Off Control):其实就是c.1(打开显示)

(4)进入模式设置(Entry Mode set):其实就是d

(5)前面就是初始化,后面就是写显示数据了

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

下面是Atmega AVR驱动LCD1602液晶显示模块代码,第一行显示“LCD1602 DEMO”,第二行显示“--CNBLOGS--”,这里没有读状态指令的使用,实际使用时,在写指令或数据时加一些延时即可

注意:分了三个文件,main.c是入口,lcd1602.h与lcd1602.c是具体的一些读写函数

/*******************************************************************************
* 文件名: main.c
* 功能描述: LCD1602显示屏驱动
*******************************************************************************/

#include <iom128v.h>
#include <macros.h>
#include "lcd1602.h"
/*******************************************************************************
* 函数名称: void port_init(void)
* 功能描述: LCD1602显示屏的IO口类型设置
*******************************************************************************/
void port_init(void)
{
    //以下为LCD1602相关接口引脚,客户可根据需要进行引脚更改

DDRA |= BIT(6)|BIT(7); //PA6->RS,PA7->RW

PORTA |= (BIT(6));
    PORTA |=(BIT(7));
    DDRC =0XFF; //PC->(D0-D7)
    PORTC=0X00;
    DDRG |= BIT(2); //PG2->E
    PORTG |= BIT(2);
    //以下与LCD接口无关,不同的平台可无需要关注
    DDRB |= BIT(1);
    PORTB |= BIT(0);
    DDRD =0X00;
    PORTD=0X00;
    DDRE =0X00;
    PORTE=0X00;
    DDRF =0X00;
    PORTF=0X00;
}
/*******************************************************************************
* 函数名称: void init_devices(void)
* 功能描述: 单片机系统初始化设置(不同的平台有不同的设置,此函数可不关注)

*******************************************************************************/
void init_devices(void)
{
    //stop errant interrupts until set up
    CLI(); //disable all interrupts
    XDIV = 0x00; //xtal divider
    XMCRA = 0x00; //external memory
    port_init();

MCUCR = 0x00;
    EICRA = 0x00; //extended ext ints
    EICRB = 0x00; //extended ext ints
    EIMSK = 0x00;
    TIMSK = 0x00; //timer interrupt sources
    ETIMSK = 0x00; //extended timer interrupt sources
    SEI(); //re-enable interrupts
    //all peripherals are now initialized
}

//这里是入口
void main(void)
{
    int i=0;
    init_devices();//初始化系统
    LCD_init(); //LCD初始化
    LCD_write_str(0, 0, "--Lcd1602--Demo-");
    LCD_write_str(0, 1, "-----CNBLOGS-----");
    while(1){}
}

///////////////////////以下为lcd1602.c/////////////////////////////////

#include "lcd1602.h"

//us延时函数
void delay_us(uint n) //8*0.125=1us
{
    int i,j;
    for(j=0;j<8;j++)  {
        for (i=0;i<n;i++)  {NOP();}
    }
}

//ms延时函数
void delay_ms(uint i)
{
    while(i--) {
        uint j;
        for(j=1;j<=1332;j++) {}
    }
}
//EN引脚产生一个高电平脉冲,控制LCD写时序
void LCD_en_write(void)
{
    E_ON;//EN_SET;
    delay_us(3);
    E_OFF;//EN_CLR
    delay_us(3);//
}
//写指令函数
void Write_Instruction(uchar command)
{
    RS_OFF;//RS_CLR;
    RW_OFF;//RW_CLR
    E_ON;//EN_SET;
    PORTC=command;
    LCD_en_write();//写入指令数据
}

//写数据函数
void Write_Data(uchar Wdata)
{
    RS_ON;//RS_SET;
    RW_OFF;//RW_CLR;
    E_ON;//EN_SET;
    PORTC=Wdata;
    LCD_en_write();//写入数据
}
//清屏函数
void LCD_clear(void)
{
    Write_Instruction(0x01);
    delay_ms(20);
}

//字符显示初始地址设置
void LCD_SET_XY(uchar X,uchar Y)
{
    uchar address;
    if(Y==0) {
        address=0x80+X;//Y=0,表示在第一行显示,地址基数为0x80
    } else {
        address=0xc0+X;//Y非0时,表时在第二行显示,地址基数为0XC0
    }
    Write_Instruction(address);//写指令,设置显示初始地址
}

//在第X行Y列开始显示,指针*S所指向的字符串
void LCD_write_str(uchar X,uchar Y,uchar *s)
{
    LCD_SET_XY(X,Y);//设置初始字符显示地址
    while(*s) {//逐次写入显示字符,直到最后一个字符"/0"    
       Write_Data(*s);//写入当前字符并显示
        s++;//地址指针加1,指向下一个待写字符
    }
}

//在第X行Y列开始显示Wdata所对应的单个字符
void LCD_write_char(uchar X,uchar Y,uchar Wdata)
{
    LCD_SET_XY(X,Y);//写地址
    Write_Data(Wdata);//写入当前字符并显示
}
//显示屏初始化函数
void LCD_init(void)
{
    delay_ms(5);//上电延时一段时间,使供电稳定
    Write_Instruction(0x3c);
    Write_Instruction(0x01); //清屏
    Write_Instruction(0x06); //写字符,整屏显示不移动
    Write_Instruction(0x0f); //开显示,开光标, 开闪烁
}

////////////////////////////以下为lcd1602.h//////////////////////////////////////////////////////////

#ifndef _LCD1602_H
#define _LCD1602_H

#include "iom128v.h"
#include "macros.h"

#define uchar unsigned char
#define uint unsigned int

#define RS_ON PORTA |= BIT(6);//RS置1
#define RS_OFF PORTA &= ~BIT(6);//RS置0

#define RW_ON PORTA |= BIT(7);//RW置1
#define RW_OFF PORTA &= ~BIT(7);//RW置0

#define E_ON PORTG |= BIT(2);//E置1
#define E_OFF PORTG &= ~BIT(2);//E置0

void delay_us(uint n);
void delay_ms(uint i);
void Port_init(void);
void LCD_init(void);
void LCD_en_write(void);
void LCD_clear(void);
void Write_Instruction(uchar command);
void Write_Data(uchar Wdata);
void LCD_SET_XY(uchar X,uchar Y);
void LCD_write_str(uchar X,uchar Y,uchar *s);
void LCD_write_char(uchar X,uchar Y,uchar Wdata);

#endif

时间: 2024-08-02 19:05:01

LCD1602液晶显示模块深入详解之软件篇(AVR)的相关文章

LCD1602液晶显示模块深入详解篇一

(本文以HD44780主控芯片的LCD1602为蓝本进行描述,其中的截图也来自HD44780数据手册,用户可自行搜索其datasheet,有部分整理网上的,但绝对要比你看到的要深入得多) 一.接口 LCD1602是很多单片机爱好者较早接触的字符型液晶显示器,它的主控芯片是HD44780或者其它兼容芯片.刚开始接触它的大多是单片机的初学者.由于对它的不了解,不能随心所欲地对它进行驱动.经过一段时间的学习,我对它的驱动有了一点点心得,今天把它记录在这里,以备以后查阅.与此相仿的是LCD12864液晶

opencart 模块开发详解

opencart 模块开发详解 由 xiekanxiyang » 2013年 7月 11日 10:17 pm opencart 将页面分成若干模块, 每个模块可以有多个实例(可能这样说不是很恰当) 每个实例可以指定它出现在哪个页面 这样更好的实现了代码的可重用性,可以达到更好的页面布局的可调节性. Opencar内置了几个模块,但实际应用中我们经常要根据需要开发自己模块,现在我给大家介绍下opencart的模块开发的细节 开发步骤:首先:模块代码也分前台,后台. 后台功能是模块的安装,编辑,模块

python之模块datetime详解

# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之模块datetime详解 import datetime #data=datetime.date(2015,11,9)#表示日期的类 #data=datetime.time(hour[,minute[,second[,microsecond[,tzinfo]]]])#表示时间的类,从小时时间开始为参数 #data=datetime.datetime(year,month,day[,hour[

python os.path模块常用方法详解

python os.path模块常用方法详解 1.   os.path.abspath(path)   返回path规范化的绝对路径. >>> import os    >>> os.path.abspath('pjc.txt')     '/home/pjc/pjc.txt' >>> os.path.abspath('c:\\test.csv')         #Windows主机指定完美的路径    'c:\\test.csv' 2.os.pat

nginx_http_push_module模块使用详解

关于 nginx_http_push_module模块致力成为一个成熟的http推送和comet服务,它能够处理好全部链接,并且仅通过http请求,可以完成广播消息到所有客户端,这让你写异步web应用程序时得心应手,并且在代码中完全不必理会延时请求.该模块完整的实现了Basic HTTP Push Relay Protocol 为什么选择此模块 当你要写一个实时更新的模块时,例如某些聊天室.多人在线flash游戏等.无论哪种方式,我们都要避免更新请求时刷新页面或者每隔几秒轮训服务器,这样的代码丑

Spring Boot的每个模块包详解

Spring Boot的每个模块包详解,具体如下: 1.spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和YAML. 2.spring-boot-starter-actuator 帮助监控和管理应用. 3.spring-boot-starter-amqp 通过spring-rabbit来支持AMQP协议(Advanced Message Queuing Protocol). 4.spring-boot-starter-aop 支持面向方面的编程

Python中标准模块importlib详解

Python中标准模块importlib详解 模块简介 Python提供了importlib包作为标准库的一部分.目的就是提供Python中import语句的实现(以及__import__函数).另外,importlib允许程序员创建他们自定义的对象,可用于引入过程(也称为importer). 什么是imp? 另外有一个叫做imp的模块,它提供给Python import语句机制的接口.这个模块在Python 3.4中被否决,目的就是为了只使用importlib. 这个模块有些复杂,因此我们在这

Spark 性能相关参数配置详解-shuffle篇

作者:刘旭晖 Raymond 转载请注明出处 Email:colorant at 163.com BLOG:http://blog.csdn.net/colorant/ 随着Spark的逐渐成熟完善, 越来越多的可配置参数被添加到Spark中来, 在Spark的官方文档http://spark.apache.org/docs/latest/configuration.html 中提供了这些可配置参数中相当大一部分的说明. 但是文档的更新总是落后于代码的开发的, 还有一些配置参数没有来得及被添加到

事件驱动模型实例详解(Java篇)

或许每个软件从业者都有从学习控制台应用程序到学习可视化编程的转变过程,控制台应用程序的优点在于可以方便的练习某个语言的语法和开发习惯(如.net和java),而可视化编程的学习又可以非常方便开发出各类人机对话界面(HMI).可视化编程或许是一个初学者开始对软件感兴趣的开始,也可能是一个软件学习的里程碑点,因为我们可以使用各类软件集成开发环境(IDE)方便的在现成的界面窗口上拖放各类组件(Component),这类组件包括我们常见的按钮(Button),单选按钮(Radio Button),复选框