51单片机的1602液晶显示程序
- 格式:docx
- 大小:17.52 KB
- 文档页数:3
第一章设计要求及系统组成一、基本操作时序:读状态:输入:RS=L,RW=H,E=H 输出:D0~D7=状态字写指令:输入:RS=L,RW=L,D0~D7=指令码,E=高脉冲输出:无读数据:输入:RS=H,RW=H,E= 高脉冲输出:D0~D7数据写数据:输入:RS=H,RW=L。
D0~D7=数据,E=高脉冲输出:无二、、、状态字说明:STA7 D7\ STA6 D6\ STA5 D5 \ STA4 D4 \STA3 D3 \ STA2 D2\\ STA1 D1STA0-6:当前数据地址指针的数值STA7:读写操作使能 1表示禁止,0表示允许对控制器每次进行读写操作之前,都必须进行读写检测,确保STA7为0;但是我们可以进行延时进行实现。
RAM地址映射: LCD 16字*2行00 01 02 03 04 05 06 07 08 08 09 0A 0B 0C 0D 0E 0F (27)40 41 42 4F 50 (67)指令说明:1.初始化设置 1.显示模式设置指令码:00111000(0x38)功能:设置16*2显示,5*7点阵,8位数据接口必须开显示 2.显示开、关及光标设置指令码:00001DCB,功能:D=1 开显示;D=0 关显示;C=1显示光标;B=1 光标闪烁;B=0 光标不显示 000001NS:功能:N=1当读或写一个字符后地址指针加1,且光标加1;N=0相应的减1;S=1当写一个字符,整屏显示左移(N=1)或右移(N=0),以得到光标不移动而屏幕移动的效果。
S=0 当写一个字符,正屏显示不移动。
数据控制:控制器内部设有一个数据地址指针,用户可通过它们来访问内部的全部80字节RAM4.2.1 数据指针设置:指令码:80H+地址码(0-27H,第二行开始:40H-67H) 4..2.2 读数据,写数据其它设置:01H:显示清屏:1.数据指令清零 2 所有显示清零 02H:显示回车:1.数据清零如何进行连接:实际操作中,液晶接到,第一管脚是D,第二管脚是VCC,15和16是背光,D0-D7是数据口,接到单片机的P0口,P0口接了两个锁存器,液晶,D/A,具有高阻状态的都可以随便接,没有影响,,第六管脚是LCDEN相当于 E,使能信号,它接P3^4,R/W接地,表示低电平,因为我们只进行写操作,RS接2实验板上的P3^5;只需这两端口便足以控制液晶,2和3是偏压信号,一端接地,接口信号说明:编号:1 VSS(符号表示)电源地(引脚说明)2VDD 电源正极3VL液晶显示偏压信号4RS数据/命令选择端(H/L)5R/W 读写选择端(H/L)6E使能信号7D0 Data 1/0 8D1 Data 1/0 9 D2 Data 1/0 10 D3 Data 1/0 11D4 Data 1/0 12D5 Data 1/0 13D6 Data 1/0 14D7 Data 1/0 15BLK背光源正极16 BLK背光源负极实际操作:::先写光标程序;写两个子程序,一个写数据,一个写指令:先进性两个宏定义,再位申明LCDEN与RS;为了电量充足。
基于51单片机的红外遥控+液晶LCD1602显示程序源代码/*******************红外遥控+液晶LCD1602测试程序源代码******************** 单片机型号:STC15W4K56S4,内部晶振:22.1184M。
功能:红外遥控+液晶LCD1602显示功能测试。
操作说明:按下红外遥控器上的“CH-”键,液晶LCD1602上显示“CH-”。
按下红外遥控器上的“CH”键,液晶LCD1602上显示“CH”。
按下红外遥控器上的“CH+”键,液晶LCD1602上显示“CH+”。
按下红外遥控器上的“|<<”键,液晶LCD1602上显示“|<<”。
按下红外遥控器上的“>>|”键,液晶LCD1602上显示“>>|”。
按下红外遥控器上的“>||”键,液晶LCD1602上显示“>||”。
按下红外遥控器上的“-”键,液晶LCD1602上显示“-”。
按下红外遥控器上的“+”键,液晶LCD1602上显示“+”。
按下红外遥控器上的“EQ”键,液晶LCD1602上显示“EQ”。
按下红外遥控器上的“0”键,液晶LCD1602上显示“0”。
按下红外遥控器上的“100+”键,液晶LCD1602上显示“100+”。
按下红外遥控器上的“200+”键,液晶LCD1602上显示“200+”。
按下红外遥控器上的“1”键,液晶LCD1602上显示“1”。
按下红外遥控器上的“2”键,液晶LCD1602上显示“2”。
按下红外遥控器上的“3”键,液晶LCD1602上显示“3”。
按下红外遥控器上的“4”键,液晶LCD1602上显示“4”。
按下红外遥控器上的“5”键,液晶LCD1602上显示“5”。
按下红外遥控器上的“6”键,液晶LCD1602上显示“6”。
按下红外遥控器上的“7”键,液晶LCD1602上显示“7”。
按下红外遥控器上的“8”键,液晶LCD1602上显示“8”。
//基于51单片机的1602液晶屏的时钟显示完整程序#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit en=P2^6;sbit rs=P2^4;sbit rw=P2^5;uchar count,shi,fen,miao;void delay(unsigned int);void init();void write_com(unsigned char);void write_date(unsigned char);void write_sfm(uchar,uchar);uchar code table[]="2013-2-15";uchar code table1[]="23:59:55";void main(){init();while(1){if(count==20){count=0;miao++;if(miao==60){miao=0;fen++;if(fen==60){fen=0;shi++;if(shi==24){shi=0;}write_sfm(1,shi);}write_sfm(3,fen);}write_sfm(6,miao);}}// while(1);}void delay(unsigned int z) // 延时函数{unsigned int x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void init(){unsigned char num;en=0;rw=0;write_com(0x38); //设置点阵write_com(0x0c); //设置光标不闪烁write_com(0x06); //设置光标地址后移write_com(0x01); //清屏write_com(0x80); // 表示从第一行开始显示for(num=0;num<9;num++){write_date(table[num]);delay(20);}write_com(0x80+0x40);for(num=0;num<8;num++){write_date(table1[num]);delay(20);}TMOD=0x01;TH0=(65536-50000)/256;TL0=(65535-50000)%256;EA=1;ET0=1;TR0=1;}void write_com(unsigned char com) //送指令{rs=0;rw=0;en=0;P0=com;delay(5);en=1;delay(5);en=0;}void write_date(unsigned char date) //送数据{rs=1;en=0;rw=0;P0=date;delay(5);en=1;delay(5);en=0;}void time0() interrupt 1{TH0=(65536-50000)/256;TL0=(65535-50000)%256;count++;}void write_sfm(uchar add,uchar date) //将数据分离{unsigned char shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi); //将数值转化为十六进制0是30。
LCD显示电路#include<reg51.h>sbit RS=P3^7; //寄存器选择位,将RS位定义为P2.0引脚sbit RW=P3^6; //读写选择位,将RW位定义为P2.1引脚sbit E=P2^7; //使能信号位,将E位定义为P2.2引脚sbit BF=P0^7; //忙碌标志位,将BF位定义为P0.7引脚#define Lcd_Data P0#include <string.h>#include<intrins.h> //包含_nop_()函数定义的头文件unsigned char code string1[ ]={0x77,0x75,0x20,0x79,0x61,0x6E,0x67,0x20,0x79,0x61,0x6E,0x67,0x20,0x20,0x20,0x20}; //第一行显示的字符void Lcd_delay1ms() // 函数功能:延时1ms//注:不同单片机不同晶振需要对此函数进行修改{ unsigned char i,j;for(i=0;i<90;i++)for(j=0;j<33;j++);}void Lcd_delay(unsigned int n) // 函数功能:延时若干毫秒,入口参数:n{ unsigned int i;for(i=0;i<n;i++)Lcd_delay1ms();}/*****************************************************函数功能:判断液晶模块的忙碌状态返回值:result。
result=1,忙碌;result=0,不忙***************************************************/bit Lcd_BusyTest(void)bit result;RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态RW=1;E=1; //E=1,才允许读写_nop_(); //空操作_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间result=BF; //将忙碌标志电平赋给resultE=0;return result;}/*****************************************************函数功能:将模式设置指令或显示地址写入液晶模块入口参数:dictate***************************************************/void Lcd_WriteCom (unsigned char dictate){ while(Lcd_BusyTest()==1); //如果忙就等待RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令RW=0;E=0; //E置低电平(写指令时就是让E从0到1发生正跳变,所以应先置ぜ? _nop_();_nop_(); //空操作两个机器周期,给硬件反应时间Lcd_Data=dictate; //将数据送入P0口,即写入指令或地址_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:指定字符显示的实际地址x入口参数:注:此函数已经加上了0x80,故只需写上实际地址就行***************************************************/void Lcd_WriteAddress(unsigned char x){ Lcd_WriteCom(x|0x80); //显示位置的确定方法规定为80H+地址码x/*****************************************************函数功能:将数据(字符的标准ASCII码)写入液晶模块入口参数:y(为字符常量)***************************************************/void Lcd_WriteData(unsigned char y){while(Lcd_BusyTest()==1);RS=1; //RS为高电平,RW为低电平时,可以写入数据RW=0;E=0; //E置低电平(写指令时就是让E从0到1发生正跳变所以应先置ぜ?Lcd_Data=y; //将数据送入P0口,即将数据写入液晶模块_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:对LCD的显示模式进行初始化设置***************************************************/void Lcd_Int(void){Lcd_delay(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间Lcd_WriteCom(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口Lcd_delay(5); //延时5msLcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);设置模式次写9// Lcd_WriteCom(0x38);Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x0C); //显示模式设置:显示开,有光标,光标闪烁Lcd_delay(5);Lcd_WriteCom(0x06); //显示模式设置:光标右移,字符不移Lcd_delay(5);Lcd_WriteCom(0x01); //清屏幕指令,将以前的显示内容清零Lcd_delay(5); }void hanying_show(void){unsigned char Lcd_i;Lcd_WriteCom(0x01);//清显示:清屏幕指令Lcd_delay(2);Lcd_WriteAddress(0x00); // 设置显示位置为最左侧Lcd_delay(2);Lcd_i=0;while(string1[Lcd_i]!='\0') //'\0'是数组结束标志需先将字符存入{Lcd_WriteData(string1[Lcd_i]); // 显示字符Lcd_i++;Lcd_delay(4);}}void main(){Lcd_Int(); //1602初始化while(1){hanying_show();}}。
标签:单片机LCD基于51单片机的1602LCD显示基于51单片机的1602LCD显示LCD(liquid crystal display)为液晶显示器,它一般不会单独使用,而是将LCD面板、驱动与控制电路组合成LCD模块(1iquid crystal display moulde,简称为LCM)来使用。
LCM是一种很省电的显示设备,常被应用在数字或微处理器控制的系统,做为简易的人机接口,但人们一般还是习惯称之为LCD显示器。
1 硬件设计采用51单片机控制1602LCD显示器的电路如下所示。
在桌面上双击图标,打开ISIS 7 Professional窗口(本人使用的是v7.4 SP3中文版)。
单击菜单命令“文件”→“新建设计”,选择DEFAULT 模板,保存文件名为“LCD.DSN”。
在器件选择按钮中单击“P”按钮,或执行菜单命令“库”→“拾取元件/符号”,添加如下表51单片机AT89C51 一片晶体CRYSTAL 12MHz 一只瓷片电容CAP 22pF 二只电解电容CAP-ELEC 10uF 一只电阻RES 10K 一只排阻 RESPAC-8 10K 一只1602液晶显示器 LM016L 一只若用Proteus软件进行仿真,则上图中的晶振和复位电路以及U1的31脚,都可以不画,它们都是默认的。
在ISIS原理图编辑窗口中放置元件,再单击工具箱中元件终端图标,在对象选择器中单击POWER和GROUND放置电源和地。
放置好元件后,布好线。
左键双击各元件,设置相应元件参数,完成电路图的设计。
2 软件设计用1602LCD显示两行字符的流程图如下所示。
用1602LCD显示“Welcom to China”和“Hi!Good morning!”的详细C51程序如下。
//用LCD循环显示"Welcome to China"和"Hi!Good morning!"#include<reg51.h> //包含单片机的头文件#include<intrins.h> //包含_nop_()函数定义的头文件sbit RS="P2"^0; //寄存器选择位,将RS位定义为P2.0引脚sbit RW="P2"^1; //读写选择位,将RW位定义为P2.1引脚sbit E="P2"^2; //使能信号位,将E位定义为P2.2引脚sbit BF="P0"^7; //忙碌标志位,,将BF位定义为P0.7引脚unsigned char code string[ ]={"Welcome to China"};unsigned char code string1[ ]={"Hi!Good morning!"};/*************************************************函数功能:延时1ms(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒*************************************************/void delay1ms(){unsigned char i,j;for(i=0;i<10;i++)for(j=0;j<33;j++);}/*****************************函数功能:延时若干毫秒入口参数:n******************************/void delay(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}/*******************************************函数功能:判断液晶模块的忙碌状态返回值:result。
基于51单片机控制的1602液晶电子时钟显示程序[ 2007-05-31 13:31:45 | By: kevin ]刚写好的基于51单片机控制的1602液晶电子时钟显示程序,整理了一下,并尽量加上的注释,放出来大家共享及交流。
有兴趣的可以参考一下,各管脚定义都比较明显,有一定基础的可稍作修改即可进行实验。
//基于51单片机控制的1602液晶电子时钟显示程序#i nclude <intrins.h>#i nclude <at89x51.h>#define uchar unsigned char#define LCM_RS P2_2 //定义引脚#define LCM_RW P2_1#define LCM_E P2_0#define LCM_Data P0#define Busy 0x80 //用于检测LCM状态字中的Busy标识uchar i, j, k, second, tcount, minute, hour;void WriteDataLCM(unsigned char WDLCM);void WriteCommandLCM(unsigned char WCLCM,BuysC);unsigned char ReadDataLCM(void);unsigned char ReadStatusLCM(void);void LCMInit(void);void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);void DisplayqListChar(unsigned char X, unsigned char Y, unsigned char code *DData);void Delay5Ms(void);void Delay400Ms(void);unsigned char code table[]={'0','1','2','3','4','5','6','7','8','9'};//数码管数字编码unsigned char code MyNo[] = {"NAME:Who_am_I?"};/*************************************************************************** ***************** 函数名称:delay()** 功能描述:延时子程序,大约延时n MS** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/delay(uchar n){uchar i,j,k;for(i=2;i>0;i--)for(j=n;j>0;j--)for(k=125;k>0;k--);}/*************************************************************************** ***************** 函数名称:lcd()** 功能描述:液晶初始化,然后在液晶屏第二行显示提示信息** 输入:** 输出:** 全局变量:** 调用模块:Delay400Ms(),LCMInit(),DisplayListChar()** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void lcd(void){Delay400Ms(); //启动等待,等LCM讲入工作状态LCMInit(); //LCM初始化Delay5Ms(); //延时片刻(可不要)DisplayListChar(0, 1, MyNo);}/*************************************************************************** ***************** 函数名称:WriteDataLCM()** 功能描述:写数据** 输入:WDLCM** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void WriteDataLCM(unsigned char WDLCM){ReadStatusLCM(); //检测忙LCM_Data = WDLCM;LCM_RS = 1;LCM_RW = 0;LCM_E = 0; //若晶振速度太高可以在这后加小的延时LCM_E = 0; //延时LCM_E = 1;}/*************************************************************************** ***************** 函数名称:WriteCommandLCM()** 功能描述:写指令** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测{if (BuysC) ReadStatusLCM(); //根据需要检测忙LCM_Data = WCLCM;LCM_RS = 0;LCM_RW = 0;LCM_E = 0;LCM_E = 0;LCM_E = 1;}/*************************************************************************** ***************** 函数名称:ReadDataLCM()** 功能描述:读数据** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/unsigned char ReadDataLCM(void){LCM_RS = 1;LCM_E = 0;LCM_E = 0;LCM_E = 1;return(LCM_Data);}/*************************************************************************** ***************** 函数名称:ReadStatusLCM()** 功能描述:读状态** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/unsigned char ReadStatusLCM(void){LCM_Data = 0xFF;LCM_RS = 0;LCM_E = 0;LCM_E = 0;LCM_E = 1;while (LCM_Data & Busy); //检测忙信号return(LCM_Data);}/*************************************************************************** ***************** 函数名称:LCMInit()** 功能描述:LCM初始化** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void LCMInit(void){LCM_Data = 0;WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号Delay5Ms();WriteCommandLCM(0x38,0);Delay5Ms();WriteCommandLCM(0x38,0);Delay5Ms();WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号WriteCommandLCM(0x08,1); //关闭显示WriteCommandLCM(0x01,1); //显示清屏WriteCommandLCM(0x06,1); // 显示光标移动设置WriteCommandLCM(0x0C,1); // 显示开及光标设置}/*************************************************************************** ***************** 函数名称:DisplayOneChar()** 功能描述:按指定位置显示一个字符** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData){Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;X |= 0x80; // 算出指令码WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码WriteDataLCM(DData);}/*************************************************************************** ***************** 函数名称:DisplayListChar()** 功能描述:按指定位置显示一串字符** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData){unsigned char ListLength;ListLength = 0;Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1while (DData[ListLength]>0x20) //若到达字串尾则退出{if (X <= 0xF) //X坐标应小于0xF{DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符ListLength++;X++;}}}/*************************************************************************** ***************** 函数名称:Delay5Ms()** 功能描述:5ms延时** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void Delay5Ms(void){unsigned int TempCyc = 5552;while(TempCyc--);}/*************************************************************************** ***************** 函数名称:Delay400Ms()** 功能描述:400ms延时** 输入:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void Delay400Ms(void){unsigned char TempCycA = 5;unsigned int TempCycB;while(TempCycA--){TempCycB=7269;while(TempCycB--);};}/*************************************************************************** ***************** 函数名称:timer0()** 功能描述:中断子程序,1秒重写一次液晶,以此实现60秒计数** 输入:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void timer0() interrupt 1 using 0{int i;TH0=(65536-50000)/256*3; //中断设置初始化TL0=(65536-50000)%256*3;tcount++;if(tcount==60) //满1秒{ i=0;DisplayOneChar(i++, 0, 'T'); //在第1行第1个坐标显示DisplayOneChar(i++, 0, 'I'); //在第1行第2个坐标显示DisplayOneChar(i++, 0, 'M'); //在第1行第3个坐标显示DisplayOneChar(i++, 0, 'E'); //在第1行第4个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第5个坐标显示DisplayOneChar(i++, 0, table[hour/10]); //在第1行第6个坐标显示DisplayOneChar(i++, 0, table[hour%10]); //在第1行第7个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第1个坐标显示DisplayOneChar(i++, 0, table[minute/10]); //在第1行第8个坐标显示DisplayOneChar(i++, 0, table[minute%10]); //在第1行第9个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第10个坐标显示DisplayOneChar(i++, 0, table[second/10]); //在第1行第11个坐标显示DisplayOneChar(i++, 0, table[second%10]); //在第1行第12个坐标显示tcount=0;second++;if(second==60) //满1分{second=0;minute++; //分数加1,秒数归零if(minute==60) //满1小时{minute=0;hour++; //小时数加1,分数归零if(hour==24){hour=0;}}}}}/*************************************************************************** ***************** 函数名称:main()** 功能描述:主程序,设置初始时间,中断设置初始化,液晶显示,等待中断** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void main(){uchar i;second=0;minute=0;hour=0; //设置初始时间TH0=(65536-50000)/256; //中断设置初始化TL0=(65536-50000)%256;EA=1;ET0=1;TMOD=0x21;TR0=1;lcd();i=0;DisplayOneChar(i++, 0, 'T'); //在第1行第1个坐标显示DisplayOneChar(i++, 0, 'I'); //在第1行第2个坐标显示DisplayOneChar(i++, 0, 'M'); //在第1行第3个坐标显示DisplayOneChar(i++, 0, 'E'); //在第1行第4个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第5个坐标显示DisplayOneChar(i++, 0, table[hour/10]); //在第1行第6个坐标显示DisplayOneChar(i++, 0, table[hour%10]); //在第1行第7个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第1个坐标显示DisplayOneChar(i++, 0, table[minute/10]); //在第1行第8个坐标显示DisplayOneChar(i++, 0, table[minute%10]); //在第1行第9个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第10个坐标显示DisplayOneChar(i++, 0, table[second/10]); //在第1行第11个坐标显示DisplayOneChar(i++, 0, table[second%10]); //在第1行第12个坐标显示while(1); //等待中断}。
风骚的51+LCD1602控制(四位,八位控制),1602函数全集+写入字库LCD1602写字库在文档后面。
LCD1602演示程序(很多函数哦)控制芯片为HD44780函数都是经过测试的,实物显示都通过了,呵呵,请大家放心使用^_^呵呵,支持四线数据接口模式,可以任意切换编程,只须改模式选择Port_Type_Select就可以咯!很方便的。
并且我说一下我的个人体会,希望大家在写程序的时候,最好考虑一下程序的可移植性,而且要方便更改参数和硬件资源的选择,最好使用条件编译,任意切换硬件资源,可以方便以后更改参数,就会省去以后不少的不必要的麻烦和错误以及宝贵的时间里面有标准测试,如果您觉得好的话,请您帮忙顶一下,,写出更好的功能函数。
先简单介绍一下功能函数吧:/*--------------------------------------------------------------*/ //模式选择(条件编译)#define Port_Type_Select 1 //=1, 选择八位数据模式//=0, 选择四位数据模式, LCD高四位接MCU端口高四位/*--------------------------------------------------------------*/ //函数声明void LCD_busy (void); //检测LCD是否忙void LCD_init (void); //LCD初始化void LCD_cmd (unsigned char cmd); //写入指令void LCD_dat (unsigned char dat); //写入数据void LCD_pos (unsigned char x, unsigned char y); //显示定位void LCD_printc(unsigned char x, unsigned char y, unsigned char c); //定位输出字符void LCD_prints(unsigned char x, unsigned char y, unsigned char *s); //定位输出字符串void LCD_printn(unsigned char x, unsigned char y, unsigned int num); //定位输出16位二进制数字unsigned char LCD_current_addr(void); //读出AC当前地址(DB6~DB0)或忙标志位DB7unsigned char LCD_current_addr_dat(void); //读出AC当前地址的数据unsigned char LCD_addr_dat(unsigned char x, unsigned char y); //读出AC指定地址的数据void LCD_pos_CG(unsigned char x, unsigned char *CGRAM_dat); //指定地址(x: 0-7)写入8bytes数据CGRAM/*-------------------------------------------------------------*///光标、画面移动,不影响DDRAM#define LCD_LEFT_MOVE LCD_cmd(0x18); //LCD显示左移一位#define LCD_RIGHT_MOVE LCD_cmd(0x1c); //LCD显示右移一位#define LCD_CURSOR_LEFT_MOVE LCD_cmd(0x10); //光标左移一位#define LCD_CURSOR_RIGHT_MOVE LCD_cmd(0x14); //光标右移一位/*--------------------------------------------------------------*///设置显示、光标及闪烁开、关#define LCD_DISPLAY_ON LCD_cmd(0x0c); //LCD开显示#define LCD_DISPLAY_OFF LCD_cmd(0x08); //LCD关显示#define LCD_CURSOR_ON LCD_cmd(0x0e); //光标显示#define LCD_CURSOR_OFF LCD_cmd(0x0c); //光标不显示#define LCD_CURSOR_BLINK_ON LCD_cmd(0x0f); //光标闪烁#define LCD_CURSOR_BLINK_OFF LCD_cmd(0x0e); //光标不闪烁#define LCD_GO_HOME LCD_cmd(0x02); //AC=0,光标、画面回HOME位, DDRAM内容不变#define LCD_CLR LCD_cmd(0x01); //LCD清屏, 清除DDRAM, 清除屏幕, 置AC为0, 光标回位?/*--------------------------------------------------------------*///工作方式设置#define LCD_DISPLAY8_DOUBLE_LINE LCD_cmd(0x38); //两行显示8-bits#define LCD_DISPLAY8_SINGLE_LINE LCD_cmd(0x30); //单行显示8-bits#define LCD_DISPLAY4_DOUBLE_LINE LCD_cmd(0x28); //两行显示4-bits#define LCD_DISPLAY4_SINGLE_LINE LCD_cmd(0x20); //单行显示4-bits/*--------------------------------------------------------------*///输入方式设置#define LCD_AC_AUTO_INCREMENT LCD_cmd(0x06); //数据读、写操作后,AC 自动加 1#define LCD_AC_AUTO_DECREASE LCD_cmd(0x04); //数据读、写操作后,AC自动减 1#define LCD_MOVE_ENABLE LCD_cmd(0x07); //数据读、写操作,画面平移#define LCD_MOVE_DISENABLE LCD_cmd(0x06); //数据读、写操作,画面不动以下是液晶驱动头文件:/*--------------------------------------------------------------*/ //File: LCD1602_8A.H//Time: 20:10//Modi: 09-5-17/*--------------------------------------------------------------*/ //防止被重复定义#ifndef __LCD1602_8A_H__#define __LCD1602_8A_H__/*--------------------------------------------------------------*/ //模式选择(条件编译)#define Port_Type_Select 1 //=1, 选择八位数据模式//=0, 选择四位数据模式, LCD高四位接MCU端口高四位#define Int_Transfer 1 //=1, 允许中断服务函数调用//=0, 不允许中断服务函数调用/*--------------------------------------------------------------*/ //LCD1602与单片机接口定义sfr LCD_IO = 0x80; //P0-0x80,P1-0x90,P2-0xA0,P3-0xB0;sbit LCD_RS = P2^0; //LCD数据/命令选择端(H/L)sbit LCD_RW = P2^1; //LCD 读/写选择端(H/L)sbit LCD_EN = P2^2; //LCD使能控制端/*--------------------------------------------------------------*/ //工作方式设置#define LCD_DISPLAY8_DOUBLE_LINE LCD_cmd(0x38); //两行显示8-bits #define LCD_DISPLAY8_SINGLE_LINE LCD_cmd(0x30); //单行显示8-bits #define LCD_DISPLAY4_DOUBLE_LINE LCD_cmd(0x28); //两行显示4-bits #define LCD_DISPLAY4_SINGLE_LINE LCD_cmd(0x20); //单行显示4-bits/*--------------------------------------------------------------*/ //输入方式设置#define LCD_AC_AUTO_INCREMENT LCD_cmd(0x06); //数据读、写操作后,AC 自动加 1#define LCD_AC_AUTO_DECREASE LCD_cmd(0x04); //数据读、写操作后,AC自动减 1#define LCD_MOVE_ENABLE LCD_cmd(0x07); //数据读、写操作,画面平移#define LCD_MOVE_DISENABLE LCD_cmd(0x06); //数据读、写操作,画面不动/*--------------------------------------------------------------*///设置显示、光标及闪烁开、关#define LCD_DISPLAY_ON LCD_cmd(0x0c); //LCD开显示#define LCD_DISPLAY_OFF LCD_cmd(0x08); //LCD关显示#define LCD_CURSOR_ON LCD_cmd(0x0e); //光标显示#define LCD_CURSOR_OFF LCD_cmd(0x0c); //光标不显示#define LCD_CURSOR_BLINK_ON LCD_cmd(0x0f); //光标闪烁#define LCD_CURSOR_BLINK_OFF LCD_cmd(0x0e); //光标不闪烁#define LCD_GO_HOME LCD_cmd(0x02); //AC=0,光标、画面回HOME位, DDRAM内容不变#define LCD_CLR LCD_cmd(0x01); //LCD清屏, 清除DDRAM, 清除屏幕, 置AC为0, 光标回位?/*--------------------------------------------------------------*///光标、画面移动,不影响DDRAM#define LCD_LEFT_MOVE LCD_cmd(0x18); //LCD显示左移一位#define LCD_RIGHT_MOVE LCD_cmd(0x1c); //LCD显示右移一位#define LCD_CURSOR_LEFT_MOVE LCD_cmd(0x10); //光标左移一位#define LCD_CURSOR_RIGHT_MOVE LCD_cmd(0x14); //光标右移一位/*--------------------------------------------------------------*///LCD1602地址相关/*#define LINE1_HEAD 0x80 //第一行DDRAM起始地址#define LINE2_HEAD 0xc0 //第二行DDRAM起始地址#define LINE1 0 //第一行#define LINE2 1 //第二行#define LINE_LENGTH 16 //每行的最大字符长度(40-DDRAM)/*--------------------------------------------------------------*/ //函数声明void LCD_busy (void); //检测LCD是否忙void LCD_init (void); //LCD初始化void LCD_cmd (unsigned char cmd); //写入指令void LCD_dat (unsigned char dat); //写入数据void LCD_pos (unsigned char x, unsigned char y); //显示定位void LCD_printc(unsigned char x, unsigned char y, unsigned char c); //定位输出字符void LCD_prints(unsigned char x, unsigned char y, unsigned char *s); //定位输出字符串void LCD_printn(unsigned char x, unsigned char y, unsigned int num); //定位输出16位二进制数字unsigned char LCD_current_addr(void); //读出AC当前地址(DB6~DB0)或忙标志位DB7unsigned char LCD_current_addr_dat(void); //读出AC当前地址的数据unsigned char LCD_addr_dat(unsigned char x, unsigned char y); //读出AC指定地址的数据void LCD_pos_CG(unsigned char x, unsigned char *CGRAM_dat); //指定地址(x: 0-7)写入8bytes数据CGRAM/*--------------------------------------------------------------*/ //读出AC当前地址(DB6~DB0)或忙标志位DB7#if Port_Type_Select //选择八位数据模式unsigned char LCD_current_addr(void){unsigned char ac_addr;LCD_EN = 0;LCD_RS = 0; //指令LCD_RW = 1; //读出LCD_IO = 0xff; //端口置为输入方式(P0)LCD_EN = 1;ac_addr = LCD_IO;LCD_EN = 0;return (ac_addr);}#else //选择四位数据模式unsigned char LCD_current_addr(void){unsigned char ac_addr;LCD_EN = 0;LCD_RS = 0; //指令LCD_RW = 1; //读出LCD_IO |= 0xf0; //端口置为输入方式(P0)LCD_EN = 1;ac_addr = LCD_IO & 0xf0; //高四位LCD_EN = 0;LCD_EN = 1;ac_addr |= LCD_IO >> 4; //低四位LCD_EN = 0;return (ac_addr);}#endif/*--------------------------------------------------------------*/ //检测LCD忙状态#if Int_Transfer //允许中断服务函数调用void LCD_busy(void){unsigned char ac_dat;unsigned char busy_flag;do{ac_dat = LCD_current_addr();busy_flag = ac_dat & 0x80;}while(busy_flag); //=1表示忙, =0表示空闲}#else //不允许中断服务函数调用void LCD_busy(void){unsigned char ac_dat;bit busy_flag;do{ac_dat = LCD_current_addr();busy_flag = (bit)(ac_dat & 0x80);}while(busy_flag); //=1表示忙, =0表示空闲}#endif/*--------------------------------------------------------------*/ //读出AC当前地址的数据#if Port_Type_Select //选择八位数据模式unsigned char LCD_current_addr_dat(void){unsigned char addr_dat;// unsigned char i;LCD_busy(); //或者检查忙最可靠// for(i = 0; i < 3; i++) //要连续读出三次才会有效{LCD_EN = 0;LCD_RS = 1; //数据LCD_RW = 1; //读出LCD_IO = 0xff; //端口置为输入方式(P0)LCD_EN = 1;addr_dat = LCD_IO;LCD_EN = 0;}return (addr_dat);}#else //选择四位数据模式unsigned char LCD_current_addr_dat(void){unsigned char addr_dat;// unsigned char i;LCD_busy(); //或者检查忙最可靠// for(i = 0; i < 3; i++) //要连续读出三次才会有效{LCD_EN = 0;LCD_RS = 1; //数据LCD_RW = 1; //读出LCD_IO |= 0xf0; //端口置为输入方式(P0)LCD_EN = 1;addr_dat = LCD_IO & 0xf0; //高四位LCD_EN = 0;LCD_EN = 1;addr_dat |= LCD_IO >> 4; //低四位LCD_EN = 0;}return (addr_dat);}#endif/*--------------------------------------------------------------*/ //写入指令#if Port_Type_Select //选择八位数据模式void LCD_cmd(unsigned char cmd){LCD_busy(); //检测忙LCD_RS = 0; //指令LCD_RW = 0; //写入LCD_EN = 1;LCD_IO = cmd; //传指令LCD_EN = 0; //下降沿有效}#else //选择四位数据模式void LCD_cmd(unsigned char cmd){LCD_busy(); //检测忙LCD_IO &= 0x0f; //清高四位LCD_RS = 0; //指令LCD_RW = 0; //写入LCD_EN = 1;LCD_IO |= cmd & 0xf0; //写高四位LCD_EN = 0; //下降沿有效cmd <<= 4; //低四位移到高四位LCD_IO &= 0x0f; //清高四位LCD_EN = 1;LCD_IO |= cmd & 0xf0; //写高四位LCD_EN = 0; //下降沿有效}#endif/*--------------------------------------------------------------*/ //写入数据#if Port_Type_Select //选择八位数据模式void LCD_dat(unsigned char dat){LCD_busy(); //检测忙LCD_RS = 1; //数据LCD_RW = 0; //写入LCD_EN = 1;LCD_IO = dat; //传数据LCD_EN = 0; //下降沿有效}#else //选择四位数据模式void LCD_dat(unsigned char dat){LCD_busy(); //检测忙LCD_IO &= 0x0f; //清高四位LCD_RS = 1; //数据LCD_RW = 0; //写入LCD_EN = 1;LCD_IO |= dat & 0xf0; //写高四位LCD_EN = 0; //下降沿有效dat <<= 4; //低四位移到高四位LCD_IO &= 0x0f; //清高四位LCD_EN = 1;LCD_IO |= dat & 0xf0; //写高四位LCD_EN = 0; //下降沿有效}#endif/*--------------------------------------------------------------*/ //显示定位DDRAMvoid LCD_pos(unsigned char x, unsigned char y){if(y) LCD_cmd(x|0xc0);//y=1第二行显示,y=0第一行显示0<=x<16(40-DDRAM)else LCD_cmd(x|0x80);//数据指针=80+地址码(00H~27H,40H~67H)}/*--------------------------------------------------------------*/ //指定地址(x: 0-7)写入8bytes数据CGRAMvoid LCD_pos_CG(unsigned char x, unsigned char *CGRAM_dat){unsigned char i;x <<= 3; //转化为6位数据的高三位x |= 0x40;LCD_cmd(x); //写入地址for(i = 0; i < 8; i++)LCD_dat(CGRAM_dat[i]); //写入数据}/*--------------------------------------------------------------*/ //读出AC指定地址的数据unsigned char LCD_addr_dat(unsigned char x, unsigned char y){unsigned char addr_dat;LCD_pos(x, y); //定位addr_dat = LCD_current_addr_dat(); //读出数据return (addr_dat);}/*--------------------------------------------------------------*/ //定位输出字符void LCD_printc(unsigned char x, unsigned char y, unsigned char c) {LCD_pos(x, y);LCD_dat(c);}/*--------------------------------------------------------------*/ //定位输出字符串void LCD_prints(unsigned char x, unsigned char y, unsigned char *s) {LCD_pos(x, y);while(*s){LCD_dat(*s);s++;}}/*--------------------------------------------------------------*/ //定位输出16位二进制数字// 0<= num <65536void LCD_printn(unsigned char x, unsigned char y, unsigned int num) {char i;unsigned char ii;unsigned char dat[6];for(i = 0; i < 6; i++) dat[i] = 0; i = 0; //初始化数据while(num / 10) //拆位{dat[i] = num % 10; //最低位num /= 10; i++;}dat[i] = num; //最高位ii = i; //保存dat的位数for(; i >= 0; i--) dat[i] += 48; //转化成ASCIILCD_prints(x, y, " "); //清显示区域LCD_pos(x, y);for(i = ii; i >= 0; i--) LCD_dat(dat[i]); //输出数字字符}/*--------------------------------------------------------------*/ //LCD初始化void LCD_init(void){#if Port_Type_Select //选择八位数据模式LCD_DISPLAY8_DOUBLE_LINE //设置LCD为16X2显示,5X7点阵,八位数据接口#elseLCD_DISPLAY4_DOUBLE_LINE //设置LCD为16X2显示,5X7点阵,四位数据接口#endifLCD_AC_AUTO_INCREMENT //LCD显示光标移动设置(光标地址指针加1,整屏显示不移动)LCD_DISPLAY_ON //LCD开显示及光标设置(光标不闪烁,不显示"_") LCD_CLR //清屏}/*--------------------------------------------------------------*/ [原创] 液晶1602 显示汉字研究液晶, 汉字, 研究1602是一款最常用也是最便宜的液晶显示屏。