This post was last edited by Electronic Bad Guy on 2024-5-11 16:15
Originally, we planned to use LCD1602 as the display screen, but after reading ST's definition of U0 "extending battery life", we found that LCD1602 is not very friendly to battery power supply. Therefore, this evaluation uses LCD digital tube for testing.
1. LCD Introduction
Segment LCD (Liquid Crystal Display) is a display technology that forms text and numbers by arranging individual liquid crystal cells into segments. Unlike full-matrix LCDs, segment LCDs have limited display capabilities and are usually used to display simple text and numbers, such as displays on calculators, electronic watches, home appliances, and industrial equipment. The
basic structure of a segment LCD consists of seven or more segments, each of which can be controlled independently, and different characters can be formed through different combinations. The simplest segment LCD consists of seven segments and is used to display numbers from 0 to 9. This type of LCD is called a seven-segment display. There are more complex segment LCDs, such as 14 segments, 16 segments, or even more, which can display more characters and symbols. The
working principle of segment LCD is to use the polarization properties of liquid crystal to light. When an electric current passes through a specific segment, the arrangement of liquid crystal molecules changes, thereby changing the direction of polarized light. Through polarizers and color filters, it is possible to control whether light passes through, thereby displaying segments of different light and dark, forming visible characters or images. The advantages are that it has a simple structure, low power consumption, and low cost, and is suitable for occasions where the amount of information displayed is not large. Due to its limited display capabilities, it is not suitable for displaying complex graphics or large amounts of text.
2. LCD code analysis
The ST LCD library has the definition of digital tubes, but the digital tubes are different from the commonly used "日"-shaped digital tubes, but "米"-shaped. The specific definition is as follows:
(The following code is from the U083-DK example "LCD_Segments_Drive, for reference only)
/** @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;
The specific application code is also given in this example, and the main function used is the "HAL_LCD_Write" function;
The function definition is as follows:
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;
}
}
As you can see, the code is concise enough to speed up the development of segment LCD related projects.
3. Configure LCD peripherals
The LCD selected this time has 32 pins, including 8 COM pins and 24 SEG pins.
Define LCD functions in CUBEMX according to driver data (many pins are occupied...)
Since the LCD clock and RTC are from the same source, it is also necessary to enable the RTC. For details, please refer to the previous article:
After configuration, the generated LCD code is as follows:
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 */
}
The screen I bought just arrived, but I encountered an embarrassing problem: I couldn't connect it...
The three screens all have a 2.0MM pin spacing, and the only perfboard and breadboard I have are both 2.54MM spacing, and the pins are still very fragile and not suitable for connecting Dupont wires. . .
The only thing we can do is to solve the problem, and launch EasyEDA!
As it happens, the standard version of the EasyEDA library file contains the package of the GDC05720 screen, so you can just make a board and lead it out.
That's all for this week, and then we'll just have to wait for the PCB to be made. . .