你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32液晶显示HT1621驱动原理及程序代码

[复制链接]
STMCU小助手 发布时间:2022-2-5 23:00
1、HT1621电路分析
      HT1621为32×4即128点内存映像LCD驱动器,包含内嵌的32×4位显示RAM内存和时基发生器以及WDT看门狗定时器.
      HT1621驱动电路如下图所示:

1070495-20180627225051691-2038770537.png

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

1070495-20180627225513986-195694438.png

图2
2、字符显示原理
         液晶管点亮和熄灭原理分别为在对应的RAM地址中写1和写0.首先需要清楚所驱动控制的液晶的COM-SEG对应关系,然后需要了解HT1621的32×4RAM地址映射。
         例如要控制的液晶的装脚成品图部分如下:

1070495-20180628101719637-1218396171.png

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

1070495-20180628102414101-683330418.png

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

1070495-20180628103613524-643933794.png

图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。

1070495-20180628111442268-864304970.png

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

1070495-20180628151228131-2538792.png

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

1070495-20180628152647965-1330687251.png
图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. const unsigned char Wendu[] = //温度0-9
  9.     {
  10.     0X5F, 0X50, 0X3D, 0X79, 0X72, 0X6B, 0X6F, 0X51, 0X7F, 0X7B
  11.     };
  12. ///////////////////////////////////////////////////驱动函数
  13. /*
  14. *    LCD 模式写入
  15. *    入口:MODE :COM(命令模式) DAT(数据模式)
  16. *    出口:void
  17. */
  18. void write_mode(unsigned char MODE)    //写入模式,数据or命令
  19. {
  20.     GPIO_ResetBits(GPIOB, HT1621_WR);                                //    RW = 0;
  21.     delay_us(10);
  22.     GPIO_SetBits(GPIOB, HT1621_DATA);                                    //    DA = 1;
  23.     GPIO_SetBits(GPIOB, HT1621_WR);                                    //    RW = 1;
  24.     delay_us(10);

  25.     GPIO_ResetBits(GPIOB, HT1621_WR);                                //    RW = 0;
  26.     delay_us(10);
  27.     GPIO_ResetBits(GPIOB, HT1621_DATA);                                //    DA = 0;
  28.     GPIO_SetBits(GPIOB, HT1621_WR);                                    //    RW = 1;
  29.     delay_us(10);

  30.     GPIO_ResetBits(GPIOB, HT1621_WR);                                //    RW = 0;
  31.     delay_us(10);

  32.     if (0 == MODE)
  33.     {
  34.         GPIO_ResetBits(GPIOB, HT1621_DATA);                            //    DA = 0;
  35.     }
  36.     else
  37.     {
  38.         GPIO_SetBits(GPIOB, HT1621_DATA);                                //    DA = 1;
  39.     }
  40.     delay_us(10);
  41.     GPIO_SetBits(GPIOB, HT1621_WR);                                    //    RW = 1;
  42.     delay_us(10);
  43. }

  44. /*
  45. *    LCD 命令写入函数
  46. *    入口:cbyte ,控制命令字
  47. *    出口:void
  48. */
  49. void write_command(unsigned char Cbyte)
  50. {
  51.     unsigned char i = 0;

  52.     for (i = 0; i < 8; i++)
  53.     {
  54.         GPIO_ResetBits(GPIOB, HT1621_WR);
  55.         if ((Cbyte >> (7 - i)) & 0x01)
  56.         {
  57.             GPIO_SetBits(GPIOB, HT1621_DATA);
  58.         }
  59.         else
  60.         {
  61.             GPIO_ResetBits(GPIOB, HT1621_DATA);
  62.         }
  63.         delay_us(10);
  64.         GPIO_SetBits(GPIOB, HT1621_WR);
  65.         delay_us(10);
  66.     }
  67.     GPIO_ResetBits(GPIOB, HT1621_WR);
  68.     delay_us(10);
  69.     GPIO_ResetBits(GPIOB, HT1621_DATA);
  70.     GPIO_SetBits(GPIOB, HT1621_WR);
  71.     delay_us(10);
  72. }

  73. /*
  74. *    LCD 地址写入函数
  75. *    入口:cbyte,地址
  76. *    出口:void
  77. */
  78. void write_address(unsigned char Abyte)
  79. {
  80.     unsigned char i = 0;
  81.     Abyte = Abyte << 2;

  82.     for (i = 0; i < 6; i++)
  83.     {
  84.         GPIO_ResetBits(GPIOB, HT1621_WR);
  85.         //delay_us(10);
  86.         if ((Abyte >> (7 - i)) & 0x01)
  87.         {
  88.             GPIO_SetBits(GPIOB, HT1621_DATA);
  89.         }
  90.         else
  91.         {
  92.             GPIO_ResetBits(GPIOB, HT1621_DATA);
  93.         }
  94.         delay_us(10);
  95.         GPIO_SetBits(GPIOB, HT1621_WR);
  96.         delay_us(10);
  97.     }

  98. }

  99. /*
  100. *    LCD 数据写入函数
  101. *    入口:Dbyte,数据
  102. *    出口:void
  103. */
  104. void write_data_8bit(unsigned char Dbyte)
  105. {
  106.     int i = 0;

  107.     for (i = 0; i < 8; i++)
  108.     {
  109.         GPIO_ResetBits(GPIOB, HT1621_WR);
  110.         delay_us(10);
  111.         if ((Dbyte >> (7 - i)) & 0x01)
  112.         {
  113.             GPIO_SetBits(GPIOB, HT1621_DATA);
  114.         }
  115.         else
  116.         {
  117.             GPIO_ResetBits(GPIOB, HT1621_DATA);
  118.         }
  119.         delay_us(10);
  120.         GPIO_SetBits(GPIOB, HT1621_WR);
  121.         delay_us(10);
  122.     }
  123. }

  124. void write_data_4bit(unsigned char Dbyte)
  125. {
  126.     int i = 0;

  127.     for (i = 0; i < 4; i++)
  128.     {
  129.         GPIO_ResetBits(GPIOB, HT1621_WR);
  130.         //delay_us(10);
  131.         if ((Dbyte >> (3 - i)) & 0x01)
  132.         {
  133.             GPIO_SetBits(GPIOB, HT1621_DATA);
  134.         }
  135.         else
  136.         {
  137.             GPIO_ResetBits(GPIOB, HT1621_DATA);
  138.         }
  139.         delay_us(10);
  140.         GPIO_SetBits(GPIOB, HT1621_WR);
  141.         delay_us(10);
  142.     }
  143. }



  144. //1621初始化
  145. void ht1621_init(void)
  146. {
  147.         GPIO_InitTypeDef GPIO_InitStructure;// declare the structure
  148.         GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

  149.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
  150.         memset(&GPIO_InitStructure, 0, sizeof(GPIO_InitTypeDef));
  151.         GPIO_InitStructure.GPIO_Pin =  HT1621_WR | HT1621_DATA ;//| HT1621_IRQ
  152.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  153.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  154.         GPIO_Init(GPIOB, &GPIO_InitStructure);

  155.         memset(&GPIO_InitStructure, 0, sizeof(GPIO_InitTypeDef));
  156.         GPIO_InitStructure.GPIO_Pin = HT1621_CS ;//| HT1621_IRQ
  157.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  158.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  159.         GPIO_Init(GPIOA, &GPIO_InitStructure);

  160. }

  161. /*
  162. *    LCD 初始化,对lcd自身做初始化设置
  163. *    入口:void
  164. *    出口:void
  165. */
  166. void lcd_init(void)
  167. {
  168.     //////////////////////////////////////////////////////
  169.     GPIO_SetBits(GPIOA, HT1621_CS);
  170.     GPIO_SetBits(GPIOB, HT1621_WR);
  171.     GPIO_SetBits(GPIOB, HT1621_DATA);
  172.     for (ii=0;ii<10000;ii++)
  173.     {for(j=10;j>0;j--);}
  174.     //////////////////////////////////////////////////////
  175.     GPIO_ResetBits(GPIOA, HT1621_CS);        //CS = 0;
  176.     //delay_us(10);
  177.     for (ii=0;ii<10000;ii++)
  178.     {for(j=10;j>0;j--);}
  179.     write_mode(COMMAND);    //命令模式
  180.     write_command(0x01);    //Enable System
  181.     write_command(0x03);    //Enable Bias
  182.     write_command(0x04);    //Disable Timer
  183.     write_command(0x05);    //Disable WDT
  184.     write_command(0x08);    //Tone OFF
  185.     write_command(0x18);    //on-chip RC震荡
  186.     write_command(0x29);    //1/4Duty 1/3Bias
  187.     write_command(0x80);    //Disable IRQ
  188.     write_command(0x40);    //Tone Frequency 4kHZ
  189.     write_command(0xE3);    //Normal Mode

  190.     GPIO_SetBits(GPIOA, HT1621_CS);  //CS = 1;
  191. }

  192. /*
  193. *    LCD 清屏函数
  194. *    入口:void
  195. *    出口:void
  196. */
  197. void lcd_clr(void)
  198. {
  199.     write_addr_dat_n(0x0, 0x00, 32);//15
  200. }
  201. //用于温度区域写数据
  202. void write_addr_dat_n_wendu(unsigned char _addr, unsigned char _dat, unsigned char n)
  203. {

  204.     unsigned char i = 0;
  205.     unsigned char _dat_temp1,_dat_temp2;

  206.     //WriteLcdram(_addr, _dat);



  207.     GPIO_ResetBits(GPIOA, HT1621_CS);                                // CS = 0;
  208.     write_mode(DAT);

  209.     if(Lcdram[_addr]==0x00)
  210.     {
  211.         WriteLcdram(_addr, _dat);
  212.     }
  213.         if((_addr%2)==0)
  214.         {
  215.             _dat_temp1=Lcdram[_addr];
  216.             _dat_temp2=(_dat_temp1&0x08)|_dat;

  217.             write_address(_addr);
  218.             for (i = 0; i < n; i++)
  219.         {
  220.             write_data_4bit(_dat_temp2);
  221.         }
  222.         GPIO_SetBits(GPIOA, HT1621_CS);                                    //CS = 1;

  223.         }
  224.         else if((_addr%2)!=0)
  225.         {
  226.             write_address(_addr);
  227.             for (i = 0; i < n; i++)
  228.         {
  229.             write_data_4bit(_dat);
  230.         }
  231.         GPIO_SetBits(GPIOA, HT1621_CS);
  232.         }

  233.         WriteLcdram(_addr, _dat_temp2);
  234. }

  235. //用于湿度区域写数据
  236. void write_addr_dat_n_shidu(unsigned char _addr, unsigned char _dat, unsigned char n)
  237. {

  238.     unsigned char i = 0;
  239.     unsigned char _dat_temp1,_dat_temp2;

  240.     //WriteLcdram(_addr, _dat);



  241.     GPIO_ResetBits(GPIOA, HT1621_CS);                                // CS = 0;
  242.     write_mode(DAT);

  243.     if(Lcdram[_addr]==0x00)
  244.     {
  245.         WriteLcdram(_addr, _dat);
  246.     }
  247.         if((_addr%2)==0)
  248.         {
  249.             _dat_temp1=Lcdram[_addr];
  250.             _dat_temp2=(_dat_temp1&0x01)|_dat;

  251.             write_address(_addr);
  252.             for (i = 0; i < n; i++)
  253.         {
  254.             write_data_4bit(_dat_temp2);
  255.         }
  256.         GPIO_SetBits(GPIOA, HT1621_CS);                                    //CS = 1;

  257.         }
  258.         else if((_addr%2)!=0)
  259.         {
  260.             write_address(_addr);
  261.             for (i = 0; i < n; i++)
  262.         {
  263.             write_data_4bit(_dat);
  264.         }
  265.         GPIO_SetBits(GPIOA, HT1621_CS);
  266.         }

  267.         WriteLcdram(_addr, _dat_temp2);
  268. }


  269. //用于底部数字写数据
  270. void write_addr_dat_n_others(unsigned char _addr, unsigned char _dat, unsigned char n)
  271. {

  272.     unsigned char i = 0;
  273.     unsigned char _dat_temp1,_dat_temp2;
  274.     GPIO_ResetBits(GPIOA, HT1621_CS);                                // CS = 0;
  275.     write_mode(DAT);

  276.     if(Lcdram[_addr]==0x00)
  277.     {
  278.         WriteLcdram(_addr, _dat);

  279.     }
  280.         if((_addr%2)==0)
  281.         {
  282.             _dat_temp1=Lcdram[_addr];
  283.             _dat_temp2=(_dat_temp1&0x01)|_dat;

  284.             write_address(_addr);
  285.             for (i = 0; i < n; i++)
  286.         {
  287.             write_data_4bit(_dat_temp2);
  288.         }
  289.         GPIO_SetBits(GPIOA, HT1621_CS);                                    //CS = 1;

  290.         }
  291.         else if((_addr%2)!=0)
  292.         {
  293.             write_address(_addr);
  294.             for (i = 0; i < n; i++)
  295.         {
  296.             write_data_4bit(_dat);
  297.         }
  298.         GPIO_SetBits(GPIOA, HT1621_CS);
  299.         }

  300.         //WriteLcdram(_addr, _dat);
  301.         WriteLcdram(_addr, _dat_temp2);
  302. }

  303. //用于字符写数据
  304. void write_addr_dat_n_char(unsigned char _addr, unsigned char _dat, unsigned char state)
  305. {

  306.     unsigned char i = 0;
  307.     unsigned char _dat_temp1,_dat_temp2;


  308.         GPIO_ResetBits(GPIOA, HT1621_CS);                                // CS = 0;
  309.          write_mode(DAT);

  310.                 _dat_temp1=Lcdram[_addr];
  311.             if(state==1)
  312.             {

  313.                 _dat_temp2=(_dat_temp1|_dat);
  314.             }
  315.             else if(state==0)
  316.             {
  317.                 _dat_temp2=(_dat_temp1&(~_dat));
  318.             }
  319.                  write_address(_addr);

  320.                 for (i = 0; i < 1; i++)
  321.             {
  322.                 write_data_4bit(_dat_temp2);
  323.             }
  324.             GPIO_SetBits(GPIOA, HT1621_CS);                                    //CS = 1;
  325.             WriteLcdram(_addr, _dat_temp2);




  326. }
  327. //显示温度
  328. //入口:pos,显示位置,地址0、2、4分别为从右到左的三个数字
  329. //            num:要显示的一位数
  330. void Display_Wendu_1(unsigned char add, unsigned char num )
  331. {
  332.     unsigned char n,i,j;
  333.     n=getChr_Wendu(num);
  334.     i=(n&0xF0)>>4;
  335.     j=n&0x0F;
  336.     write_addr_dat_n_wendu(add,i,1);
  337.     write_addr_dat_n_wendu(add+1,j,1);

  338. }


  339. //温度数据转换,lcd.c内部使用
  340. unsigned char getChr_Wendu(unsigned char c)
  341. {
  342.      unsigned char i;
  343.         for ( i = 0; i < 10; ++i)
  344.         {
  345.             if (c == i)
  346.             {
  347.                 return Wendu[i];
  348.             }
  349.         }
  350.     }

  351. //更新lcdram数组
  352. void WriteLcdram(unsigned char add, unsigned char data)
  353. {

  354.     Lcdram[add]=data;

  355. }
复制代码


收藏 评论1 发布时间:2022-2-5 23:00

举报

1个回答
行色匆匆 回答时间:2022-2-6 00:00:03

ST有自带段码液晶驱动型号吗?

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版