MS-DTU/Anjiehui7_Set_ZNY/User/Lcd_drv.c

372 lines
8.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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();
}