LCD displej s obvodem HD44780 a I2c převodníkem PCF8574 vyžaduje napájecí napětí 5V.
Při napájení LCD displeje z 3.3V sice displej pracuje, ale není na něm skoro nic vidět. Nedá se ani regulovat jas potenciometrem zespodu displeje. Něco málo je vidět pouze při maximálním jasu.
Podle tohoto schématu s pull up rezistory 10k na linii 3.3V z pinu 36 a napájení displeje 5 Volty všechno funguje excelentně. Odběr celého zařízení je okolo 40 mA.
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "pico/binary_info.h"
/* Example code to drive a 16x2 LCD panel via a I2C bridge chip (e.g. PCF8574)
NOTE: The panel must be capable of being driven at 3.3v NOT 5v. The Pico
GPIO (and therefor I2C) cannot be used at 5v.
You will need to use a level shifter on the I2C lines if you want to run the
board at 5v.
Connections on Raspberry Pi Pico board, other boards may vary.
GPIO 4 (pin 6)-> SDA on LCD bridge board
GPIO 5 (pin 7)-> SCL on LCD bridge board
3.3v (pin 36) -> VCC on LCD bridge board
GND (pin 38) -> GND on LCD bridge board
*/
// commands
const int LCD_CLEARDISPLAY = 0x01;
const int LCD_RETURNHOME = 0x02;
const int LCD_ENTRYMODESET = 0x04;
const int LCD_DISPLAYCONTROL = 0x08;
const int LCD_CURSORSHIFT = 0x10;
const int LCD_FUNCTIONSET = 0x20;
const int LCD_SETCGRAMADDR = 0x40;
const int LCD_SETDDRAMADDR = 0x80;
// flags for display entry mode
const int LCD_ENTRYSHIFTINCREMENT = 0x01;
const int LCD_ENTRYLEFT = 0x02;
// flags for display and cursor control
const int LCD_BLINKON = 0x01;
const int LCD_CURSORON = 0x02;
const int LCD_DISPLAYON = 0x04;
// flags for display and cursor shift
const int LCD_MOVERIGHT = 0x04;
const int LCD_DISPLAYMOVE = 0x08;
// flags for function set
const int LCD_5x10DOTS = 0x04;
const int LCD_2LINE = 0x08;
const int LCD_8BITMODE = 0x10;
// flag for backlight control
const int LCD_BACKLIGHT = 0x08;
const int LCD_ENABLE_BIT = 0x04;
// By default these LCD display drivers are on bus address 0x27
static int addr = 0x27;
// Modes for lcd_send_byte
#define LCD_CHARACTER 1
#define LCD_COMMAND 0
#define MAX_LINES 2
#define MAX_CHARS 16
/* Quick helper function for single byte transfers */
void i2c_write_byte(uint8_t val) {
#ifdef i2c_default
i2c_write_blocking(i2c_default, addr, &val, 1, false);
#endif
}
void lcd_toggle_enable(uint8_t val) {
// Toggle enable pin on LCD display
// We cannot do this too quickly or things don't work
#define DELAY_US 600
sleep_us(DELAY_US);
i2c_write_byte(val | LCD_ENABLE_BIT);
sleep_us(DELAY_US);
i2c_write_byte(val & ~LCD_ENABLE_BIT);
sleep_us(DELAY_US);
}
// The display is sent a byte as two separate nibble transfers
void lcd_send_byte(uint8_t val, int mode) {
uint8_t high = mode | (val & 0xF0) | LCD_BACKLIGHT;
uint8_t low = mode | ((val << 4) & 0xF0) | LCD_BACKLIGHT;
i2c_write_byte(high);
lcd_toggle_enable(high);
i2c_write_byte(low);
lcd_toggle_enable(low);
}
void lcd_clear(void) {
lcd_send_byte(LCD_CLEARDISPLAY, LCD_COMMAND);
}
// go to location on LCD
void lcd_set_cursor(int line, int position) {
int val = (line == 0) ? 0x80 + position : 0xC0 + position;
lcd_send_byte(val, LCD_COMMAND);
}
static void inline lcd_char(char val) {
lcd_send_byte(val, LCD_CHARACTER);
}
void lcd_string(const char *s) {
while (*s) {
lcd_char(*s++);
}
}
void lcd_init() {
lcd_send_byte(0x03, LCD_COMMAND);
lcd_send_byte(0x03, LCD_COMMAND);
lcd_send_byte(0x03, LCD_COMMAND);
lcd_send_byte(0x02, LCD_COMMAND);
lcd_send_byte(LCD_ENTRYMODESET | LCD_ENTRYLEFT, LCD_COMMAND);
lcd_send_byte(LCD_FUNCTIONSET | LCD_2LINE, LCD_COMMAND);
lcd_send_byte(LCD_DISPLAYCONTROL | LCD_DISPLAYON, LCD_COMMAND);
lcd_clear();
}
int main() {
#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN)
#warning i2c/lcd_1602_i2c example requires a board with I2C pins
#else
// This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico)
i2c_init(i2c_default, 100 * 1000); // 100 KHz
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
// Make the I2C pins available to picotool
bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));
lcd_init();
static char *message[] =
{
"Testovani LCD", "displeje I2c0x27",
"abcdefghijklmnop", "qrstuvwxyz",
"ABCDEFGHIJKLMNOP", "QRSTUVWXYZ",
"0123456789", ".,+-*/@&$#^{}()?",
"Program je psan", "v Cecku!"
};
while (1) {
for (int m = 0; m < sizeof(message) / sizeof(message[0]); m += MAX_LINES) {
for (int line = 0; line < MAX_LINES; line++) {
lcd_set_cursor(line, (MAX_CHARS / 2) - strlen(message[m + line]) / 2);
lcd_string(message[m + line]);
}
sleep_ms(3000);
lcd_clear();
}
}
#endif
}
add_executable(lcd_1602_i2c
lcd_1602_i2c.c
)
# pull in common dependencies and additional i2c hardware support
target_link_libraries(lcd_1602_i2c pico_stdlib hardware_i2c)
# create map/bin/hex file etc.
pico_add_extra_outputs(lcd_1602_i2c)
# add url via pico_set_program_url
example_auto_set_url(lcd_1602_i2c)
Problém u tohoto dipleje je v tom, že neumí zobrazovat časká písmenka. Prvních 127 znaků odpovídají ASCII znakům a na pozicích 128—255 jsou nějaké nepoužitelné paznaky. Budeme si muset nadefinovat svoje písmenka.

