LCD1602-51单片机汇编程序
51单片机驱动LCD1602程序设计(C语言)

字符液晶绝大多数是基于 HD44780 液晶芯片的,控制原理是完全相同的,因此 HD44780 写 的控制程序可以很方便地应用于市面上大部分的字符型液晶。字符型 LCD 通常有 14 条引脚线或 16 条引脚线的 LCD,多出来的 2 条线是背光电源线 VCC(15 脚)和地线 GND(16 脚),其控制原理 与 14 脚的 LCD 完全一样,定义如下表所示:
for(i=0;i<count;i++) {
if (0 == y) x |= 0x80; //当要显示第一行时地址码+0x80; else x |= 0xC0; //在第二行显示是地址码+0xC0; Write_com(x); //发送地址码 Write_dat(*p); //发送要显示的字符编码 x++; p++; }
01110
○■■■○
10001
■○○○■
10001
■○○○■
10001
■○○○■
11111
■■■■■
10001
■○○○■
10001
■○○○■
上图左边的数据就是字模数据,右边就是将左边数据用“○”代表 0,用“■”代表 1。看出是个“A”
字了吗?在文本文件中“A”字的代码是 41H,PC 收到 41H 的代码后就去字模文件中将代表 A 字的
字符型 LCD 的引脚定义
HD44780 内置了 DDRAM、CGROM 和 CGRAM。DDRAM 就是显示数据 RAM,用来寄存 待显示的字符代码。共 80 个字节,其地址和屏幕的对应关系如下表:
也就是说想要在 LCD1602 屏幕的第一行第一列显示一个"A"字,就要向 DDRAM 的 00H 地址写 入“A”字的代码就行了。但具体的写入是要按 LCD 模块的指令格式来进行的。在 1602 中我们用前 16 个就行了。第二行也一样用前 16 个地址。对应如下:
LCD1602与MCS-51单片机的接口

LCD1602与MCS-51单片机的接口液晶显示器(LCD)具有工作电压低、微功耗、显示信息量大和接口方便等优点,现在已被广泛应用于计算机和数字式仪表等领域,成为测量结果显示和人机对话的重要工具。
液晶显示器按其功能可分为三类:笔段式液晶显示器、字符点阵式液晶显示器和图形点阵式液晶显示器。
前两种可显示数字、字符和符号等,而图形点阵式液晶显示器还可以显示汉字和任意图形,达到图文并茂的效果,其应用越来越广泛。
本节将以RT-1602C液晶显示模块为例,介绍液晶显示器的结构和功能,讨论其与MCS-51单片机的硬件接口电路及软件编程方法。
7.1.1 LCD1602概述LCD1602是2 16字符型液晶显示模块,可以显示两行,每行16个字符,采用5×7点阵显示,工作电压4.5~5.5V,工作电流2.0mA(5.0V),其控制器采用HD44780液晶芯片(市面上字符液晶显示器的控制器绝大多数都是基于HD44780液晶芯片,它们的控制原理是完全相同的)。
LCD1602可采用标准的14引脚接口或16引脚接口,多出来的2条引脚是背光源正极BLA(15脚)和背光源负极BLK(16脚),其外观形状如图7.1所示。
(a) 正面(b) 背面图7.1 RT-1602C的外观(a)图是LCD1602的正面,(b)图LCD1602的背面。
标准的16引脚接口如下:第1脚:V SS,电源地。
第2脚:V DD,+5V电源。
第3脚:V EE,液晶显示对比度调整输入端。
接正电源时对比度最弱,接地时对比度最高。
使用时通常通过一个10K的电位器来调整对比度。
第4脚:RS,数据/命令选择端,高电平时选择数据寄存器,低电平时选择指令寄存器。
第5脚:R/W,读/写选择端,高电平时进行读操作,低电平时进行写操作。
当RS和R/W共同为低电平时,可以写入指令或者显示地址;当RS为低电平、R/W为高电平时,可以读忙信号;当RS为高电平、R/W为低电平时,可以写入数据。
LCD1602-51单片机汇编程序.

1602汇编程序,刃单片机汇编程序,仅需修改引脚定义即可。
晶振大小12M,程序测试完全正确。
内部包含写数据、写命令(包括读忙和不读忙、初始化等子函数。
调用时先给LCD_DAT赋值,给出需要写入的数据或命令,然后调用。
;端口引脚定义区LCD_RS BIT P2.4 ;1602数据命令选择端口LCD_RW BIT P2.5 ;1602 读写选择端口LCD_EN BIT P2.6 ;1602 使能端口LCD_DATA EQU P0 ;1602 数据端口;变量声明区ALL_FLAG EQU 20H ;标志位LCD_FLAG EQU AL「FLAG.7 ;1602 读忙标志位LCD_DAT EQU 30H ;1602 数据命令字DELAYED EQU 31H 涎时字广★★★****★★★★★★★*★*★★**★*★★★*★*★★★★★*★*★*★1602读命令函数,高位存至LCD_LAG中★★★★★★★★★★★★★★★★★★★★★if******************* /LCD_R_DATA:MOV LCD_DATA,#OFFHSETB L CD RWNOPSETB L CD_ENNOPMOV Acc丄CD_DATAMOV C,Acc.7MOV LCD_FLAG,CCLR LCD_ENNOPJB LCD_FLAG ,L CD_BUSYRET/★****★***★*★***********************★*★*★*1602写数据函数,数据存在LCD_DAT★ if*************************************** /LCD_W_DATA:LCALLLCD_R_DATASETB L CD_RSNOPMOV LCD_DATA丄CD_DATSETB L CD_ENNOPCLR LCD_ENRET/* 1602LCD_DAT,检测忙信号LCD_W_CMD:LCALLLCD_R_DATACLR LCD_RSCLR LCD_RWNOPMOV LCD_DATA, LCD_DAT SETB L CD_ENNOPCLR LCD_ENRET /* 1602 与命令函数,命令存在LCD_DAT,不检测忙信号LCD CMD: 才***********才********************才才*****7写命令函数,命令存F在CLR LCD RWNOPMOV LCD_DATA, LCD_DAT SETB L CD_ENNOPCLR LCD_ENRET/***************************************** 4 QCC初始化函数★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★*/ LCD INIT:MOV DELAYED,#30LCALL DELAY_MSMOV LCD_DAT,#38HLCALL LCD_CMDMOV DELAYED,#10LCALL DELAY_MSMOV LCD_DAT,#38HLCALL LCD_CMDMOV DELAYED,#10LCALL DELAY_MSMOV LCD_DAT,#38HLCALL LCD CMDMOV DELAYED,#®LCALL DELAY_MSMOV LCD_DAT,#038HLCALL LCD_W_CMDMOV LCD_DAT,#08HLCALL LCD_W_CMDMOV LCD_DAT,#01HLCALL LCD_W_CMDMOV LCD_DAT,#06HLCALL LCD_W_CMDMOV LCD_DAT,#OCHLCALL LCD_W_CMDRET****************************************延时函数,延时时间为DELAYEDP.5毫秒0-100毫秒的延时***************************************** /DELAY_MS:MOV R7QELAYEDD1: MOV R6,#0F8HD2: DJNZ R6,D2DJNZ R7,D1RET广****************************************延时函数,延时时间为DELAYED*2微秒0-500微秒的延时***************************************** /DELAY_US:MOV R乙ADU1:DJNZ R7,DU1RET。
1602液晶初始化程序(汇编)

〔原创〕1602液晶初始化程序(2007-12-22 18:10:40)标签:1602液晶it/科技汇编语言液晶初始化,显示数字,按秒计数RS EQU P2.0RW EQU P2.1E EQU P2.2IN_0 EQU P0SECL EQU 40H ;秒低位SECH EQU 41H ;秒高位MH1 EQU 42H ;冒号MINL EQU 43H ;分低位MINH EQU 44H ;分高位MH2 EQU 45H ;冒号HOURL EQU 46H ;时低位HOURH EQU 47H ;时高位;*********************************ORG 0000HAJMP STARTORG 000BHAJMP INTT_0START:MOV SP,#70HMOV R2,#20ACALL INIT_LCD ;初始化液晶MOV R5,#00HMOV IN_0,#84H ;写入显示起始地址(第一行第五个位置ACALL ENABLEMOV TH0,#3fH ;50MSMOV TL0,#0b0HMOV TMOD,#01HACALL SJCZSTART1:SETB EASETB ET0SETB TR0LCALL WDATAAJMP START1;*****时间初值*******SJCZ: MOV 40H,#8 ;显示初值是 08:08:08MOV 41H,#0MOV 42H,#10MOV 43H,#8MOV 44H,#0MOV 45H,#10MOV 46H,#8MOV 47H,#0RET;****T0定时器中断****INTT_0: PUSH ACCMOV TL0,#0b0H ;送定时初值MOV TH0,#3fHDJNZ R2,TTMOV R2,#20INC SECL ;秒记数,到60S就清0MOV A,SECLCJNE A,#0AH,TTINC SECHMOV SECL,#0MOV A,SECHCJNE A,#06H,TTMOV SECH,#0INC MINL ;分记数,到60分请0MOV A,MINLCJNE A,#0AH,TTMOV MINL,#0INC MINHMOV A,MINHCJNE A,#06H,TTMOV MINH,#0INC HOURL ;时记数,到24时清0MOV A,HOURLCJNE A,#04H,TT2MOV A,HOURHCJNE A,#02H,TT1MOV HOURL,#0MOV HOURH,#0AJMP TTTT2: CJNE A,#0AH,TTMOV HOURL ,#0INC HOURHAJMP TTTT1: MOV A,HOURLCJNE A,#0AH,TTMOV HOURL ,#0INC HOURHAJMP TTTT: POP ACCRETI;*******液晶初始化*****INIT_LCD:CALL DELAYL ;延时20ms,等待LCD完成电源的启动MOV IN_0,#01H ;清屏并光标复位ACALL ENABLEMOV IN_0,#38H ;设置显示模式:8位2行5x7点阵ACALL ENABLEMOV IN_0,#0FH ;显示器开、光标开、光标允许闪烁ACALL ENABLEMOV IN_0,#06H ;文字不动,光标自动右移ACALL ENABLEMOV IN_0,#0C0H ;写入显示起始地址(第二行第一个位置)ACALL ENABLERET;******写数据程序***WDATA: MOV IN_0,#84H ;写入显示起始地址(第一行第五个位置ACALL ENABLEMOV R1,#8MOV R0,#47HWDATA1: MOV A,@R0MOV DPTR,#TABLEMOVC A,@A+DPTRMOV IN_0,A ;写入数据SETB RSCLR RWCLR EACALL CHECKBUSYSETB E ; 忙检测DEC R0DJNZ R1,WDATA1MOV R1,#8RET;*******显示字母表********TABLE: DB 30H,31H,32H,33H,34H,35H ;0 1 2 3 4 5DB 36H,37H,38H,39H,3AH,80H,2EH ;6 7 8 9 : 空格 .;*********写指令*****ENABLE: CLR RS ;写入控制命令的子程序CLR RWCLR EACALL CHECKBUSYSETB ERET;*******程序忙检测***CHECKBUSY:MOV IN_0,#0FFH ;判断液晶显示器是否忙的子程序CLR RSSETB RWCLR ENOPSETB EJB P0.7,CHECKBUSY ;如果P1.7为高电平表示忙就循环等待RET;******延时程序****DELAY: MOV R6,#50DEL: MOV R7,#48DJNZ R7,$DJNZ R6,DELRETDELAYL: MOV R7,#100 ;长延时20msD1: MOV R6,#98DJNZ R6,$DJNZ R7,D1RETEND51单片机的1602没做过,只做过其他的控制。
51单片机控制1602LCD显示程序

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();}}。
51单片机驱动1602液晶汇编语言程序

