zoukankan      html  css  js  c++  java
  • PIC18F452之1602自定义字符

    显示自定义字符

      步骤如下:
        1. 先将自定义字符写入CGRAM ; 2. 再将CGRAM中的自定义字符送到DDRAM中显示
      很简单的:看好了
      查看LCD1602 的CGROM 字符代码表,可以发现 从00000000B~00000111B00H~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”。

    View Code
      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);
    }

  • 相关阅读:
    帮你拿下 Java 面试题!
    JavaGUI编程的宿世此生
    从事Java开发可以往那些方面发展
    java初学者都要掌握的案例
    两数之和(java)
    2020年java就业前景
    300 行代码带你秒懂 Java 多线程!
    安卓程序员如何快速入门后端开发常识
    连夜整理的Java开源项目,有后台管理类、商城类、秒杀类、支付类
    Java面试题及答案,2020年最新面试题集合
  • 原文地址:https://www.cnblogs.com/wangh0802PositiveANDupward/p/2590841.html
Copyright © 2011-2022 走看看