目录
最近学习了段式屏幕LCD,纯手巧时序图代码,以此记录自己的成长过程!
最近学习了段式屏幕LCD,纯手巧时序图代码,以此记录自己的成长过程!
HT1621B内部具有32×4位的显示RAM,用于存储显示数据。
显示RAM的内部由32个地址连续的RAM单元组成。从地址为0的单元到地址为31的单元,分别对应LCD的段电极输出SEG0到SEG31。其中每一个RAM单元又分为4位,从低位到高位分别对应背电极输出COM0到COM3。
也就是说,32×4位RAM内存中的每一位都对应着一个LCD显示段,所以,HT1621B最多可以驱动128段的LCD显示屏。
首先明白两个术语:写命令,写数据
1.写命令:是告诉液晶屏你要做什么,
2.写数据:是把你要显示的数据送给液晶屏
首先声明在本程序中和移植相关的针对不同MCU所需要的做出的修改如下:
#include “HT1621b.h”
#define COMMAND_CODE 0x80 //命令码---100
#define WRITE_DATA_CODE 0xA0 //写命令---101
#define READ_DATA_CODE 0xC0 //读命令---110
#define SYSDIS 0X800 //0B 1000 0000 000X 关振荡器和LCD偏压发生器
#define SYSEN 0X802 //0B 1000 0000 001X 打开系统振荡器
#define LCDOFF 0X804 //0B 1000 0000 010X 关LCD偏压
#define LCDON 0x806 //0B 1000 0000 011X 开LCD偏压
#define TIMERDIS 0x808 //0B 1000 0000 100X 时基输出失效
#define WDTDIS 0X80A //0B 1000 0000 101X WDT溢出标志输出失效
#define TIMEREN 0X80C //0B 1000 0000 110X 时基输出使能
#define WDTEN 0X80E //0B 1000 0000 111X WDT溢出标志输出有效
#define TONEOFF 0X810 //0B 1000 0001 000X 关闭声音输出
#define TONEON 0X812 //0B 1000 0001 001X 打开声音输出
#define CLRTIMER 0X818 //0B 1000 0001 100X 时基发生器清零
#define CLRWDT 0X81C //0B 1000 0001 110X 清除WDT状态
#define XTAL_32K 0X828 //0B 1000 0010 100X 系统时钟源,晶振
#define RC256 0X830 //0B 1000 0011 000X 系统时钟源,片内RC
#define EXT256 0X838 //0B 1000 0011 100X 系统时钟源,外部时钟源
#define BIAS1_2_2COM 0X840 //0B 1000 0100 000X LCD 1/2偏压选项,2个公共口
#define BIAS1_2_3COM 0X848 //0B 1000 0100 100X LCD 1/2偏压选项,3个公共口
#define BIAS1_2_4COM 0X850 //0B 1000 0101 000X LCD 1/2偏压选项,4个公共口
#define BIAS1_3_2COM 0X842 //0B 1000 0100 001X LCD 1/3偏压选项,2个公共口
#define BIAS1_3_3COM 0X85A //0B 1000 0100 101X LCD 1/3偏压选项,3个公共口
#define BIAS1_3_4COM 0X852 //0B 1000 0101 001X LCD 1/3偏压选项,4个公共口
#define TONE4K 0X880 //0B 1000 1000 000X 声音频率4K
#define TONE2K 0X8C0 //0B 1000 1100 000X 声音频率2K
#define IRQ_DIS 0X900 //0B 1001 0000 000X 使/IRQ输出失效
#define IRQ_EN 0X910 //0B 1001 0001 000X 使/IRQ输出有效
#define BIAS 0x852 //0b 1000 0101 0010 1/3duty 4com
命令格式100开始,8位命令,1位补位
例如:打开LCD偏置发生器 LCD ON 命令
100 00000011 x
写数据格式101开始,6位地址,4位数据
101 A5A4A3A2A1A0 D0D1D2D3
地址就是SEG的序号
我的真值表是这样子的,你们就对应自己的就好
例如我这里30个SEG脚,每两个控制一个数码管,记住每两个控制一个数码管,划重点,这句话很关键,以第一个数码管为例
1----亮
0-----灭
数据位是
0b 0110 1101=0x6D
D0D1D2D3D0D1D2D3,,每个是四个二进制码,这里使用8个二进制码,地址自动向下移一位。
上面说写数据中的6位地址就是SEG的序号。是真的地址,10进制的。
控制SEG29 地址码就是1D,SEG30的地址是1E
控制代码:
由于HT1621B需要一定的延时
void Delayms(u32 Cnt)
{
u32 Delay=16000;
for(;Cnt>0;Cnt--)
{
for(Delay=16000; Delay>0; Delay--);
}
}
先设置引脚。MCU要控制的是WR,DA,CS三个引脚。用户自己选择自己板子的引脚设置,我的是这三个
向HT1621发送字节的函数。sdat是具体数据,cnt是要发送的个数(单位是二进制)
void HT1621_SendBit(uint8_t sdat,uint8_t cnt)
{
uint8_t i=0;
for(i=0;i<cnt;i++)
{
RESET_WR();
HAL_Delay_us(20);
if(sdat&0x80)
{
SET_DA();
}
else
{
RESET_DA();
}
HAL_Delay_us(20);
SET_WR();
HAL_Delay_us(20);
sdat<<=1;
}
}
发送命令函数,0x80是0b10000000,100是HT1621的命令指令,command就是要控制的指令,如打开时钟等。此函数一般在液晶初始化设置模式时使用。
void HT1621_SendCmd(uint8_t command)
{
RESET_CS();
HT1621_SendBit(0x80,4);
HT1621_SendBit(command,8);
SET_CS();
}
发送数据函数,addr是地址(也就是上面说的SEG的引脚序号),左移2位是因为地址时六位,而uint8_t型是八位,前面空了两位。sdat是数据(就是四个COM口)
void HT1621_WriteData(uint8_t addr,uint8_t sdat)
{
addr<<=2;
sdat<<=4;
RESET_CS();
HT1621_SendBit(0xa0,3);//1010
HT1621_SendBit(addr,6);
HT1621_SendBit(sdat,4); //一次只发送4位数据,一个地址发送1次,低四位
SET_CS();
}
/*********************************************************
函数名:LCD_Init(void)
返回值:无
功 能:LCD初始化
*********************************************************/
void LCD_Init(void)
{
Write_Cmd(LCD_OFF);//关闭LCD 偏压发生器
HT1621_Delay(DELAY_TEST);
Write_Cmd(SYSEN);//打开系统振荡器
HT1621_Delay(DELAY_TEST);
Write_Cmd(BIAS1_3_4COM);//LCD 1/3偏压选项,4个公共口
HT1621_Delay(DELAY_TEST);
Write_Cmd(LCD_ON);//打开LCD 偏压发生器
HT1621_Delay(DELAY_TEST);
}
最后就实现功能了
分享一下代码连接:
链接:https://pan.baidu.com/s/1qmDTdIRe3brbGXixLjnaGg
提取码:m3pf