LCMRS EQU P2.4 LCMRW EQU P2.5 LCMEN EQU P2.6 LCMDATA EQU P0 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV SP,#60H LCALL LCMSET LCALL LCMCLR MOV A,#80H LCALL LCMWR0 MOV DPTR,#TAB0 LCALL LCMWR2 MOV A,#0C0H LCALL LCMWR0 MOV DPTR,#TAB1 LCALL LCMWR2 SJMP $
LCALL LCMLAY CLR LCMEN CLR LCMRS CLR LCMRW SETB LCMEN MOV LCMDATA,A
CLR LCMEN RET LCMWR1: ;写入数据
LCALL LCMLAY CLR LCMEN SETB LCMRS CLR LCMRW SETB LCMEN MOV LCMDATA,A CLR LCMEN RET LCMWR2: PUSH ACC LOOP1: CLR A MOVC A,@A+DPTR JZ LOOP2 LCALL LCMWR1 INC DPTR LJMP LOOP1 LOOP2: POP ACC 写入字符串(字符串属于数据)
TAB0: DB "I AM YUAN MING",00H TAB1: DB "NICE TO MEET YOU",00H LCMLAY: PUSH ACC LOOP: CLR LCMEN CLR LCMRS SETB LCMRW SETB LCMEN MOV A,LCMDATA CLR LCMEN JB ACC.7,LOOP POP ACC LCALL DELAY RET LCMWR0: ;写入指令 ;读忙程序,用于判断 d7 是否为 0
LCD1602液晶秒表C51程序

