本来在计划中准备使用LCD1602作为显示屏的,但是看过ST对U0“延长电池使用时间”的定义后,发现LCD1602对于电池供电貌似不是很友好。所以本次测评使用LCD数码管进行测试
1.LCD简介
段式LCD(Liquid Crystal Display,液晶显示屏)是一种显示屏技术,通过排列成段的单个液晶单元格来形成文字和数字。与全点阵LCD不同,段式LCD的显示能力较为有限,通常用于显示简单的文本和数字,如计算器、电子表、家用电器和工业设备上的显示屏。
段式LCD的基本结构包括七个或更多的段,每个段可以独立控制,通过不同的组合可以形成不同的字符。最简单的段式LCD由七个段组成,用于显示0到9的数字,这种LCD被称为七段显示。还有一些更复杂的段式LCD,比如14段、16段甚至更多,它们可以显示更多的字符和符号。
段式LCD的工作原理是利用液晶对光的偏振性质。当电流通过特定的段时,液晶分子的排列方式会改变,从而改变偏振光的方向。通过偏振片和滤色片,可以控制光线是否通过,从而显示出明暗不同的段,形成可见的字符或图像。优点在于其结构简单、功耗低、成本较低,适合用于显示信息量不大的场合。由于其显示能力的限制,不适合用于显示复杂的图形或大量的文本。
2.LCD代码解析
ST的LCD库里有数码管的定义,不过数码管不同于常用的“日”字型数码管,而是“米”字型的,具体定义如下:
(以下代码来自U083-DK的示例“LCD_Segments_Drive,仅供参考)
/** @defgroup STM32U083C_DK_GLASS_LCD_Private_Variables Private Variables
* @{
*/
/* this variable can be used for accelerate the scrolling exit when push user button */
__IO uint8_t bLCDGlass_KeyPressed = 0;
/**
@verbatim
================================================================================
GLASS LCD MAPPING
================================================================================
LCD allows to display information on six 14-segment digits and 4 bars:
1 2 3 4 5 6
----- ----- ----- ----- ----- -----
|\|/| o |\|/| o |\|/| o |\|/| o |\|/| |\|/| BAR3
-- -- -- -- -- -- -- -- -- -- -- -- BAR2
|/|\| o |/|\| o |/|\| o |/|\| o |/|\| |/|\| BAR1
----- * ----- * ----- * ----- * ----- ----- BAR0
LCD segment mapping:
--------------------
-----A----- _
|\ | /| COL |_|
F H J K B
| \ | / | _
--G-- --M-- COL |_|
| / | \ |
E Q P N C
|/ | \| _
-----D----- DP |_|
An LCD character coding is based on the following matrix:
COM 0 1 2 3
SEG(n) { E , D , P , N }
SEG(n+1) { M , C , COL , DP }
SEG(23-n-1) { B , A , K , J }
SEG(23-n) { G , F , Q , H }
with n positive odd number.
The character 'A' for example is:
-------------------------------
LSB { 1 , 0 , 0 , 0 }
{ 1 , 1 , 0 , 0 }
{ 1 , 1 , 0 , 0 }
MSB { 1 , 1 , 0 , 0 }
-------------------
'A' = F E 0 0 hexa
@endverbatim
*/
LCD_HandleTypeDef LCDHandle;
/* Constant table for cap characters 'A' --> 'Z' */
const uint16_t CapLetterMap[26] =
{
/* A B C D E F G H I */
0xFE00, 0x6714, 0x1D00, 0x4714, 0x9D00, 0x9C00, 0x3F00, 0xFA00, 0x0014,
/* J K L M N O P Q R */
0x5300, 0x9841, 0x1900, 0x5A48, 0x5A09, 0x5F00, 0xFC00, 0x5F01, 0xFC01,
/* S T U V W X Y Z */
0xAF00, 0x0414, 0x5b00, 0x18C0, 0x5A81, 0x00C9, 0x0058, 0x05C0
};
/* Constant table for number '0' --> '9' */
const uint16_t NumberMap[10] =
{
/* 0 1 2 3 4 5 6 7 8 9 */
0x5F00, 0x4200, 0xF500, 0x6700, 0xEa00, 0xAF00, 0xBF00, 0x04600, 0xFF00, 0xEF00
};
uint32_t Digit[4]; /* Digit frame buffer */
/* LCD BAR status: To save the bar setting after writing in LCD RAM memory */
uint8_t LCDBar = BATTERYLEVEL_FULL;
具体的应用代码在这个示例里也给出了,主要使用的是“HAL_LCD_Write”这个函数;
函数定义如下:
HAL_StatusTypeDef HAL_LCD_Write(LCD_HandleTypeDef *hlcd, uint32_t RAMRegisterIndex, uint32_t RAMRegisterMask,
uint32_t Data)
{
uint32_t tickstart;
HAL_LCD_StateTypeDef state = hlcd->State;
if ((state == HAL_LCD_STATE_READY) || (state == HAL_LCD_STATE_BUSY))
{
/* Check the parameters */
assert_param(IS_LCD_RAM_REGISTER(RAMRegisterIndex));
if (hlcd->State == HAL_LCD_STATE_READY)
{
/* Process Locked */
__HAL_LOCK(hlcd);
hlcd->State = HAL_LCD_STATE_BUSY;
/* Get timeout */
tickstart = HAL_GetTick();
/*!< Wait Until the LCD is ready */
while (__HAL_LCD_GET_FLAG(hlcd, LCD_FLAG_UDR) != RESET)
{
if ((HAL_GetTick() - tickstart) > LCD_TIMEOUT_VALUE)
{
hlcd->ErrorCode = HAL_LCD_ERROR_UDR;
/* Process Unlocked */
__HAL_UNLOCK(hlcd);
return HAL_TIMEOUT;
}
}
}
/* Copy the new Data bytes to LCD RAM register */
MODIFY_REG(hlcd->Instance->RAM[RAMRegisterIndex], ~(RAMRegisterMask), Data);
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}
可以看到,该代码足够简洁,能够加速段式LCD相关项目的开发。
3.配置LCD外设
本次选用的LCD,LCD液晶管引脚多达32个,其中有8个COM脚,24个SEG脚
根据驱动数据在CUBEMX中定义LCD功能(引脚占用非常多。。。)
由于LCD的时钟和RTC为同源,故还需要使能RTC,详情可以看上一篇文章:
static void MX_LCD_Init(void)
{
/* USER CODE BEGIN LCD_Init 0 */
/* USER CODE END LCD_Init 0 */
/* USER CODE BEGIN LCD_Init 1 */
/* USER CODE END LCD_Init 1 */
hlcd.Instance = LCD;
hlcd.Init.Prescaler = LCD_PRESCALER_1;
hlcd.Init.Divider = LCD_DIVIDER_16;
hlcd.Init.Duty = LCD_DUTY_1_8;
hlcd.Init.Bias = LCD_BIAS_1_4;
hlcd.Init.VoltageSource = LCD_VOLTAGESOURCE_INTERNAL;
hlcd.Init.Contrast = LCD_CONTRASTLEVEL_3;
hlcd.Init.DeadTime = LCD_DEADTIME_2;
hlcd.Init.PulseOnDuration = LCD_PULSEONDURATION_7;
hlcd.Init.BlinkMode = LCD_BLINKMODE_OFF;
hlcd.Init.BlinkFrequency = LCD_BLINKFREQUENCY_DIV8;
hlcd.Init.MuxSegment = LCD_MUXSEGMENT_DISABLE;
if (HAL_LCD_Init(&hlcd) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN LCD_Init 2 */
/* USER CODE END LCD_Init 2 */
}
正好买的屏幕到了,但是遇到一个尴尬的问题,没法连线。。。
三片屏幕都是2.0MM的引脚间距,手上唯一的洞洞板和面包板都是2.54MM间距的,这个引脚还很脆弱,不适合接杜邦线。。。
只能动手解决问题了,立创EDA启动!
正巧,立创EDA标准版库文件里有GDC05720屏幕的封装,直接做一个板子引出即可。
这周就先这样,接下来就等PCB制作完成了。。。