PIC18F452之1602自定义字符
显示自定义字符
步骤如下:
1. 先将自定义字符写入CGRAM ; 2. 再将CGRAM中的自定义字符送到DDRAM中显示
很简单的:看好了
查看LCD1602 的CGROM 字符代码表,可以发现 从00000000B~00000111B(00H~07H)地址的内容是没有定义的,它是留给用户自己定义的,用户可以通过先定义LCD1602的CGRAM中的内容,然后就可以同调用CGROM字符一样来调用自定义好的字符(这里提示一下,自定义的字符最多可写8个),那么如何设定CGRAM中的内容呢?
首先我们要把所要编写的字符对应于5X8点阵的“字模”提取出来,我们可以通过相关的软件来提取,也可以手工提取。说白了也就是将点阵的某一行中有显示的点用1表示,无显示的点用0表示,以此形成该行对应的字模数据。
设定CGRAM的内容,要一行一行的设定,每一行对应一个CGRAM,5X8点阵,每行5点,共8行,因此要将8行的字模数据都写入CGRAM。写好后,就可像调
用CGROM字符一样来来调用它了。
定义一行的内容,分两步:
1. 设定行地址(CGRAM地址):
用到的命令如下:
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 1 DATA
其中:DB5,DB4,DB3为字符号,也就是你将来要显示该字符时要用到的字符地址。
DB2,DB1,DB0为行号。
2. 设定CGRAM数据(内容)指令码如下:
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
1 0 DATA
其中:DB4,DB3,DB2,DB1,DB0对应于每行5点的字模数据。
DB7,DB6,DB5可为任何数据,一般取“000”。
1 #include <pic18.h> //调用头文件,可以去PICC18软件下去查找PIC18FXX2.H 2 __CONFIG(1,XT) ; //晶振为外部4M 3 __CONFIG(2,WDTDIS) ; //看门狗关闭 4 __CONFIG(4,LVPDIS) ; //禁止低电压编程 5 6 #define RSPIN RB5 //Data or Instrument Select 7 #define RWPIN RB4 //Write or Read 8 #define EPIN RB3 //6800 mode Enable single 9 unsigned char table[]="LCD check ok"; //要显示的内容1放入数组tablel 10 11 //此函数定义八个字符分别写入CGRAM的八个地址 12 unsigned char pic[]={ 13 0x03,0x07,0x0f,0x1f,0x1f,0x1f,0x1f,0x1f, 14 0x18,0x1E,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, 15 0x07,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, 16 0x10,0x18,0x1c,0x1E,0x1E,0x1E,0x1E,0x1E, 17 0x0f,0x07,0x03,0x01,0x00,0x00,0x00,0x00, 18 0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x07,0x01, 19 0x1f,0x1f,0x1f,0x1f,0x1f,0x1c,0x18,0x00, 20 0x1c,0x18,0x10,0x00,0x00,0x00,0x00,0x00 21 22 }; 23 ///--------------------------------------- 24 //名称: 延时函数 25 //----------------------------------------- 26 void delay(unsigned int t) 27 { 28 unsigned int i,j; 29 for(i=0;i<t;i++) 30 { 31 for(j=0;j<10;j++); 32 } 33 } 34 35 //--------------------------------------- 36 //名称: 1602忙检测函数 37 //----------------------------------------- 38 void lcd_wait_busy(void) 39 { 40 TRISD7=1; //为读状态做准备 41 RSPIN=0; //选择指令寄存器 42 RWPIN=1; //选择读 43 EPIN=1; //使能线电平变化 44 while(RD7==1); //读忙状态,不忙时退出 45 EPIN=0; //恢复使能线电平 46 TRISD7=0; 47 } 48 //--------------------------------------- 49 //名称: 1602写命令函数 50 //----------------------------------------- 51 void lcd_write_com(unsigned char combuf) 52 { 53 RSPIN=0; //选择指令寄存器 54 RWPIN=0; //选择写 55 PORTD=combuf; //把命令字送入RD 56 EPIN=1; //使能线电平变化,命令送入1602的8位数据口 57 asm("NOP"); 58 EPIN=0; //恢复使能线电平 59 } 60 //--------------------------------------- 61 //名称: 1602写命令函数(带忙检测) 62 //----------------------------------------- 63 void lcd_write_com_busy(unsigned char combuf) 64 { 65 lcd_wait_busy(); //调用忙检测函数 66 lcd_write_com(combuf); //调用写命令函数 67 } 68 //--------------------------------------- 69 //名称: 1602写数据函数(带忙检测) 70 //----------------------------------------- 71 void lcd_write_data(unsigned char databuf) 72 { 73 lcd_wait_busy(); //调用忙检测函数 74 RSPIN=1; //选择数据寄存器 75 RWPIN=0; //选择写 76 PORTD=databuf; //把数据字送入P2 77 EPIN=1; //使能线电平变化,命令送入1602的8位数据口 78 asm("NOP"); 79 EPIN=0; //恢复使能线电平 80 } 81 //--------------------------------------- 82 //名称: 1602显示地址写函数 83 //----------------------------------------- 84 void lcd_write_address(unsigned char x,unsigned char y) 85 { 86 x&=0x0f; //列地址限制在0-15 87 y&=0x01; //行地址限制在0-1 88 if(y==0x00) 89 lcd_write_com_busy(x|0x80); //第一行的列地址写入 90 else 91 lcd_write_com_busy((x+0x40)|0x80); //第二行的列地址写入 92 } 93 //--------------------------------------- 94 //名称: 1602初始化函数 95 //----------------------------------------- 96 void lcdreset(void) 97 { 98 lcd_write_com_busy(0x38); //8位数据,双列,5*7字形 99 lcd_write_com_busy(0x08); //显示功能关,无光标 100 lcd_write_com_busy(0x01); //清屏指令 101 lcd_write_com_busy(0x06); //写入新的数据后,光标右移,显示屏不移动 102 lcd_write_com_busy(0x0c); //显示功能开,无光标, 103 } 104 //--------------------------------------- 105 //名称: 指定地址写入函数 106 //----------------------------------------- 107 void lcd_write_char(unsigned char x,unsigned char y,unsigned char buf) 108 { 109 lcd_write_address(x,y); //写入地址 110 lcd_write_data(buf); //写入显示数据 111 } 112 113 //显示字符串 ,还不能准确应用 114 void lcd1602_write_character(unsigned char add,unsigned char *p) 115 { 116 lcd_write_com_busy(add); 117 while (*p!='\0') 118 { 119 lcd_write_data(*p++); 120 } 121 } 122 123 //将自定义字符写入CGRAM 124 //add是CGRAM 的地址(0~7) 125 //*pic_num是指向一个8位数组的首地址 126 void lcd1602_write_pic(unsigned char add,unsigned char pic_num) 127 { 128 unsigned char i; 129 add=add<<3; 130 for(i=0;i<8;i++) 131 { 132 lcd_write_com_busy(0x40|add+i); //设定行地址,DB6=1,所以地址可定要加上0X40; 133 lcd_write_data(pic_num); 134 } 135 } 136 137 //--------------------------------------- 138 //名称: 主函数 139 //----------------------------------------- 140 void main(void) 141 { 142 char i,m; 143 ADCON1=0X06; //所有IO均为数字口,模拟量输入禁止 144 TRISB=0B11000111; //RB3-5设置为输出 145 TRISD=0B00000000; //RD设置为输出 146 lcdreset(); //复位1602 147 lcd_write_char(6,0,0x31); //1 148 lcd_write_char(7,0,0x36); //6 149 lcd_write_char(8,0,0x30); //0 150 lcd_write_char(9,0,0x32); //2 151 lcd_write_char(10,0,0x35); //5 152 lcd_write_char(11,0,'g'); //g 153 lcd_write_char(12,0,'o'); //o 154 lcd_write_char(13,0,'o'); //o 155 lcd_write_char(14,0,'d'); //d 156 lcd_write_com_busy(0x80+0x44);//8.重新设定显示地址为0xc0,即下排第0位 157 for(m=0;m<12;m++) //将table1[]中的数据依次写入1602显示 158 { 159 lcd_write_data(table[m]); 160 } 161 //写八个自定义字符到CGRAM 162 lcd_write_com_busy(0x40); //7.设定CGRAM地址0100; 0x06 163 for(i=0;i<64;i++) //将心型代码写入CGRAM中 164 lcd_write_data(pic[i]);//lcd1602_write_pic(i,pic[i]); 165 //显示八个自定义字符 166 lcd_write_com_busy(0x80);//设定上排的显示位置 167 for(i=0;i<0x04;i++)//显示心型图案的上半部分 168 lcd_write_data(i); 169 lcd_write_com_busy(0xc0);////将显示坐标转移到下排和上排相对应的地方 170 for(i=4;i<0x08;i++) 171 lcd_write_data(i); 172 while(1) 173 { 174 175 } 176 }
使用4线数据传输
画完自定义字符这是第三步,在液晶屏刷新率不高的情况下,我们可以用1602的另一种4线数据传输可减少io口的使用数量。希望大家喜欢,由于没有找到相关资料这里只将程序贴出来给大家参考参考
#include<reg52.h>
#include<intrins.h>
sbit lcd1602_rs=P0^7;
sbit lcd1602_rw=P0^6;
sbit lcd1602_e=P0^5;
/*#define lcd1602_io_writ lcd1602_rw=0;
#define lcd1602_io_read lcd1602_rw=1;
#define lcd1602_io_com lcd1602_rs=0;
#define lcd1602_io_dat lcd1602_rs=1;
#define lcd1602_io_able lcd1602_e=0;
#define lcd1602_io_unable lcd1602_e=1;
*/
sbit lcd1602_dat1=P0^0;
sbit lcd1602_dat2=P0^1;
sbit lcd1602_dat3=P0^2;
sbit lcd1602_dat4=P0^3;
//unsigned char code table[]="ball hahhahhaha";
//unsigned char code table1[]="THE BEST!";
void delay(unsigned int z)
{
unsigned int a,b;
for(a=z;a>0;a--)
for(b=114;b>0;b--);
}
void lcd1602_write(bit cd,unsigned char dat)//cd=0,指令;c
{
int i;
unsigned char j;
lcd1602_rs=cd;
for(j=0;j<2;j++)
{
lcd1602_e=1;
for(i=0;i<200;i++)
_nop_();
lcd1602_dat4=dat&0x80;
lcd1602_dat3=(dat<<1)&0x80;
lcd1602_dat2=(dat<<2)&0x80;
lcd1602_dat1=(dat<<3)&0x80;
lcd1602_e=0;
//lcd1602_e=1;
dat<<=4;
}
}
/*unsigned char lcd1602_read_dat(unsigned char add)
{
unsigned char dat;
return dat;
}*/
void main()
{
lcd1602_rw=0;
lcd1602_e=0;
lcd1602_write(0,0x28);
lcd1602_write(0,0x0f);
lcd1602_write(0,0x06);
lcd1602_write(0,0x01);
lcd1602_write(0,0x80);
lcd1602_write(1,'q');
while(1);
}