LCD1602液晶秒表C51程序此程序是基于51hei单片机开发板上面写的,如需要移植到自己的电路上,修改相应的端口即可,开发板完整的电路图下载: 点这里(注意:只需要看1602部分即可,其他部分可以忽略)/*************************************************** *********************** @file main.c* @author xr* @date 2014年5月8日22:11:33 -- 2014年5月9日12:03:49* @version V1.2.3* @brief LCD1602液晶跑表单片机STC89C52RC MCU 晶振 11.0592MHZ************************************************* ***********************/#include ;/* 系统时钟 */#define SYS_XTAL (11059200UL/12)/* 定时器T0重载值 */unsigned char thr0, tlr0;unsigned char thr1, tlr1;/* 跑表计数 */unsigned char timer[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; //分别表示跑表的各个位上的数字bit flag10ms = 0;extern bit stopflag;//跑表走停标志位extern void InitalLCD1602();extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str);extern void KeyDriver();extern void KeyScan();void DisplayTimer();void ConfigTimer0(unsigned int xms);void ConfigTimer1(unsigned int xms);/* 主函数main() */void main(void){ConfigTimer0(10); //定时10msConfigTimer1(1);InitalLCD1602();LcdShowStr(0, 0, "stopwatch");LcdShowStr(2, 1, "0000000.00s"); //液晶初始化显示LcdShowStr(10, 0, "stop!");while (1){KeyDriver();DisplayTimer();if ((flag10ms == 1) && (stopflag == 1)){flag10ms = 0;timer[0]++;if (timer[0] >; 9){timer[0] = 0;timer[1]++;if (timer[1] >; 9){timer[1] = 0;timer[2]++;if (timer[2] >; 9) {timer[2] = 0;timer[3]++;if (timer[3] >; 9) {timer[3] = 0;timer[4]++;if (timer[4] >; 9) {timer[4] = 0;timer[5]++;if (timer[5] >; 9) {timer[5] = 0;timer[6]++;if (timer[6] >; 9) {timer[6] = 0;timer[7]++;if (timer[7] >; 9){timer[7] = 0;timer[8]++;if (timer[8] >; 9){timer[8] = 0;}}}}}}}}}}}}/* 将跑表时间显示到液晶上 */ void DisplayTimer(){unsigned char str[20];/* 分解timer */str[0] = timer[8] + '0';str[1] = timer[7] + '0';str[2] = timer[6] + '0';str[3] = timer[5] + '0';str[4] = timer[4] + '0';str[5] = timer[3] + '0';str[6] = timer[2] + '0';str[7] = '.';str[8] = timer[1] + '0';str[9] = timer[0] + '0';str[10] = '\0';LcdShowStr(2, 1, str);}/* 定时器T0配置 */void ConfigTimer0(unsigned int xms) {unsigned long tmp;tmp = (SYS_XTAL * xms) / 1000;tmp = 65536-tmp + 18;thr0 = (unsigned char)(tmp >;>; 8) ; tlr0 = (unsigned char)tmp;TMOD &= 0xF0; //清零T0控制位TMOD |= 0x01; //定时器方式1TH0 = thr0;TL0 = tlr0;TR0 = 1; //开启timer0ET0 = 1; //开启T0中断EA = 1; //开启总中断}/* 配置定时器T1 */void ConfigTimer1(unsigned int xms) {unsigned long tmp;tmp = (SYS_XTAL * xms) / 1000;tmp = 65536 - tmp + 18;thr1 = (unsigned char)(tmp >;>; 8); tlr1 = (unsigned char)tmp;TMOD &= 0x0F;TMOD |= 0x10;TH1 = thr1;TL1 = tlr1;TR1 = 1;ET1 = 1;EA = 1;}/* 定时器T0中断服务 */void Timer0_ISP() interrupt 1{TH0 = thr0;TL0 = tlr0;flag10ms = 1; //定时10ms}/* 定时器T1中断服务 */void Timer1_ISP() interrupt 3{TH1 = thr1;TL1 = tlr1; //定时1msKeyScan();}/*************************************************** *********************** @file Lcd1602.c* @author xr* @date 2014年5月7日13:33:17* @version V1.2.3* @brief LCD1602液晶底层驱动************************************************* ***********************/#include ;//LCD1602_IOsbit LCD1602_RS = P1^0;sbit LCD1602_RW = P1^1;sbit LCD1602_EN = P1^5;#define LCD1602_DB P0/* 液晶忙碌等待 */void LCD1602Wait(){unsigned char sta;LCD1602_DB = 0xFF;//总线拉高,检测液晶状态字LCD1602_RS = 0;LCD1602_RW = 1;do{LCD1602_EN = 1;sta = LCD1602_DB;LCD1602_EN = 0;//避免液晶输出数据} while (sta & 0x80);//状态字最高位STA7 == 0空闲,1忙碌}/* 液晶写命令 */void LCD1602WriteCmd(unsigned char cmd){LCD1602Wait();LCD1602_RS = 0;LCD1602_RW = 0;LCD1602_EN = 0;LCD1602_DB = cmd;LCD1602_EN = 1;LCD1602_EN = 0;}/* 液晶写数据 */void LCD1602WriteData(unsigned char dat){LCD1602Wait();LCD1602_RS = 1;LCD1602_RW = 0;LCD1602_EN = 0;LCD1602_DB = dat;LCD1602_EN = 1;LCD1602_EN = 0;}/* 液晶初始化 */void InitalLCD1602(){LCD1602WriteCmd(0x38);LCD1602WriteCmd(0x0C);LCD1602WriteCmd(0x06);LCD1602WriteCmd(0x01);//清屏}/* 写数据到液晶上,字符串str,坐标(x, y),地址addr */void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str){unsigned char addr;if (y == 0){addr = 0x00 + x;}else{addr = 0x40 + x;}LCD1602WriteCmd(addr | 0x80);while (*str != '\0'){LCD1602WriteData(*str++);}}/*************************************************** *********************** @file keyboard.c* @author xr* @date 2014年5月8日22:11:33 -- 2014年5月9日12:03:49* @version V1.2.3* @brief 按键驱动单片机STC89C52RC MCU 晶振11.0592MHZ************************************************* ***********************/#include ;/* 按键输出输入端口定义 */sbit KEY_IN1 = P2^4;sbit KEY_IN2 = P2^5;sbit KEY_IN3 = P2^6;sbit KEY_IN4 = P2^7;sbit KEY_OUT1 = P2^3;sbit KEY_OUT2 = P2^2;sbit KEY_OUT3 = P2^1;sbit KEY_OUT4 = P2^0;extern unsigned char timer[9]; //分别表示跑表的各个位上的数字/* 按键当前状态 */unsigned char volatile keySta[4][4] = {{1, 1, 1, 1},{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};/* 按键对应标准PC键盘编码 */const unsigned char code keyCodeMap[4][4] = {{'1', '2', '3', 0x26}, /* 数字键 1, 2, 3 和向上键 */{'4', '5', '6', 0x25}, /* 数字键 4, 5, 6 和向左键 */{'7', '8', '9', 0x28}, /* 数字键 7, 8, 9 和向下键 */{'0', 0x1B, 0x0D, 0x27} /* 数字键 0 和向右键*/};bit stopflag = 0;//跑表走停标志位 0 停止,1运行void KeyAction(unsigned char keycode);void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str);/* 按键驱动函数 */void KeyDriver(){/* 上一次按键的备份值 */static unsigned char keybackup[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};for (i = 0; i < 4; i++){for (j = 0; j < 4; j++){if (keySta[i][j] != keybackup[i][j]) //当前按键状态和上一次的按键状态不同{ //按键有动作if (keybackup[i][j] != 0) //上一次按键是弹起 {KeyAction(keyCodeMap[i][j]); //当前按键是想、按下}keybackup[i][j] = keySta[i][j]; //备份当前按键值}}}}/* 按键扫描函数 */void KeyScan(){static unsigned char keyout = 0;//按键行索引static unsigned char keybuf[4][4] = {{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}};/* 按键消抖 */keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN1;keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN2;keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN3;keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN4;/* 更新按键的值 */for (i = 0; i < 4; i++){if ((keybuf[keyout][i] & 0x1F) == 0x1F){//五次检测按键的值都是1keySta[keyout][i] = 1;}else if ((keybuf[keyout][i] & 0x1F) == 0x00) {//五次检测的按键值都是0keySta[keyout][i] = 0;}}/* 按键行索引++ */keyout++;keyout &= 0x03;//到4归零/* 根据按键索引选择行按键进行扫描 */switch (keyout){case 0: KEY_OUT1 = 0; KEY_OUT4 = 1;//选择第一行按键case 1: KEY_OUT2 = 0; KEY_OUT1 = 1;case 2: KEY_OUT3 = 0; KEY_OUT2 = 1;case 3: KEY_OUT4 = 0; KEY_OUT3 = 1;default: break;}}/* 按键动作函数 */void KeyAction(unsigned char keycode){unsigned char i = 0;if (keycode == 0x1B) //ESC{/* 跑表复位 */stopflag = 0;for (i = 0; i < 9; i++){timer[i] = 0;}LcdShowStr(2, 1, "0000000.00s"); LcdShowStr(10, 0, "reset!");}else if (keycode == 0x0D) //回车键跑表走停{if (stopflag == 0){stopflag = 1;LcdShowStr(10, 0, "start!");}else{stopflag = 0;LcdShowStr(10, 0, "stop! "); //多写入一个空格}}}。
51单片机LCD1602液晶显示程序

LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/******************************************************************************
*
*函数名 * 函数功能
: 初始化 LCD 屏 :无 :无
*******************************************************************************
/
#ifndef
LCD1602_4PINS
void LcdInit()
//LCD 初始化子程序
{ LcdWriteCom(0x38); //开显示
//以下程序都是在 VC++6.0 上调试运行过的程序,没有错误,没有警告。 //单片机是 STC89C52RC,但是在所有的 51 52 单片机上都是通用的。51 只是一个学习的基础 平台,你懂得。 //程序在关键的位置添加了注释。 //用//11111111111111111 代表第一个程序。//2222222222222222222222222 代表第二个程序, 以此类推
for(a=1;a>0;a--); } }
//误差 0us
}
/******************************************************************************
*
*函数名 * 函数功能
: LcdWriteCom : 向 LCD 写入一个字节的命令
LCD1602_E = 0;
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1602汇编程序,51单片机汇编程序,仅需修改引脚定义即可。
晶振大小12M,程序测试完全正确。
内部包含写数据、写命令(包括读忙和不读忙)、初始化等子函数。
调用时先给LCD_DAT赋值,给出需要写入的数据或命令,然后调用。
;端口引脚定义区
LCD_RS BIT P2.4 ;1602数据命令选择端口
LCD_RW BIT P2.5 ;1602读写选择端口
LCD_EN BIT P2.6 ;1602使能端口
LCD_DATA EQU P0 ;1602数据端口
;变量声明区
ALL_FLAG EQU 20H ;标志位
LCD_FLAG EQU ALL_FLAG.7 ;1602读忙标志位
LCD_DAT EQU 30H ;1602数据命令字
DELAYED EQU 31H ;延时字
/*****************************************
1602读命令函数,高位存至LCD_LAG中
*****************************************/
LCD_R_DATA:
MOV LCD_DATA,#0FFH
LCD_BUSY: CLR LCD_RS
SETB L CD_RW
NOP
SETB L CD_EN
NOP
MOV Acc,LCD_DATA
MOV C,Acc.7
MOV LCD_FLAG,C
CLR LCD_EN
NOP
JB LCD_FLAG,LCD_BUSY
RET
/*****************************************
1602写数据函数,数据存在LCD_DAT
*****************************************/
LCD_W_DATA:
LCALL LCD_R_DATA
SETB L CD_RS
CLR LCD_RW
NOP
MOV LCD_DATA,LCD_DAT
SETB L CD_EN
NOP
CLR LCD_EN
RET
/***************************************** 1602写命令函数,命令存在LCD_DAT,检测忙信号
*****************************************/ LCD_W_CMD:
LCALL LCD_R_DATA
CLR LCD_RS
CLR LCD_RW
NOP
MOV LCD_DATA,LCD_DAT
SETB L CD_EN
NOP
CLR LCD_EN
RET
/***************************************** 1602写命令函数,命令存在LCD_DAT,不检测忙信号*****************************************/ LCD_CMD:
CLR LCD_RS
CLR LCD_RW
NOP
MOV LCD_DATA,LCD_DAT
SETB L CD_EN
NOP
CLR LCD_EN
RET
/***************************************** 1602初始化函数
*****************************************/ LCD_INIT:
MOV DELAYED,#30
LCALL DELAY_MS
MOV LCD_DAT,#38H
LCALL LCD_CMD
MOV DELAYED,#10
LCALL DELAY_MS
MOV LCD_DAT,#38H
LCALL LCD_CMD
MOV DELAYED,#10
LCALL DELAY_MS
MOV LCD_DAT,#38H
LCALL LCD_CMD
MOV DELAYED,#10
LCALL DELAY_MS
MOV LCD_DAT,#038H
LCALL LCD_W_CMD
MOV LCD_DAT,#08H
LCALL LCD_W_CMD
MOV LCD_DAT,#01H
LCALL LCD_W_CMD
MOV LCD_DAT,#06H
LCALL LCD_W_CMD
MOV LCD_DAT,#0CH
LCALL LCD_W_CMD
RET
/*****************************************
延时函数,延时时间为DELAYED*0.5毫秒0~100毫秒的延时*****************************************/
DELAY_MS:
MOV R7,DELAYED
D1: MOV R6,#0F8H
D2: DJNZ R6,D2
DJNZ R7,D1
RET
/*****************************************
延时函数,延时时间为DELAYED*2微秒0~500微秒的延时*****************************************/
DELAY_US:
MOV R7,A
DU1:
DJNZ R7,DU1
RET。