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); //Function Set
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
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
写博文时我手头上暂时没有LCD1602,所以用单片机驱动手头上的虚拟器件模块,在手机上看到的效果如下图所示,与实际LCD1602液晶显示屏效果是一样的:
LCD1602液晶显示模块的单片机驱动深入详解之软件篇(AVR)的更多相关文章
- LCD1602液晶显示模块的单片机驱动深入详解之硬件篇
(本文以HD44780主控芯片的LCD1602为蓝本进行描述,其中的截图也来自HD44780数据手册,用户可自行搜索其datasheet,有部分整理网上的,但绝对要比你看到的要深入得多) 一.接口 L ...
- 【转】Linux下Android ADB驱动安装详解
原文网址:http://blog.csdn.net/zhenwenxian/article/details/5901350 Linux下Android ADB驱动安装详解 概述 最近由于内置的合作商比 ...
- 转: javascript模块加载框架seajs详解
javascript模块加载框架seajs详解 SeaJS是一个遵循commonJS规范的javascript模块加载框架,可以实现javascript的模块化开发和模块化加载(模块可按需加载或全部加 ...
- Linux设备驱动开发详解
Linux设备驱动开发详解 http://download.csdn.net/detail/wuyouzi067/9581380
- python中日志logging模块的性能及多进程详解
python中日志logging模块的性能及多进程详解 使用Python来写后台任务时,时常需要使用输出日志来记录程序运行的状态,并在发生错误时将错误的详细信息保存下来,以别调试和分析.Python的 ...
- IIS负载均衡-Application Request Route详解第四篇:使用ARR实现三层部署架构(转载)
IIS负载均衡-Application Request Route详解第四篇:使用ARR实现三层部署架构 系列文章链接: IIS负载均衡-Application Request Route详解第一篇: ...
- [转]ANDROID L——Material Design详解(动画篇)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 转自:http://blog.csdn.net/a396901990/article/de ...
- appledoc导出iOS代码文档的使用和问题详解(干货篇)
appledoc导出iOS代码文档的使用和问题详解(干货篇) 1. 简单说一下背景和自己感受 背景: 项目好像突然黄了,公司让详细写项目代码的注释并且导出文档,弄完之后就要封版. 说实话:听到这个消息 ...
- Android为TV端助力 转载:Android绘图Canvas十八般武器之Shader详解及实战篇(上)
前言 Android中绘图离不开的就是Canvas了,Canvas是一个庞大的知识体系,有Java层的,也有jni层深入到Framework.Canvas有许多的知识内容,构建了一个武器库一般,所谓十 ...
随机推荐
- Windows进程间通讯(IPC)----管道
管道的分类 管道其实际就是一段共享内存,只不过Windows规定需要使用I/O的形式类访问这块共享内存,管道可以分为匿名管道和命名管道. 匿名管道就是没有名字的管道,其支持单向传输数据,如果需要双向传 ...
- [bug] Flask:jinja2.exceptions.UndefinedError: 'None' has no attribute 'id'
问题 Python Flask做的购物网站,添加购物车时,提示错误 解决 检查发现是MySQL中不正常的空数据导致,删除此条记录即可 参考 https://www.jb51.cc/python/186 ...
- hive beeline详解
Hive客户端工具后续将使用Beeline 替代HiveCLI ,并且后续版本也会废弃掉HiveCLI 客户端工具,Beeline是 Hive 0.11版本引入的新命令行客户端工具,它是基于SQLLi ...
- bashshell删除列
删除所有空白列cat yum.log | awk '{$1=$2=$3=$4=null;print $0}'>>yum.log7删除文件中的所有空格sed -i s/[[:space:]] ...
- Ubuntu20.04 网络配置
Ubuntu20.04 网络配置 设置 ROOT 密码 先设置 root 密码,后面直接使用 root 用户操作 it@it:~$ sudo passwd root [sudo] password f ...
- 如何在 CentOS 8 中安装 Cockpit Web 控制台
如何在 CentOS 8 中安装 Cockpit Web 控制台 [日期:2019-10-31] 来源:Linux公社 作者:醉落红尘 [字体:大 中 小] 在本文中,我们将帮助您在CentOS ...
- 戴尔 R730xd 服务器更改管理口密码 图文教程
一.开机根据提示按F2进入配置界面 - 选择中间的iDRAC Setting选项,回车确认 二.进入之后选择 user configuration 选项 三.在change password 处键入新 ...
- C++ short/int/long/long long 等数据类型大小
表 1 整型数据类型 数据类型 字节大小 数值范围 short int (短整型) 2 字节 -32 768 〜+32 767 unsigned short int(无符号短整型) 2 字节 0 〜+ ...
- 四:net core(.NET 6)使用Filter过滤器拦截webapi方法
Filter的基本用法 代码在最下方 使用filter过滤器,来实现拦截接口信息.咱们先新建一个项目,在原有的webapi上面,选择添加项目,添加一个类库项目: 我起个名字,就叫 Wsk.Core.F ...
- 【七】Kubernetes 探针介绍 - 存活、就绪探针案例测试
一.探针概述 探针是有 kubelet 对容器执行的定期诊断,并不是由 Master 节点发起的探测,而是由每一个 Node 所在的 kubelet 进行探测,这样可以减轻 Master 节点系统负载 ...