Definice vlastních znaků
Displej má 64 bytovou paměť (CGRAM) pro uložení 8 uživatelsky definovaných znaků. Tyto znaky odpovídají znakovým kódům 00h až 07h. Znakové kódy 08h až 0Fh také odpovídají osmi uživatelsky definovaným znakům.
Každý uživatelsky definovaný znak má 5 sloupců a 8 řádků, přičemž osmý řádek je vyhrazen pro kurzor. Mapování mezi CG RAM a obrázkem na displeji je ukázána na následujícím obrázku.
x v CG adrese je bázová adresa pro jednotlivé znaky: znak_0 = 00h, znak_1 = 08h, znak_2 = 10h, znak_3 = 18h, znak_4 = 20h, znak_5 = 28h, znak6 = 30h a znak_7 = 38h.
Jak je vidět z obrázku, každý bajt CGRAM reprezentuje jeden řádek pixelů znaku (bity D0 až D4), kde bit D0 je nejvíce vlevo a D4 je nejvíce vpravo. Horní bity D5 až D7 se nepoužívají. První adresa v definici znaku je nahoře a poslední 8. adresa je vyhrazena pro kurzor. Jednička v bitu znamená, že pixel je na displeji "černý" a nula znamená, že pixel je "bílý". CGRAM je v jiném adresovém prostoru, než DDRAM.
Při definici našich znaků nejdříve musíme přepnout displej do režimu programování uživatelských znaků a současně zadat bázovou adresu a potom můžeme posílat jednotlivé řádky. Každý zápis definice řádku pixelů automaticky posune adresu v CGRAM o jeden bajt, takže další řádek definice můžeme zapisovat bez toho, že bychom znovu museli určovat adresu v CGRAM.
Po ukončení zápisu definice musíme přepnout displej do normálního režimu.
RS R/W D7----D0 0 0 01011000 Přepnutí do programovacího režimu a nastaveni CG adresy na znak #3 1 0 00000010 Zapsání horního řádku pixelů 1 0 00000100 : 1 0 00001110 : 1 0 00000001 : 1 0 00001111 : 1 0 00010001 : 1 0 00001111 Zapsání spodního řádku pixelů 1 0 00000000 Zapsání místa pro kurzor
RS je pin, který přepíná význam dat: je-li 0, data jsou příkazem pro displej, je-li 1, data jsou skutečná data.
R/W je pin, který přepíná směr: je-li 0, data se zapisují do displeje, je-li 1, data se z displeje čtou.

| Příkaz | RS | R/W | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | Popis | prodleva |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
Clear Display |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
Vymaže displej a dává kurzor úplně doleva na 1. řádek |
1.5 ms |
Return Home |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
X |
Přesun kurzoru úplně doleva |
\(40 \mu s\) |
Entry Mode Set |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
I/D |
SH |
Nastavení směru pohybu kurzoru a povolení pohybu displeje |
\(40 \mu s\) |
Diplay ON/OFF control |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
D |
C |
B |
Zapíná indikátor (D=1), kuzor (C=1) a vybírá typ kurzoru (B=1 je blikající blok, B=0 je blikající podrtžítko) |
\(40 \mu s\) |
Cursor or Display shift |
0 |
0 |
0 |
0 |
0 |
1 |
S/C |
R/L |
X |
X |
Nastavuje posun displeje nebo kurzoru (S/C) doprava nebo doleva (R/L) |
\(40 \mu s\) |
Function Set |
0 |
0 |
0 |
0 |
1 |
DL |
1 |
0 |
P |
0 |
Nastavení komunikace interface DL=0/1 — 4bitový/8bitový a stránky generátoru znaků P |
\(40 \mu s\) |
Set CGRAM Address |
0 |
0 |
0 |
1 |
adresa CGRAM |
Nastavení adresy pro následující operace s CGRAM (a nastavení kurzoru) a výběr oblasti CGRAM |
\(40 \mu s\) |
|||||
Sed DDRAM Adress |
0 |
0 |
1 |
adresa DDRAM |
Nastavení adresy pro následující operace s DDRAM a výběr oblasti DDRAM |
\(40 \mu s\) |
||||||
Read BUSY flag and Address |
0 |
1 |
BS |
AC |
Přečíst flag BUSY a adresu |
— |
||||||
Write Data to RAM |
1 |
0 |
zapisovaná data |
Zápis dat do aktivní oblasti |
\(40 \mu s\) |
|||||||
Read Data from RAM |
1 |
1 |
čtená data |
Čtení dat z aktivní oblasti |
\(40 \mu s\) |
|||||||
Poznámky: Prodleva je maximální. Prodlevu není nutné dodržet při čtení flagu BS, jakmile je BS=0, je možné hned zadávat další příkaz. Jestliže se flag BS před posláním příkazu neprověřuje -- je nezbytné udělat prodlevu dle tabulky, aby modul pracoval korektně. Velké písmeno X znamená, že tam může být 0 nebo 1 (nemá to na nic vliv).
Podrobný popis jednotlivých pinů je možno zjistit z z datasheetu čipu HD44780 nebo z článku na electronicsforu.com.
Uživatelsky definovaný znak můžeme poslat do displeje pomocí následujícího fragmentu Céčkového kódu:
// pro RS pin
#define LCD_CHARACTER 1 // přepíná display do režimu zobrazovaní znaků (nebo posílání dat)
#define LCD_COMMAND 0 // přepíná display do režimu programování
const int LCD_SETCGRAMADDR = 0x40; // v režimu programování nastavujeme CGRAM adresu
const int LCD_SETDDRAMADDR = 0x80; // v režimu programování nastavujeme DDRAM adresu
uint8_t location = 7; // bázová adresa v CGRAM, zde je pozice 7 v CGRAM paměti
char map[8] = // definice znaku ý
{
0b00000010,
0b00000100,
0b00010001,
0b00010001,
0b00001111,
0b00010001,
0b00001110,
0b00000000
},
location = location << 3; (1)
lcd_send_byte(LCD_SETCGRAMADDR | location, LCD_COMMAND); (2)
for(int i=0; i<8; i++) {
lcd_send_byte(map[i],LCD_CHARACTER); (3)
sleep_us(40);
}
uint8_t adr = (cursor_y == 0) ? 0x80 + cursor_x : 0xC0 + cursor_x; (4)
lcd_send_byte(LCD_SETDDRAMADDR | adr, LCD_COMMAND); (5)
| 1 | location musíme posunout o 3 bity doleva |
| 2 | pošleme příkaz na programování CGRAM |
| 3 | postupně pošleme 8 řádků definice znaku |
| 4 | musíme si někde pamatovat pozici kurzoru, před programováním CGRAM a po ukončení posunout DDRAM o tuto pozici, bez toho se displej vzteká a dějí se hlouposti |
| 5 | ukončíme programování CGRAM (posunujeme o adresu adr) a vrátíme se do normálního režimu práce displeje |
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
* Copyright (c) 2023 Jirka Chráska <jirka@lixis.cz>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "pico/binary_info.h"
/* Example code to drive a 16x2 LCD panel via a I2C bridge chip (e.g. PCF8574)
NOTE: The panel must be capable of being driven at 3.3v NOT 5v. The Pico
GPIO (and therefor I2C) cannot be used at 5v.
You will need to use a level shifter on the I2C lines if you want to run the
board at 5v.
Connections on Raspberry Pi Pico board, other boards may vary.
GPIO 4 (pin 6)-> SDA on LCD bridge board
GPIO 5 (pin 7)-> SCL on LCD bridge board
3.3v (pin 36) -> VCC on LCD bridge board
GND (pin 38) -> GND on LCD bridge board
*/
// commands
const int LCD_CLEARDISPLAY = 0x01;
const int LCD_RETURNHOME = 0x02;
const int LCD_ENTRYMODESET = 0x04;
const int LCD_DISPLAYCONTROL = 0x08;
const int LCD_CURSORSHIFT = 0x10;
const int LCD_FUNCTIONSET = 0x20;
const int LCD_SETCGRAMADDR = 0x40;
const int LCD_SETDDRAMADDR = 0x80;
// flags for display entry mode
const int LCD_ENTRYSHIFTINCREMENT = 0x01;
const int LCD_ENTRYLEFT = 0x02;
// flags for display and cursor control
const int LCD_BLINKON = 0x01;
const int LCD_CURSORON = 0x02;
const int LCD_DISPLAYON = 0x04;
// flags for display and cursor shift
const int LCD_MOVERIGHT = 0x04;
const int LCD_DISPLAYMOVE = 0x08;
// flags for function set
const int LCD_5x10DOTS = 0x04;
const int LCD_2LINE = 0x08;
const int LCD_8BITMODE = 0x10;
// flag for backlight control
const int LCD_BACKLIGHT = 0x08;
const int LCD_ENABLE_BIT = 0x04;
// By default these LCD display drivers are on bus address 0x27
static int addr = 0x27;
// Modes for lcd_send_byte
#define LCD_CHARACTER 1
#define LCD_COMMAND 0
#define MAX_LINES 2
#define MAX_CHARS 16
// Custom characters
typedef struct cchar {
char znak;
char map[8];
char location;
} CCHAR;
#define znak_a_acute 0
#define znak_e_acute 1
#define znak_e_caron 2
#define znak_c_caron 3
#define znak_d_caron 4
#define znak_i_acute 5
#define znak_o_acute 6
#define znak_y_acute 7
static CCHAR znak1 = {
znak_a_acute,
{
0b00000010,
0b00000100,
0b00001110,
0b00000001,
0b00001111,
0b00010001,
0b00001111,
0b00000000
},
0
};
static CCHAR znak2 = {
znak_e_acute,
{
0b00000010,
0b00000100,
0b00001110,
0b00010001,
0b00011111,
0b00010000,
0b00001110,
0b00000000
},
1
};
static CCHAR znak3 = {
znak_e_caron,
{
0b00001010,
0b00000100,
0b00001110,
0b00010001,
0b00011111,
0b00010000,
0b00001110,
0b00000000
},
2
};
static CCHAR znak4 = {
znak_c_caron,
{
0b00001010,
0b00000100,
0b00001110,
0b00010000,
0b00010000,
0b00010001,
0b00001110,
0b00000000
},
3
};
static CCHAR znak5 = {
znak_d_caron,
{
0b00001010,
0b00000101,
0b00001101,
0b00010011,
0b00010001,
0b00010001,
0b00001110,
0b00000000
},
4
};
static CCHAR znak6 = {
znak_i_acute,
{
0b00000010,
0b00000100,
0b00000000,
0b00001100,
0b00000100,
0b00000100,
0b00001110,
0b00000000
},
5
};
static CCHAR znak7= {
znak_o_acute,
{
0b00000010,
0b00000100,
0b00001110,
0b00010001,
0b00010001,
0b00010001,
0b00001110,
0b00000000
},
6
};
static CCHAR znak8= {
znak_y_acute,
{
0b00000010,
0b00000100,
0b00010001,
0b00010001,
0b00001111,
0b00010001,
0b00001110,
0b00000000
},
7
};
/* Quick helper function for single byte transfers */
void i2c_write_byte(uint8_t val) {
#ifdef i2c_default
i2c_write_blocking(i2c_default, addr, &val, 1, false);
#endif
}
void lcd_toggle_enable(uint8_t val) {
// Toggle enable pin on LCD display
// We cannot do this too quickly or things don't work
#define DELAY_US 600
sleep_us(DELAY_US);
i2c_write_byte(val | LCD_ENABLE_BIT);
sleep_us(DELAY_US);
i2c_write_byte(val & ~LCD_ENABLE_BIT);
sleep_us(DELAY_US);
}
// The display is sent a byte as two separate nibble transfers
void lcd_send_byte(uint8_t val, int mode) {
uint8_t high = mode | (val & 0xF0) | LCD_BACKLIGHT;
uint8_t low = mode | ((val << 4) & 0xF0) | LCD_BACKLIGHT;
i2c_write_byte(high);
lcd_toggle_enable(high);
i2c_write_byte(low);
lcd_toggle_enable(low);
}
void lcd_clear(void) {
lcd_send_byte(LCD_CLEARDISPLAY, LCD_COMMAND);
}
// go to location on LCD
void lcd_set_cursor(int line, int position) {
int val = (line == 0) ? 0x80 + position : 0xC0 + position;
lcd_send_byte(val, LCD_COMMAND);
}
static void inline lcd_char(char val) {
lcd_send_byte(val, LCD_CHARACTER);
}
void lcd_string(const char *s) {
while (*s) {
lcd_char(*s++);
}
}
void lcd_init()
{
lcd_send_byte(0x03, LCD_COMMAND);
lcd_send_byte(0x03, LCD_COMMAND);
lcd_send_byte(0x03, LCD_COMMAND);
lcd_send_byte(0x02, LCD_COMMAND);
lcd_send_byte(LCD_ENTRYMODESET | LCD_ENTRYLEFT, LCD_COMMAND);
lcd_send_byte(LCD_FUNCTIONSET | LCD_2LINE, LCD_COMMAND);
lcd_send_byte(LCD_DISPLAYCONTROL | LCD_DISPLAYON, LCD_COMMAND);
lcd_clear();
}
// custom character definition
void lcd_create_custom_char(uint8_t location, const char map[] )
{
location = location << 3;
lcd_send_byte(LCD_SETCGRAMADDR | location,LCD_COMMAND);
for(int i=0; i<8; i++) {
lcd_send_byte(map[i],LCD_CHARACTER);
}
lcd_send_byte(LCD_SETDDRAMADDR, LCD_COMMAND);
}
int init_gpio()
{
// This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico)
i2c_init(i2c_default, 100 * 1000);
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
// Make the I2C pins available to picotool
// bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));
}
int main()
{
static char d1[17];
static char d2[17];
init_gpio();
for(int i=0; i<17; i++) {
d1[i] = '\0';
d2[i] = '\0';
}
lcd_init();
lcd_set_cursor(0,0);
// definice vlastních znaků
lcd_create_custom_char((uint8_t)0, znak1.map);
lcd_create_custom_char((uint8_t)1, znak2.map);
lcd_create_custom_char((uint8_t)2, znak3.map);
lcd_create_custom_char((uint8_t)3, znak4.map);
lcd_create_custom_char((uint8_t)4, znak5.map);
lcd_create_custom_char((uint8_t)5, znak6.map);
lcd_create_custom_char((uint8_t)6, znak7.map);
lcd_create_custom_char((uint8_t)7, znak8.map);
// jedeme
lcd_string("Program init.");
lcd_set_cursor(1,0);
lcd_string("Jirka Chr"); lcd_char(0x8); lcd_string("ska"); (1)
sleep_ms(10000); // spíme 10 sekund
lcd_clear();
d1[0] = 'D'; d1[1] = 'e'; d1[2] = 'c'; d1[3] = ':'; d1[4] = ' ';
d2[0] = 'Z'; d2[1] = 'n'; d2[2] = 'a'; d2[3] = 'k'; d2[4] = ' ';
while(1) {
for(int j=8; j<16; j++) {
d1[5]=' ';
d1[6]=' ';
d1[7]=' ';
switch(j%10) { // jednotky
case 0: d1[7] = '0'; break;
case 1: d1[7] = '1'; break;
case 2: d1[7] = '2'; break;
case 3: d1[7] = '3'; break;
case 4: d1[7] = '4'; break;
case 5: d1[7] = '5'; break;
case 6: d1[7] = '6'; break;
case 7: d1[7] = '7'; break;
case 8: d1[7] = '8'; break;
case 9: d1[7] = '9'; break;
}
switch( (j%100)/10 ) { // desitky
case 0: d1[6] = '0'; break;
case 1: d1[6] = '1'; break;
case 2: d1[6] = '2'; break;
case 3: d1[6] = '3'; break;
case 4: d1[6] = '4'; break;
case 5: d1[6] = '5'; break;
case 6: d1[6] = '6'; break;
case 7: d1[6] = '7'; break;
case 8: d1[6] = '8'; break;
case 9: d1[6] = '9'; break;
}
switch(j/100) { // stovky
case 0: d1[5] = '0'; break;
case 1: d1[5] = '1'; break;
case 2: d1[5] = '2'; break;
}
d1[8] = '\0';
d2[5] = (char) j;
d2[6] = '\0';
lcd_set_cursor(0,0);
lcd_string(d1);
lcd_set_cursor(1,0);
lcd_string(d2);
sleep_ms(1000);
lcd_clear();
}
}
return 0;
}
| 1 | místo dlouhého á musíme poslat na displej znak s kódem 0x8 (kód 0x0 funguje blbě). |
Dokončený program se všemi českými znaky a snad bez chyb
/**
* Copyright (c) 2024 Jirka Chráska <jirka@lixis.cz> All rigths reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Český překlad
* Copyright (c) 2024 Jirka Chráska <jirka@lixis.cz>. Všechna práva vyhrazena.
*
* Redistribuce a použití zdrojových i binárních forem díla, v původním i upravovaném tvaru, jsou
* povoleny za následujících podmínek:
*
* 1. Šířený zdrojový kód musí obsahovat výše uvedenou informaci o copyrightu, tento seznam
* podmínek a níže uvedené zřeknutí se odpovědnosti.
* 2. Šířený binární tvar musí nést výše uvedenou informaci o copyrightu, tento seznam
* podmínek a níže uvedené zřeknutí se odpovědnosti ve své dokumentaci a/nebo dalších
* poskytovaných materiálech.
* 3. Ani jméno vlastníka práv, ani jména přispěvatelů nemohou být použita při podpoře nebo
* právních aktech souvisejících s produkty odvozenými z tohoto softwaru bez výslovného
* písemného povolení.
*
* TENTO SOFTWARE JE POSKYTOVÁN DRŽITELEM LICENCE A JEHO PŘISPĚVATELI "JAK STOJÍ A LEŽÍ" A JAKÉKOLIV
* VÝSLOVNÉ NEBO PŘEDPOKLÁDANÉ ZÁRUKY VČETNĚ, ALE NEJEN, PŘEDPOKLÁDANÝCH OBCHODNÍCH ZÁRUK A ZÁRUKY
* VHODNOSTI PRO JAKÝKOLIV ÚČEL JSOU POPŘENY. DRŽITEL, ANI PŘISPĚVATELÉ NEBUDOU V ŽÁDNÉM PŘÍPADĚ
* ODPOVĚDNI ZA JAKÉKOLIV PŘÍMÉ, NEPŘÍMÉ, NÁHODNÉ, ZVLÁŠTNÍ, PŘÍKLADNÉ NEBO VYPLÝVAJÍCÍ ŠKODY
* (VČETNĚ, ALE NEJEN, ŠKOD VZNIKLÝCH NARUŠENÍM DODÁVEK ZBOŽÍ NEBO SLUŽEB; ZTRÁTOU POUŽITELNOSTI,
* DAT NEBO ZISKŮ; NEBO PŘERUŠENÍM OBCHODNÍ ČINNOSTI) JAKKOLIV ZPŮSOBENÉ NA ZÁKLADĚ JAKÉKOLIV TEORIE
* O ZODPOVĚDNOSTI, AŤ UŽ PLYNOUCÍ Z JINÉHO SMLUVNÍHO VZTAHU, URČITÉ ZODPOVĚDNOSTI NEBO PŘEČINU
* (VČETNĚ NEDBALOSTI) NA JAKÉMKOLIV ZPŮSOBU POUŽITÍ TOHOTO SOFTWARE, I V PŘÍPADĚ, ŽE DRŽITEL PRÁV
* BYL UPOZORNĚN NA MOŽNOST TAKOVÝCH ŠKOD.
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "pico/binary_info.h"
// commands
const int LCD_CLEARDISPLAY = 0x01;
const int LCD_RETURNHOME = 0x02;
const int LCD_ENTRYMODESET = 0x04;
const int LCD_DISPLAYCONTROL = 0x08;
const int LCD_CURSORSHIFT = 0x10;
const int LCD_FUNCTIONSET = 0x20;
const int LCD_SETCGRAMADDR = 0x40;
const int LCD_SETDDRAMADDR = 0x80;
// flags for display entry mode
const int LCD_ENTRYSHIFTINCREMENT = 0x01;
const int LCD_ENTRYLEFT = 0x02;
// flags for display and cursor control
const int LCD_BLINKON = 0x01;
const int LCD_CURSORON = 0x02;
const int LCD_DISPLAYON = 0x04;
// flags for display and cursor shift
const int LCD_MOVERIGHT = 0x04;
const int LCD_DISPLAYMOVE = 0x08;
// flags for function set
const int LCD_5x10DOTS = 0x04;
const int LCD_2LINE = 0x08;
const int LCD_8BITMODE = 0x10;
// flag for backlight control
const int LCD_BACKLIGHT = 0x08;
const int LCD_ENABLE_BIT = 0x04;
// By default these LCD display drivers are on bus address 0x27
static int addr = 0x27;
// Modes for lcd_send_byte
#define LCD_CHARACTER 1
#define LCD_COMMAND 0
#define MAX_LINES 2
#define MAX_CHARS 16
// czech characters ISO-8859-2
const unsigned char znak_a_acute = '\xE1'; // á
const unsigned char znak_A_acute = '\xC1'; // Á
const unsigned char znak_c_caron = '\xE8'; // č
const unsigned char znak_C_caron = '\xC8'; // Č
const unsigned char znak_d_caron = '\xEF'; // ď
const unsigned char znak_D_caron = '\xCF'; // Ď
const unsigned char znak_e_acute = '\xE9'; // é
const unsigned char znak_E_acute = '\xC9'; // É
const unsigned char znak_e_caron = '\xEC'; // ě
const unsigned char znak_E_caron = '\xCC'; // Ě
const unsigned char znak_i_acute = '\xED'; // í
const unsigned char znak_I_acute = '\xCD'; // Í
const unsigned char znak_n_caron = '\xF2'; // ň
const unsigned char znak_N_caron = '\xD2'; // Ň
const unsigned char znak_o_acute = '\xF3'; // ó
const unsigned char znak_O_acute = '\xD3'; // Ó
const unsigned char znak_r_caron = '\xF8'; // ř
const unsigned char znak_R_caron = '\xD8'; // Ř
const unsigned char znak_s_caron = '\xB9'; // š
const unsigned char znak_S_caron = '\xA9'; // Š
const unsigned char znak_t_caron = '\xBB'; // ť
const unsigned char znak_T_caron = '\xAB'; // Ť
const unsigned char znak_u_acute = '\xFA'; // ú
const unsigned char znak_U_acute = '\xDA'; // Ú
const unsigned char znak_u_ogonek = '\xF9'; // ů
const unsigned char znak_U_ogonek = '\xD9'; // Ů
const unsigned char znak_y_acute = '\xFD'; // ý
const unsigned char znak_Y_acute = '\xDD'; // Ý
const unsigned char znak_z_caron = '\xBE'; // ž
const unsigned char znak_Z_caron = '\xAE'; // Ž
// Custom characters
static unsigned char c_char[256];
static unsigned char cz_char[8]; // custom chars definitions
static uint8_t volna_pozice = 0;
static uint8_t cursor_x = 0;
static uint8_t cursor_y = 0;
static uint8_t num_columns = 40;
static uint8_t num_lines = 2;
typedef struct cchar {
unsigned char znak;
char map[8];
char location;
} CZCHAR;
#define pismenek 30
static CZCHAR czech_chars[pismenek] = {
{
znak_a_acute, // 1
{
0b00000010,
0b00000100,
0b00001110,
0b00000001,
0b00001111,
0b00010001,
0b00001111,
0b00000000
},
0
},
{
znak_A_acute, // 2
{
0b00000010,
0b00000100,
0b00001010,
0b00010001,
0b00011111,
0b00010001,
0b00010001,
0b00000000
},
0
},
{
znak_c_caron, // 3
{
0b00001010,
0b00000100,
0b00001110,
0b00010001,
0b00010000,
0b00010001,
0b00001110,
0b00000000
},
0
},
{
znak_C_caron, // 4
{
0b00001010,
0b00001110,
0b00010001,
0b00010000,
0b00010000,
0b00010001,
0b00001110,
0b00000000
},
0
},
{
znak_d_caron, // 5
{
0b00010101,
0b00001001,
0b00001101,
0b00010011,
0b00010001,
0b00010001,
0b00001110,
0b00000000
},
0
},
{
znak_D_caron, // 6
{
0b00011101,
0b00010010,
0b00010001,
0b00010001,
0b00010001,
0b00010010,
0b00011100,
0b00000000
},
0
},
{
znak_e_acute, // 7
{
0b00000010,
0b00000100,
0b00001110,
0b00010001,
0b00011111,
0b00010000,
0b00001110,
0b00000000
},
0
},
{
znak_E_acute, // 8
{
0b00000010,
0b00000100,
0b00011111,
0b00010000,
0b00011111,
0b00010000,
0b00011111,
0b00000000
},
0
},
{
znak_e_caron, // 9
{
0b00001010,
0b00000100,
0b00001110,
0b00010001,
0b00011111,
0b00010000,
0b00001110,
0b00000000
},
0
},
{
znak_E_caron, // 10
{
0b00001010,
0b00000100,
0b00011111,
0b00010000,
0b00011111,
0b00010000,
0b00011111,
0b00000000
},
0
},
{
znak_i_acute, // 11
{
0b00000010,
0b00000100,
0b00000000,
0b00001100,
0b00000100,
0b00000100,
0b00001110,
0b00000000
},
0
},
{
znak_I_acute, // 12
{
0b00000010,
0b00000101,
0b00000000,
0b00001110,
0b00000100,
0b00000100,
0b00001110,
0b00000000
},
0
},
{
znak_n_caron, // 13
{
0b00001010,
0b00000100,
0b00010110,
0b00011101,
0b00010001,
0b00010001,
0b00010001,
0b00000000
},
0
},
{
znak_N_caron, // 14
{
0b00001010,
0b00000100,
0b00010001,
0b00011001,
0b00010101,
0b00010011,
0b00010001,
0b00000000
},
0
},
{
znak_o_acute, // 15
{
0b00000010,
0b00000100,
0b00001110,
0b00010001,
0b00010001,
0b00010001,
0b00001110,
0b00000000
},
0
},
{
znak_O_acute, // 16
{
0b00000001,
0b00001110,
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00001110,
0b00000000
},
0
},
{
znak_r_caron, // 17
{
0b00001010,
0b00000100,
0b00010110,
0b00011001,
0b00010000,
0b00010000,
0b00010000,
0b00000000
},
0
},
{
znak_R_caron, // 18
{
0b00001010,
0b00011110,
0b00010001,
0b00010001,
0b00011110,
0b00010010,
0b00010001,
0b00000000
},
0
},
{
znak_s_caron, // 19
{
0b00001010,
0b00000100,
0b00001111,
0b00010000,
0b00001110,
0b00000001,
0b00011110,
0b00000000
},
0
},
{
znak_S_caron, // 20
{
0b00001010,
0b00001111,
0b00010000,
0b00010000,
0b00001110,
0b00000001,
0b00011110,
0b00000000
},
0
},
{
znak_t_caron, // 21
{
0b00001101,
0b00001010,
0b00011100,
0b00001000,
0b00001000,
0b00001001,
0b00000110,
0b00000000
},
0
},
{
znak_T_caron, // 22
{
0b00001010,
0b00011111,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000000
},
0
},
{
znak_u_acute, // 23
{
0b00000010,
0b00000100,
0b00010001,
0b00010001,
0b00010001,
0b00010011,
0b00001101,
0b00000000
},
0
},
{
znak_U_acute, // 24
{
0b00000010,
0b00010101,
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00001110,
0b00000000
},
0
},
{
znak_u_ogonek, // 25
{
0b00000100,
0b00001010,
0b00010101,
0b00010001,
0b00010001,
0b00010011,
0b00001101,
0b00000000
},
0
},
{
znak_U_ogonek, // 26
{
0b00000100,
0b00001010,
0b00010101,
0b00010001,
0b00010001,
0b00010001,
0b00001110,
0b00000000
},
0
},
{
znak_y_acute, // 27
{
0b00000010,
0b00000100,
0b00010001,
0b00010001,
0b00001111,
0b00000001,
0b00001110,
0b00000000
},
0
},
{
znak_Y_acute, // 28
{
0b00000010,
0b00010101,
0b00010001,
0b00001010,
0b00000100,
0b00000100,
0b00001110,
0b00000000
},
0
},
{
znak_z_caron, // 29
{
0b00001010,
0b00000100,
0b00011111,
0b00000010,
0b00000100,
0b00001000,
0b00011111,
0b00000000
},
0
},
{
znak_Z_caron, // 30
{
0b00001010,
0b00010101,
0b00000001,
0b00000010,
0b00000100,
0b00001000,
0b00011111,
0b00000000
},
0
}
};
/* Quick helper function for single byte transfers */
void i2c_write_byte(uint8_t val)
{
#ifdef i2c_default
i2c_write_blocking(i2c_default, addr, &val, 1, false);
#endif
}
/* Quick helper function for single byte transfers */
uint8_t i2c_read_byte()
{
uint8_t val = 0;
#ifdef i2c_default
i2c_read_blocking(i2c_default, addr, &val, 1, false);
#endif
return val;
}
void lcd_toggle_enable(uint8_t val)
{
// Toggle enable pin on LCD display
// We cannot do this too quickly or things don't work
#define DELAY_US 600
sleep_us(DELAY_US);
i2c_write_byte(val | LCD_ENABLE_BIT);
sleep_us(DELAY_US);
i2c_write_byte(val & ~LCD_ENABLE_BIT);
sleep_us(DELAY_US);
}
// The display is sent a byte as two separate nibble transfers
void lcd_send_byte(uint8_t val, int mode)
{
uint8_t high = mode | (val & 0xF0) | LCD_BACKLIGHT;
uint8_t low = mode | ((val << 4) & 0xF0) | LCD_BACKLIGHT;
i2c_write_byte(high);
lcd_toggle_enable(high);
i2c_write_byte(low);
lcd_toggle_enable(low);
}
// vymaže display včetně na definovaných znaků
void lcd_clear(void)
{
lcd_send_byte(LCD_CLEARDISPLAY, LCD_COMMAND);
for(int i=0; i<8; i++) {
cz_char[i] = '\x00';
}
volna_pozice = 0;
}
void lcd_home(void)
{
lcd_send_byte(LCD_RETURNHOME, LCD_COMMAND);
cursor_x = 0;
cursor_y = 0;
}
void lcd_move_left(void) // pohyb doleva
{
lcd_send_byte(LCD_CURSORSHIFT|LCD_DISPLAYMOVE, LCD_COMMAND);
// printf("lcd_move_left ");
}
void lcd_move_right(void) // pohyb doprava
{
lcd_send_byte(LCD_CURSORSHIFT|LCD_DISPLAYMOVE|LCD_MOVERIGHT, LCD_COMMAND);
// printf("lcd_move_right ");
}
// go to location on LCD
void lcd_set_cursor(int line, int position)
{
int val = (line == 0) ? 0x80 + position : 0xC0 + position;
cursor_x = position;
cursor_y = line;
lcd_send_byte(val, LCD_COMMAND);
}
static void inline lcd_char(char val)
{
lcd_send_byte(val, LCD_CHARACTER);
cursor_x += 1;
if(cursor_x >= num_columns) {
cursor_x = 0;
cursor_y += 1;
}
if(cursor_y >= num_lines) {
cursor_y = 0;
}
// printf("x=%d,y=%d ",cursor_x,cursor_y);
}
void lcd_string(const char *s)
{
while (*s) {
lcd_char(*s++);
}
}
// inicializace displeje
void lcd_init()
{
lcd_send_byte(0x03, LCD_COMMAND);
lcd_send_byte(0x03, LCD_COMMAND);
lcd_send_byte(0x03, LCD_COMMAND);
lcd_send_byte(0x02, LCD_COMMAND);
lcd_send_byte(LCD_ENTRYMODESET | LCD_ENTRYLEFT, LCD_COMMAND);
lcd_send_byte(LCD_FUNCTIONSET | LCD_2LINE, LCD_COMMAND);
lcd_send_byte(LCD_DISPLAYCONTROL | LCD_DISPLAYON, LCD_COMMAND);
lcd_clear();
}
// custom character definition
void lcd_create_custom_char(uint8_t location, const char map[] )
{
location = location << 3;
// printf("location=%x ", LCD_SETCGRAMADDR | location);
lcd_send_byte(LCD_SETCGRAMADDR | location, LCD_COMMAND);
for(int i=0; i<8; i++) {
lcd_send_byte(map[i],LCD_CHARACTER);
sleep_us(40);
}
uint8_t adr = (cursor_y == 0) ? 0x80 + cursor_x : 0xC0 + cursor_x;
lcd_send_byte(LCD_SETDDRAMADDR | adr, LCD_COMMAND);
}
void lcd_characters_init()
{
for(int i=0; i<256; i++) {
if(i < 0x20) c_char[i] = '\x20';
if(i >= 0x20 && i< 0x80) c_char[i] = (unsigned char) i;
if(i >= 0x80) c_char[i] = '\x80';
}
for(int i=0; i<8; i++) {
cz_char[i] = '\x00';
}
volna_pozice = 0;
c_char[znak_a_acute] = '\xFF';
c_char[znak_A_acute] = '\xFF';
c_char[znak_c_caron] = '\xFF';
c_char[znak_C_caron] = '\xFF';
c_char[znak_d_caron] = '\xFF';
c_char[znak_D_caron] = '\xFF';
c_char[znak_e_acute] = '\xFF';
c_char[znak_E_acute] = '\xFF';
c_char[znak_e_caron] = '\xFF';
c_char[znak_E_caron] = '\xFF';
c_char[znak_i_acute] = '\xFF';
c_char[znak_I_acute] = '\xFF';
c_char[znak_n_caron] = '\xFF';
c_char[znak_N_caron] = '\xFF';
c_char[znak_o_acute] = '\xFF';
c_char[znak_O_acute] = '\xFF';
c_char[znak_r_caron] = '\xFF';
c_char[znak_R_caron] = '\xFF';
c_char[znak_s_caron] = '\xFF';
c_char[znak_S_caron] = '\xFF';
c_char[znak_t_caron] = '\xFF';
c_char[znak_T_caron] = '\xFF';
c_char[znak_u_acute] = '\xFF';
c_char[znak_U_acute] = '\xFF';
c_char[znak_u_ogonek] = '\xFF';
c_char[znak_U_ogonek] = '\xFF';
c_char[znak_y_acute] = '\xFF';
c_char[znak_Y_acute] = '\xFF';
c_char[znak_z_caron] = '\xFF';
c_char[znak_Z_caron] = '\xFF';
}
/*void debug_char(char c){
switch(c){
case '\x00': lcd_string("00"); break;
case '\x01': lcd_string("01"); break;
case '\x02': lcd_string("02"); break;
case '\x03': lcd_string("03"); break;
case '\x04': lcd_string("04"); break;
case '\x05': lcd_string("05"); break;
case '\x06': lcd_string("06"); break;
case '\x07': lcd_string("07"); break;
case '\x08': lcd_string("08"); break;
case '\x09': lcd_string("09"); break;
case '\x0a': lcd_string("0A"); break;
case '\x0b': lcd_string("0B"); break;
case '\x0c': lcd_string("0C"); break;
case '\x0d': lcd_string("0D"); break;
case '\x0e': lcd_string("0E"); break;
case '\x0f': lcd_string("0F"); break;
case '\x10': lcd_string("10"); break;
case '\x11': lcd_string("11"); break;
case '\x12': lcd_string("12"); break;
case '\x13': lcd_string("13"); break;
case '\x14': lcd_string("14"); break;
case '\x15': lcd_string("15"); break;
case '\x16': lcd_string("16"); break;
case '\x17': lcd_string("17"); break;
case '\x18': lcd_string("18"); break;
case '\x19': lcd_string("19"); break;
case '\x1a': lcd_string("1A"); break;
case '\x1b': lcd_string("1B"); break;
case '\x1c': lcd_string("1C"); break;
case '\x1d': lcd_string("1D"); break;
case '\x1e': lcd_string("1E"); break;
case '\x1f': lcd_string("1F"); break;
case '\x20': lcd_string("20"); break;
case '\x21': lcd_string("21"); break;
case '\x22': lcd_string("22"); break;
case '\x23': lcd_string("23"); break;
case '\x24': lcd_string("24"); break;
case '\x25': lcd_string("25"); break;
case '\x26': lcd_string("26"); break;
case '\x27': lcd_string("27"); break;
case '\x28': lcd_string("28"); break;
case '\x29': lcd_string("29"); break;
case '\x2a': lcd_string("2A"); break;
case '\x2b': lcd_string("2B"); break;
case '\x2c': lcd_string("2C"); break;
case '\x2d': lcd_string("2D"); break;
case '\x2e': lcd_string("2E"); break;
case '\x2f': lcd_string("2F"); break;
case '\x30': lcd_string("30"); break;
case '\x31': lcd_string("31"); break;
case '\x32': lcd_string("32"); break;
case '\x33': lcd_string("33"); break;
case '\x34': lcd_string("34"); break;
case '\x35': lcd_string("35"); break;
case '\x36': lcd_string("36"); break;
case '\x37': lcd_string("37"); break;
case '\x38': lcd_string("38"); break;
case '\x39': lcd_string("39"); break;
case '\x3a': lcd_string("3A"); break;
case '\x3b': lcd_string("3B"); break;
case '\x3c': lcd_string("3C"); break;
case '\x3d': lcd_string("3D"); break;
case '\x3e': lcd_string("3E"); break;
case '\x3f': lcd_string("3F"); break;
case '\x40': lcd_string("40"); break;
case '\x41': lcd_string("41"); break;
case '\x42': lcd_string("42"); break;
case '\x43': lcd_string("43"); break;
case '\x44': lcd_string("44"); break;
case '\x45': lcd_string("45"); break;
case '\x46': lcd_string("46"); break;
case '\x47': lcd_string("47"); break;
case '\x48': lcd_string("48"); break;
case '\x49': lcd_string("49"); break;
case '\x4a': lcd_string("4A"); break;
case '\x4b': lcd_string("4B"); break;
case '\x4c': lcd_string("4C"); break;
case '\x4d': lcd_string("4D"); break;
case '\x4e': lcd_string("4E"); break;
case '\x4f': lcd_string("4F"); break;
case '\x50': lcd_string("50"); break;
case '\x51': lcd_string("51"); break;
case '\x52': lcd_string("52"); break;
case '\x53': lcd_string("53"); break;
case '\x54': lcd_string("54"); break;
case '\x55': lcd_string("55"); break;
case '\x56': lcd_string("56"); break;
case '\x57': lcd_string("57"); break;
case '\x58': lcd_string("58"); break;
case '\x59': lcd_string("59"); break;
case '\x5a': lcd_string("5A"); break;
case '\x5b': lcd_string("5B"); break;
case '\x5c': lcd_string("5C"); break;
case '\x5d': lcd_string("5D"); break;
case '\x5e': lcd_string("5E"); break;
case '\x5f': lcd_string("5F"); break;
case '\x60': lcd_string("60"); break;
case '\x61': lcd_string("61"); break;
case '\x62': lcd_string("62"); break;
case '\x63': lcd_string("63"); break;
case '\x64': lcd_string("64"); break;
case '\x65': lcd_string("65"); break;
case '\x66': lcd_string("66"); break;
case '\x67': lcd_string("67"); break;
case '\x68': lcd_string("68"); break;
case '\x69': lcd_string("69"); break;
case '\x6a': lcd_string("6A"); break;
case '\x6b': lcd_string("6B"); break;
case '\x6c': lcd_string("6C"); break;
case '\x6d': lcd_string("6D"); break;
case '\x6e': lcd_string("6E"); break;
case '\x6f': lcd_string("6F"); break;
case '\x70': lcd_string("70"); break;
case '\x71': lcd_string("71"); break;
case '\x72': lcd_string("72"); break;
case '\x73': lcd_string("73"); break;
case '\x74': lcd_string("74"); break;
case '\x75': lcd_string("75"); break;
case '\x76': lcd_string("76"); break;
case '\x77': lcd_string("77"); break;
case '\x78': lcd_string("78"); break;
case '\x79': lcd_string("79"); break;
case '\x7a': lcd_string("7A"); break;
case '\x7b': lcd_string("7B"); break;
case '\x7c': lcd_string("7C"); break;
case '\x7d': lcd_string("7D"); break;
case '\x7e': lcd_string("7E"); break;
case '\x7f': lcd_string("7F"); break;
case '\x80': lcd_string("80"); break;
case '\x81': lcd_string("81"); break;
case '\x82': lcd_string("82"); break;
case '\x83': lcd_string("83"); break;
case '\x84': lcd_string("84"); break;
case '\x85': lcd_string("85"); break;
case '\x86': lcd_string("86"); break;
case '\x87': lcd_string("87"); break;
case '\x88': lcd_string("88"); break;
case '\x89': lcd_string("89"); break;
case '\x8a': lcd_string("8A"); break;
case '\x8b': lcd_string("8B"); break;
case '\x8c': lcd_string("8C"); break;
case '\x8d': lcd_string("8D"); break;
case '\x8e': lcd_string("8E"); break;
case '\x8f': lcd_string("8F"); break;
case '\x90': lcd_string("90"); break;
case '\x91': lcd_string("91"); break;
case '\x92': lcd_string("92"); break;
case '\x93': lcd_string("93"); break;
case '\x94': lcd_string("94"); break;
case '\x95': lcd_string("95"); break;
case '\x96': lcd_string("96"); break;
case '\x97': lcd_string("97"); break;
case '\x98': lcd_string("98"); break;
case '\x99': lcd_string("99"); break;
case '\x9a': lcd_string("9A"); break;
case '\x9b': lcd_string("9B"); break;
case '\x9c': lcd_string("9C"); break;
case '\x9d': lcd_string("9D"); break;
case '\x9e': lcd_string("9E"); break;
case '\x9f': lcd_string("9F"); break;
case '\xa0': lcd_string("A0"); break;
case '\xa1': lcd_string("A1"); break;
case '\xa2': lcd_string("A2"); break;
case '\xa3': lcd_string("A3"); break;
case '\xa4': lcd_string("A4"); break;
case '\xa5': lcd_string("A5"); break;
case '\xa6': lcd_string("A6"); break;
case '\xa7': lcd_string("A7"); break;
case '\xa8': lcd_string("A8"); break;
case '\xa9': lcd_string("A9"); break;
case '\xaa': lcd_string("AA"); break;
case '\xab': lcd_string("AB"); break;
case '\xac': lcd_string("AC"); break;
case '\xad': lcd_string("AD"); break;
case '\xae': lcd_string("AE"); break;
case '\xaf': lcd_string("AF"); break;
case '\xb0': lcd_string("B0"); break;
case '\xb1': lcd_string("B1"); break;
case '\xb2': lcd_string("B2"); break;
case '\xb3': lcd_string("B3"); break;
case '\xb4': lcd_string("B4"); break;
case '\xb5': lcd_string("B5"); break;
case '\xb6': lcd_string("B6"); break;
case '\xb7': lcd_string("B7"); break;
case '\xb8': lcd_string("B8"); break;
case '\xb9': lcd_string("B9"); break;
case '\xba': lcd_string("BA"); break;
case '\xbb': lcd_string("BB"); break;
case '\xbc': lcd_string("BC"); break;
case '\xbd': lcd_string("BD"); break;
case '\xbe': lcd_string("BE"); break;
case '\xbf': lcd_string("BF"); break;
case '\xc0': lcd_string("C0"); break;
case '\xc1': lcd_string("C1"); break;
case '\xc2': lcd_string("C2"); break;
case '\xc3': lcd_string("C3"); break;
case '\xc4': lcd_string("C4"); break;
case '\xc5': lcd_string("C5"); break;
case '\xc6': lcd_string("C6"); break;
case '\xc7': lcd_string("C7"); break;
case '\xc8': lcd_string("C8"); break;
case '\xc9': lcd_string("C9"); break;
case '\xca': lcd_string("CA"); break;
case '\xcb': lcd_string("CB"); break;
case '\xcc': lcd_string("CC"); break;
case '\xcd': lcd_string("CD"); break;
case '\xce': lcd_string("CE"); break;
case '\xcf': lcd_string("CF"); break;
case '\xd0': lcd_string("D0"); break;
case '\xd1': lcd_string("D1"); break;
case '\xd2': lcd_string("D2"); break;
case '\xd3': lcd_string("D3"); break;
case '\xd4': lcd_string("D4"); break;
case '\xd5': lcd_string("D5"); break;
case '\xd6': lcd_string("D6"); break;
case '\xd7': lcd_string("D7"); break;
case '\xd8': lcd_string("D8"); break;
case '\xd9': lcd_string("D9"); break;
case '\xda': lcd_string("DA"); break;
case '\xdb': lcd_string("DB"); break;
case '\xdc': lcd_string("DC"); break;
case '\xdd': lcd_string("DD"); break;
case '\xde': lcd_string("DE"); break;
case '\xdf': lcd_string("DF"); break;
case '\xe0': lcd_string("E0"); break;
case '\xe1': lcd_string("E1"); break;
case '\xe2': lcd_string("E2"); break;
case '\xe3': lcd_string("E3"); break;
case '\xe4': lcd_string("E4"); break;
case '\xe5': lcd_string("E5"); break;
case '\xe6': lcd_string("E6"); break;
case '\xe7': lcd_string("E7"); break;
case '\xe8': lcd_string("E8"); break;
case '\xe9': lcd_string("E9"); break;
case '\xea': lcd_string("EA"); break;
case '\xeb': lcd_string("EB"); break;
case '\xec': lcd_string("EC"); break;
case '\xed': lcd_string("ED"); break;
case '\xee': lcd_string("EE"); break;
case '\xef': lcd_string("EF"); break;
case '\xf0': lcd_string("F0"); break;
case '\xf1': lcd_string("F1"); break;
case '\xf2': lcd_string("F2"); break;
case '\xf3': lcd_string("F3"); break;
case '\xf4': lcd_string("F4"); break;
case '\xf5': lcd_string("F5"); break;
case '\xf6': lcd_string("F6"); break;
case '\xf7': lcd_string("F7"); break;
case '\xf8': lcd_string("F8"); break;
case '\xf9': lcd_string("F9"); break;
case '\xfa': lcd_string("FA"); break;
case '\xfb': lcd_string("FB"); break;
case '\xfc': lcd_string("FC"); break;
case '\xfd': lcd_string("FD"); break;
case '\xfe': lcd_string("FE"); break;
case '\xff': lcd_string("FF"); break;
}
}*/
// tisk znaků na LCD displej
int lcd_czchar_define(const char *str)
{
char c;
uint8_t nadefinovano = 8;
while(*str) {
c = *str;
// printf("c=%c,'0x%x' ",c,c);
nadefinovano = 8;
if(c > '\x7F' && c < '\xFF' && c_char[c] == '\xFF') { // musíme použít custom znak: podíváme, zda už ho máme nadefinovaný anebo ho budeme definovat
for(unsigned int k = 0; k<8; k++) {
if(cz_char[k] == c) { // máme nadefinováno
nadefinovano = k;
}
}
if(nadefinovano == 8) { // nemáme nadefinováno
// vyhledame volnou pozici k definici
if(volna_pozice > 7) {
volna_pozice = 0;
}
for(unsigned int j=0; j < pismenek; j++) { // vyhledame definici
if(czech_chars[j].znak == c) { // definice noveho znaku
lcd_create_custom_char(volna_pozice, czech_chars[j].map);
cz_char[volna_pozice] = c;
nadefinovano = volna_pozice;
volna_pozice++;
}
}
}
// máme nadefinováno
c = nadefinovano + 8;
} // nemusíme použít custom znak
lcd_char(c);
str++;
} // for str
}
// inicializace GPIO
int init_gpio()
{
// This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico)
i2c_init(i2c_default, 400 * 1000);
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
// Make the I2C pins available to picotool
bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));
}
// posunování celého textu na displeji tam a zpátky, pokud se tam celý text nevejde
void twist(int chars, int pause, int repeat)
{
int i=0;
while(repeat) {
sleep_ms(pause*2);
for(i=0; i<chars;i++) {
lcd_move_left();
sleep_ms(pause);
}
sleep_ms(pause*2);
for(i=0; i<chars;i++) {
lcd_move_right();
sleep_ms(pause);
}
sleep_ms(pause*2);
repeat--;
}
}
int main()
{
init_gpio();
stdio_init_all();
lcd_characters_init();
lcd_init();
lcd_clear();
while (1) {
lcd_clear();
lcd_home();
lcd_set_cursor(0,0);
lcd_czchar_define("Střední škola, Podorlické vzděl. centrum");
lcd_home();
lcd_set_cursor(1,0);
lcd_czchar_define(" Dobruška Dobruška Dobruška Dobruška ");
twist(24,700,2);
lcd_clear();
lcd_home();
lcd_set_cursor(0,0);
lcd_czchar_define("Mgr. Ing. Jiří Chráska ");
lcd_set_cursor(1,0);
lcd_czchar_define("Jaroměř <jirka@lixis.cz>");
twist(8,700,4);
}
return 0;
}
add_executable(lcd_czech_chars
lcd_czech_chars.c
)
# pull in common dependencies and additional i2c hardware support
target_link_libraries(lcd_czech_chars pico_stdlib hardware_i2c)
pico_enable_stdio_usb(lcd_czech_chars 1)
pico_enable_stdio_uart(lcd_czech_chars 0)
# create map/bin/hex file etc.
pico_add_extra_outputs(lcd_czech_chars)
Zdroje a odkazy
https://www.raspberrypi.com/documentation/pico-sdk/rp2__common_2hardware__i2c_2include_2hardware_2i2c_8h.html