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;
基于51单片机的lcd1602显示程序模块
这个是我自己编写的基于51单片机控制lcd602显示的库函数,请下载我的头文件,在网上本人还分享了很多热门模块的库函数,都是现成的,欢迎下载!!!!/************************************************************************1,先初始化1602:lcd_init();2,调整显示位置:lcd_pos(hang,lie);3,送显示:lcd_wdat(uchar dat);显示字符lcd_show(uchar dis[]);显示字符串4,清屏为:lcd_wcmd(0x01); //清除lcd内容delay12_ms(2);注:显示的时候必须传送对应的ASK码显示字符串的时候如果超过本行显示范围不会自动跳到第二行占用了P0和P25,P26,P27同时包含delay.c文件必须************************************************************************/#include"myconfig.h"#include"delay.h"#define LCD_RS P26 //1602的命令和数据选择端#define LCD_RW P25 //1602的读写控制端#define LCD_EP P27 //1602是能信号#define LCD_DATE P0 //1602的数据传输或命令端口/****************(外部不操作)测忙程序************************/uchar lcd_bz(){uchar result;LCD_RS =0;LCD_RW =1;LCD_EP =1;_nop_();_nop_();_nop_();_nop_();result =(P0 &0x80);LCD_EP =0;return result;//返回结果,1为忙,0位空闲}/****************(外部不操作)写命令函数************************/void lcd_wcmd(int cmd){while(lcd_bz());LCD_RS =0;LCD_RW =0;LCD_EP =0;_nop_();_nop_();LCD_DATE = cmd;_nop_();_nop_();_nop_();_nop_();LCD_EP =1;_nop_();_nop_();_nop_();_nop_();LCD_EP =0;}/****************设置显示位置************************/void lcd_pos(uchar hang, uchar lie){if(hang ==1)lcd_wcmd(0x80+ lie -1);elselcd_wcmd(0xc0+ lie -1);}/****************1602显示字符************************/void lcd_wdat(uchar dat){while(lcd_bz());LCD_RS =1;LCD_RW =0;LCD_EP =0;LCD_DATE = dat;_nop_();_nop_();_nop_();_nop_();LCD_EP =1;_nop_();_nop_();_nop_();_nop_();LCD_EP =0;}/****************1602显示字符串************************/void lcd_show(uchar dis[]){int i =0;while(dis[i]!='\0'){lcd_wdat(dis[i]);i++;}}/****************1602初始化程序(模式已经确定)************************/ void lcd_init(void){lcd_wcmd(0x38);//16*2显示,5*7点阵,8位数据delay12_ms(1);lcd_wcmd(0x0e);//显示开,关光标delay12_ms(1);lcd_wcmd(0x01);//清除lcd内容delay12_ms(1);lcd_wcmd(0x02);//光标回homedelay12_ms(1);}/************************************************************************ 1,先初始化1602:lcd_init();2,调整显示位置:lcd_pos(hang,lie);3,送显示:lcd_wdat(uchar dat);显示字符lcd_show(uchar dis[]);显示字符串4,清屏为:lcd_wcmd(0x01); //清除lcd内容delay12_ms(2);注:显示的时候必须传送对应的ASK码显示字符串的时候如果超过本行显示范围不会自动跳到第二行占用了P0和P25,P26,P27同时包含delay.c文件必须************************************************************************/ #ifndef__DISP_1602_H#define__DISP_1602_H#include"myconfig.h"/****************(外部不操作)测忙************************/uchar lcd_bz();/****************(外部不操作)写命令函数************************/void lcd_wcmd(int cmd);/****************设置显示位置************************/void lcd_pos(uchar hang, uchar lie);/****************1602显示字符************************/void lcd_wdat(uchar dat);/****************1602显示字符串************************/void lcd_show(uchar dis[]);/****************1602初始化程序(模式已经确定)************************/ void lcd_init(void);#endif。
LCD1602.H51单片机LCD1602显示驱动程序
LCD1602.H(51单片机LCD1602显示驱动程序)/*无敌高氯酸修改函数功能delay_ms(time) 延时time毫秒LCD_init() 初始化清空LCD屏LCD_print(x,y,str)在(x,y)坐标上显示str字符0=;0;i--)for (j=0;j<1140;j++);}/************************************************ *********************函数名称:LCD_print()功能描述:显示字符或字符串入口参数:字符或字符串返回值:无************************************************* *********************/void LCD_print(uchar x,uchar y,uchar *str){LCD_gotoxy(x,y);while(*str!='\0'){LCD_wdata(*str);str++;}}/************************************************** *******************函数名称:LCD_wcommand()功能描述:LCD写指令入口参数:uchar lcd_cmd:命令字,uchar busy_f:忙检测标志位返回值:无************************************************* ********************/void LCD_wcommand(uchar lcd_cmd,busy_f){if (busy_f) Rstatus(); //不忙才执行下个程序Port = lcd_cmd;Rw = 0;En = 0;En = 0;En = 1;}/************************************************ *********************函数名称:LCD_wdata()功能描述:LCD写数据入口参数:uchar wdata:所写数据返回值:无************************************************* ********************/void LCD_wdata(uchar wdata){Rstatus();Port = wdata;Rs = 1;Rw = 0;En = 0; //若晶振速度太高可以在这后加小的延时En = 0; //延时}/************************************************ *********************函数名称:LCD_rdata()功能描述:LCD读数据入口参数:无返回值:所读数据************************************************* ********************/uchar LCD_rdata(void){Rs = 1;Rw = 1;En = 0;En = 0;En = 1;return Port;}/************************************************ *********************函数名称:Rstatus()功能描述:LCD读忙状态入口参数:无返回值:若忙,则等待,不忙则返回Port************************************************* ********************/uchar Rstatus(void){Port = 0xFF;Rs = 0;Rw = 1;En = 0;En = 0;En = 1;while (Port & 0x80); //检测忙信号,不忙则退出等待return(Port);}/************************************************ *********************函数名称:LCD_init()功能描述:LCD初始化入口参数:无返回值:无************************************************* ********************/void LCD_init(void){Port = 0;LCD_wcommand(0x38,0); //三次显示模式设置,不检测忙信号delay_ms(3);LCD_wcommand(0x38,0);delay_ms(3);LCD_wcommand(0x38,0);delay_ms(3);LCD_wcommand(0x38,1); //显示模式设置(0X38双行(5*7),0X34单行(5*10)),0X30单行(5*7);开始要求每次检测忙信号LCD_wcommand(0x08,1); //关闭显示LCD_wcommand(0x01,1); //显示清屏LCD_wcommand(0x06,1); // 显示光标移动设置LCD_wcommand(0x0C,1); // 显示开及光标设置}/************************************************ *********************函数名称:LCD_gotoxy()功能描述:定位到(x,y)位置入口参数:x为行(0~1),y为列(0~15)返回值:无************************************************* ********************/void LCD_gotoxy(uchar x, uchar y){x &= 0x1; //限制x不能大于1,y不能大于15y &= 0xF;if(!x) LCD_wcommand(0x80|y,1);else LCD_wcommand(0xC0|y,1);}。
lcd1602程序 汇编版本
LCALL WR_LCD_CMD
MOV DAT_PORT,#06H ; 光标右移,文字不移
LCALL WR_LCD_CMD
INIT_DS: CLR DS_RST
CLR DS_CLK
SETB DS_RST
MOV DS_DAT,8EH
LCALL WR_DS
MOV R2,#00H
CLR LCD_RS ;选择指令寄存器
SETB LCD_RW ;高电平,读操作
CLR LCD_E ;电平由高到低,执行命令
;=====================DS1302子程序===============================
;---------------------取DS1302数据-------------------------------
;---------------------读DS1302-----------------------------------
RD_DS: MOV R0,#SECOND
MOV R7,#7
MOV R1,#80H ;SECOND ADRESS 80H
SET1: CLR DS_RST
CLR DS_CLK
DS_ADDR EQU 30H
DS_DAT EQU 31H
SECOND EQU 32H
MINUTE EQU 33H
ORG 0000H
LJMP MAIN
ORG 0060H
;=====================初始化程序=================================
51单片机控制LCD液晶1602源代码
void Lcd1602_Clear_All(void);
void Lcd1602_Demo1(void);
void Lcd1602_Demo2(void);
void Delay_ms(unsigned char second);
if(++row==3)
return;
else
{
switch(row)//这种结构保持以后升级到多行显示液晶
_nop_();
LCD_EN=HIGH ;
_nop_();
LCD_EN=LOW;
LCD_DATA_PORT=0xFF; //prevent port is 0.
}
//===========================
case 2:Lcd1602_Write_Command(0x80+0x40);break; //将数据地址指针定位到第二行
default: break;
}
}
//==================================================
{
while(1)
{
Lcd1602_Demo1();
// Lcd1602_Demo2();
}
}
void Lcd1602_Ini(void)
{
Delay_ms(20);
Lcd1602_Write_Command_Nocheck(0x38);//设定LCD为16*2显示,5*7点阵,8位数据接口
{
Lcd1602_Write_String(row,column," ");
1602液晶电子时钟程序51单片机
1602液晶电子时钟程序[日期:2009-06-11 ] [来源:net 作者:佚名] [字体:大中小] (投递新闻)连线图:; DB0---DPROT.0 DB4---DPROT.4 RS-------------P1.2; DB1---DPROT.1 DB5---DPROT.5 RW-------------P1.3; DB2---DPROT.2 DB6---DPROT.6 E--------------P1.4; DB3---DPROT.3 DB7---DPROT.7 VLCD接10K可调电阻到GND*#include "reg52.h"//头文件#include "intrins.h"#define uchar unsigned char//宏定义#define uint unsigned int//宏定义sbit RS=P1^2;//定义I/O的硬件接口sbit RW=P1^3;sbit E=P1^4;sbit led_1=P1^7;//;;;LED秒闪烁uchar Hours=0;//定义小时uchar Minutes=0;//定义分钟uchar Seconds=0;//定义秒bit Seconds_Scintillation=1;//定义秒闪烁标志#define DPDR P0//并行数据接口定义uchar code DispTab_1[]={'0','1','2','3','4','5','6','7','8','9'};//1602:0-9 数字uchar code DispTab_2[]={'A','B','C','D','E','a','b','c','d','e'};//1602:A-e 字母uchar DispBuf[8]; //8字节的显示缓冲区char char_char_1[]={" "};//定义字符串char char_char_2[]={" "};//定义空字符串void delay(uint z)//1ms延时{uchar x,x1;for(;z>0;z--){for(x=0;x<114;x++){for(x1=0;x1<1;x1++);}}}void Timer0() interrupt 1{static uchar Count_50;//uchar temp;TH0=0xb7;TL0=0xff;//定时时间为20ms,每20ms中断一次Count_50++;if(Count_50==50)//20ms*50=1秒{ Seconds_Scintillation=~Seconds_Scintillation; led_1=~led_1;Count_50=0;Seconds++;if(Seconds==60){Seconds=0;Minutes++;if(Minutes==60){Minutes=0;Hours++;if(Hours==24){Hours=0;}}}}if(Seconds_Scintillation==1)//秒闪烁标志判断DispBuf[6]=':';elseDispBuf[6]=' ';DispBuf[0]=Hours/10;//转换成10进制显示DispBuf[1]=Hours%10;DispBuf[2]=Minutes/10;DispBuf[3]=Minutes%10;DispBuf[4]=Seconds/10;DispBuf[5]=Seconds%10;temp=DispBuf[0];DispBuf[0]=DispTab_1[temp];//查表取字符temp=DispBuf[1];DispBuf[1]=DispTab_1[temp];temp=DispBuf[2];DispBuf[2]=DispTab_1[temp];temp=DispBuf[3];DispBuf[3]=DispTab_1[temp];temp=DispBuf[4];DispBuf[4]=DispTab_1[temp];temp=DispBuf[5];DispBuf[5]=DispTab_1[temp];}void write_Directive(uchar a)//写指令{RS=0;RW=0;delay(1);E=0;DPDR=a;delay(1);E=1;delay(1);E=0;delay(1);}void write_Data(uchar a)//写数据{RS=1;RW=0;delay(1);E=0;DPDR=a;delay(1);E=1;delay(1);E=0;delay(1);}void init()//初始化{ uchar i;TMOD=0x01;TH0=0xb7;TL0=0xff;//定时时间为20ms,每20ms中断一次ET0=1; //开T0中断EA=1; //开总中断TR0=1; //T0开始运行DispBuf[6]=':';delay(15);write_Directive(0x38);delay(5);write_Directive(0x38);delay(5);write_Directive(0x38);write_Directive(0x01);write_Directive(0x02);//初始化后数据地址为0x80;即第一行,第一个位置write_Directive(0x0c);//不显示光标write_Directive(0x80+0x40);//第二行第一位地址for(i=0;i<16;i++){write_Data(char_char_1[i]);//显示字符串" "}}void write_Data_String()//显示时间函数{write_Directive(0x80+0x04);//第一行,第五个位置地址write_Data(DispBuf[0]);//第一行,第五个位置write_Data(DispBuf[1]);//第一行,第六个位置write_Data(DispBuf[6]);//第一行,第七个位置write_Data(DispBuf[2]);//第一行,第八个位置write_Data(DispBuf[3]);//第一行,第九个位置write_Data(DispBuf[6]);//第一行,第十个位置write_Data(DispBuf[4]);//第一行,第十一个位置write_Data(DispBuf[5]);//第一行,第十二个位置}void main(){init();while(1){write_Data_String();//调用写连续的16 个字符,1表示第一行;2表示第二行delay(100);//延时100ms,扫描一次}}液晶显示器以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用。
基于51单片机的用 LCD1602 显示时钟的程序
用LCD1602 显示的时钟2012-04-30 15:04有这样一个题目:求一个为51 单片机编写的LCD 电子时钟的设计,简单就好!希望说一下怎么设计这个时钟,都需要些什么东西,最重要的——把这个设计需要的程序写出来。
设计的任务:以单片机控制的时钟,在LCD 显示器上显示当前的时间。
设计的基本要求:1.使用文字型LCD 显示器显示当前时间。
2.显示格式为“时时:分分:秒秒”。
3.用4个功能键操作来设置当前时间。
各个功能键的功能如下:K1:进入设置现在的时间。
K2:设置小时。
K3:设置分钟。
K4:确认完成设置。
4. 程序执行后工作指示灯LED 闪烁,表示程序开始执行,LCD 显示“00:00:00”,然后开始计时。
题目链接:/question/416705477.html//==================================================提到设计时钟,很多人都想到了时钟芯片DS1302,都说它简单、准确。
其实,这是个误区。
仅仅使用一般的单片机,简单的编程,达到相同DS1302 的准确度,并不是难事。
如果不要求计算平闰年、不要求分清大小月、不要求计算星期几,只是要求一个简单的时钟(及日历),用DS1302,就是自寻烦恼。
大家可以打开题目链接,看看其中的一些答案,就可以看出使用DS1302 是多么的繁琐了,简直就是一场噩梦。
做而论道以前就使用普通的单片机和LCD1602 设计过《时钟与日历》,程序设计的非常合理,时间精度就完全取决于晶振的精度。
设计出来的时钟,几个月都差不上一秒。
针对这个题目,做而论道翻出了以前的设计,删节了一些不需要的功能,设计出了符合题目要求的时钟,用PROTEUS 仿真截图如下:程序用C 语言编写,全部代码如下://---------------------------------------------------#include<reg52.h>#define uchar unsigned char#define uint unsigned int#define KEY_IO P3#define LCD_IO P0sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;sbit SPK = P1^2;sbit LED = P2^4;bit new_s, modify = 0;char t0, sec = 50, min = 59, hour = 23;char code LCD_line1[] = "Designed by ZELD"; char code LCD_line2[] = "Timer: 00:00:00 "; char Timer_buf[] = "23:59:50";//---------------------------------------------------void delay(uint z){uint x, y;for(x = z; x > 0; x--) for(y = 100; y > 0; y--);//---------------------------------------------------void W_LCD_Com(uchar com) //写指令{LCD_RS = 0; LCD_IO = com; // LCD_RS和R/W都为低电平时,写入指令LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲}//---------------------------------------------------void W_LCD_Dat(uchar dat) //写数据{LCD_RS = 1; LCD_IO = dat; // LCD_RS为高、R/W为低时,写入数据LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲}//---------------------------------------------------void W_LCD_STR(uchar *s) //写字符串{while(*s) W_LCD_Dat(*s++);}//---------------------------------------------------void W_BUFF(void) //填写显示缓冲区{Timer_buf[7] = sec % 10 + 48; Timer_buf[6] = sec / 10 + 48;Timer_buf[4] = min % 10 + 48; Timer_buf[3] = min / 10 + 48;Timer_buf[1] = hour % 10 + 48;Timer_buf[0] = hour / 10 + 48;W_LCD_Com(0xc0 + 7); W_LCD_STR(Timer_buf);}//---------------------------------------------------uchar read_key(void){uchar x1, x2;KEY_IO = 255;x1 = KEY_IO;if (x1 != 255) {delay(100);x2 = KEY_IO;if (x1 != x2) return 255;while(x2 != 255) x2 = KEY_IO;if (x1 == 0x7f) return 0;else if (x1 == 0xbf) return 1;else if (x1 == 0xdf) return 2;else if (x1 == 0xef) return 3;else if (x1 == 0xf7) return 4;}return 255;//---------------------------------------------------void Init(){LCD_RW = 0;W_LCD_Com(0x38); delay(50);W_LCD_Com(0x0c);W_LCD_Com(0x06);W_LCD_Com(0x01);W_LCD_Com(0x80); W_LCD_STR(LCD_line1);W_LCD_Com(0xC0); W_LCD_STR(LCD_line2);TMOD = 0x01; //T0定时方式1TH0 = 0x4c;TR0 = 1; //启动T0PT0 = 1; //高优先级, 以保证定时精度ET0 = 1;EA = 1;}//---------------------------------------------------void main(){uint i, j;uchar Key;Init();while(1) {//-------------------------------if (new_s) { //如果出现了新的一秒, 修改时间new_s = 0; sec++; sec %= 60;if(!sec) { min++; min %= 60;if(!min) { hour++; hour %= 24;}}W_BUFF(); //写显示//-------------------------------if (!sec && !min) { //整点报时for (i = 0; i < 200; i++) {SPK = 0; for (j = 0; j < 100; j++);SPK = 1; for (j = 0; j < 100; j++);} }}//-------------------------------Key = read_key(); //读出按键switch(Key) { //分别处理四个按键case 0: modify = 1; break;case 1: if(modify) {min++; min %= 60; W_BUFF(); break;}case 2: if(modify) {hour++; hour %= 24; W_BUFF(); break;}case 3: modify = 0; break;} }}//---------------------------------------------------void timer0(void) interrupt 1 //T0中断函数, 50ms执行一次{TH0 = 0x4c;t0++; t0 %= 20; //20, 一秒钟if(t0 == 0) {new_s = 1; LED = ~LED;}if(modify) LED = 0;}//===================================================呵呵,全部程序,也不过120 行左右。
基于51单片机的液晶LCD1602显示程序源代码(带LCD1602液晶接口电路))
液晶LCD1602显示字符和数字程序源代码/***********************液晶LCD1602测试程序源代码*************************单片机型号:STC15W4K56S4,内部晶振:22.1184M。
功能:液晶LCD1602显示功能测试。
操作说明:液晶LCD1602显示字符和倒计时。
**************************************************************************/#include "stc15.h" //包含头文件stc15.h#include <intrins.h> //包含头文件intrins.h#define Busy 0x80 //LCD忙sbit LCD_D0 = P0^0; //LCD_D0对应P0.0sbit LCD_D1 = P0^1; //LCD_D1对应P0.1sbit LCD_D2 = P0^2; //LCD_D2对应P0.2sbit LCD_D3 = P0^3; //LCD_D3对应P0.3sbit LCD_D4 = P0^4; //LCD_D4对应P0.4sbit LCD_D5 = P0^5; //LCD_D5对应P0.5sbit LCD_D6 = P0^6; //LCD_D6对应P0.6sbit LCD_D7 = P0^7; //LCD_D7对应P0.7sbit LCD_RS = P1^0; //LCD_RS对应P1.0sbit LCD_RW = P1^1; //LCD_RW对应P1.1sbit LCD_EN = P3^4; //LCD_EN对应P3.4void delay(unsigned int t); //delay延时函数void delay_us(unsigned int t); //delay_us延时函数void delay_ms(unsigned int t); //delay_ms延时函数void Delay5Ms(void); //5Ms延时函数void GPIO_1602_Configuration(void); //LCD1602液晶IO口初始化void WriteDataLCD(unsigned char WDLCD); //LCD写数据函数void WriteCommandLCD(unsigned char WCLCD,BuysC); //LCD写命令函数unsigned char ReadDataLCD(void); //LCD读数据函数unsigned char ReadStatusLCD(void); //LCD读状态函数void LCDInit(void); //LCD初始化void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);//LCD显示一个字符void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);//LCD显示一个字符串unsigned char code welcome[] = {"Hello My Friends"};//液晶LCD1602显示Hello My Friendsunsigned char code countdown[] = {"CountDown: S"};//液晶LCD1602显示CountDown: Svoid delay(unsigned int t) //delay延时函数{while(t--);}void delay_us(unsigned int t) //delay_us延时函数{unsigned char i;while(t--){i=3;while(i--)delay(1);}}void delay_ms(unsigned int t) //delay_ms延时函数{while(t--){delay_us(t);}}void Delay5Ms(void) //5ms延时函数{unsigned int TempCyc = 3552;while(TempCyc--);}void GPIO_1602_Configuration(void) //LCD1602液晶IO口初始化{P0M1 = P3M1&0x00;P0M0 = P3M0&0x00;P1M1 = P3M1&0xfc;P1M0 = P3M0&0xfc;P3M1 = P4M1&0xef;P3M0 = P4M0&0xef;}unsigned char ReadStatusLCD(void) //测试LCD忙碌状态{LCD_D7 = 1; //LCD的D7置1LCD_RS = 0; //LCD管脚RS设置成低电平LCD_RW = 1; //LCD管脚RW设置成高电平LCD_EN = 0; //LCD管脚E设置成低电平LCD_EN = 0; //LCD管脚E设置成低电平LCD_EN = 1; //LCD管脚E设置成高电平while(LCD_D7); //检测忙信号return(Busy); //表示当前忙}void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC为0时忽略忙检测{if(BuysC) ReadStatusLCD(); //根据需要检测忙LCD_EN = 0; //LCD管脚E设置成低电平_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_RS = 0; //LCD管脚RS设置成低电平LCD_RW = 0; //LCD管脚RW设置成低电平_nop_(); //空操作,延时_nop_(); //空操作,延时P0 = WCLCD; //将数据送入P0口,即写入指令或地址_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_EN = 1; //E置高电平_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_EN = 0;//当E由高电平跳变成低电平时,液晶模块开始执行命令}void WriteDataLCD(unsigned char WDLCD) //LCD写数据函数{ReadStatusLCD(); //读取LCD状态LCD_EN = 0; //LCD管脚E设置成低电平_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_RS = 1; //LCD管脚RS设置成高电平LCD_RW = 0; //LCD管脚RW设置成低电平P0 = WDLCD;//将数据送入P0口,即将数据写入液晶模块_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_EN = 1; //E置高电平_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_EN = 0;//当E由高电平跳变成低电平时,液晶模块开始执行命令}void LCDInit(void) //LCD初始化{WriteCommandLCD(0x38,0); //三次显示模式设置,不检测忙信号Delay5Ms();WriteCommandLCD(0x38,0);Delay5Ms();WriteCommandLCD(0x38,0);Delay5Ms();WriteCommandLCD(0x38,0);WriteCommandLCD(0x08,1); //关闭显示WriteCommandLCD(0x01,1); //显示清屏WriteCommandLCD(0x06,1); //显示光标移动设置WriteCommandLCD(0x0C,1); //显示开及光标设置}void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData){Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1 if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;X |= 0x80; //算出指令码WriteCommandLCD(X,0); //这里不检测忙信号,发送地址码WriteDataLCD(DData); //发送数据}void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData){unsigned char ListLength;ListLength = 0;Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1 while (DData[ListLength]>=0x20) //若到达字串尾则退出{if (X <= 0xF) //X坐标应小于0xF{DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符ListLength++;X++;}}}void main(void){GPIO_1602_Configuration(); //LCD1602液晶IO口初始化delay_ms(10); //延时LCDInit(); //LCD1602初始化delay_ms(10); //延时DisplayListChar(0,0,welcome); //LCD1602显示Hello My Friends delay_ms(10); //延时DisplayListChar(0,1,countdown); //LCD1602显示CountDown: S delay_ms(10); //延时DisplayOneChar(14,1,0x39); //LCD1602显示9delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x38); //LCD1602显示8delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x37); //LCD1602显示7delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x36); //LCD1602显示6delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x35); //LCD1602显示5delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x34); //LCD1602显示4delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x33); //LCD1602显示3delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x32); //LCD1602显示2delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x31); //LCD1602显示1delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x30); //LCD1602显示0delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时while(1){;}}程序源代码是编译通过并在电路板上测试过参考液晶LCD1602接口电路图该程序的实际运行效果。
(整理)LCD1602汇编程序.
(整理)LCD1602汇编程序.LCD1602汇编程序;* 描述: LCD1602 滚动显示*;* 显示方式:*;* 1、从左到右逐字显示,闪动二次,清屏。
*;* 2、再从右到左逐字显示,闪动二次,清屏。
*;* 3、周期性地重复上述显示方式。
*;************************************************************** ***** LCD_RS EQU P2.0LCD_RW EQU P2.1LCD_EN EQU P2.2;************************************************************** ***** ORG 0000HAJMP MAINORG 0030H;************************************************************** ***** MAIN:MOV SP,#60HMOV R4,#02H ;设置闪烁次数ACALL LCD_INITMAIN1:ACALL LCDSET1MOV DPTR,#CHAR1ACALL WRITE1 ;MOV A,#0C0H ;显示第二行左边第一位位置ACALL LCD_CMDMOV DPTR,#CHAR2 ;显示ACALL WRITE1ACALL DELAY4 ;延时ACALL DELAY4ACALL SHAN ;闪烁两次ACALL LCDSET2MOV DPTR,#CHAR3 ;ACALL WRITE1MOV A,#0C0H ;显示第二行右边第一位位置ACALL LCD_CMDMOV DPTR,#CHAR4 ;显示ACALL WRITE1ACALL DELAY4 ;延时ACALL DELAY4ACALL SHAN ;闪烁两次ACALL MAIN1;************************************************************** *;LCD初始化设定子程序;************************************************************** * LCD_INIT:ACALL DELAY5MS ;延时15MSACALL DELAY5MS ;等待LCD 电源稳定ACALL DELAY5MSMOV A,#38H ;16*2 显示,5*7 点阵,8 位数据ACALL LCD_CMD_NC ;不进行LCD 忙检测ACALL DELAY5MSMOV A,#38H ;16*2 显示,5*7 点阵,8 位数据ACALL LCD_CMD_NC ;不进行LCD 忙检测ACALL DELAY5MSMOV A,#38H ;16*2 显示,5*7 点阵,8 位数据ACALL LCD_CMD_NC ;不进行LCD 忙检测ACALL DELAY5MSMOV A,#08H ;显示关ACALL LCD_CMD ;进行LCD 忙检测MOV A,#01H ;清除屏幕ACALL LCD_CMD ;进行LCD忙检测MOV A,#06H ;移动光标ACALL LCD_CMD ;进行LCD 忙检测MOV A,#0CH ;显示开,关光标ACALL LCD_CMD ;进行LCD 忙检测RET;************************************************************** * ;显示位置与移动光标设定;************************************************************** * LCDSET1:MOV A,#01H ;清除屏幕ACALL LCD_CMDACALL DELAY5MSMOV A,#06H ;移动光标(光标加1)ACALL LCD_CMDACALL DELAY5MSMOV A,#80H ;显示第一行左边第一位位置ACALL LCD_CMDACALL DELAY5MSRETLCDSET2:MOV A,#01H ;清除屏幕ACALL LCD_CMDACALL DELAY5MSMOV A,#06H ;移动光标(光标减1)ACALL LCD_CMDACALL DELAY5MSMOV A,#80H ;显示第一行右边第一位位置ACALL LCD_CMDACALL DELAY5MSRET;************************************************************** * ;写指令数据到LCD;RS=L,RW=L,D0-D7=指令码,E=高脉冲;************************************************************** * LCD_CMD:ACALL CHECKBUSYLCD_CMD_NC:CLR LCD_RSCLR LCD_RWMOV P0,ASETB LCD_ENNOPNOPNOPNOPCLR LCD_ENRET;************************************************************** * ; 发送字符串子程序;************************************************************** * WRITE1:MOV R0,#16WRITE0:CLR AMOVC A,@A+DPTRINC DPTRACALL LCD_WDATACALL DELAY ;加延时形成滚动效果DJNZ R0,WRITE0RET;************************************************************** * ;写显示数据到LCD;RS=H,RW=L,D0-D7=数据,E=高脉冲;************************************************************** * LCD_WDATA:ACALL CHECKBUSYSETB LCD_RSCLR LCD_RWMOV P0,ASETB LCD_ENNOPNOPNOPNOPCLR LCD_ENRET;************************************************************** * ;检测LCD 控制器忙状态;读数据;RS=L,RW=H,E=H,输出:D0-D7=数据;************************************************************** * CHECKBUSY:PUSH ACCMOV P0,#0FFHCLR LCD_RSSETB LCD_RWSETB LCD_ENBUSYLOOP:NOPJB P0.7,BUSYLOOPCLR LCD_ENPOP ACCRET;************************************************************** * ;闪烁子程序;************************************************************** * SHAN:MOV A,#08H ;关闭显示ACALL LCD_CMDACALL DELAY4MOV A,#0CH ;开显示,关闭光标ACALL LCD_CMDACALL DELAY4DJNZ R4,SHANMOV R4,#02H ;设置闪烁次数RET;************************************************************** * ;延时120MS 子程序;发送字符串时使用;************************************************************** * DELAY:MOV R7,#240DL1: MOV R6,#250DL2: DJNZ R6,DL2DJNZ R7,DL1RET;************************************************************** * ;延时800MS 子程序;闪烁时使用;************************************************************** * DELAY4:MOV R0,#40DL3: MOV R1,#100DL4: MOV R2,#100DL5: DJNZ R2,DL5DJNZ R1,DL4DJNZ R0,DL3RET;************************************************************** * ;延时5MS子程序;LCD初始化使用;************************************************************** * DELAY5MS:MOV R1,#10DL6: MOV R2,#249DL7: DJNZ R2,DL7DJNZ R1,DL6RET;************************************************************** * ;延时1MS子程序;************************************************************** * DELAY1MS:MOV R6,#14H ;20DL8: MOV R7,#19H ;25DL9: DJNZ R7,DL9DJNZ R6,DL8RET;************************************************************** * CHAR1:DB "Welcome to Cras-"CHAR2:DB " yBoye WorkGroup"CHAR3:DB " QQ: 15910380 "CHAR4:DB "TEL: 139********";************************************************************** *END12864汇编程序X EQU 26H ;LCD 地址变量RS EQU P2.0RW EQU P2.1EN EQU P2.2PSB EQU P2.3RST EQU P2.5ORG 0000HJMP MAINORG 0003H ;外部中断INT0入口地址MAIN:MOV SP,#40HMOV A,#00HMOV R0,#20HLOOP0: MOV @R0,A ;20H-26H清零INC R0CJNE R0,#27H,LOOP0MOV IE,#81H ;允许总中断中断,使能INT0 外部中断MOV TCON,#01H ;触发方式为脉冲负边沿触发SETB RSTNOPSETB PSB ;8位数据,并口CALL SET_LCD ;初始化TS12864mCALL MENU1CALL MENU2CALL MENU3CALL MENU4LOOP1:MOV A,22HCJNE A,#40H,LOOP2LOOP2: CJNE A,#04H,LOOP3LOOP3: JMP LOOP1;====================================== =======; LCD 初始化设置;====================================== =======-SET_LCD:CLR ENMOV A,#34H ;34H--扩充指令操作CALL WCOMMOV A,#30H ;30H--基本指令操作CALL WCOMMOV A,#0CH ;开显示,关光标,CALL WCOMMOV A,#01H ;清除LCM 显示屏CALL WCOMRET;====================================== ============= ;在LCM 各行显示信息字符;====================================== ============= LCD_SHOW:CJNE A,#1,LINE2 ;判断是否为第一行LINE1: MOV A,#80H ;设置LCD 的第一行地址CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#80H ;设置LCD 的第一行地址CALL WCOM ;写入命令JMP FILLLINE2: CJNE A,#2,LINE3 ;判断是否为第三行MOV A,#090H ;设置LCD 的第三行地址CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#090H ;设置LCD 的第三行地址CALL WCOMJMP FILLLINE3: CJNE A,#3,LINE4 ;判断是否为第三行MOV A,#088H ;设置LCD 的第三行地址CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#088H ;设置LCD 的第三行地址CALL WCOMJMP FILLLINE4: CJNE A,#4,LINE5 ;判断是否为第三行MOV A,#098H ;设置LCD 的第三行地址CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#098H ;设置LCD 的第三行地址CALL WCOMFILL: CLR A ;填入字符MOVC A,@A+DPTR ;由消息区取出字符CJNE A,#0,LC1 ;判断是否为结束码LINE5: RETLC1: CALL WDA TA ;写入数据INC DPTR ;指针加1JMP FILL ;继续填入字符RET;====================================== =========== ;清除该行LCM 的字符;====================================== =========== CLR_LINE:MOV R0,#16CL1: MOV A,#' 'CALL WDATADJNZ R0,CL1RET;====================================== ============ ;LCM 显示工作菜单信息;====================================== ============ MENU1:MOV DPTR,#MENU1AMOV A,#1 ;在第一行显示信息CALL LCD_SHOWRETMENU1A: DB "MUC 控制GPRS模块",0MENU2:MOV DPTR,#MENU2AMOV A,#2 ;在第二行显示信息CALL LCD_SHOWRETMENU2A: DB "TEL:139********",0MENU3:MOV DPTR,#MENU3AMOV A,#3 ;在第三行显示信息CALL LCD_SHOWRETMENU3A: DB "方案设计: 龚伟",0MENU4:MOV DPTR,#MENU4AMOV A,#4 ;在第四行显示信息CALL LCD_SHOWRETMENU4A: DB "程序编写: 靳鹏",0;====================================== ======== ; 写指令使能子程序;RS=L,RW=L,D0-D7=指令码,E=高脉冲;====================================== ======== WCOM:MOV P0,ACLR RSCLR RWSETB ENCALL DELAY0CLR ENRET;====================================== ======= ;写数据使能子程序;RS=H,RW=L,D0-D7=数据,E=高脉冲;=============================================WDATA:MOV P0,ASETB RSCLR RWSETB ENCALL DELAY0CLR ENRETDELAY0: MOV R7,#250 ;延时500微秒DJNZ R7,$RET END。
- 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。