Небольшое дополнение к посту Микроконтроллеры STM32: работа с экранчиком 1602 по I2C . HD44780-совместимые ЖК-индикаторы позволяют определить до восьми собственных символов 5 x 8 точек. Вот как этим пользоваться.
Обратимся к таблице доступных инструкций :
Нас интересует строка «Set CGRAM Address». CGRAM означает Character Generator Random Access Memory. CGRAM состоит из 64-х ячеек памяти по 5 бит, что позволяет хранить восемь символов 5 x 8. Этим символам будут соответствовать коды x00
.. x07
.
Обладая этой информацией, нетрудно написать код. Вот его полная версия:
#define PIN_EN (1 << 2)
#define BACKLIGHT (1 << 3)
#define LCD_DELAY_MS 5
uint8_t lcd_addr = ( 0x27 << 1 ) ;
HAL_StatusTypeDef LCD_SendInternal ( uint8_t data , uint8_t flags ) {
HAL_StatusTypeDef res ;
for ( ;; ) {
res = HAL_I2C_IsDeviceReady ( & hi2c1 , lcd_addr , 1 ,
HAL_MAX_DELAY ) ;
if ( res == HAL_OK )
break ;
}
uint8_t up = data & 0xF0 ;
uint8_t lo = ( data << 4 ) & 0xF0 ;
uint8_t data_arr [ 4 ] ;
data_arr [ 0 ] = up | flags | BACKLIGHT | PIN_EN ;
data_arr [ 1 ] = up | flags | BACKLIGHT ;
data_arr [ 2 ] = lo | flags | BACKLIGHT | PIN_EN ;
data_arr [ 3 ] = lo | flags | BACKLIGHT ;
res = HAL_I2C_Master_Transmit ( & hi2c1 , lcd_addr , data_arr ,
sizeof ( data_arr ) , HAL_MAX_DELAY ) ;
HAL_Delay ( LCD_DELAY_MS ) ;
return res ;
}
void LCD_SendCommand ( uint8_t cmd ) {
LCD_SendInternal ( cmd , 0 ) ;
}
void LCD_SendData ( uint8_t data ) {
LCD_SendInternal ( data , PIN_RS ) ;
}
void LCD_Init ( ) {
// 4-bit mode, 2 lines, 5×7 format
LCD_SendCommand ( 0b00110000 ) ;
// display & cursor home (keep this!)
LCD_SendCommand ( 0b00000010 ) ;
// display on, underline off, blink off
LCD_SendCommand ( 0b00001100 ) ;
// clear display (optional here)
LCD_SendCommand ( 0b00000001 ) ;
}
void LCD_SendString ( char * str ) {
while ( * str ) {
LCD_SendData ( ( uint8_t ) ( * str ) ) ;
str ++;
}
}
void init ( ) {
// check for an alternative LCD address
HAL_StatusTypeDef res ;
res = HAL_I2C_IsDeviceReady ( & hi2c1 , ( 0x3F << 1 ) , 1 , HAL_MAX_DELAY ) ;
if ( res == HAL_OK ) {
lcd_addr = ( 0x3F << 1 ) ;
}
LCD_Init ( ) ;
// create 8 custom characters for the S-meter
for ( uint8_t ch = 0 ; ch < 8 ; ch ++ ) {
// set CGRAM Address
LCD_SendCommand ( 0b01000000 + ( ch << 3 ) ) ;
for ( uint8_t line = 0 ; line < 8 ; line ++ ) {
if ( ch >= ( 7 — line ) ) {
LCD_SendData ( 0b11111 ) ;
} else {
LCD_SendData ( 0b00000 ) ;
}
}
}
LCD_SendCommand ( 0b11000000 ) ;
LCD_SendString ( » » ) ;
for ( uint8_t ch = 0 ; ch < 8 ; ch ++ ) {
LCD_SendData ( ch ) ;
}
while ( 1 ) { HAL_Delay ( 1000 ) ; }
}
Результат:
Код был успешно протестирован на пяти разных ЖК-индикаторах 1602 и 0802.
Приведенные символы могут быть использованы для отображения громкости или изображать S-метр в самодельном трансивере . Само собой разумеется, можно определить и другие символы. Заметьте, что ничто не мешает переопределять символы на лету. То есть, собственных символов может быть и больше восьми, но одновременно отобразить можно только восемь разных символов.