Diese Library dient zum Ansteuern eines Text LC-Display mit HD44780 Treiber, welches seriell über I2C und einem PCF8574 mit dem Mikrocontroller verbunden ist. Dabei sind die I2C Adresse, die Anzahl Zeilen und die Anzahl Zeichen je Zeile konfigurierbar.
Günstige Displays haben z.B. 16×2 oder 20×4 Zeichen und können z.B. hier erworben werden:
- 16×2 Character Blue Backlight LCD Display (2.81 €)
- 20×4 Character Blue Backligt LCD Display (5.58 €)
Der PCF8574 ist ein via I2C-Bus angeschlossener 8-Bit I/O Port-Expander. Ein seriell an den Baustein gesendeter Wert wird auf dessen Pins parallel ausgegeben. Ein typisches Datenblatt findet ihr z.B. hier. Daraus ersichtlich ist auch die I2C Adressbelegung, welche bei einigen Modulen über Lötbrücken verändert werden kann. Hinweis zu den Angaben der ersten drei Spalten A2, A1 und A0: der Wert VSS bedeutet, dass eine Lötbrücke vorhanden ist, der Wert VDD bedeutet keine Lötbrücke:
Mein verwendetes Modul ist im Auslieferungszustand auf die I2C Adresse 0x7E eingestellt (keine Lötbrücken). Durch Lötbrücken an A0 bis A2 können bei Bedarf auch andere Adressen (0x77 bis 0x7E) eingestellt werden. Es gibt wohl auch Module, bei denen die I2C Adresse von 0x20 bis 0x27, oder von 0x38 bis 0x3F einzustellen ist, oder auch von 0x47 bis 0x4E geht. Hinweis: In meiner Library habe ich eine PortScan Funktion eingebunden, damit bei unbekannter I2C Adresse diese automatisch erkannt und verwendet werden kann;)
Oberhalb der Lötbrücken (A0 bis A2) ist am I2C Modul ein Drehregler, mit dem der Kontrast geregelt werden kann. Achtung: Oft ist der Kontrast im Auslieferungszustand sehr weit runter geschraubt. Daher sollte man den Kontrast zu beginn mit dem Drehregler ganz nach rechts an den Anschlag drehen. Später, wenn die Ansteuerung funktioniert, dann könnt ihr den Kontrast entsprechend korrigieren.
Zur Ansteuerung werden neben der Versorgungsspannung (5V und GND) nur zwei Leitungen benötigt (SCL, SDA). Hier im Beispiel wurde I2C3 benutzt.
Benutzte Pins :
GND an GND VCC an +5V SDA an PC9 SCL an PA8
Als Grundlage der I2C Kommunikation habe ich das I2C LoLevel Library verwendet, wobei ich alle drei Module (I2C1, I2C2 und I2C3) eingebunden habe.
Programmtechnisch muss nach wie vor die Protokollverwaltung des HD44780 umgesetzt werden, denn wie bereits erwähnt ist der PCF8574 „nur“ ein I2C I/O Expander.
Hier habe ich zwei Skizzen für euch, welche die Anbindung schematisch verdeutlichen:
Deshalb sind die Funktionen dieser Library sehr ähnlich der Funktionen aus der LCD_2x16-Library. Allerdings wollte ich etwas flexibler sein, was die Konfiguration der Pinbelegung und Display-Einstellung betrifft. Deshalb erfolgt die Konfiguration eines LCD Displays über eine Struktur mit folgenden Attributen:
1 2 3 4 5 6 7 8 9 10 | //-------------------------------------------------------------- // Struktur eines LCD Displays //-------------------------------------------------------------- typedef struct { TI2C_t i2c; // I2C Modul (1=I2C1, 2=I2C2 oder 3=I2C3) uint8_t slave_adr; // I2C Adresse (z.B. 0x27) uint8_t maxx; // Max. Anzahl Zeichen je Zeile (1..20) uint8_t maxy; // Max Anzahl Zeilen (1..4) uint8_t backlight; // LCD Hintergrundbeleuchtung (0=Aus, 1=Ein) }LCD_TEXT_DISPLAY_t; |
Voraussetzungen :
CMSIS_BOOT, M4_CMSIS_CORE stm32_ub_i2c1.c (ab Version 1.3) stm32_ub_i2c2.c (ab Version 1.3) stm32_ub_i2c3.c (ab Version 1.3) printf.c (ab Version 07.11.2013)
Funktionen :
1 2 3 4 5 6 7 8 9 10 11 12 | void UB_I2C_Init(LCD_TEXT_DISPLAY_t *lcd); void UB_LCD_TEXT_I2C_Delay(uint32_t delay); void UB_LCD_TEXT_I2C_Init(LCD_TEXT_DISPLAY_t *lcd); void UB_LCD_TEXT_I2C_Clear(LCD_TEXT_DISPLAY_t *lcd); void UB_LCD_TEXT_I2C_SetMode(LCD_TEXT_DISPLAY_t *lcd, TLCD_TEXT_I2C_MODE_t mode); void UB_LCD_TEXT_I2C_String(LCD_TEXT_DISPLAY_t *lcd, uint8_t x, uint8_t y, char *ptr); void UB_LCD_TEXT_I2C_WriteCG(LCD_TEXT_DISPLAY_t *lcd, uint8_t nr, uint8_t *pixeldata); void UB_LCD_TEXT_I2C_PrintCG(LCD_TEXT_DISPLAY_t *lcd, uint8_t x, uint8_t y, uint8_t nr); void UB_LCD_TEXT_I2C_Backlight_On(LCD_TEXT_DISPLAY_t *lcd); void UB_LCD_TEXT_I2C_Backlight_Off(LCD_TEXT_DISPLAY_t *lcd); void UB_LCD_TEXT_I2C_Backlight_Toggle(LCD_TEXT_DISPLAY_t *lcd); uint8_t UB_LCD_TEXT_I2C_PortScan(LCD_TEXT_DISPLAY_t *lcd, uint8_t start, uint8_t ende); |
Beispiel :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | //-------------------------------------------------------------- // File : main.c // Datum : 24.02.2018 // Version : 1.01 // Autor : Manfred Becker (MB) // EMail : - // Web : http://mikrocontroller.bplaced.net/ // CPU : STM32F429 (Discovery-Board) // IDE : CooCox CoIDE 1.7.8 // GCC : 4.7 2012q4 // Module : CMSIS_BOOT, M4_CMSIS_CORE // : stm32_ub_i2c1.c (ab Version 1.3) // : stm32_ub_i2c2.c (ab Version 1.3) // : stm32_ub_i2c3.c (ab Version 1.3) // : stm32_ub_lcd_text_i2c.c (ab Version 1.0) // : printf.c (ab Version 07.11.2013) // Funktion : Demo der LCD Text Anbindung ueber I2C-LoLevel-Library // Hinweis : Diese zwei Files muessen auf 8MHz stehen // "cmsis_boot/stm32f4xx.h" // "cmsis_boot/system_stm32f4xx.c" // In Configuration diese Define hinzufügen : // "STM32F429_439xx" , "__ASSEMBLY__" , "USE_STDPERIPH_DRIVER" //-------------------------------------------------------------- #include "main.h" #include "stm32_ub_lcd_text_i2c.h" #include "stdio.h" // fuer sprintf() Funktion int main(void) { LCD_TEXT_DISPLAY_t myLCD = { TI2C3, // I2C Modul (1=I2C1, 2=I2C2 oder 3=I2C3) 0, // I2C Adresse des LCD Displays. Falls unbekannt dann auf 0 setzen und PortScan laufen lassen. 16, // Anzahl Zeichen je Zeile 2, // Anzahl Zeilen 1 // LCD Hintergrundbeleuchtung (0=Aus, 1=Ein) }; SystemInit(); // Quarz Einstellungen aktivieren // Init der I2C1-Schnittstelle UB_I2C_Init(&myLCD); // I2C Port Scan starten? if (myLCD.slave_adr==0x00) { uint8_t n; // I2C Port Scan starten von 0x01 bis 0x7F if ((myLCD.slave_adr = UB_LCD_TEXT_I2C_PortScan(&myLCD, 0x01, 0x7F)) != 0x00) { char txt[16]; sprintf(txt,"I2C-Adr: 0x%02x", myLCD.slave_adr); // Init vom LC-Display UB_LCD_TEXT_I2C_Init(&myLCD); // Text auf Zeile-1 ausgeben UB_LCD_TEXT_I2C_String(&myLCD,0,0,txt); UB_LCD_TEXT_I2C_Delay(150); for (n=0; n < 11; n++) { UB_LCD_TEXT_I2C_Backlight_Toggle(&myLCD); UB_LCD_TEXT_I2C_Delay(50); } UB_LCD_TEXT_I2C_Backlight_On(&myLCD); UB_LCD_TEXT_I2C_Delay(3000); } else { //ToDo: Fehlerbehandlung } } // Init vom LC-Display UB_LCD_TEXT_I2C_Init(&myLCD); // Text auf Zeile-1 ausgeben UB_LCD_TEXT_I2C_String(&myLCD,0,0,"Hello STM32F429-"); // Text auf Zeile-2 ausgeben UB_LCD_TEXT_I2C_String(&myLCD,0,1,"Mikrocontroller!"); UB_LCD_TEXT_I2C_Delay(2000); // 4-Zeilen LCD Display? if (myLCD.maxy>=4) { // Clear UB_LCD_TEXT_I2C_Clear(&myLCD); UB_LCD_TEXT_I2C_SetMode(&myLCD, TLCD_TEXT_I2C_BLINK); // Display=EIN, Cursor=EIN, Blinken=EIN // Text auf Zeile-1 bis 4 ausgeben UB_LCD_TEXT_I2C_String(&myLCD,0,0,"1"); UB_LCD_TEXT_I2C_String(&myLCD,5,1,"5"); UB_LCD_TEXT_I2C_String(&myLCD,10,2,"10"); UB_LCD_TEXT_I2C_String(&myLCD,15,3,"15"); UB_LCD_TEXT_I2C_Delay(2000); UB_LCD_TEXT_I2C_SetMode(&myLCD, TLCD_TEXT_I2C_ON); // Display=EIN, Cursor=AUS, Blinken=Aus } // Clear UB_LCD_TEXT_I2C_Clear(&myLCD); // Definition eines Sonderzeichens in 8 Bytes uint8_t buf[8]; buf[0]=0b01000000; buf[1]=0b01100000; buf[2]=0b01110000; buf[3]=0b01111000; buf[4]=0b01111100; buf[5]=0b01111110; buf[6]=0b01111111; buf[7]=0b00000000; UB_LCD_TEXT_I2C_WriteCG(&myLCD, 0, buf); // Speichern eines Sonderzeichens im CG-RAM vom Display uint8_t x,y,n; char* ch; for (y=0; y < myLCD.maxy; y++) for (x=0; x < myLCD.maxx; x++) UB_LCD_TEXT_I2C_PrintCG(&myLCD, x, y, 0); // Ausgabe des Sonderzeichens bei Pos. x,y UB_LCD_TEXT_I2C_Delay(2000); while(1) { // Testfunktion im Dauerlauf UB_LCD_TEXT_I2C_Clear(&myLCD); UB_LCD_TEXT_I2C_String(&myLCD,0,0,"LCD Txt I2C Test"); UB_LCD_TEXT_I2C_String(&myLCD,0,1,"Please wait....."); UB_LCD_TEXT_I2C_Delay(2000); x=0; y=0; for (n=0; n < 256; n++) { ch=(char)n; UB_LCD_TEXT_I2C_String(&myLCD,x,y,&ch); if ((++x)>=myLCD.maxx) { x=0; if ((++y)>=myLCD.maxy) { y=0; UB_LCD_TEXT_I2C_Delay(500); } } } } } |
Downloads:
Hier die Library zum Download :
Hier der komplette CooCox-Projektordner zum Download :
Viel Spass damit,
Manfred
PS: Dieses Library gibt’s auch für den STM32F407 Disco.
Hallo, hier noch kurz ein Beispiel, wie man zwei LCD Displays am selben I2C Port betreibt: