【STM32】_02_使用HT1621B驱动段码液晶屏
一、简介
1.1 什么是段码液晶屏
详细的介绍可以看这位博主的帖子:那头时空。
着急的朋友就不用看了,简单来说段码液晶屏的驱动需要交流电,有些MCU会自带LCD液晶驱动,而通常我们则会采用像HT1621B这样的LCD驱动器来控制段码屏。
1.2 HT1621B
简单来说,HT1621B最多可以控制具有128个显示点位的段码屏,与MCU之间的通信仅需三线即可CS片选线,低电平有效、WR写时钟线,上升沿写入、DATA线,串行数据输入/输出。
详细的内容请看数据手册:HT1621B数据手册。
二、HT1621B的驱动电路
最简单的连接方式就是将段码屏SEG0-SEG13(我这个屏SEG脚有14个,这种屏都是定制的,具体你要用几个脚要看你定制的屏有几个) 和HT1621B的SEG0-SEG13按照顺序对应的连到一起 (如果你的硬件是乱序相连的,那你就只能在软件上进行一下转换了,也就是你写入数据的地址可能不是从0开始的,也可能不连续),将段码屏COM0-COM3和HT1621B的COM0-COM3按照顺序对应的连到一起 。将HT1621B的CS、WR、DATA与MCU的3个IO口(任选)相连,这样硬件的连接就完成了。
三、驱动程序
3.1 写一位数据到HT1621B
时序图如下
从图中可看出,在片选为低电平且写时钟线的上升沿时才能写入数据。
/**
* @brief 写数据到HT1621
* @param Data:要写入的数据bits
* @param num:传送数据位数
* @retval 无
*/
void write_bit_ht1621(uint8_t data, uint8_t num)
{
uint8_t i;
for (i = 0; i < num; i++)
{
LCD_WR_0(); /* 拉低WR脚 Data线上的数据在WR脚位上升沿写入 */
if (((data & 0x80) >> 7) == 1) /* 如果当前bit为1,就拉高DATA引脚 */
{
LCD_DATA_1();
}
else if (((data & 0x80) >> 7) == 0) /* 如果当前bit为0,就拉低DATA引脚 */
{
LCD_DATA_0();
}
LCD_WR_1(); /* 当前这一bit写完,拉高WR脚,为下次WR为上升沿做准备 */
data <<= 1; /* 当前位用完了,移到下一位继续上述动作 */
}
}
3.2 向HT1621B相应地址写入数据,来控制段码屏显示相应字符
首先,我们先了解一下HT1621B的地址映射,如下图
这个图的意思就是SEG0就是地址0,程序中传地址时你可以写为十进制的0也可以写为十六进制的0,每个地址位可以控制4个位,对应LCD屏上4个点的显示(在下面数码管中,a、b、c、d就代表4个点)
在编写具体的显示程序时,要根据厂商给出的真值表进行编写,如下图是我所用的,
我的思路是,14个地址,一个地址4bit,那就相当于7个8bit数据,所以我定义了1个char型的数组有7个元素。HT1621B是支持连续写的。
/* 真值表顺序 FGEABCD */
/* 0,1,2,3,4,5,6,7,8,9,灭 */
const char num[] = {
0x5F, 0x06, 0x3D, 0x2F, 0x66, 0x6B, 0x7B, 0x0E, 0x7F, 0x6F, 0x00};
char dispnum[7] = {
0x00};
/**
* @brief 将要显示的数据写到HT1621
* @param Addr:写入初始地址
* @param Data:要写入的数据
* @param Mode:COMMAND_CODE(0X80) / WRITE_DATA_CODE(0XA0)
* @retval 无
*/
void write_ht1621(uint8_t addr, uint8_t data)
{
LCD_CS_0();
write_bit_ht1621(WRITE_DATA_CODE, 3); /* 命令模式或数据模式 */
write_bit_ht1621(addr << 2, 6); /* 写入地址 */
write_bit_ht1621(data, 8); /* 写入数据 */
LCD_CS_1();
}
这里可能会有人有疑问,时序图中数据是低位先传,而我们这里却是高位先传,不用担心我们在编写真值表时已经将低位放在了高位,所以完全没问题。
3.3 向HT1621B写入命令
从时序图中可以看出,命令模式码有3位,而命令代码有9位,但最后一位0、1都行,有些朋友喜欢直接舍弃不管它,而我则是把C8和3位命令码放在一起 C0和C7放在一起注意不同的排序方法,命令代码的值不同,数据手册有详细的命令代码
/* HT1621 命令定义 */
#define COMMAND_CODE 0x80 /* 命令码 */
#define WRITE_DATA_CODE 0xA0 /* 写命令 */
#define HT1621_SYS_EN 0x02 /* 打开系统振荡器 */
#define HT1621_RC256 0x30 /* 内部时钟 */
#define HT1621_BIAS 0x52 /* 1/3duty 4com LCD偏置 */
/**
* @brief 写命令到HT1621
* @param Cmd:命令
* @retval 无
*/
void write_cmd_ht1621(uint8_t cmd)
{
LCD_CS_0(); /* 拉低CS脚 CS拉低时WR有效 */
write_bit_ht1621(COMMAND_CODE, 4); /* 写入命令标志100 0x80 */
write_bit_ht1621(cmd, 8); /* 写入命令数据 */
LCD_CS_1(); /* 拉高CS脚 */
}
从真值表来看,有些单个符号在和数码管显示混在了一起,这时只需使用位与和位或就可以单独控制它了,可以看下lcd_display(),看下各位就有思路了。
3.4 ht1621.h
#ifndef __HT1621_H
#define __HT1621_H
#include "stm32f10x.h"
/* HT1621硬件连接端口定义 */
#define HT1621_CS_PORT GPIOB /* GPIO端口 */
#define HT1621_CS_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define HT1621_CS_PIN GPIO_Pin_12 /* 定义HT1621的CS管脚 */
#define HT1621_DATA_PORT GPIOB /* GPIO端口 */
#define HT1621_DATA_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define HT1621_DATA_PIN GPIO_Pin_1