×
单片机 > 单片机程序设计 > 详情

PIC18F452之1602自定义字符

发布时间:2020-06-08 发布时间:
|

显示自定义字符

  步骤如下: 
    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       //调用头文件,可以去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

 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 
#include 
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); 
}





『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32中断向量表的位置.重定向