在LCD1602上显示0--99999 源程序
- 格式:docx
- 大小:17.46 KB
- 文档页数:4
单片机LCD1602显示字符和数字的汇编程序(无聊原创)1,单片机和LCD1602的连线,和程序结果显示如下图:2,LCD第一行显示字符XIAORENGUANG第二行显示RAM中40H到46H中的数字。
程序如下:ORG 0000HAJMP MAINRS EQU P2.4RW EQU P2.5E EQU P2.6MAIN: MOV SP,#60HMOV 40H,#01HMOV 41H,#02HMOV 42H,#03HMOV 43H,#04HMOV 44H,#05HMOV 45H,#06HMOV 46H,#07HACALL DD1 ;DD1是LCD初始化MOV DPTR,#TABLE1ACALL DD2;DD2是LCD第一行显示TABLE1ACALL PPP ;PPP是LCD第二行显示RAM中40H到46H中的数据SJMP $DD1: MOV p0,#01H ;清屏CALL ENABLEMOV p0,#38H ;显示功能CALL ENABLEMOV p0,#0FH ;显示开关控制CALL ENABLEMOV p0,#06H ;+1CALL ENABLERETDD2: MOV p0,#80H;第一行的开始位置cALL ENABLECALL WRITE1;到TABLE1取码?RETDD3: MOV p0,#0C0H;第二行的位置CALL ENABLECALL WRITE1;到TABLE2 取码RETENABLE: CLR RS ;送命令CLR RWCLR ECALL DELAYSETB ERETWRITE1: MOV R1,#00H ;显示table中的值A1: MOV A,R1;到table取码MOVC A,@A+DPTRcall wRITE2 ;显示到lcdINC R1CJNE A,#00H,A1 ;是否到00hRETWRITE2:MOV p0,A ;显示SETB RSCLR RWCLR ECALL DELAYSETB ERET(动态显示频率、幅度核心程序设计思想:可以利用如下程序)MOV 40H,#01HMOV 41H,#02HMOV 42H,#03H)MOV R1,#40H ;显示table中的值MOV A,R1;到table取码MOVC A,@A+DPTRMOV P0,AINC R1LJMP LOOPDELAY: P USH ACCMOV A,R4MOV R4,#05D1: MOV R5,#0FFHDJNZ R5,$DJNZ R4,D1MOV R4,APOP ACCRETPPP: M OV p0,#0C0H;第二行的位置CALL ENABLEMOV DPTR,#TAB;显示CALL WRITE3;到TABLE2 取码RETWRITE3: MOV R1,#40H ;显示table中的值MOV R7,#07HA2: MOV A,@R1;到table取码MOVC A,@A+DPTRcall wRITE2 ;显示到lcdINC R1DJNZ R7,A2 ;是否到00hRETtable1: db"XIAORENGUANG ",00HTAB: DB 30H, 31H, 32H, 33HDB 34H, 35H, 36H, 37HDB 38H, 39HEND。
/***********************DA源程序*****************************************/#include<reg52.h>#include"lm1602.h"#include<intrins.h>sbit Key0 = P2^7;sbit Key1 = P2^0;sbit Key2 = P2^1;sbit Key3 = P2^2;sbit Key4 = P2^3;sbit OE = P3^6;bit flag = 0;unsigned char Square[]="Square Wave"; //方波unsigned char Triangular[]="Triangular Wave"; //三角波unsigned char Sawtooth[]="Sawtooth Wave"; //锯齿波unsigned char Sine[]="Sine Wave";unsigned char Frequency[]="Freq:";unsigned char Hz[]="Hz";unsigned char Cycle[]="25000";//unsigned char PWM[]="PWM:50%";unsigned int X = 0;unsigned char code sin[]={125,128,131,134,138,141,144,147,150,153,156,159, 162,165,168,171,174,177,180,182,185,188,191,193,196,198,201,203,206,208,211,213,215,217,219,221,223,225,227,229,231,232,234,235,237,238,239,241,242,243,244,245,246,246,247,248,248,249,249,250,250,250,250,250,250,250,250,249,249,248,248,247,246,246,245,244,243,242,241,239,238,237,235,234,232,231,229,227,225,223,221,219,217,215,213,211,208,206,203,201,198,196,193,191,188,185,182,180,177,174,171,168,165,162,159,156,153,150,147,144,141,138,134,131,128,125,122,119,116,112,109,106,103,100,97,94,91,88,85,82,79,76,73,70,68,65,62,59,57,54,52,49,47,44,42,39,37,35,33,31,29,27,25,27,29,27,25,23,21,19,18,16,15,13,12,11,9,8,7,6,5,4,4,3,2,2,1,1,0,0,0,0,0,0,0,0,1,1,2,2,3,4,4,5,6,7,8,9,11,12,13,15,16,18,19,21,23,25,27,29,31,33,35,37,39,42,44,47,49,52,54,57,59,62,65,68,70,73,76,79,82,85,88,97,94,97,100,103,106,109,112,116,119,122};void Delay(unsigned int num){unsigned int i;for(i=0;i<num;i++);}void SanJiao(unsigned char num){unsigned char dat =0;LCD_Write_String(0x80,Triangular);while(1){P1 = dat++;Delay(num);if(dat==0xff)flag = 1;if(Key0==0){Delay(5000);if(Key0==0)break;}while(flag){P1 = dat--;Delay(num);if(dat==0)flag = 0;if(Key0==0){Delay(5000);if(Key0==0)break;}}if(Key1==0){Delay(5000);if(Key1==0){num = num+5;X = num*500;Cycle[0] = X/10000+0x30;Cycle[1] = X%10000/1000+0x30;Cycle[2] = X%1000/100+0x30;Cycle[3] = X%100/10+0x30;Cycle[4] = X%10+0x30;LCD_Write_String(0xc5,Cycle);}}if(Key2==0){Delay(5000);if(Key2==0){num = num-5;X = num*500;Cycle[0] = X/10000+0x30;Cycle[1] = X%10000/1000+0x30;Cycle[2] = X%1000/100+0x30;Cycle[3] = X%100/10+0x30;Cycle[4] = X%10+0x30;LCD_Write_String(0xc5,Cycle);}}}}void JuChi(unsigned char num){unsigned char dat =0;LCD_Write_String(0x80,Sawtooth);while(1){P1 = dat++;if(dat==0xff)dat = 0;Delay(num);if(Key0==0){Delay(5000);if(Key0==0)break;}if(Key1==0){Delay(5000);if(Key1==0){num = num+5;X = num*255;Cycle[0] = X/10000+0x30;Cycle[1] = X%10000/1000+0x30;Cycle[2] = X%1000/100+0x30;Cycle[3] = X%100/10+0x30;Cycle[4] = X%10+0x30;LCD_Write_String(0xc5,Cycle);}}if(Key2==0){Delay(5000);if(Key2==0){num = num-5;X = num*255;Cycle[0] = X/10000+0x30;Cycle[1] = X%10000/1000+0x30;Cycle[2] = X%1000/100+0x30;Cycle[3] = X%100/10+0x30;Cycle[4] = X%10+0x30;LCD_Write_String(0xc5,Cycle);}}}}void ZhengXuan(unsigned char num){unsigned char i=0;LCD_Write_String(0x84,Sine);while(1){P1 = sin[i++];Delay(num);if(i==255)i=0;if(Key0==0){Delay(5000);if(Key0==0)break;}if(Key1==0){Delay(5000);if(Key1==0){num = num+5;X = num*255;Cycle[0] = X/10000+0x30;Cycle[1] = X%10000/1000+0x30;Cycle[2] = X%1000/100+0x30;Cycle[3] = X%100/10+0x30;Cycle[4] = X%10+0x30;LCD_Write_String(0xc5,Cycle);}}if(Key2==0){Delay(5000);if(Key2==0){num = num-5;X = num*255;Cycle[0] = X/10000+0x30;Cycle[1] = X%10000/1000+0x30;Cycle[2] = X%1000/100+0x30;Cycle[3] = X%100/10+0x30;Cycle[4] = X%10+0x30;LCD_Write_String(0xc5,Cycle);}}}}void FangBo(unsigned int num){unsigned char dat=0xff;LCD_Write_String(0x80,Square);while(1){P1 = dat;Delay(num);P1 = ~dat;Delay(num);if(Key0==0){Delay(1000);if(Key0==0);break;}if(Key1==0){Delay(5000);if(Key1==0){num = num+3000;X = num;Cycle[0] = X/10000+0x30;Cycle[1] = X%10000/1000+0x30;Cycle[2] = X%1000/100+0x30;Cycle[3] = X%100/10+0x30;Cycle[4] = X%10+0x30;LCD_Write_String(0xc5,Cycle);}}if(Key2==0){Delay(5000);if(Key2==0){num = num-3000;X = num;Cycle[0] = X/10000+0x30;Cycle[1] = X%10000/1000+0x30;Cycle[2] = X%1000/100+0x30;Cycle[3] = X%100/10+0x30;Cycle[4] = X%10+0x30;LCD_Write_String(0xc5,Cycle);}}}}void main(void){unsigned char i=0;LCD_Init();LCD_Write_String(0xc0,Frequency);LCD_Write_String(0xca,Hz);OE = 0;while(1){if(Key1==0)SanJiao(2);if(Key4==0)JuChi(2);if(Key3==0)ZhengXuan(2);if(Key2==0)FangBo(30000);}}/*******************************************************1602.c文件************/ #include"lm1602.h"void delay_us(unsigned int num){unsigned int i;for(i=0;i<num;i++);}void write_cmd(unsigned char dd){c_rs=0;c_rw=0;c_e=0;delay_us(50);P0=dd;c_e=1;delay_us(50);c_e=0;delay_us(50);}void write_dat(unsigned char dd){c_rs=1;c_rw=0;c_e=0;delay_us(50);P0=dd;c_e=1;delay_us(50);c_e=0;delay_us(50);}void LCD_Init( ){delay_us(200);write_cmd(0x38);delay_us(200);write_cmd(0x38);delay_us(200);write_cmd(0x38);delay_us(200);write_cmd(0x08);delay_us(200);write_cmd(0x01);delay_us(200);write_cmd(0x06);delay_us(200);write_cmd(0x0c);}void LCD_Write_String(unsigned char x,unsigned char *s){write_cmd(x);while (*s){write_dat(*s);s++;}}void LCD_Write_Char(unsigned char x,unsigned char Data){write_cmd(x);write_dat(Data);}/************************lcd.h封装模块********************************/ #ifndef __LM1602_H__#define __LM1602_H__#include<reg52.h>#include<intrins.h>sbit c_rs = P2^4;sbit c_rw = P2^5;sbit c_e = P2^6;void LCD_Write_Char(unsigned char x,unsigned char Data); void LCD_Write_String(unsigned char x,unsigned char *s); void LCD_Init(void);#endif仿真图。
HD44780内置了DDRAM、CGROM和CGRAM。
CGROM和CGRAM就是内置192个常用字符产生器,用户自定义的字符产生器RAM DDRAM就是显示数据RAM,用来寄存待显示的字符代码。
共80个字节,其地址和屏幕的对应关系如下表:显示位置: 1 2 3 4 5 6 7 8 (40)第一行: 00H 01H 02H 03H 04H 05H 06H 07H ..... 27H第二行: 40H 41H 42H 43H 44H 45H 46H 47H ..... 67H*/1602LCD的RAM地址映射液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。
要显示字符时要先输入显示字符地址,也就是告诉模块在,哪里显示字符,图是1602的内部显示地址。
也就是说想要在LCD1602屏幕的第一行第一列显示一个"A"字,就要向DDRAM的00H地址写入“A”字的代码就行了。
但具体的写入是要按LCD模块的指令格式来进行的,后面我会说到的。
那么一行可有40个地址呀?是的,在1602中我们就用前16个就行了。
第二行也一样用前16个地址。
对应如下:DDRAM地址与显示位置的对应关系图五:LCD1602内部显示地址例如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位D7恒定为高电平1,所以实际写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H)。
/*1602液晶模块内部的控制器共有11条控制指令,如下表序号指令RS R/W D7 D6 D5 D4 D3 D2 D1 D01 清显示0 0 0 0 0 0 0 0 0 12 光标返回0 0 0 0 0 0 0 0 1 *3 置输入模式0 0 0 0 0 0 0 1 I/D S4 显示开/关控制0 0 0 0 0 0 1 D C B5 光标或字符移位0 0 0 0 0 1 S/C R/L * *D3=1移字符D3=0移光标D2=1右移D2=0左移6 功能设置0 0 0 0 1 DL N F * *DL=1总线8位DL=0总线4位N=0显单行N=1显双行F=0 5X7点阵F=1 5X10点阵7 置字符发生器地址0 0 0 1 -字符发生存贮器地址(6位)-8 置数据存贮器地址0 0 1 --显示数据存贮器地址(7位)---9 读忙标志或地址0 1 BF ----计数器地址(7位)---------10 写CGRAM或DDRAM 1 0 --------要写的数据内容(8位------11 读CGRAM或DDRAM 1 1 --------读出的数据内容(8位)-----*/// 51单片机对lcd1602一些基础程序/* 基本操作时序:写指令输入:RS=0,RW=0,E=下降沿脉冲,DB0~DB7=指令码输出:无写数据输入:RS=1,RW=0,E=下降沿脉冲,DB0~DB7=数据输出:无读状态输入:RS=0,RW=1,E=1 输出:DB0~DB7=状态字读数据输入:RS=1,RW=1,E=1 输出:DB0~DB7=数据/*//*lcd_1602指令:指令位D7 D6 D5 D4 D3 D2 D1 D0功能设置0 0 1 DL N F * *DL=1总线8位DL=0总线4位N=0显单行N=1显双行F=0 5X7点阵F=1 5X10点阵lcd_1602指令汇总0x28 设置16*2显示,5*7点阵,4位数据接口0x38 设置16*2显示,5*7点阵,8位数据接口0x01 清屏,光标复位到地址00H位置0x02 光标归原点,DDRAM中内容不变,地址计数器AC=0;(此时地址为0x80)0x0F 开显示,显示光标,光标闪烁0x0e 开显示,显示光标,光标不闪烁0x0c 开显示,不显示光标0x08 只开显示0x06 地址加一,当写入数据的时候光标右移设定显示屏或光标移动方向指令0x18 字符全部左移一格,但光标不动0x1c 字符全部右移一格,但光标不动0x10 光标左移1格,且AC值减10x14 光标右移1格,且AC值加1*/#include <intrins.h>#define dataport P1sbit RS=P2^ 6;sbit RW=P2^5;sbit EN=P2^4;void waitfor() //检测忙信号函数{dataport=0xff;RS=0;RW=1; //选择指令寄存器读操作RS=0指令RS=1数据; RW=0写RW=1读EN=1; //使能操作while(dataport&0x80); //如果最高位是1 表示1602正忙原地踏步忙完后芯片会将高位拉低EN=0;}void writedata(unsigned char dataw) //写数据到LCD1602{waitfor(); //测忙RS=1;RW=0; //选择数据寄存器写操作RS=0指令RS=1数据; RW=0写RW=1读dataport=dataw; //将数据送到数据口EN=1;EN=0; //使能下降沿脉冲}void writecmd(unsigned char cmd) //写命令到LCD1602{waitfor(); //测忙RS=0;RW=0; //选择指令寄存器写操作dataport=cmd; //将数据送到数据口EN=1;EN=0; //使能下降沿脉冲}void init(void) // 初始化函数{writecmd(0x38); //功能设定8位数据传输双行显示设置工作方式:0x28=4位总线字符两行显示,0x38=8位总线字符两行显示writecmd(0x0c); //显示器开关writecmd(0x01); //清屏writecmd(0x06); //字符进入模式每进入一个字符光标向右移动一格原有字符不动}void location(unsigned char x,unsigned char y) //坐标函数{unsigned char temp;temp=x&0x0f; //只要x数据的后四位if(y){temp=temp|0x40;} //第一行为0 第二行为1 如果y=1则地址加0x40temp|=0x80; //DDRAM地址的命令DB7为一writecmd(temp);}void DisplayOneChar(unsigned char x,unsigned char y,unsigned char dataw) //显示一个字符函数{location(x,y);writedata(dataw);}void displaylistchar(unsigned char x,unsigned char y,unsigned char *p) //显示字符串{while(*p) //当一个字符型数组读完时*P指的为零{displayonechar(x,y,*(p++));x++;}}void WriteCgram(unsigned char address,unsigned char *p) //写CGRAM的数据{unsigned char i=8;writecmd(address); //CGRAM里的地址初始值0x40 每次加0x80while(i--){writedata(*p);p++;}}void DisplayOneChar(unsigned char x,unsigned char y,unsigned char address,unsigned char *p) //显示一个自定义字符{unsigned char i=8;writecmd(address); //CGRAM里的地址初始值0x40 每次加0x08while(i--){writedata(*p);p++;}location(x,y); //设定要显示的位置writedata((address&=0x3f)/0x08); //要从CGRAM中读出数据在1602上显示搞了半天发现CGRAM里的地址} //和DDRAM里的地址有上面的转换关系void displynumber(unsigned char x,unsigned char y,unsigned long num) //显示一个整数{unsigned int number[8];int k,gh;for(k=0;;k++){*(number+k)=(unsigned int)(num%10);//强制类型转换num=num/10;if(num==0)break;}for(gh=k;gh>=0;gh--){displyonechar(x,y,(*(number+gh)+48));x++;}}//字型码uchar code nian[]={0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02};// "年"uchar code yue[]={0x0f,0x09,0x0f,0x09,0x0f,0x09,0x0b,0x11};// "月"uchar code ri[]={0x1f,0x11,0x11,0x1f,0x11,0x11,0x11,0x1f};// "日"//显示汉字displyonecharacter(0,0,0x40,nian);displyonecharacter(1,0,0x80,yue);displyonecharacter(1,0,0xc0,ri);。
LCD1602原理与显示程序LCD1602的原理是基于液晶显示技术。
液晶是一种特殊的物质,具有双折射性质,即能将入射的光线分成两束,通过改变液晶分子的排列方式,可以改变其双折射的性质,从而使得光线透过液晶时会发生偏转。
LCD1602利用这一原理,在液晶显示面板上设置了16列和2行的像素点阵,通过控制每个像素点的液晶分子的排列方式,来实现字符的显示。
初始化是指在使用LCD1602之前,需要对其进行一系列的初始化操作,以确保其正常工作。
具体的初始化步骤如下:1.设置通信协议:LCD1602可以通过并行接口和串行接口进行通信,根据具体的接口方式,选择相应的通信协议。
2.设置工作模式:LCD1602有两种工作模式,分别是4位模式和8位模式。
选择适合的工作模式,并设置相应的控制寄存器。
3.设置显示模式:LCD1602可以显示不同的字符集,如英文字符、数字、特殊符号等。
选择合适的字符集,并设置显示模式。
4.清除显示:设置清除显示寄存器,将显示区域清空。
5.光标设置:设置光标位置和显示方式,如光标是否闪烁、光标位置等。
完成初始化后,就可以将要显示的数据写入LCD1602数据写入是指将要显示的字符或数字写入到LCD1602的显示区域。
具体的数据写入步骤如下:1.设置光标位置:根据需要显示的字符位置,设置光标的位置。
2.数据写入:通过通信接口,将要显示的数据写入到LCD1602的数据寄存器。
3.延时:由于LCD1602的刷新速度较慢,需要等待一定的时间,使得数据能够稳定显示在液晶屏上。
4.更新光标位置:根据数据的长度和显示方式,更新光标的位置。
通过以上的步骤,就可以实现LCD1602的显示功能。
总结起来,LCD1602的原理是基于液晶显示技术,通过控制液晶分子排列方式来实现字符的显示。
其显示程序包括初始化和数据写入两个方面的内容,通过设置通信协议、工作模式、显示模式等参数,并将要显示的数据写入到LCD1602的显示区域,来实现字符的显示。
/**************************************************** LCD1602显示** 描述:4线数据宽度,操作Lcd1602* 在LCD1602屏幕上第一行显示Hello!LCD1602* 第二行显示123456789abcdef** 时间:2012年3月15日调试成功(出现问题主要是因为LCD初始化)** 硬件电路:MSP430F2132* 硬件连接:** MSP430与LCD连接信息* LCD1602,4位接口,即使用D4-D7数据口,D0-D3不接入MCU* PIN1 --> 地* PIN2 --> VCC(一定要接+5V)* PIN3 -->仿真时悬空,实际电路2K电阻-->地(一定要接好,否则没有任何显示) * PIN4 --> RS --> P2.2* PIN5 --> R/W --> GND* PIN6 --> EN --> P2.1* PIN7 --> D0不接* PIN8 --> D1不接* PIN9 --> D2不接* PIN10 --> D3不接* PIN11 --> D4 --> P1.4* PIN12 --> D5 --> P1.5* PIN13 --> D6 --> P1.6* PIN14 --> D7 --> P1.7* PIN15 --> VCC(一定要接+5V,如果不要背光可以不接* PIN16 --> 地* 调试器:MSP430FET全系列JTAG仿真器* 调试软件:CCS5.1.1 编译**************************************************/#include "msp430f2132.h"#include <intrinsics.h>//定义////////////////////////////////////////////////////////////////////#define LCD_EN_PORT P2OUT//以下2个要设为同一个口#define LCD_EN_DDR P2DIR#define LCD_RS_PORT P2OUT//以下2个要设为同一个口#define LCD_RS_DDR P2DIR#define LCD_DATA_PORT P1OUT //以下3个要设为同一个口#define LCD_DATA_DDR P1DIR //一定要用高4位#define LCD_RS BIT2#define LCD_EN BIT1//#define LCD_DATA BIT0|BIT1|BIT2|BIT3|BIT4|BIT5|BIT6|BIT7 //8位数据线连接模式时使用#define LCD_DATA BIT4|BIT5|BIT6|BIT7 //4位数据线连接模式时使用////预定义函数//////////////////////////////////////////////////////////////////void LCD_init(void);void LCD_en_write(void);void LCD_write_command(unsigned char command);void LCD_write_data(unsigned char data);void LCD_set_xy (unsigned char x, unsigned char y);void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s);void LCD_write_char(unsigned char X,unsigned char Y,unsigned char data);void delay_1ms(void);void delay_nus(unsigned int n);void delay_nms(unsigned int n);void main(){WDTCTL = WDTPW + WDTHOLD; // Stop watchdogLCD_init();delay_1ms();LCD_write_string(0,0,"Hello!LCD1602");delay_1ms();LCD_write_string(0,1,"123456789abcdef");}//LCD液晶操作函数/////////////////////////////////////////////////////////////////LCD1602液晶初始化void LCD_init(void){delay_nms(15);LCD_DATA_DDR|=LCD_DATA; //数据口方向为输出LCD_EN_DDR|=LCD_EN; //设置EN方向为输出LCD_RS_DDR|=LCD_RS; //设置RS方向为输出delay_1ms(); //这4行不要改,否则仿真没显示// LCD_write_command(0x38); //8位数据接口时,使用这行,否则仿真没显示LCD_write_command(0x33); //4位数据接口时,使用这行,否则仿真没显示delay_1ms(); //// LCD_write_command(0x38); //8位数据接口时,使用这行,否则仿真没显示LCD_write_command(0x32); //4位数据接口时,使用这行,否则仿真没显示delay_1ms();// LCD_write_command(0x38); //8位数据接口时,使用这行,否则仿真没显示delay_1ms();// LCD_write_command(0x38); //8位数据接口LCD_write_command(0x2c); //4位数据接口delay_1ms();LCD_write_command(0x0c); //显示开delay_1ms();LCD_write_command(0x01); //清屏delay_1ms();LCD_write_command(0x06);}//液晶使能void LCD_en_write(void){LCD_EN_PORT|=LCD_EN;delay_nus(10);LCD_EN_PORT&=~LCD_EN;}//写指令void LCD_write_command(unsigned char command) {delay_nus(16);LCD_RS_PORT&=~LCD_RS; //RS=0LCD_DATA_PORT&=0X0f; //清高四位LCD_DATA_PORT|=command&0xf0; //写高四位//LCD_DATA_PORT = command; //写8位delay_nus(16);LCD_en_write();command=command<<4; //低四位移到高四位LCD_DATA_PORT&=0x0f; //清高四位LCD_DATA_PORT|=command&0xf0; //写低四位LCD_en_write();}//写数据void LCD_write_data(unsigned char data){delay_nus(16);LCD_RS_PORT|=LCD_RS; //RS=1LCD_DATA_PORT&=0X0f; //清高四位LCD_DATA_PORT|=data&0xf0; //写高四位//LCD_DATA_PORT = data; //写8位LCD_en_write();data=data<<4; //低四位移到高四位LCD_DATA_PORT&=0X0f; //清高四位LCD_DATA_PORT|=data&0xf0; //写低四位LCD_en_write();}//写地址函数void LCD_set_xy( unsigned char x, unsigned char y ){unsigned char address;if (y == 0) address = 0x80 + x;else address = 0xc0 + x;LCD_write_command( address);}//LCD在任意位置写字符串//列x=0~15,行y=0,1void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s) {LCD_set_xy( X, Y ); //写地址while (*s) // 写显示字符{LCD_write_data( *s );s ++;}}//LCD在任意位置写字符//列x=0~15,行y=0,1void LCD_write_char(unsigned char X,unsigned char Y,unsigned char data) {LCD_set_xy( X, Y ); //写地址LCD_write_data( data);}//延时函数////////////////////////////////////////////////////////////////////////1us延时函数void delay_1us(void){asm("nop");}//N us延时函数void delay_nus(unsigned int n) {unsigned int i;for (i=0;i<n;i++)delay_1us();}//1ms延时函数void delay_1ms(void){unsigned int i;for (i=0;i<1140;i++);}//N ms延时函数void delay_nms(unsigned int n) {unsigned int i=0;for (i=0;i<n;i++)delay_1ms();}。
在日常生活中,我们对液晶显示器并不陌生。
液晶显示模块已作为很多电子产品的通过器件,如在计算器、万用表、电子表及很多家用电子产品中都可以看到,显示的主要是数字、专用符号和图形.在单片机的人机交流界面中,一般的输出方式有以下几种:发光管、LED数码管、液晶显示器.发光管和LED数码管比较常用,软硬件都比较简单,在前面章节已经介绍过,在此不作介绍,本章重点介绍字符型液晶显示器的应用。
在单片机系统中应用晶液显示器作为输出器件有以下几个优点:显示质量高由于液晶显示器每一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点.因此,液晶显示器画质高且不会闪烁.数字式接口液晶显示器都是数字式的,和单片机系统的接口更加简单可靠,操作更加方便.体积小、重量轻液晶显示器通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比相同显示面积的传统显示器要轻得多.功耗低相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多.10.8.1 液晶显示简介①液晶显示原理液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形。
液晶显示器具有厚度薄、适用于大规模集成电路直接驱动、易于实现全彩色显示的特点,目前已经被广泛应用在便携式电脑、数字摄像机、PDA移动通信工具等众多领域.②液晶显示器的分类液晶显示的分类方法有很多种,通常可按其显示方式分为段式、字符式、点阵式等。
除了黑白显示外,液晶显示器还有多灰度有彩色显示等。
如果根据驱动方式来分,可以分为静态驱动(Static)、单纯矩阵驱动(Simple Matrix)和主动矩阵驱动(Active Matrix)三种。
③液晶显示器各种图形的显示原理:线段的显示点阵图形式液晶由M×N个显示单元组成,假设LCD显示屏有64行,每行有128列,每8列对应1字节的8位,即每行由16字节,共16×8=128个点组成,屏上64×16个显示单元与显示RAM区1024字节相对应,每一字节的内容和显示屏上相应位置的亮暗对应。
在日常生活中,我们对液晶显示器并不陌生。
液晶显示模块已作为很多电子产品的通过器件,如在计算器、万用表、电子表与很多家用电子产品中都可以看到,显示的主要是数字、专用符号和图形。
在单片机的人机交流界面中,一般的输出方式有以下几种:发光管、LED数码管、液晶显示器。
发光管和LED数码管比较常用,软硬件都比较简单,在前面章节已经介绍过,在此不作介绍,本章重点介绍字符型液晶显示器的应用。
在单片机系统中应用晶液显示器作为输出器件有以下几个优点:显示质量高由于液晶显示器每一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点。
因此,液晶显示器画质高且不会闪烁。
数字式接口液晶显示器都是数字式的,和单片机系统的接口更加简单可靠,操作更加方便。
体积小、重量轻液晶显示器通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比一样显示面积的传统显示器要轻得多。
功耗低相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多。
10.8.1 液晶显示简介①液晶显示原理液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形。
液晶显示器具有厚度薄、适用于大规模集成电路直接驱动、易于实现全彩色显示的特点,目前已经被广泛应用在便携式电脑、数字摄像机、PDA移动通信工具等众多领域。
②液晶显示器的分类液晶显示的分类方法有很多种,通常可按其显示方式分为段式、字符式、点阵式等。
除了黑白显示外,液晶显示器还有多灰度有彩色显示等。
如果根据驱动方式来分,可以分为静态驱动(Static)、单纯矩阵驱动(Simple Matrix)和主动矩阵驱动(Active Matrix)三种。
③液晶显示器各种图形的显示原理:线段的显示点阵图形式液晶由M×N个显示单元组成,假设LCD显示屏有64行,每行有128列,每8列对应1字节的8位,即每行由16字节,共16×8=128个点组成,屏上64×16个显示单元与显示RAM区1024字节相对应,每一字节的内容和显示屏上相应位置的亮暗对应。
LCD1602快速显示源程序(附真实序列图)/*********************************************************************** 文件名称: LCD1602.c* 当前版本: 1.0* 功能: LCD1602字符液晶的驱动实现* 作者:杜运福* 完成时间: 2013-01-04* 原始版本: 1.0* 修改人员、时间、版本及修改内容:* 其他说明:**********************************************************************/#ifndef LCD1602_H#define LCD1602_H/* 公共类型定义 */typedef unsigned char uint8;typedef signed char sint8;typedef unsigned short uint16;typedef signed short sint16;typedef unsigned long uint32;typedef signed long sint32;/** 函数名称:LCD_WriteCMD* 功能描述:写单个命令* 输入参数:CMD 命令字节,低7位有效* 输出参数:无* 返回值:0 执行成功,-1 执行失败* 其它说明:* 修改日期修改人修改内容* -----------------------------------------------* XXXX-XX-XX XXXX XXXX*/sint8 LCD_WriteCMD(uint8 CMD);/** 函数名称:LCD_SetPos* 功能描述:设置显示位置* 输入参数:XPos 行位置1,2;YPos 列位置,1~16* 输出参数:无* 返回值:0 执行成功,-1 执行失败* 其它说明:* 0x00----------------0x0f 0x10-------0x27 第一行(一次显示16个字符)* 0x40----------------0x4f 0x50-------0x67 第二行* 修改日期修改人修改内容* -----------------------------------------------* XXXX-XX-XX XXXX XXXX*/sint8 LCD_SetPos(uint8 XPos, uint8 YPos);/** 函数名称:LCD_WriteByte* 功能描述:写入单个字节显示数据* 输入参数:Byte 待写入字节数据* 输出参数:无* 返回值:0 执行成功,-1 执行失败* 其它说明:* 修改日期修改人修改内容* -----------------------------------------------* XXXX-XX-XX XXXX XXXX*/sint8 LCD_WriteByte(uint8 Byte);/** 函数名称:LCD_DispChar* 功能描述:指定位置显示单个字符* 输入参数:XPos 行位置1,2;YPos 列位置,1~16* ch 待显示字符* 输出参数:无* 返回值:0 执行成功,<0 执行失败* 其它说明:当行或列位置不合法时,不设置显示位置,直接在当前光标处显示 * 修改日期修改人修改内容* -----------------------------------------------* XXXX-XX-XX XXXX XXXX*/sint8 LCD_DispChar(uint8 XPos, uint8 YPos, char ch);/** 函数名称:LCD_DispString* 功能描述:指定位置显示字符串* 输入参数:XPos 行位置1,2;YPos 列位置,1~16* pStr 待显示字符串首地址* 输出参数:无* 返回值:0 执行成功,<0 执行失败* 其它说明:当行或列位置不合法时,不设置显示位置,直接在当前光标处显示 * 修改日期修改人修改内容* -----------------------------------------------* XXXX-XX-XX XXXX XXXX*/sint8 LCD_DispString(uint8 XPos, uint8 YPos, const char *pStr);/** 函数名称:LCD_Init* 功能描述:初始化LCD1602* 输入参数:无* 输出参数:无* 返回值:0 执行成功,-1 执行失败* 其它说明:8位数据总线模式、5*7点阵字符、AC自增、屏不移动、光标不显示、不闪烁 * 常用命令:0x38:16*2显示,5*7点阵显示字符,8位数据;指令执行时间40us* 0x0C:开显示,关光标 40us* 0x08:关显示,关光标 40us* 0x06:写完数据自动右移光标,普通情形,从左向右显示 40us* 0x04:写完数据自动左移光标,可以从右向左显示 40us* 0x01:清除显示内容,即清屏 1.64ms* 0x02:使光标还回起始位置 1.64ms* 0x18:屏幕上所有字符同时左移一格,适合滚动显示 40us* 0x1C:屏幕上所有字符同时右移一格,适合滚动显示 40us* 修改日期修改人修改内容* -----------------------------------------------* XXXX-XX-XX XXXX XXXX*/sint8 LCD_Init(void);#endif /* end LCD1602_H *//*********************************************************************** 文件名称: LCD1602.c* 当前版本: 1.0* 功能: LCD1602字符液晶的驱动实现* 作者:杜运福* 完成时间: 2013-01-04* 原始版本: 1.0* 修改人员、时间、版本及修改内容:* 其他说明:**********************************************************************/#include <reg52.h>#include <intrins.h>#include "LCD1602.h"/* LCD1602引脚定义 */#define LCD_CTRL P2 /* LCD控制口 */#define EN 0x80 /* P2.7 */#define RS 0x40 /* P2.6 */#define RW 0x20 /* P2.5 */#define LCD_DATA P0 /* LCD数据口 */#define LCD_DATAIN_SET LCD_DATA=0xFF /* 数据口输入设置宏 *//* 控制线置位与复位带参宏定义 */#define SET(X) LCD_CTRL |= (X)#define RESET(X) LCD_CTRL &= ~(X)/* 读取LCD忙状态 BF bit7 */#define LCD_STATE LCD_DATA & 0x80/* 延时1us宏定义 */#define NOP() _nop_()/** 延时N毫秒*/static void DelayNms(int N){int i = 0;while (N--){for (i = 0; i < 75; i++){}}}/* 等待LCD空闲,BF=0 */static void LCD_WaitIdle(void){uint8 State = 0;/* 读BF时序建立 */RESET(RS);SET(RW);SET(EN);/* 设置BF对应引脚为输入 */LCD_DATAIN_SET;/* 等待BF=0,LCD空闲 */while ((State = LCD_STATE)!=0);/* 拉低LCD使能 */RESET(EN);}/* 写一个字节命令 */sint8 LCD_WriteCMD(uint8 CMD){/* 若为无效命令,则直接返回 */if ((CMD & 0x3F)== 0){return -1;}LCD_DATA = CMD;RESET(RS);RESET(RW);SET(EN);RESET(EN); /* 产生下降沿,启动写入操作 */LCD_WaitIdle(); /* 等待LCD空闲 */return 0;}/* 设置显示位置 */sint8 LCD_SetPos(uint8 XPos, uint8 YPos){uint8 Pos = 0;if ((XPos != 1) && (XPos != 2)) /* 判断行坐标是否合法 */ {return -1;}if (YPos > 40) /* 每行有40个地址 */{return -1;}if (XPos == 1) /* 第一行 */{Pos = 0x00 + YPos -1;}else /* 第二行*/{Pos = 0x40 + YPos -1;}LCD_DATA = Pos | 0x80;RESET(RS);RESET(RW);SET(EN);RESET(EN); /* 产生下降沿 */LCD_WaitIdle(); /* 等待LCD空闲 */return 0;}/* 写入一个字节数据 */sint8 LCD_WriteByte(uint8 Byte){if (Byte == 0){return -1;}LCD_DATA = Byte;SET(RS);RESET(RW);SET(EN);RESET(EN); /* 产生下降沿 */LCD_WaitIdle(); /* 等待LCD空闲 */return 0;}/* 指定位置显示一个字符 */sint8 LCD_DispChar(uint8 XPos, uint8 YPos, char ch){sint8 ret = 0;ret += LCD_SetPos(XPos, YPos);ret += LCD_WriteByte((uint8)ch);return ret;}/* 指定位置显示一个字符串 */sint8 LCD_DispString(uint8 XPos, uint8 YPos, const char *pStr) {sint8 ret = 0;sint8 Cnt = 0;ret += LCD_SetPos(XPos, YPos);/* 逐个显示字符,最多可以显示41-YPos个字符(含超出一屏的内容)例:YPos=1,则Cnt范围为0~39 */while ((pStr[Cnt] != '\0') && (Cnt <= 40-YPos)){ret += LCD_WriteByte((uint8)pStr[Cnt]);Cnt++;}if (Cnt + YPos > 40) /* 字符串过长!! */{ret = -1;}return ret;}/* LCD1602初始化 */sint8 LCD_Init(void){/* 上电等待LCD硬件自动复位完成,不少于10ms */DelayNms(10);/* 关显示 */LCD_WriteCMD(0x08);/* 功能设置,两行显示、5*7点阵字体、8位数据总线 */LCD_WriteCMD(0x38);/* 设置输入模式,AC自动加1,显示不移位,光标自动移位 */ LCD_WriteCMD(0x06);/* 开显示,关光标,关闪烁 */LCD_WriteCMD(0x0C);/* 清显示,清除DDRAM,光标归位 */LCD_WriteCMD(0x01);return 0;}/** 文件名称: main.c* LCD1602模块测试程序*/#include <reg52.h>#include <intrins.h>#include "LCD1602.h"/* 延时N个10us */static void DelayN10us(uint16 N){while (N--);}int main(){LCD_Init();while(1){LCD_DispString(2,2,"Welcome!!"); DelayN10us(65535);DelayN10us(65535);LCD_WriteCMD(0x01);LCD_DispString(2,2,"Hello!!"); DelayN10us(65535);DelayN10us(65535);LCD_WriteCMD(0x01);//DelayN10us(65535);}return 0;}写清屏命令0x01序列图:写模式设置命令0x38序列图:写显示地址序列图:写一字节数据序列图:注:以上序列图为本人亲测!!。
======================================== 作者:Ni的年少W^o轻狂创建时间:2008.06.25========================================//==========程序功能===========// 在LCD1602上显示0--99999//=============================#include<reg51.h>#include"LCD1602.h"voidIntTOStr(uintn,uchar *str);ucharstr[10 ];//存储数据main(){uint count;LCD_init();LCD_write_command(0x01);//清屏显示delay(200);gotoxy(2,1);LCD_display("2008/06/27");gotoxy(3,2);LCD_display("01:56:56");delay1(2000);LCD_write_command(0x01);//清屏显示delay(200);gotoxy(2,1);LCD_display("LCD1602 TEST");gotoxy(4,2);LCD_display("SUCCESS");delay1(2000);LCD_write_command(0x01);//清屏显示delay(200);while(1){IntTOStr(count++,str);gotoxy(4,2);LCD_display(str);delay1(100);}}voidIntTOStr(uintn,uchar *str){uchar a[5];uchari,j;a[0]=(n/10000)%10;a[1]=(n/1000)%10;a[2]=(n/100)%10;a[3]=(n/10)%10;a[4]=(n/1)%10;for(i=0;i<5;i++)a[i]='0'+a[i];for(i=0; a[i]=='0' && i<=3; i++ );for(j=0;j<i;j++){*str=' '; str++;}for(; i<5; i++){*str=a[i];str++;}*str='\0';}========LCD驱动程序========#define LCD_DB P0//定义LCD的数据端口sbit LCD_RS=P2^0;sbit LCD_RW=P2^1;sbit LCD_E=P2^2;#define uchar unsigned char#define uint unsigned int//===========延时子函数======================== void delay(uint x){uinti,j;for(i=x;i>0;i--)for(j=0;j<2;j++);}//==================写指令函数================= voidLCD_write_command(uchar command){LCD_DB=command;LCD_RS=0;//指令LCD_RW=0;//写入LCD_E=1;LCD_E=0;delay(1);//等待执行完毕。
======================================== 作者:Ni的年少W^o轻狂
创建时间:2008.06.25
========================================
//==========程序功能===========
// 在LCD1602上显示0--99999
//=============================
#include<reg51.h>
#include"LCD1602.h"
voidIntTOStr(uintn,uchar *str);
ucharstr[10 ];//存储数据
main()
{
uint count;
LCD_init();
LCD_write_command(0x01);//清屏显示
delay(200);
gotoxy(2,1);
LCD_display("2008/06/27");
gotoxy(3,2);
LCD_display("01:56:56");
delay1(2000);
LCD_write_command(0x01);//清屏显示
delay(200);
gotoxy(2,1);
LCD_display("LCD1602 TEST");
gotoxy(4,2);
LCD_display("SUCCESS");
delay1(2000);
LCD_write_command(0x01);//清屏显示
delay(200);
while(1)
{IntTOStr(count++,str);
gotoxy(4,2);
LCD_display(str);
delay1(100);
}
}
voidIntTOStr(uintn,uchar *str)
{uchar a[5];
uchari,j;
a[0]=(n/10000)%10;
a[1]=(n/1000)%10;
a[2]=(n/100)%10;
a[3]=(n/10)%10;
a[4]=(n/1)%10;
for(i=0;i<5;i++)
a[i]='0'+a[i];
for(i=0; a[i]=='0' && i<=3; i++ );
for(j=0;j<i;j++)
{*str=' '; str++;}
for(; i<5; i++)
{*str=a[i];str++;}
*str='\0';
}
========LCD驱动程序========
#define LCD_DB P0//定义LCD的数据端口
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_E=P2^2;
#define uchar unsigned char
#define uint unsigned int
//===========延时子函数======================== void delay(uint x)
{uinti,j;
for(i=x;i>0;i--)
for(j=0;j<2;j++);
}
//==================写指令函数================= voidLCD_write_command(uchar command)
{LCD_DB=command;
LCD_RS=0;//指令
LCD_RW=0;//写入
LCD_E=1;
LCD_E=0;
delay(1);//等待执行完毕。
}
//===================写数据函数================= voidLCD_write_data(uchardat)
{LCD_DB=dat;
LCD_RS=1;//数据寄存器
LCD_RW=0;//写入数据
LCD_E=1;
LCD_E=0;
delay(1);//等待程序执行完毕。
}
/*============显示一个字符子函数=============== voidLCD_disp_char(ucharx,uchar y, uchardat)
{ uchar address;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_write_command(address);
LCD_write_data(dat);
}
===================================*/
//==========延时1====================
void delay1(uint x)
{uinti,j;
for(j=0;j<x;j++)
for(i=0;i<100;i++);
}
//===========初始化函数=============
voidLCD_init(void)
{LCD_write_command(0x38);//设置8位格式,2行,5*7 LCD_write_command(0x0c);//整体显示,关光标,不闪烁LCD_write_command(0x06);//设定输入方式,增量不移位LCD_write_command(0x01);//清屏显示
delay(200);
}
//==========光标定位======================= voidgotoxy(ucharx,uchar y)
{uchar address;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_write_command(address);
}
//=========显示一个字符串================== voidLCD_display(uchar *dat)
{ while(*dat!='\0')
{LCD_write_data(*dat);
dat++;
}
}。