LCD1602 自定义字符
- 格式:doc
- 大小:85.50 KB
- 文档页数:9
LCD1602的数据写入及CGRAM的使用1.当使能端E由1变为0时,执行写指令,数据被写入。
例如,欲写入数据i到DDRAM:void WDR(uchar i){CheckBusy();//检忙LCD_RS=1;LCD_RW=0;LCD_EN=0;Delay();LCD_DATA=i;//数据输出到定义端口Delay();LCD_EN=1;Delay();LCD_EN=0;//这一步才开始写入到LCDDelay();}2.CGRAM1602能存储8个自定义字符,这8个自定义字符存储空间的首地址分别是:0X40,0X48,0X50,0X58,0X60,0X68,0X70,0X78。
以0x40来说,它的存储空间如图所示:如果使用5*7字符的话,那么最左3位和最后一行的数据实际上是没用的,通常置0。
如果要自定义一个℃符号,那么先填框,如图(红1白0):这样我们就得到每个地址需要写入的数据:地址:数据0x40:0x160x41:0x090x42:0x08其他类推。
将这8个数据写入到对应地址即可。
使用时,先确定显示的位置,例如0X80,然后向DDRAM写入自定义字符的使用代码。
0X40-0X78对应为0X00-0X07。
本例中,先写入指令寄存器0X80确定显示位置为第一行第一个,然后写入数据寄存器0X00,这样就会在第一行第一个位置显示出℃符号。
以下是源程序如果网页格式导致部分字符丢失请下载c程序源文件:/f/avr1602c.rar#include <iom16.h>#include <intrinsics.h>#define u8 uchar unsigned char#define u16 uchar unsigned int#define uchar unsigned char#define uint unsigned intuchar zi[]={0x16,0x09,0x08,0x08,0x08,0x09,0x06,0x00}; //自定义字符摄氏度#include"1602.h"#include"18b20.h"void port_init(){PORTA=0xff;DDRA=0xff;PORTB=0xff;DDRB=0xff;PORTC=0xff;DDRC=0xff;PORTD=0xff;DDRD=0x00;}void setzi() //把设定字存入CGRAM{uchar i;writecmd(0x40); //设置第一个字的起始地址for(i=0;i<8;i++){writedata(zi[i]);}}void show_temp(uint k){displayonechar(1,1,(k/100)+48);displayonechar(2,1,(k%100/10)+48);displayonechar(3,1,'.');displayonechar(4,1,(k%10)+48);}void main(){uint TT; //显示的温度值port_init();delay(1000);init1602();displaychar(0,0,"Set zi Test");setzi();displayonechar(5,1,0x00); //0x00表示 0x40地址的值 while(1){TT=read_temper();show_temp(TT);}}//---------------1602.h----------------#define RS PORTB_Bit0#define RW PORTB_Bit1#define EN PORTB_Bit2#define DATA PORTA#define busy 0x80void delay(uint k){uint i,j;for(i=0;i<k;i++)for(j=0;j<1140;j++);}void wait(){uchar val;DATA=0xff;RS=0;RW=1;__no_operation();__no_operation();EN=1;__no_operation();__no_operation();DDRA=0x00;val=PINA;while(val&busy){val=PINA;}EN=0;DDRA=0xff;}void writecmd(uchar cmd)wait();RS=0;RW=0;__no_operation();DATA=cmd;__no_operation();EN=1;__no_operation();__no_operation();EN=0;}void writedata(uchar data){wait();RS=1;RW=0;__no_operation();DATA=data;__no_operation();EN=1;__no_operation();__no_operation();EN=0;}void displayonechar(uchar x,uchar y,uchar dda) {y&=0x01;x&=0x0f;if(y)x|=0x40;x|=0x80;writecmd(x);writedata(dda);}void displaychar(uchar x,uchar y,uchar *p) {y&=0x01;x&=0x0f;while(*p!='\0'){if(x<=0x0f){displayonechar(x,y,*p);p++;x++;}}}void init1602(){delay(15);writecmd(0x38);delay(5);writecmd(0x38);delay(5);writecmd(0x38);writecmd(0x80);writecmd(0x01);writecmd(0x06);writecmd(0x0c);}//--------------18B20.h------------uchar teml,temh;uchar sign;uchar Flag_1820Error;uint tempp; //温度值/*********************************/void delay_15us(void) //15us左右{uchar x=27;while(x){x--;}}/********************************/void delay_60us(void) //60us左右{uchar x=117;while(x){x--;}}void init_1820(void){uchar i;uint j=0;PORTC|=(1<<7); //"1"PORTC&=~(1<<7); //"0"for(i=0;i<8;i++)delay_60us();//480us以上 PORTC|=(1<<7); //"1"DDRC&=~(1<<7); //"PINC7 is INPUT"delay_15us(); //15~60usdelay_15us();Flag_1820Error=0;while(PINC&(1<<7)){ delay_60us();j++;if(j>=18000){Flag_1820Error=1;break;}}DDRC|=(1<<7); //PORTC7 is OUTPUTPORTC|=(1<<7); //"1"for(i=0;i<4;i++)delay_60us(); //240us}/********************************/void delay_5us(void) //5us左右{uchar x=7;while(x){x--;}}/********************************/void write_1820(uchar x){uchar m;for(m=0;m<8;m++){if(x&(1<<m)) //写数据,从低位开始{PORTC&=~(1<<7);delay_5us(); //"0",5us PORTC|=(1<<7); //write"1"delay_15us(); //15~45usdelay_15us();delay_15us();}else{PORTC&=~(1<<7);delay_15us();//"0",15us delay_15us(); //write"0"delay_15us(); //15~45usdelay_15us();PORTC|=(1<<7); //"1"}}PORTC|=(1<<7); //"1"}/*******************************/uchar read_1820(void){uchar temp,k,n;temp=0;for(n=0;n<8;n++){PORTC&=~(1<<7); //"0"delay_5us();PORTC|=(1<<7); //"1"delay_5us();DDRC&=~(1<<7); //"PINC7 is INPUT"k=(PINC&(1<<7)); //读数据,从低位开始if(k)temp|=(1<<n); //read"1"elsetemp&=~(1<<n); //read"0"delay_15us(); //45usdelay_15us();delay_15us();DDRC|=(1<<7); //PORTC7 is OUTPUT }return (temp);}/*************************************/uint read_temper(void){uchar TX; //小数位uchar TZ; //整数位init_1820(); //复位18b20write_1820(0xcc); // 发出转换命令write_1820(0x44);;;;;;;init_1820();write_1820(0xcc); //发出读命令write_1820(0xbe);teml=read_1820(); //读数据byte1temh=read_1820(); //byte2TX=teml&0x0f;temh=temh<<4;temh|=(teml&0xf0)>>4;TZ=temh;tempp=TZ*10+TX;return tempp;}。
lcd1602 使用手册,LCD1602 的使用详解LCD1602 是很多单片机爱好者较早接触的字符型液晶显示器,它的主控芯片是HD44780 或者其它兼容芯片。
刚开始接触它的大多是单片机的初学者。
由于对它的不了解,不能随心所欲地对它进行驱动。
经过一段时间的学习,我对它的驱动有了一点点心得,今天把它记录在这里,以备以后查阅。
一般来说,LCD1602 有16 条引脚,据说还有14 条引脚的,与16 脚的相比缺少了背光电源A(15 脚)和地线K(16 脚)。
我手里这块LCD1602 的型号是HJ1602A,是绘晶科技公司的产品,它有16 条引脚。
LCD1602 的基本操作1. 读状态:输入RS=0,RW=1,E=高脉冲。
输出:D0D7 为状态字。
2. 读数据:输入RS=1,RW=1,E=高脉冲。
输出:D0D7 为数据。
3. 写命令:输入RS=0,RW=0,E=低脉冲。
输出:无。
(写完置E= 高脉冲)4. 写数据:输入RS=1,RW=0,E=低脉冲。
输出:无。
分析时序图(1)写操作(单片机至HD44780)首先要对寄存器的选择和读、写操作选择进行配置。
RS 是寄存器选择,RS = 1 对数据进行操作;RS = 0 对指令进行操作。
接着对读写操作选择进行配置,RW = 0 写操作。
打开使能端,输入使能信号E = 1。
数据总线,对DB0~DB7 赋值,进行数据的传输【注】如果先打开使能,再进行其他配置的话,有可能传输的数据不是自己想要的。
(2)读操作(HD44780 至单片机)显示模块的指令集,根据自己的显示需要进行相应的配置显示的位置设置DDRAM显示在第一行某一列的数据可以写命令:0x80 | 0x**,显示在第二行某一列的数据可以写命令:0x80 | 0x40 | 0x** = 0xC0 | 0x**,0x80 是因为在设置DDRAM 地址时,DB7 固定是为1 的。
LCD1602 写入自己的字符及显示汉字1、由于LCD 是外部设备,处理速度比CPU 速度慢,向LCD 写入命令到完成功能需要一定的时间,在这个过程中,LCD 处于忙状态,不能向LCD 写入新的内容。
LCD1602自定义显示字符及汉字整理:大海橡树第一篇讲解一下LCD1602,学过单片机的朋友们都知道它了吧,可以说是用的最广,最简单,也是学液晶入门级别的一块液晶了。
LCD1602顾名思义就是两行显示的液晶,每行最多显示16个字符(里面总共有160个字符),其中包括阿拉伯数字、英文字母的大小写,常用符号,及日文的假名!每个字符对应一个ASCII码,我们通过向液晶送相应符号的ASCII码来显示这个字符。
下面看一下Proteus软件中的LCD1602,在Proteus软件的元件库中,LCD1602为LM016L,下面是这块液晶的引脚图:具体的相关引脚和功能设定参看LCD1602的PDF文档资料,由于篇幅问题,这里就不赘述了!还有一点要说的就是大家在仿真LCD1602时,要是用的是DB7~DB0连单片机的P0口的话,一定要加上拉电阻,要不然驱动不了,因为单片机的四组IO口就P0的内部无上拉,驱动能力弱!看下面的图:在P0口加了排阻(RESPACK-8)对于自带字符的显示,只需要将对应的ASCII码写入LCD中显示即可,这个是每个人开始学习液晶最开始要学会的了,看看数据手册,写写程序,想必大家都会了,这里就不做介绍,本篇着重讲解一下怎样自定义显示字符,比如显示自定的字符、显示汉字等等这些!要显示我们自定义的字符,就要用到LCD中的CGRAM存储器(character generate RAM),而我们之前用的显示自带的字符用到的是DDRAM,两个是不同的。
看液晶手册我们知道,CGRAM的地址是0x40~0x7F,共128个字节,而一个字符是8个字节,所以一共能显示8个自定义的字符。
内部常用字符的显示是从0x20开始的,0x00~0x0F是专门留给自定义字符显示用的。
那么怎样显示一个自定义字符呢?首先我们要清楚LCD1602显示字符的点阵大小,眼力好的可以看出来,LCD1602一个显示字符的位置是5*8的点阵,也就是说它所能显示的点阵图形的大小是5*8的!要显示一个自定义的字符,首先我们要知道所显示自定义字符的点阵数据,也就是在一个5*8的点阵上那个点是黑的(将该点点黑,就是高电平----1),哪个点是白的(该点不显示,为低电平----0),但是我们送入到LCD中的是ASCII码,它是8位的数据,而一个显示字符的点阵大小只是5*8的,显然不够,显示的办法是8*8点阵的前三列不用,也就是不显示,我们只用后面的5列来显示。
通用型LCD1602自定义字符的显示LCD1602主要用来显示数字、字母、图形以及少量自定义字符。
由于其显示控制简单,性价比高,广泛用于电子表、冰箱、空调、汽车电子仪表等装置。
本文主要研究一下如何在LCD1602显示自定义字符。
虽然技术含量不高,但是注意编程的细节还是很有必要去探讨一番。
1.引言液晶显示器的英文名是Liquid CrystalDisplay,简称LCD.液晶显示器作为显示器件具有体积小、重量轻、功耗低,性价比高等优点,所以LCD日渐成为各种便携式电子产品的理想显示器,1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块,它有若干个5X7或5X11点阵字符位组成,每个点阵字符位都可以显示一个字符。
每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此,所以它不能像12864一样显示图形,但是有时候很想要用图形表示,那么LCD1602提供了8个空间的自定义字符,如图1所示,显示的年月日,.C 就是自定义字符。
2.通用型LCD1602操作方法LCD1602是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。
目前市面上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。
如图2所示,字符型LCD1602通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源线VCC(15脚)和地线GND(16脚),从左到右分别是1引脚到16引脚在这里要说明的是:(1)要用1602型LCD显示字符必须解决3个问题:a.待显示字符ASCII标准码产生;b.液晶显示模式的设置;c.字符显示位置的指定。
(2)若想在00H处显示数据的话,则必须将00H加上80H,即0x00H+0x80H,若要在01H处显示数据,也必须加0x80H,例如要将某字符显示在第2行第5列,则确定地址的。
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,但是没有汉字库。
每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
今天偶然在网上发现有的人利用1602显示简单的汉字,对这个产生了兴趣,上网搜了一些资料,自己慢慢的研究了一下,终于弄懂了怎么回事,自己也写了一个显示“天”,“℃”,“你”,“土”,心形,“明”的程序。
下面就和大家一起分享一下。
查看LCD1602的CGROM字符代码表,可以发现从00000000B~00000111B (00H~07H)地址的内容是没有定义的,它是留给用户自己定义的,用户可以通过先定义LCD1602的CGRAM中的内容,最多可以自定义8个字符,然后就可以同调用CGROM字符一样来调用自定义好的字符。
那么如何设定CGRAM中的内容呢?首先我们要把所要编写的字符对应于5X8点阵的“字模”提取出来,我们可以通过相关的软件来提取,也可以手工提取。
说白了也就是将点阵的某一行中有显示的点用1表示,无显示的点用0表示,以此形成该行对应的字模数据。
设定CGRAM的内容,要一行一行的设定,每一行对应一个CGRAM,5X8点阵,每行5点,共8行,因此要将8行的字模数据都写入CGRAM。
写好后,就可像调用CGROM字符一样来来调用它了(CGRAM是可写可读的,CGROM只可读不可写)。
下面贴出我的程序(见1602LCD文件夹中的1602显示汉字.Uv2文件),实物图和Proteus仿真图,由于一个字符的点数为5X8,点数太少所以显示效果不是很好,经实验发现实物效果比仿真要好,下面为两者的效果图。
⽤1602液晶显⽰⾃定义字符1602是⼀款最常⽤也是最便宜的液晶显⽰屏。
最多可以显⽰两⾏标准字符,每⾏最多可以显⽰16个字符。
1602可以显⽰内部常⽤字符(包括阿拉伯数字,英⽂字母⼤⼩写,常⽤符号和⽇⽂假名等),也可以显⽰⾃定义字符(单或多个字符组成的简单汉字,符号,图案等,最多可以产⽣8个⾃定义字符)。
⼀、显⽰常⽤字符。
1602液晶模块内部的字符发⽣存储器(CGROM)已经存储了160个不同的点阵字符图形,如下表所⽰,这些字符有:阿拉伯数字、英⽂字母的⼤⼩写、常⽤的符号、和⽇⽂假名等,每⼀个字符都有⼀个固定的代码,⽐如⼤写的英⽂字母“A”的代码是41H,显⽰时模块把地址41H中的点阵字符图形显⽰出来,我们就能看到字母“A”⼗进制⼗六进制 ASCII字符⼗进制⼗六进制 ASCII字符⼗进制⼗六进制 ASCII字符00 00 ⾃定义字符1 56 38 8 96 60 `01 01 ⾃定义字符2 57 39 9 97 61 a02 02 ⾃定义字符3 58 3A : 98 62 b03 03 ⾃定义字符4 59 3B ; 99 63 c04 04 ⾃定义字符5 60 3C < 100 64 d05 05 ⾃定义字符6 61 3D = 101 65 e06 06 ⾃定义字符7 62 3E > 102 66 f07 07 ⾃定义字符8 63 3F ? 103 67 g08 08 ⾃定义字符1 64 40 @ 104 68 h09 09 ⾃定义字符2 65 41 A 105 69 i10 0A ⾃定义字符3 66 42 B 106 6A j11 0B ⾃定义字符4 67 43 C 107 6B k12 0C ⾃定义字符5 68 44 D 108 6C l13 0D ⾃定义字符6 69 45 E 109 6D m14 0E ⾃定义字符7 70 46 F 110 6E n15 0F ⾃定义字符8 71 47 G 111 6F o32 20 空格 72 48 H 112 70 p33 21 ! 73 49 I 113 71 q34 22 " 74 4A J 114 72 r35 23 # 75 4B K 115 73 s36 24 $ 76 4C L 116 74 t37 25 % 77 4D M 117 75 u38 26 & 78 4E N 118 76 v39 27 ' 79 4F O 119 77 w40 28 ( 80 50 P 120 78 x41 29 ) 81 51 Q 121 79 y42 2A * 82 52 R 122 7A z43 2B + 83 53 S 123 7B {44 2C , 84 54 T 124 7C |45 2D - 85 55 U 125 7D }46 2E . 86 56 V 126 7E ~47 2F / 87 57 W48 30 0 88 58 X49 31 1 89 59 Y50 32 2 90 5A Z51 33 3 91 5B [52 34 4 92 5C \53 35 5 93 5D ]54 36 6 94 5E ^55 37 7 95 5F _显⽰操作的过程:⾸先确认显⽰的位置,即在第⼏⾏,第⼏个字符开始显⽰。
1602自定义字符显示摄氏度符号LCD1602 的数据写入及CGRAM 的使用1.当使能端E 由1 变为0 时,执行写指令,数据被写入。
例如,欲写入数据i 到DDRAM:void WDR(uchar i){ CheckBusy();//检忙LCD_RS=1; LCD_RW=0; LCD_EN=0; Delay(); LCD_DATA=i;//数据输出到定义端口Delay(); LCD_EN=1; Delay(); LCD_EN=0;//这一步才开始写入到LCD Delay();}2.CGRAM1602 能存储8 个自定义字符,这8 个自定义字符存储空间的首地址分别是:0X40,0X48,0X50,0X58,0X60,0X68,0X70,0X78。
以0x40 来说,它的存储空间如图所示:如果使用5*7 字符的话,那么最左3 位和最后一行的数据实际上是没用的,通常置0。
如果要自定义一个℃符号,那么先填框,如图(红1 白0):这样我们就得到每个地址需要写入的数据:地址:数据0x40:0x160x41:0x090x42:0x08 其他类推。
将这8 个数据写入到对应地址即可。
使用时,先确定显示的位置,例如0X80,然后向DDRAM 写入自定义字符的使用代码。
0X40-0X78 对应为0X00-0X07。
本例中,先写入指令寄存器0X80确定显示位置为第一行第一个,然后写入数据寄存器0X00,这样就会在第一行第一个位置显示出℃符号。
以下是源程序如果网页格式导致部分字符丢失请下载c 程序源文件:51hei/f/avr1602c.rar#include #include #define u8 uchar unsigned char#define u16 uchar unsigned int#define uchar unsigned char#define uintunsigned intuchar zi[]={0x16,0x09,0x08,0x08,0x08,0x09,0x06,0x00}; //自定义字符摄氏度#include”1602.h”#include”18b20.h”void port_init(){ PORTA=0xff; DDRA=0xff; PORTB=0xff; DDRB=0xff; PORTC=0xff; DDRC=0xff; PORTD=0xff; DDRD=0x00;}void setzi() //把设定字存入CGRAM{ uchar i; writecmd(0x40); //设置第一个字的起始地址for(i=0;i<8;i++) { writedata(zi[i]); }}void show_temp(uint。
液晶显示模块可以分为字段,字符点阵,图形点阵 3 种。
一般只有后者可以显示汉字和图形。
LCD 1602 是常见的16 × 2 行,6 × 8 字符点阵液晶模块,广泛应用于智能仪表、通信、办公自动化设备中,其字符发生器 ROM 中自带数字和英文字母及一些特殊符号的字符库,没有汉字。
我们利用 1602 可以建立 8 个 6 × 8 点阵自定义字库的特点,在一个测温的实例中成功显示了少量汉字和特殊符号——℃,下面是显示部分的实施方法。
一、电路构成简图LCD1602 液晶显示模块按图 1 所示连接单片机,其接口的引脚功能介绍如下:BLA :背光源正极,接 +5V ;BLK :背光源负极,接地;VO :液晶显示偏压信号,通过电位器 W1 调节, 1602 偏压接近 0V ;RS :接 P1 . 2 ,决定传输类型是数据或命令, 1- 表示数据, 0- 表示命令;R / W :接 P1 . 6 ,读/写控制, 1 一表示读, O 一表示写;E :接 P13 ,使能端,高电平有效;DB0 ~ DB7 :数据端口,连接 P0 。
液晶显示模块 1602 更详细的信息可以查阅相关的资料,此处不再赘述。
二、自定义字库的建立及关键子程序的软件实现若要显示汉字,关键是先要自己建立欲显示的汉字字库。
1602 提供了,在片内CGRAM 的 00H 一 3FH 共 64 个字节的空间,可以存放 8 个 6 × 8 点阵的自建字符库,其代码分别为 00H 一 07H ,然后在显示时只要用查表法调用汉字的相应代码就可以了。
下面给出相应的子程序,为了更好地理解 1602 液晶显示模块的相关指令,以注释的方式存程序中给出解释 .1 .显示自定义字符内容的流程图图3为 6 × 8点阵形成的“日”字,前面3位补0,其编码为1FH,11H,11H,1FH,11H,1FH,00H。
其他汉字可以以此编出相应的编码。
LCD1602的数据写入及CGRAM的使用1.当使能端E由1变为0时,执行写指令,数据被写入。
例如,欲写入数据i到DDRAM:void WDR(uchar i){CheckBusy();//检忙LCD_RS=1;LCD_RW=0;LCD_EN=0;Delay();LCD_DATA=i;//数据输出到定义端口Delay();LCD_EN=1;Delay();LCD_EN=0;//这一步才开始写入到LCDDelay();}2.CGRAM1602能存储8个自定义字符,这8个自定义字符存储空间的首地址分别是:0X40,0X48,0X50,0X58,0X60,0X68,0X70,0X78。
以0x40来说,它的存储空间如图所示:如果使用5*7字符的话,那么最左3位和最后一行的数据实际上是没用的,通常置0。
如果要自定义一个℃符号,那么先填框,如图(红1白0):这样我们就得到每个地址需要写入的数据:地址:数据0x40:0x160x41:0x090x42:0x08其他类推。
将这8个数据写入到对应地址即可。
使用时,先确定显示的位置,例如0X80,然后向DDRAM写入自定义字符的使用代码。
0X40-0X78对应为0X00-0X07。
本例中,先写入指令寄存器0X80确定显示位置为第一行第一个,然后写入数据寄存器0X00,这样就会在第一行第一个位置显示出℃符号。
以下是源程序如果网页格式导致部分字符丢失请下载c程序源文件:/f/avr1602c.rar#include <iom16.h>#include <intrinsics.h>#define u8 uchar unsigned char#define u16 uchar unsigned int#define uchar unsigned char#define uint unsigned intuchar zi[]={0x16,0x09,0x08,0x08,0x08,0x09,0x06,0x00}; //自定义字符摄氏度#include"1602.h"#include"18b20.h"void port_init(){PORTA=0xff;DDRA=0xff;PORTB=0xff;DDRB=0xff;PORTC=0xff;DDRC=0xff;PORTD=0xff;DDRD=0x00;}void setzi() //把设定字存入CGRAM{uchar i;writecmd(0x40); //设置第一个字的起始地址for(i=0;i<8;i++){writedata(zi[i]);}}void show_temp(uint k){displayonechar(1,1,(k/100)+48);displayonechar(2,1,(k%100/10)+48);displayonechar(3,1,'.');displayonechar(4,1,(k%10)+48);}void main(){uint TT; //显示的温度值port_init();delay(1000);init1602();displaychar(0,0,"Set zi Test");setzi();displayonechar(5,1,0x00); //0x00表示 0x40地址的值 while(1){TT=read_temper();show_temp(TT);}}//---------------1602.h----------------#define RS PORTB_Bit0#define RW PORTB_Bit1#define EN PORTB_Bit2#define DATA PORTA#define busy 0x80void delay(uint k){uint i,j;for(i=0;i<k;i++)for(j=0;j<1140;j++);}void wait(){uchar val;DATA=0xff;RS=0;RW=1;__no_operation();__no_operation();EN=1;__no_operation();__no_operation();DDRA=0x00;val=PINA;while(val&busy){val=PINA;}EN=0;DDRA=0xff;}void writecmd(uchar cmd)wait();RS=0;RW=0;__no_operation();DATA=cmd;__no_operation();EN=1;__no_operation();__no_operation();EN=0;}void writedata(uchar data){wait();RS=1;RW=0;__no_operation();DATA=data;__no_operation();EN=1;__no_operation();__no_operation();EN=0;}void displayonechar(uchar x,uchar y,uchar dda) {y&=0x01;x&=0x0f;if(y)x|=0x40;x|=0x80;writecmd(x);writedata(dda);}void displaychar(uchar x,uchar y,uchar *p) {y&=0x01;x&=0x0f;while(*p!='\0'){if(x<=0x0f){displayonechar(x,y,*p);p++;x++;}}}void init1602(){delay(15);writecmd(0x38);delay(5);writecmd(0x38);delay(5);writecmd(0x38);writecmd(0x80);writecmd(0x01);writecmd(0x06);writecmd(0x0c);}//--------------18B20.h------------uchar teml,temh;uchar sign;uchar Flag_1820Error;uint tempp; //温度值/*********************************/void delay_15us(void) //15us左右{uchar x=27;while(x){x--;}}/********************************/void delay_60us(void) //60us左右{uchar x=117;while(x){x--;}}void init_1820(void){uchar i;uint j=0;PORTC|=(1<<7); //"1"PORTC&=~(1<<7); //"0"for(i=0;i<8;i++)delay_60us();//480us以上 PORTC|=(1<<7); //"1"DDRC&=~(1<<7); //"PINC7 is INPUT"delay_15us(); //15~60usdelay_15us();Flag_1820Error=0;while(PINC&(1<<7)){ delay_60us();j++;if(j>=18000){Flag_1820Error=1;break;}}DDRC|=(1<<7); //PORTC7 is OUTPUTPORTC|=(1<<7); //"1"for(i=0;i<4;i++)delay_60us(); //240us}/********************************/void delay_5us(void) //5us左右{uchar x=7;while(x){x--;}}/********************************/void write_1820(uchar x){uchar m;for(m=0;m<8;m++){if(x&(1<<m)) //写数据,从低位开始{PORTC&=~(1<<7);delay_5us(); //"0",5us PORTC|=(1<<7); //write"1"delay_15us(); //15~45usdelay_15us();delay_15us();}else{PORTC&=~(1<<7);delay_15us();//"0",15us delay_15us(); //write"0"delay_15us(); //15~45usdelay_15us();PORTC|=(1<<7); //"1"}}PORTC|=(1<<7); //"1"}/*******************************/uchar read_1820(void){uchar temp,k,n;temp=0;for(n=0;n<8;n++){PORTC&=~(1<<7); //"0"delay_5us();PORTC|=(1<<7); //"1"delay_5us();DDRC&=~(1<<7); //"PINC7 is INPUT"k=(PINC&(1<<7)); //读数据,从低位开始if(k)temp|=(1<<n); //read"1"elsetemp&=~(1<<n); //read"0"delay_15us(); //45usdelay_15us();delay_15us();DDRC|=(1<<7); //PORTC7 is OUTPUT }return (temp);}/*************************************/uint read_temper(void){uchar TX; //小数位uchar TZ; //整数位init_1820(); //复位18b20write_1820(0xcc); // 发出转换命令write_1820(0x44);;;;;;;init_1820();write_1820(0xcc); //发出读命令write_1820(0xbe);teml=read_1820(); //读数据byte1temh=read_1820(); //byte2TX=teml&0x0f;temh=temh<<4;temh|=(teml&0xf0)>>4;TZ=temh;tempp=TZ*10+TX;return tempp;}。
LCD1602 自定义字符2011-09-06 20:40:55| 分类:1602|举报|字号订阅用户自定义字符的应用:我们从CGROM表上可以看到,在表的最左边是一列可以允许用户自定义的CGRAM,从上往下看着是16个,实际只有8个字节可用。
它的字符码是00000000-00000111这8个地址,表的下面还有8个字节,但因为这个CGRAM 的字符码规定0-2位为地址,3位无效,4-7全为零。
因此CGRAM的字符码只有最后三位能用也就是8个字节了。
等效为0000X111,X为无效位,最后三位为000-111共8个。
如果我们要想显示这8个用户自定义的字符,操作方法和显示CGROM的一样,先设置DDRAM位置,再向DDRAM写入字符码,例如“A”就是41H。
现在我们要显示CGRAM的第一个自定义字符,就向DDRAM写入00000000B(00H),如果要显示第8个就写入00000111(08H),简单吧!好!现在我们来看怎么向这八个自定义字符写入字模。
有个设置CGRAM地址的指令如下图:从这个指令可以看出指令数据的高2位已固定是01,只有后面的6位是地址数据,而这6位中的高3位就表示这八个自定义字符,最后的3位就是字模数据的八个地址了。
例如第一个自定义字符的字模地址为01000000-01000111八个地址。
我们向这8个字节写入字模数据,让它能显示出“℃”地址:01000000数据:00010000 图示: ○○○■○○○○0100000100000110 ○○○○○■■○0100001000001001 ○○○○■○○■0100001100001000 ○○○○■○○○0100010000001000 ○○○○■○○○0100010100001001 ○○○○■○○■0100011000000110 ○○○○○■■○0100011100000000 ○○○○○○○○图示:下面我们写一段程序让这8个自定义字符显示出一个心的图案:# include <reg51.h>unsigned char table1[]={0x03,0x07,0x0f,0x1f,0x1f,0x1f,0x1f,0x1f,0x18,0x1E,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x07,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x10,0x18,0x1c,0x1E,0x1E,0x1E,0x1E,0x1E,0x0f,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x07,0x01,0x1f,0x1f,0x1f,0x1f,0x1f,0x1c,0x18,0x00,0x1c,0x18,0x10,0x00,0x00,0x00,0x00,0x00};//心图案unsigned char table[]={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};//字符℃#define CLEARSCREEN LCD_write_command(0x01)/**************定义接口************************/#define LCDIO P2sbit LCD1602_RS=P3^0;sbit LCD1602_RW=P3^1;sbit LCD1602_EN=P3^2;/**************定义函数************************/void LCD_write_command(unsigned char command);//写入指令函数void LCD_write_dat(unsigned char dat);//写入数据函数void LCD_set_xy( unsigned char x, unsigned char y );//设置显示位置函数void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat);//显示一个字符函数void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char*s);//显示字符串函数void LCD_init(void);//初始化函数void delay_nms(unsigned int n);//延时函数/********************************************//************初始化函数****************/void LCD_init(void){CLEARSCREEN;//clear screenLCD_write_command(0x38);//set 8 bit data transmission mode LCD_write_command(0x0c);//open display (enable lcd display) LCD_write_command(0x80);//set lcd first display address CLEARSCREEN;//clear screen}/****************************************************//**************写指令函数********************************/void LCD_write_command(unsigned char command){LCDIO=command;LCD1602_RS=0;LCD1602_RW=0;LCD1602_EN=0;LCD1602_EN=1;delay_nms(10);}/***************************************************/ /****************写数据函数************************/ void LCD_write_dat(unsigned char dat){LCDIO=dat;LCD1602_RS=1;LCD1602_RW=0;LCD1602_EN=0;delay_nms(1);LCD1602_EN=1;}/****************************************************//***************设置显示位置**************************/ void LCD_set_xy( unsigned char x, unsigned char y ) {unsigned char address;if (y == 1)address = 0x80 + x;elseaddress =0xc0+ x;LCD_write_command(address);}/***************************************************//****************显示一个字符**********************/void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat){LCD_set_xy( x, y );LCD_write_dat(dat);}/**********************************************//***************显示字符串函数***************/void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s) {LCD_set_xy( X, Y );while (*s){LCD_write_dat(*s);s ++;}}/***********************************************//********** 延时**********************/void delay_nms(unsigned int n){unsigned int i=0,j=0;for (i=n;i>0;i--)for (j=0;j<10;j++);}/**************************************//***********主函数**************/void main(void){unsigned char i,j,k,tmp;LCD_init();delay_nms(100);tmp=0x40;//设置CGRAM地址的格式字k=0;for(j=0;j<8;j++){for(i=0;i<8;i++){LCD_write_command(tmp+i); // 设置自定义字符的CGRAM 地址delay_nms(2);LCD_write_dat(table1[k]); // 向CGRAM写入自定义字符表的数据k++;delay_nms(2);}tmp=tmp+8;}LCD_dsp_string(1,1,"LCD TEST ");//在第一行第一列显示“LCD TEST”LCD_dsp_string(1,2,"SUCCESSFUL ");//在第二行第一列显示“SUCCESSFUL”for (i=0;i<4;i++){LCD_dsp_char( 12+i,1,i);//在第一行第12列位置显示心图案的上半部delay_nms(1);}for (i=4;i<8;i++){LCD_dsp_char( 12+i-4,2,i);在第二行第12列位置显示心图案的下半部delay_nms(1);}while (1);}/********************************************************************/实际效果如图:。