LCD液晶屏资料
LCD液晶屏资料
重要参数:
- 工作电压: 3V
- 可视角度:120°
- 1/4 ,1/3
TH1621 驱动
HT1621 LCD控制驱动芯片介绍
VLCD 和 VCC 电压符合规格书,最好都取3.3V 。电压太高或太低都会出现段码液晶屏乱码的情况,要么多一笔,要么若隐若现的显示一笔。
TH1621.h
/*******************************************************************************
Copyright 2016-2018 anxzhu (github.com/anxzhu)
Copyright 2018-2020 Valerio Nappi (github.com/valerionew) (changes)
Based on segment-lcd-with-ht1621 from anxzhu (2016-2018)
(https://github.com/anxzhu/segment-lcd-with-ht1621)
Partially rewritten and extended by Valerio Nappi (github.com/valerionew) in 2018
This file is part of the HT1621 arduino library, and thus under the MIT license.
More info on the project and the license conditions on :
https://github.com/valerionew/ht1621-7-seg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/
#ifndef HT1621_H_
#define HT1621_H_ //防止重复包含
const unsigned char LCDCODE[11]={0xFA,0x0A,0xBC,0x9E,0x4E,0xD6,0xF6,0x8A,0xFE,0xDE,0x00}; // LCDCODE[10] = 0x00 不显示任何东西
#define BIAS 0x52 //0b1000 0101 0010 1/3duty 4com
#define SYSDIS 0X00 //0b1000 0000 0000 关振系统荡器和LCD偏压发生器
#define SYSEN 0X02 //0b1000 0000 0010 打开系统振荡器
#define LCDOFF 0X04 //0b1000 0000 0100 关LCD偏压
#define LCDON 0X06 //0b1000 0000 0110 打开LCD偏压
#define XTAL 0x28 //0b1000 0010 1000 外部接时钟
#define RC256 0X30 //0b1000 0011 0000 内部时钟
#define TONEON 0X12 //0b1000 0001 0010 打开声音输出
#define TONEOFF 0X10 //0b1000 0001 0000 关闭声音输出
#define WDTDIS1 0X0A //0b1000 0000 1010 禁止看门狗
#define BUFFERSIZE 12
// #define HT1621_DEBUG
class HT1621
{
public:
HT1621();
void begin(int cs_p, int wr_p, int data_p, int backlight_p);
void begin(int cs_p, int wr_p, int data_p);
void clear();
void backlight();
void noBacklight();
void setBatteryLevel(int level,unsigned char *s);
void print(long num, const char* flags="%6li", int precision = 0);
void print(double num, int precision = 3);
void printCelsius(double num); // precision is always 1
void print(const char* str, bool leftPadded = false);
void display();
void noDisplay();
private:
int _cs_p;
int _wr_p;
int _data_p;
int _backlight_p;
bool _backlight_en;
char _buffer[BUFFERSIZE];
unsigned char _battery[3];
void wrone(unsigned char addr, unsigned char sdata);
void wrclrdata(unsigned char addr, unsigned char sdata);
void wrCLR(unsigned char len);
void wrDATA(unsigned char data, unsigned char cnt);
void wrCMD(unsigned char CMD);
void setdecimalseparator(int dpposition);
void config(); // legacy: why not in begin func
void update();
char charToSegBits(char character);
};
#endif
HT1621.cpp
/*******************************************************************************
Copyright 2016-2018 anxzhu (github.com/anxzhu)
Copyright 2018-2020 Valerio Nappi (github.com/5N44P) (changes)
Based on segment-lcd-with-ht1621 from anxzhu (2016-2018)
(https://github.com/anxzhu/segment-lcd-with-ht1621)
Partially rewritten and extended by Valerio Nappi (github.com/5N44P) in 2018
This file is part of the HT1621 arduino library, and thus under the MIT license.
More info on the project and the license conditions on :
https://github.com/5N44P/ht1621-7-seg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/
#include <Arduino.h>
#include "HT1621.h"
HT1621::HT1621(){
_buffer[0] = 0x00;
_buffer[1] = 0x00;
_buffer[2] = 0x00;
_buffer[3] = 0x00;
_buffer[4] = 0x00;
_buffer[5] = 0x00;
_buffer[6] = 0x00;
}
void HT1621::begin(int cs_p, int wr_p, int data_p, int backlight_p)
{
pinMode(cs_p, OUTPUT);
pinMode(wr_p, OUTPUT);
pinMode(data_p, OUTPUT);
pinMode(backlight_p, OUTPUT);
_cs_p=cs_p;
_wr_p=wr_p;
_data_p=data_p;
_backlight_p=backlight_p;
_backlight_en=true;
config();
}
void HT1621::begin(int cs_p, int wr_p, int data_p)
{
pinMode(cs_p, OUTPUT);
pinMode(wr_p, OUTPUT);
pinMode(data_p, OUTPUT);
_cs_p=cs_p;
_wr_p=wr_p;
_data_p=data_p;
_backlight_en = false;
config();
}
void HT1621::wrDATA(unsigned char data, unsigned char cnt) {
unsigned char i;
for (i = 0; i < cnt; i++) {
digitalWrite(_wr_p, LOW);
delayMicroseconds(4);
if (data & 0x80) {
digitalWrite(_data_p, HIGH);
}
else {
digitalWrite(_data_p, LOW);
}
digitalWrite(_wr_p, HIGH);
delayMicroseconds(4);
data <<= 1;
}
}
void HT1621::wrclrdata(unsigned char addr, unsigned char sdata)
{
addr+=9;
addr <<= 2;
digitalWrite(_cs_p, LOW);
wrDATA(0xa0, 3);
wrDATA(addr, 6);
wrDATA(sdata, 8);
digitalWrite(_cs_p, HIGH);
}
void HT1621::display()
{
wrCMD(LCDON);
}
void HT1621::noDisplay()
{
wrCMD(LCDOFF);
}
// 写数据到RAM命令格式为:101+6位RAM地址+4位数据,其中RAM地址为SEG序号 (参考:https://blog.csdn.net/qq_36347513/article/details/107330387)
//
void HT1621::wrone(unsigned char addr, unsigned char sdata)// 101 数据模式 读写之间变换
{
addr+=9;// HT1621 SSOP-24 芯片的SEG脚从SEG9开始的 ,所以addr+9;
addr <<= 2;
digitalWrite(_cs_p, LOW);
wrDATA(0xa0, 3);// 101
wrDATA(addr, 6);
wrDATA(sdata, 8); // 0XF7 "8"
digitalWrite(_cs_p, HIGH);
}
// void HT1621::update(){
the buffer is backwards with respect to the lcd. could be improved
// wrone(0, _buffer[5]);
// wrone(2, _buffer[4]);
// wrone(4, _buffer[3]);
// wrone(6, _buffer[2]);
// wrone(8, _buffer[1]);
// wrone(10,_buffer[0]);
// }
void HT1621::backlight()
{
if (_backlight_en)
digitalWrite(_backlight_p, HIGH);
delay(1);
}
void HT1621::noBacklight()
{
if(_backlight_en)
digitalWrite(_backlight_p, LOW);
delay(1);
}
void HT1621::wrCMD(unsigned char CMD) { //100 命令模式
digitalWrite(_cs_p, LOW);
wrDATA(0x80, 4);
wrDATA(CMD, 8);
digitalWrite(_cs_p, HIGH);
}
void HT1621::config()
{
wrCMD(BIAS);
wrCMD(RC256);
wrCMD(SYSDIS);
wrCMD(WDTDIS1);
wrCMD(SYSEN);
wrCMD(LCDON);
}
// #define BIAS 0x52 //0b1000 0101 0010 1/3duty 4com
/*
1000 010abXcX
c=0:1/2 偏置
c=1:1/3 偏置
ab=00:2 COMS
ab=01:3 COMS
ab=10:4 COMS
*/
// #define SYSDIS 0X00 //0b1000 0000 0000 关振系统荡器和LCD偏压发生器
// #define SYSEN 0X02 //0b1000 0000 0010 打开系统振荡器
// #define LCDOFF 0X04 //0b1000 0000 0100 关LCD偏压
// #define LCDON 0X06 //0b1000 0000 0110 打开LCD偏压
// #define XTAL 0x28 //0b1000 0010 1000 外部接时钟
// #define RC256 0X30 //0b1000 0011 0000 内部时钟
// #define TONEON 0X12 //0b1000 0001 0010 打开声音输出
// #define TONEOFF 0X10 //0b1000 0001 0000 关闭声音输出
// #define WDTDIS1 0X0A //0b1000 0000 1010 禁止看门狗
void HT1621::wrCLR(unsigned char len) {
unsigned char addr = 0;
unsigned char i;
for (i = 0; i < len; i++) {
wrclrdata(addr, 0x00);
addr = addr + 2;
}
}
void HT1621::setBatteryLevel(int level,unsigned char *s) {
// zero out the previous (otherwise the or couldn't be possible)
// _buffer[0] &= 0x7F;
// _buffer[1] &= 0x7F;
// _buffer[2] &= 0x7F;
unsigned char i;
for(i=0;i<6;i++)
{
_buffer[i] &= 0x00;
}
switch(level){
case 3: // battery on and all 3 segments
// _buffer[0] |= 0x80;
// _buffer[0] |= 0xFE;
_buffer[0] |= LCDCODE[s[0]];
_buffer[1] |= LCDCODE[s[1]];
_buffer[2] |= LCDCODE[s[2]];
_buffer[3] |= LCDCODE[s[3]];
_buffer[4] |= LCDCODE[s[4]];
// _buffer[5] |= 0xFE;
// _buffer[6] |= 0xEF;
case 2: // battery on and 2 segments
// _buffer[1] |= 0x80;
case 1: // battery on and 1 segment
// _buffer[2] |= 0x80;
case 0: // battery indication off
default:
break;
}
update();
}
void HT1621::clear(){
wrCLR(16);
// wrCLR(31);
}
// takes the buffer and puts it straight into the driver
void HT1621::update(){
// the buffer is backwards with respect to the lcd. could be improved
// wrone(0, _buffer[5]);
wrone(0, _buffer[0]);
wrone(2, _buffer[1]);
wrone(4, _buffer[2]);
wrone(6, _buffer[3]);
wrone(8, _buffer[4]);
// wrone(10, _buffer[5]);
// wrone(12, _buffer[6]);
// wrone(0, _buffer[5]);
// wrone(2, _buffer[4]);
// wrone(4, _buffer[3]);
// wrone(6, _buffer[2]);
// wrone(8, _buffer[1]);
// wrone(10,_buffer[0]);
}
void HT1621::print(long num, const char* flags, int precision){
if(num > 999999) // basic checks
num = 999999; // clip into 999999
if(num < -99999) // basic checks
num = -99999; // clip into -99999
char localbuffer[7]; //buffer to work within the function
snprintf(localbuffer, 7, flags, num); // convert the decimal into string
#ifdef _HTDEBUG
Serial.begin(9600);
Serial.print(localbuffer);
Serial.print("\t");
#endif
// horrible handling but should get us working. needs refactor in next major
if (precision > 0 && (num) < pow(10, precision)) {
// we remove extra leading zeros
for (int i = 0; i < (5 - precision); i++) {
#ifdef _HTDEBUG
Serial.print(localbuffer[1]);
#endif // _HTDEBUG
if(localbuffer[i+1] == '0' && localbuffer[i] != '-'){ // we remove only if there is another zero ahead AND if it's not a minus sign
localbuffer[i] = ' ';
}
else{
break;
}
#ifdef _HTDEBUG
Serial.println();buffer[1]);
#endif // _HTDEBUG
}
}
for(int i=0; i<6; i++){
_buffer[i] &= 0x80; // mask the first bit, used by batter and decimal point
_buffer[i] |= charToSegBits(localbuffer[i]);
}
update();
}
void HT1621::print(double num, int precision){
if(num > 999999) // basic checks
num = 999999; // clip into 999999
if(num < -99999) // basic checks
num = -99999; // clip into -99999
if(precision > 3 && num > 0)
precision = 3; // if positive max precision allowed = 3
else if(precision > 2 && num < 0)
precision = 2;// if negative max precision allowed = 2
if(precision < 0)
precision = 0; // negative precision?!
const char* flags = (precision > 0 && abs(num) < 1) ? "%06li" : "%6li";
long integerpart;
integerpart = ((long)(num*pow(10,precision)));
print(integerpart, flags, precision); // draw the integerized number
setdecimalseparator(precision); // draw the decimal point
update();
}
void HT1621::printCelsius(double num){
if(num > 9999) // basic checks
num = 9999; // clip into 999999
if(num < -999) // basic checks
num = -999; // clip into -99999
int precision;
if(num <= -100 || num >= 999)
precision = 0; // if negative max precision allowed = 0
else
precision = 1; // if positive max precision allowed = 1
const char* flags = (precision > 0 && abs(num) < 1) ? "%04li*C" : "%4li*C";
long integerpart;
integerpart = ((long)(num*pow(10,precision)));
print(integerpart, flags, precision); // draw the integerized number
if(precision > 0)
setdecimalseparator(precision+2); // draw the decimal point shifted by 2
else
setdecimalseparator(0); // or clear the decimal separator
update();
}
void HT1621::print(const char* str, bool leftPadded){
int chars = strlen(str);
int padding = 6 - chars;
for(int i = 0; i < 6; i++){
_buffer[i] &= 0x80; // mask the first bit, used by batter and decimal point
char character = leftPadded
? i < padding ? ' ' : str[i - padding]
: i >= chars ? ' ' : str[i];
_buffer[i] |= charToSegBits(character);
}
setdecimalseparator(0); // Hide decimal point
update();
}
void HT1621::setdecimalseparator(int decimaldigits) {
// zero out the eight bit
_buffer[3] &= 0x7F;
_buffer[4] &= 0x7F;
_buffer[5] &= 0x7F;
if( decimaldigits <= 0 || decimaldigits > 3){
return;
}
// 3 is the digit offset
// the first three eights bits in the buffer are for the battery signs
// the last three are for the decimal point
_buffer[6-decimaldigits] |= 0x80;
}
char HT1621::charToSegBits(char character) {
switch (character) {
case '*': // For degree for now
return 0b0110011;
case '|':
return 0b0000101;
case '-':
return 0b0000010;
case '_':
return 0b0001000;
case '0':
return 0b1111101;
case '1':
return 0b1100000;
case '2':
return 0b111110;
case '3':
return 0b1111010;
case '4':
return 0b1100011;
case '5':
return 0b1011011;
case '6':
return 0b1011111;
case '7':
return 0b1110000;
case '8':
return 0b1111111;
case '9':
return 0b1111011;
case 'A':
case 'a':
return 0b1110111;
case 'b':
case 'B':
return 0b1001111;
case 'c':
// return 0b0001110;
case 'C':
return 0b0011101;
case 'd':
case 'D':
return 0b1101110;
case 'e':
// return 0b0001110;
case 'E':
return 0b0011111;
case 'f':
// return 0b0000111;
case 'F':
return 0b0010111;
case 'G':
case 'g':
return 0b1011101;
case 'h':
// return 0b1000111;
case 'H':
return 0b1100111;
case 'i':
// return 0b1000000;
case 'I':
return 0b1100000;
case 'J':
case 'j':
return 0b1101000;
case 'l':
// return 0b1100000;
case 'L':
return 0b0001101;
case 'm':
case 'M':
return 0b1010100;
case 'n':
case 'N':
return 0b1000110;
case 'O': // we can keep this for zero
// return 0b1111101;
case 'o':
return 0b1001110;
case 'P':
case 'p':
return 0b0110111;
case 'q':
case 'Q':
return 0b1110011;
case 'r':
case 'R':
return 0b0000110;
case 'S':
case 's':
return 0b1011011;
case 't':
case 'T':
return 0b0001111;
case 'u':
// return 0b1001100;
case 'U':
return 0b1101101;
case 'Y':
case 'y':
return 0b1101011;
case 'z':
case 'Z':
return 0b0111110;
case ' ':
default:
return 0b0000000;
}
}
Battery_levels.ino
/*
Battery Levels
Displays the various battery levels with 500ms
pause between.
The circuit:
cs to pin 13
wr to pin 12
Data to pin 8
backlight to pin 10
Created 9 dec 2018
By valerio\new (5N44P)
https://github.com/valerionew/ht1621-7-seg
*/
#include <HT1621.h> // include our library
HT1621 lcd; // create an "lcd" object
unsigned char LCD_tmp[5];
void setup(){
// start the lcd:
// cs to pin 13
// wr to pin 12
// Data to pin 8
// backlight to pin 10
// you can chose whichever pin you want
lcd.begin(13, 12, 8, 10); // (cs, wr, Data, backlight)
// if no backlight control is given, you can also use:
// lcd.begin(13, 12, 8); // (cs, wr, Data)
lcd.backlight(); // turn on the backlight led
lcd.clear(); // clear the screen
}
void loop(){
static unsigned int num = 0;
num++;
LCD_tmp[0] = num/10000%10; // 万位:第1位显示的内容(左->右)
LCD_tmp[1] = num/1000%10; // 千位
LCD_tmp[2] = num/100%10; // 百位
LCD_tmp[3] = num/10%10; // 十位
LCD_tmp[4] = num%10; // 个位
if(num >= 100000){num = 0;}
//设置四前面千/百/十位不要显示0
if(LCD_tmp[0] <= 0 && num < 10000){LCD_tmp[0]=10;}
if(LCD_tmp[1] <= 0 && num < 1000){LCD_tmp[1]=10;} // CODE[10] 是 0X00 不显示
if(LCD_tmp[2] <= 0 && num < 100){LCD_tmp[2]=10;}
if(LCD_tmp[3] <= 0 && num < 10){LCD_tmp[3]=10;}
lcd.setBatteryLevel(3,LCD_tmp);
delay(100);
lcd.setBatteryLevel(2);
// delay(500);
// lcd.setBatteryLevel(3);
// delay(500);
}
成果展示
“Arduino UNO TH1621 LCD成果展示”
资料下载
- 【CSDN】汇总:TH1621 LCD开发资料(20240406)
参考资料
- [1] 【Github】ht1621-7-seg (forked from anxzhu/segment-lcd-with-ht1621)
- [2] 【CSDN@weiDev101】LCD Glass段码屏的驱动
- [3] 【CSDN】STM32F103学习笔记(4)——LCD段码屏HT1621使用