372 lines
8.0 KiB
C
372 lines
8.0 KiB
C
#include "includes.h"
|
||
|
||
// 是否自检屏状态
|
||
u8 self_check_state = 0;
|
||
|
||
// 显示缓冲区
|
||
TVideoBuf VideoBuf = {0};
|
||
TVideoBuf Last_VideoBuf = {0};
|
||
|
||
// 定义7段字库编码
|
||
// |-A-|
|
||
// F B
|
||
// |-G-|
|
||
// E C
|
||
// |-D-|
|
||
|
||
typedef struct
|
||
{
|
||
unsigned A : 1;
|
||
unsigned B : 1;
|
||
unsigned C : 1;
|
||
unsigned D : 1;
|
||
unsigned E : 1;
|
||
unsigned F : 1;
|
||
unsigned G : 1;
|
||
unsigned : 1;
|
||
} TChar;
|
||
|
||
// 字库,不带小数点或单位
|
||
const TChar CLib[] =
|
||
{
|
||
{0, 0, 0, 0, 0, 0, 0}, // ' '
|
||
{0, 0, 0, 0, 0, 0, 1}, // '-'
|
||
{0, 1, 1, 0, 0, 0, 1}, // '+' = '-|'
|
||
{1, 0, 0, 0, 0, 0, 0}, // '^'
|
||
|
||
{1, 1, 1, 0, 1, 1, 1}, // 'A'
|
||
{0, 0, 1, 1, 1, 1, 1}, // 'b'
|
||
{0, 0, 0, 1, 1, 0, 1}, // 'c'
|
||
{0, 1, 1, 1, 1, 0, 1}, // 'd'
|
||
{1, 0, 0, 1, 1, 1, 1}, // 'E'
|
||
{1, 0, 0, 0, 1, 1, 1}, // 'F'
|
||
{1, 0, 1, 1, 1, 1, 0}, // 'G'
|
||
{0, 0, 1, 0, 1, 1, 1}, // 'h'
|
||
{0, 0, 0, 0, 1, 1, 0}, // 'I'
|
||
{0, 1, 1, 1, 0, 0, 0}, // 'J'
|
||
{0, 0, 0, 1, 0, 0, 0}, // 'K' = '_'
|
||
{0, 0, 0, 1, 1, 1, 0}, // 'L'
|
||
{0, 0, 0, 1, 0, 0, 0}, // 'M' = '_'
|
||
{0, 0, 1, 0, 1, 0, 1}, // 'n'
|
||
{0, 0, 1, 1, 1, 0, 1}, // 'o'
|
||
{1, 1, 0, 0, 1, 1, 1}, // 'P'
|
||
{1, 1, 1, 0, 0, 1, 1}, // 'q'
|
||
{0, 0, 0, 0, 1, 0, 1}, // 'r'
|
||
{1, 0, 1, 1, 0, 1, 1}, // 'S'
|
||
{0, 0, 1, 0, 0, 0, 1}, // 't'
|
||
{0, 1, 1, 1, 1, 1, 0}, // 'U'
|
||
{0, 1, 0, 0, 1, 1, 1}, // 'V'
|
||
{0, 0, 0, 1, 0, 0, 0}, // 'W' = '_'
|
||
{0, 0, 0, 1, 0, 0, 0}, // 'X' = '_'
|
||
{0, 1, 1, 1, 0, 1, 1}, // 'y'
|
||
{0, 0, 0, 1, 0, 0, 0}, // 'Z' = '_'
|
||
|
||
{1, 1, 1, 1, 1, 1, 0}, // '0'
|
||
{0, 1, 1, 0, 0, 0, 0}, // '1'
|
||
{1, 1, 0, 1, 1, 0, 1}, // '2'
|
||
{1, 1, 1, 1, 0, 0, 1}, // '3'
|
||
{0, 1, 1, 0, 0, 1, 1}, // '4'
|
||
{1, 0, 1, 1, 0, 1, 1}, // '5'
|
||
{1, 0, 1, 1, 1, 1, 1}, // '6'
|
||
{1, 1, 1, 0, 0, 0, 0}, // '7'
|
||
{1, 1, 1, 1, 1, 1, 1}, // '8'
|
||
{1, 1, 1, 1, 0, 1, 1}, // '9'
|
||
};
|
||
|
||
// 字符在字库中的编码
|
||
typedef enum
|
||
{
|
||
CODE_SPACE, CODE_MINUS, CODE_PLUS, CODE_EXP,
|
||
CODE_A, CODE_B, CODE_C, CODE_D, CODE_E, CODE_F, CODE_G,
|
||
CODE_H, CODE_I, CODE_J, CODE_K, CODE_L, CODE_M, CODE_N,
|
||
CODE_O, CODE_P, CODE_Q, CODE_R, CODE_S, CODE_T,
|
||
CODE_U, CODE_V, CODE_W, CODE_X, CODE_Y, CODE_Z,
|
||
CODE_0, CODE_1, CODE_2, CODE_3, CODE_4, CODE_5, CODE_6, CODE_7, CODE_8, CODE_9
|
||
} TCode;
|
||
|
||
TCode HT1621_Char2Code(char c)
|
||
{
|
||
if(c >= '0' && c <= '9')
|
||
return CODE_0 + (c - '0');
|
||
|
||
if(c >= 'a' && c <= 'z')
|
||
return CODE_A + (c - 'a');
|
||
|
||
if(c >= 'A' && c <= 'Z')
|
||
return CODE_A + (c - 'A');
|
||
|
||
if(c == '-')
|
||
return CODE_MINUS;
|
||
|
||
if(c == '+')
|
||
return CODE_PLUS;
|
||
|
||
if(c == '^')
|
||
return CODE_EXP;
|
||
|
||
return CODE_SPACE;
|
||
}
|
||
|
||
// pin_no: 1~32
|
||
// com_no: 1~4
|
||
void HT1621_WriteBuf(u16 pin_com, u8 bit_val)
|
||
{
|
||
uint8_t byte_index, bit_index;
|
||
uint8_t pin_no = pin_com / 10;
|
||
uint8_t com_no = pin_com % 10;
|
||
|
||
if(pin_no < 1 || pin_no > 25)
|
||
return;
|
||
if(com_no < 1 || com_no > 6)
|
||
return;
|
||
|
||
byte_index = pin_no - 1;
|
||
bit_index = com_no - 1; // COM6高位,COM1低位
|
||
if(bit_val)
|
||
VideoBuf.buf[byte_index] |= (1 << bit_index);
|
||
else
|
||
VideoBuf.buf[byte_index] &= ~(1 << bit_index);
|
||
}
|
||
|
||
// 写一个七段码字符
|
||
// pin_comA = (A段的pin_no) * 10 + (A段的com_no)
|
||
void HT1621_WriteChar(char c, u16 pin_comA, u16 pin_comB, u16 pin_comC, u16 pin_comD, u16 pin_comE, u16 pin_comF, u16 pin_comG)
|
||
{
|
||
TCode code = HT1621_Char2Code(c);
|
||
|
||
HT1621_WriteBuf(pin_comA, CLib[code].A);
|
||
HT1621_WriteBuf(pin_comB, CLib[code].B);
|
||
HT1621_WriteBuf(pin_comC, CLib[code].C);
|
||
HT1621_WriteBuf(pin_comD, CLib[code].D);
|
||
HT1621_WriteBuf(pin_comE, CLib[code].E);
|
||
HT1621_WriteBuf(pin_comF, CLib[code].F);
|
||
HT1621_WriteBuf(pin_comG, CLib[code].G);
|
||
}
|
||
|
||
// 写一个七段码数据
|
||
// pin_comA = (A段的pin_no) * 10 + (A段的com_no)
|
||
void HT1621_Write7Seg(u8 val, u16 pin_comA, u16 pin_comB, u16 pin_comC, u16 pin_comD, u16 pin_comE, u16 pin_comF, u16 pin_comG)
|
||
{
|
||
HT1621_WriteBuf(pin_comA, val & 1);
|
||
val >>= 1;
|
||
HT1621_WriteBuf(pin_comB, val & 1);
|
||
val >>= 1;
|
||
HT1621_WriteBuf(pin_comC, val & 1);
|
||
val >>= 1;
|
||
HT1621_WriteBuf(pin_comD, val & 1);
|
||
val >>= 1;
|
||
HT1621_WriteBuf(pin_comE, val & 1);
|
||
val >>= 1;
|
||
HT1621_WriteBuf(pin_comF, val & 1);
|
||
val >>= 1;
|
||
HT1621_WriteBuf(pin_comG, val & 1);
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
// 以下定义适用于HT16L23驱动芯片
|
||
//命令
|
||
#define WRITE_LCD 0x80
|
||
#define DRIVE_MODE_CMD 0x82
|
||
#define SYS_MODE_CMD 0x84
|
||
#define FRQ_CMD 0x86
|
||
#define BLINK_FRQ_CMD 0x88
|
||
#define VOL_SET_CMD 0x8a
|
||
|
||
//参数定义
|
||
#define BIAS_LCD 0x34 // 驱动模式 SEG40*8com显示段位模式 1/8duty 1/3bias
|
||
#define SYS_MODE_LCD 0x03 //显示和内部晶振都打开
|
||
#define FRQ_LCD 0x02 //3--128HZ 2--64
|
||
#define BLINK_FRQ_LCD 0x00 //blinking off
|
||
#define VOL_LCD 0x02 //1--内部V 电压3.3v
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
|
||
void HT1621_Delay()
|
||
{
|
||
__NOP();
|
||
}
|
||
|
||
// 通讯定义
|
||
#define HT1621_CS_EN() \
|
||
{ \
|
||
LL_GPIO_ResetOutputPin(GPIOD, LL_GPIO_PIN_12); \
|
||
HT1621_Delay(); \
|
||
}
|
||
|
||
#define HT1621_CS_DIS() \
|
||
{ \
|
||
LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_12); \
|
||
HT1621_Delay(); \
|
||
}
|
||
|
||
#define HT1621_CLK_LOW() \
|
||
{ \
|
||
LL_GPIO_ResetOutputPin(GPIOD, LL_GPIO_PIN_13); \
|
||
HT1621_Delay(); \
|
||
}
|
||
|
||
#define HT1621_CLK_HIGH() \
|
||
{ \
|
||
LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_13); \
|
||
HT1621_Delay(); \
|
||
}
|
||
|
||
#define HT1621_DATA_1() \
|
||
{ \
|
||
LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_14); \
|
||
HT1621_Delay(); \
|
||
}
|
||
|
||
#define HT1621_DATA_0() \
|
||
{ \
|
||
LL_GPIO_ResetOutputPin(GPIOD, LL_GPIO_PIN_14); \
|
||
HT1621_Delay(); \
|
||
}
|
||
|
||
// 写 1 bit
|
||
void HT1621_Bit(u8 b1)
|
||
{
|
||
HT1621_CLK_LOW();
|
||
if(b1)
|
||
{
|
||
HT1621_DATA_1();
|
||
}
|
||
else
|
||
{
|
||
HT1621_DATA_0();
|
||
}
|
||
HT1621_CLK_HIGH();
|
||
}
|
||
|
||
// 写多个bits
|
||
void HT1621_Bits(u8 byte, u8 num)
|
||
{
|
||
while(num--)
|
||
{
|
||
HT1621_Bit(byte & 0x80);
|
||
byte <<= 1;
|
||
}
|
||
}
|
||
|
||
// 写命令
|
||
void HT1621_Cmd(u8 cmd, u8 val)
|
||
{
|
||
// 片选
|
||
HT1621_CS_EN();
|
||
|
||
HT1621_Bits(cmd, 8);
|
||
HT1621_Bits(val, 8);
|
||
|
||
// 取消片选
|
||
HT1621_CS_DIS();
|
||
}
|
||
|
||
// 设置参数
|
||
void HT1621_SetParams()
|
||
{
|
||
HT1621_Cmd(DRIVE_MODE_CMD, BIAS_LCD);
|
||
HT1621_Cmd(VOL_SET_CMD, VOL_LCD); //使用内部振荡器
|
||
HT1621_Cmd(FRQ_CMD, FRQ_LCD);
|
||
HT1621_Cmd(BLINK_FRQ_CMD, BLINK_FRQ_LCD);
|
||
HT1621_Cmd(SYS_MODE_CMD, SYS_MODE_LCD);
|
||
}
|
||
|
||
// 刷新整个显示屏内容
|
||
void HT1621_Refresh()
|
||
{
|
||
u8 i;
|
||
|
||
// 比较显示内容和标志位,如无改变则不操作
|
||
if(memcmp(&VideoBuf, &Last_VideoBuf, sizeof(VideoBuf)) == 0)
|
||
return;
|
||
|
||
// 保存显示内容和标志位
|
||
Last_VideoBuf = VideoBuf;
|
||
|
||
// 处理闪烁,根据标志位临时改变显示内容
|
||
if(!self_check_state && !VideoBuf.blink_visible)
|
||
{
|
||
// 隐藏数字(显示界面)
|
||
if(VideoBuf.fld1_blink) // 显示1
|
||
{
|
||
Disp_Fld1Text(" ");
|
||
Disp_Fld1PointOff();
|
||
}
|
||
if(VideoBuf.fld2_blink) // 显示2
|
||
{
|
||
Disp_Fld2Text(" ");
|
||
Disp_Fld2PointOff();
|
||
}
|
||
if(VideoBuf.fld3_blink) // 显示3
|
||
{
|
||
Disp_Fld3Text(" ");
|
||
Disp_Fld3PointOff();
|
||
}
|
||
if(VideoBuf.fld4_blink) // 显示4
|
||
{
|
||
Disp_Fld4Text(" ");
|
||
Disp_Fld4PointOff();
|
||
}
|
||
if(VideoBuf.battery_blink) // 电池
|
||
Disp_WriteBattery(0);
|
||
|
||
// 光标闪烁(配置界面)
|
||
for(i = 0; i < VideoBuf.cursor_width; i++)
|
||
Disp_DispChar(VideoBuf.cursor_pos + i, ' ');
|
||
}
|
||
|
||
// 片选
|
||
HT1621_CS_EN();
|
||
|
||
HT1621_Bits(WRITE_LCD, 8); // cmd
|
||
HT1621_Bits(0, 8); // addr
|
||
for(i = 0; i < sizeof(VideoBuf.buf); i++)
|
||
HT1621_Bits(VideoBuf.buf[i], 8);
|
||
|
||
// 取消片选
|
||
HT1621_CS_DIS();
|
||
|
||
// 恢复显示内容和标志位
|
||
VideoBuf = Last_VideoBuf;
|
||
}
|
||
|
||
// 整个屏幕全熄灭
|
||
void HT1621_AllOff()
|
||
{
|
||
self_check_state = 1;
|
||
memset(VideoBuf.buf, 0x00, sizeof(VideoBuf.buf)); // 不影响最后的状态
|
||
HT1621_Refresh();
|
||
self_check_state = 0;
|
||
}
|
||
|
||
// 整个屏幕全点亮
|
||
void HT1621_AllOn()
|
||
{
|
||
self_check_state = 1;
|
||
memset(VideoBuf.buf, 0xFF, sizeof(VideoBuf.buf)); // 不影响最后的状态
|
||
HT1621_Refresh();
|
||
self_check_state = 0;
|
||
}
|
||
|
||
void LCD_Init()
|
||
{
|
||
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||
|
||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
|
||
|
||
/**/
|
||
LL_GPIO_SetOutputPin(GPIOD, LL_GPIO_PIN_11|LL_GPIO_PIN_12|LL_GPIO_PIN_13|LL_GPIO_PIN_14);
|
||
|
||
/**/
|
||
GPIO_InitStruct.Pin = LL_GPIO_PIN_11|LL_GPIO_PIN_12|LL_GPIO_PIN_13|LL_GPIO_PIN_14;
|
||
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
|
||
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
|
||
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
||
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
|
||
LL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||
}
|
||
|
||
void LCD_MyOpen()
|
||
{
|
||
HT1621_SetParams();
|
||
}
|