• STM32液晶显示HT1621驱动原理及程序代码


    1、HT1621电路分析

          HT1621为32×4即128点内存映像LCD驱动器,包含内嵌的32×4位显示RAM内存和时基发生器以及WDT看门狗定时器.

          HT1621驱动电路如下图所示:

    图1

              与单片机相连接控制的有9脚CS,3脚WR,12脚DATA,其功能描述如下表。

    图2

    2、字符显示原理

             液晶管点亮和熄灭原理分别为在对应的RAM地址中写1和写0.首先需要清楚所驱动控制的液晶的COM-SEG对应关系,然后需要了解HT1621的32×4RAM地址映射。

             例如要控制的液晶的装脚成品图部分如下:

    图3

            着重看一个液晶数码管,我们了解原理就行。可以看到图3中是第2个液晶数码管,有7段,分别为A,B,C,D,E,F,G。也就分别为下面COMSEG地址对应关系图中的2A,2B,2C,2D,2E,2F,2G。

            液晶的显示字符的部分COM公共端输出口和SEG段输出口的分布如下表所示,同理我们可以看到例如:2D对应(SEG5,COM0),2E对应(SEG5,COM1),2F对应(SEG5,COM2),2A对应(SEG5,COM3),2C对应(SEG4,COM1),2G对应(SEG4,COM2),2B对应(SEG4,COM3)。

    图4

             搞清楚我们要控制的对象之后那,  HT1621的RAM 地址映射如下图所示:

    图5

            可以清楚的看到要控制液晶段对应SEG号作为6位地址,COM号对应作为4位数据写入,此时注意4位数据的高低位。写数据到RAM命令格式为:101+6位RAM地址+4位数据,其中RAM地址为SEG序号.

            例如我们在图3的第二个液晶数码管上显示数字,首先我们根据图3得到地址映射关系,先写入地址SEG4中的四位数据(COM3,COM2,COM1,COM0),再写如地址SEG5中的四位数据(COM3,COM2,COM1,COM0),对应关系如下:

    SEG4

    SEG5

    COM3

    COM2

    COM1

    COM0

    COM3

    COM2

    COM1

    COM0

    2B

    2G

    2C

    T10

    2A

    2F

    2E

    2D

            所以如果在图3中显示“5”,则在显示的液晶段对应地址上写1,不显示写0,如下图所示。所以SEG4地址应写入的数据为0110 ,SEG5地址应写入数据1101。

    图6

    3、显示的保持       

         写数据过程需要保证写前无关位数据的保持,因此在单片机程序中开辟32×4数组作为虚拟ARM,存储写前LCD显示数据.通过与清零,或置位操作实现,例如6位地址Address当前显示的数据为Data_last .若Xi(i=0,1,2,3) 位需要保持,则Xi为1,否则Xi为0.写入的数据为Data_now,变换公式为:

    4、程序

          主要的程序编写流程如下:

    图7

                程序的参考步骤:①Display_Wendu_1②write_addr_dat_n_wendu③write_mode④write_address⑤write_data_4bit,其中Lcdram数组为建立的虚拟数组。

      1 unsigned char Lcdram[32]=
      2     {
      3                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      4                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      5                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      6                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
      7     };
      8 
      9 const unsigned char Wendu[] = //温度0-9
     10     {   
     11     0X5F, 0X50, 0X3D, 0X79, 0X72, 0X6B, 0X6F, 0X51, 0X7F, 0X7B 
     12     };
     13 ///////////////////////////////////////////////////驱动函数
     14 /*
     15 *    LCD 模式写入
     16 *    入口:MODE :COM(命令模式) DAT(数据模式)
     17 *    出口:void
     18 */
     19 void write_mode(unsigned char MODE)    //写入模式,数据or命令
     20 {
     21     GPIO_ResetBits(GPIOB, HT1621_WR);                                //    RW = 0;
     22     delay_us(10);
     23     GPIO_SetBits(GPIOB, HT1621_DATA);                                    //    DA = 1;
     24     GPIO_SetBits(GPIOB, HT1621_WR);                                    //    RW = 1;
     25     delay_us(10);
     26 
     27     GPIO_ResetBits(GPIOB, HT1621_WR);                                //    RW = 0;
     28     delay_us(10);
     29     GPIO_ResetBits(GPIOB, HT1621_DATA);                                //    DA = 0;
     30     GPIO_SetBits(GPIOB, HT1621_WR);                                    //    RW = 1;
     31     delay_us(10);
     32 
     33     GPIO_ResetBits(GPIOB, HT1621_WR);                                //    RW = 0;
     34     delay_us(10);
     35 
     36     if (0 == MODE)
     37     {
     38         GPIO_ResetBits(GPIOB, HT1621_DATA);                            //    DA = 0;
     39     }
     40     else
     41     {
     42         GPIO_SetBits(GPIOB, HT1621_DATA);                                //    DA = 1;
     43     }
     44     delay_us(10);
     45     GPIO_SetBits(GPIOB, HT1621_WR);                                    //    RW = 1;
     46     delay_us(10);
     47 }
     48 
     49 /*
     50 *    LCD 命令写入函数
     51 *    入口:cbyte ,控制命令字
     52 *    出口:void
     53 */
     54 void write_command(unsigned char Cbyte)
     55 {
     56     unsigned char i = 0;
     57 
     58     for (i = 0; i < 8; i++)
     59     {
     60         GPIO_ResetBits(GPIOB, HT1621_WR);
     61         if ((Cbyte >> (7 - i)) & 0x01)
     62         {
     63             GPIO_SetBits(GPIOB, HT1621_DATA);
     64         }
     65         else
     66         {
     67             GPIO_ResetBits(GPIOB, HT1621_DATA);
     68         }
     69         delay_us(10);
     70         GPIO_SetBits(GPIOB, HT1621_WR);
     71         delay_us(10);
     72     }
     73     GPIO_ResetBits(GPIOB, HT1621_WR);
     74     delay_us(10);
     75     GPIO_ResetBits(GPIOB, HT1621_DATA);
     76     GPIO_SetBits(GPIOB, HT1621_WR);
     77     delay_us(10);
     78 }
     79 
     80 /*
     81 *    LCD 地址写入函数
     82 *    入口:cbyte,地址
     83 *    出口:void
     84 */
     85 void write_address(unsigned char Abyte)
     86 {
     87     unsigned char i = 0;
     88     Abyte = Abyte << 2;
     89 
     90     for (i = 0; i < 6; i++)
     91     {
     92         GPIO_ResetBits(GPIOB, HT1621_WR);
     93         //delay_us(10);
     94         if ((Abyte >> (7 - i)) & 0x01)
     95         {
     96             GPIO_SetBits(GPIOB, HT1621_DATA);
     97         }
     98         else
     99         {
    100             GPIO_ResetBits(GPIOB, HT1621_DATA);
    101         }
    102         delay_us(10);
    103         GPIO_SetBits(GPIOB, HT1621_WR);
    104         delay_us(10);
    105     }
    106     
    107 }
    108 
    109 /*
    110 *    LCD 数据写入函数
    111 *    入口:Dbyte,数据
    112 *    出口:void
    113 */
    114 void write_data_8bit(unsigned char Dbyte)
    115 {
    116     int i = 0;
    117 
    118     for (i = 0; i < 8; i++)
    119     {
    120         GPIO_ResetBits(GPIOB, HT1621_WR);
    121         delay_us(10);
    122         if ((Dbyte >> (7 - i)) & 0x01)
    123         {
    124             GPIO_SetBits(GPIOB, HT1621_DATA);
    125         }
    126         else
    127         {
    128             GPIO_ResetBits(GPIOB, HT1621_DATA);
    129         }
    130         delay_us(10);
    131         GPIO_SetBits(GPIOB, HT1621_WR);
    132         delay_us(10);
    133     }
    134 }
    135 
    136 void write_data_4bit(unsigned char Dbyte)
    137 {
    138     int i = 0;
    139 
    140     for (i = 0; i < 4; i++)
    141     {
    142         GPIO_ResetBits(GPIOB, HT1621_WR);
    143         //delay_us(10);
    144         if ((Dbyte >> (3 - i)) & 0x01)
    145         {
    146             GPIO_SetBits(GPIOB, HT1621_DATA);
    147         }
    148         else
    149         {
    150             GPIO_ResetBits(GPIOB, HT1621_DATA);
    151         }
    152         delay_us(10);
    153         GPIO_SetBits(GPIOB, HT1621_WR);
    154         delay_us(10);
    155     }
    156 }
    157 
    158 
    159 
    160 //1621初始化
    161 void ht1621_init(void)
    162 {
    163         GPIO_InitTypeDef GPIO_InitStructure;// declare the structure 
    164         GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
    165 
    166         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
    167         memset(&GPIO_InitStructure, 0, sizeof(GPIO_InitTypeDef));
    168         GPIO_InitStructure.GPIO_Pin =  HT1621_WR | HT1621_DATA ;//| HT1621_IRQ
    169         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    170         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    171         GPIO_Init(GPIOB, &GPIO_InitStructure);
    172 
    173         memset(&GPIO_InitStructure, 0, sizeof(GPIO_InitTypeDef));
    174         GPIO_InitStructure.GPIO_Pin = HT1621_CS ;//| HT1621_IRQ
    175         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    176         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    177         GPIO_Init(GPIOA, &GPIO_InitStructure);
    178 
    179 }
    180 
    181 /*
    182 *    LCD 初始化,对lcd自身做初始化设置
    183 *    入口:void
    184 *    出口:void
    185 */
    186 void lcd_init(void)
    187 {
    188     //////////////////////////////////////////////////////
    189     GPIO_SetBits(GPIOA, HT1621_CS);
    190     GPIO_SetBits(GPIOB, HT1621_WR);
    191     GPIO_SetBits(GPIOB, HT1621_DATA);
    192     for (ii=0;ii<10000;ii++)
    193     {for(j=10;j>0;j--);}
    194     //////////////////////////////////////////////////////        
    195     GPIO_ResetBits(GPIOA, HT1621_CS);        //CS = 0;
    196     //delay_us(10);
    197     for (ii=0;ii<10000;ii++)
    198     {for(j=10;j>0;j--);}
    199     write_mode(COMMAND);    //命令模式
    200     write_command(0x01);    //Enable System
    201     write_command(0x03);    //Enable Bias
    202     write_command(0x04);    //Disable Timer
    203     write_command(0x05);    //Disable WDT
    204     write_command(0x08);    //Tone OFF
    205     write_command(0x18);    //on-chip RC震荡
    206     write_command(0x29);    //1/4Duty 1/3Bias
    207     write_command(0x80);    //Disable IRQ
    208     write_command(0x40);    //Tone Frequency 4kHZ
    209     write_command(0xE3);    //Normal Mode
    210 
    211     GPIO_SetBits(GPIOA, HT1621_CS);  //CS = 1;
    212 }
    213 
    214 /*
    215 *    LCD 清屏函数
    216 *    入口:void
    217 *    出口:void
    218 */
    219 void lcd_clr(void)
    220 {
    221     write_addr_dat_n(0x0, 0x00, 32);//15
    222 }
    223 //用于温度区域写数据
    224 void write_addr_dat_n_wendu(unsigned char _addr, unsigned char _dat, unsigned char n)
    225 {
    226     
    227     unsigned char i = 0;
    228     unsigned char _dat_temp1,_dat_temp2;
    229     
    230     //WriteLcdram(_addr, _dat);
    231         
    232     
    233 
    234     GPIO_ResetBits(GPIOA, HT1621_CS);                                // CS = 0;
    235     write_mode(DAT);
    236     
    237     if(Lcdram[_addr]==0x00)
    238     {
    239         WriteLcdram(_addr, _dat);
    240     }
    241         if((_addr%2)==0)
    242         {
    243             _dat_temp1=Lcdram[_addr];
    244             _dat_temp2=(_dat_temp1&0x08)|_dat;
    245             
    246             write_address(_addr);
    247             for (i = 0; i < n; i++)
    248         {
    249             write_data_4bit(_dat_temp2);
    250         }
    251         GPIO_SetBits(GPIOA, HT1621_CS);                                    //CS = 1;
    252             
    253         }
    254         else if((_addr%2)!=0)
    255         {
    256             write_address(_addr);
    257             for (i = 0; i < n; i++)
    258         {
    259             write_data_4bit(_dat);
    260         }
    261         GPIO_SetBits(GPIOA, HT1621_CS);
    262         }
    263         
    264         WriteLcdram(_addr, _dat_temp2);
    265 }
    266 
    267 //用于湿度区域写数据
    268 void write_addr_dat_n_shidu(unsigned char _addr, unsigned char _dat, unsigned char n)
    269 {
    270     
    271     unsigned char i = 0;
    272     unsigned char _dat_temp1,_dat_temp2;
    273     
    274     //WriteLcdram(_addr, _dat);
    275         
    276     
    277 
    278     GPIO_ResetBits(GPIOA, HT1621_CS);                                // CS = 0;
    279     write_mode(DAT);
    280     
    281     if(Lcdram[_addr]==0x00)
    282     {
    283         WriteLcdram(_addr, _dat);
    284     }
    285         if((_addr%2)==0)
    286         {
    287             _dat_temp1=Lcdram[_addr];
    288             _dat_temp2=(_dat_temp1&0x01)|_dat;
    289             
    290             write_address(_addr);
    291             for (i = 0; i < n; i++)
    292         {
    293             write_data_4bit(_dat_temp2);
    294         }
    295         GPIO_SetBits(GPIOA, HT1621_CS);                                    //CS = 1;
    296             
    297         }
    298         else if((_addr%2)!=0)
    299         {
    300             write_address(_addr);
    301             for (i = 0; i < n; i++)
    302         {
    303             write_data_4bit(_dat);
    304         }
    305         GPIO_SetBits(GPIOA, HT1621_CS);
    306         }
    307         
    308         WriteLcdram(_addr, _dat_temp2);
    309 }
    310 
    311 
    312 //用于底部数字写数据
    313 void write_addr_dat_n_others(unsigned char _addr, unsigned char _dat, unsigned char n)
    314 {
    315     
    316     unsigned char i = 0;
    317     unsigned char _dat_temp1,_dat_temp2;
    318     GPIO_ResetBits(GPIOA, HT1621_CS);                                // CS = 0;
    319     write_mode(DAT);
    320     
    321     if(Lcdram[_addr]==0x00)
    322     {
    323         WriteLcdram(_addr, _dat);
    324         
    325     }
    326         if((_addr%2)==0)
    327         {
    328             _dat_temp1=Lcdram[_addr];
    329             _dat_temp2=(_dat_temp1&0x01)|_dat;
    330             
    331             write_address(_addr);
    332             for (i = 0; i < n; i++)
    333         {
    334             write_data_4bit(_dat_temp2);
    335         }
    336         GPIO_SetBits(GPIOA, HT1621_CS);                                    //CS = 1;
    337             
    338         }
    339         else if((_addr%2)!=0)
    340         {
    341             write_address(_addr);
    342             for (i = 0; i < n; i++)
    343         {
    344             write_data_4bit(_dat);
    345         }
    346         GPIO_SetBits(GPIOA, HT1621_CS);
    347         }
    348         
    349         //WriteLcdram(_addr, _dat);
    350         WriteLcdram(_addr, _dat_temp2);
    351 }
    352 
    353 //用于字符写数据
    354 void write_addr_dat_n_char(unsigned char _addr, unsigned char _dat, unsigned char state)
    355 {
    356     
    357     unsigned char i = 0;
    358     unsigned char _dat_temp1,_dat_temp2;
    359     
    360 
    361         GPIO_ResetBits(GPIOA, HT1621_CS);                                // CS = 0;
    362          write_mode(DAT);
    363             
    364                 _dat_temp1=Lcdram[_addr];
    365             if(state==1)
    366             {
    367                 
    368                 _dat_temp2=(_dat_temp1|_dat);
    369             }
    370             else if(state==0)
    371             {
    372                 _dat_temp2=(_dat_temp1&(~_dat));
    373             }
    374                  write_address(_addr);
    375             
    376                 for (i = 0; i < 1; i++)
    377             {
    378                 write_data_4bit(_dat_temp2);
    379             }
    380             GPIO_SetBits(GPIOA, HT1621_CS);                                    //CS = 1;
    381             WriteLcdram(_addr, _dat_temp2);
    382         
    383         
    384         
    385     
    386 }
    387 //显示温度
    388 //入口:pos,显示位置,地址0、2、4分别为从右到左的三个数字
    389 //            num:要显示的一位数
    390 void Display_Wendu_1(unsigned char add, unsigned char num )
    391 {
    392     unsigned char n,i,j;
    393     n=getChr_Wendu(num);
    394     i=(n&0xF0)>>4;
    395     j=n&0x0F;
    396     write_addr_dat_n_wendu(add,i,1);
    397     write_addr_dat_n_wendu(add+1,j,1);
    398     
    399 }
    400 
    401 
    402 //温度数据转换,lcd.c内部使用
    403  unsigned char getChr_Wendu(unsigned char c)
    404  {
    405      unsigned char i;
    406         for ( i = 0; i < 10; ++i)
    407         {
    408             if (c == i)
    409             {
    410                 return Wendu[i];
    411             }
    412         }
    413     }
    414 
    415 //更新lcdram数组
    416 void WriteLcdram(unsigned char add, unsigned char data)
    417 {
    418     
    419     Lcdram[add]=data;
    420     
    421 }
    View Code

     当轩不是怜苍翠,只要人知耐岁寒。

    转载需说明出处,笔者总结之前的知识,与大家分享,有问题的可以留给我哦~

  • 相关阅读:
    使用Tensorflow和MNIST识别自己手写的数字
    js 判断浏览器是否64位
    Spring动态注册bean实现动态多数据源
    springMVC 静态资源加版本号
    自定义Jquery插件——由于项目需要,对页面中过长的文本进行截取,鼠标移上去有一个title的提示,所以做了一个Jquery过长文本处理的插件
    MySQL Community Server 5.5.56 ZIP Archive 绿色解压版 window安装步骤
    【我整理的java开源项目】
    Java使用反射来获取成员变量泛型信息
    Intellij IDEA 各种乱码解决方案 posted @ 2017-06-23 15:31:06
    Django drf:cbv源码、resful规范及接口、drf使用、response源码、序列化
  • 原文地址:https://www.cnblogs.com/lemonzhang/p/9239172.html
Copyright © 2020-2023  润新知