1 | //***********************************************************************************************
|
2 | // Programm: LCD Funktionen (DOG-M, SPI, 3.3V)
|
3 | // Mikrocontroller: STM32F103RE (ARM 32-bit CORTEX-M3)
|
4 | // Speicher: 512KB FLASH, 64KB SRAM
|
5 | // Taktfrequenz: 8MHz, PLL: 72MHz
|
6 | // Stand: 08.04.2011
|
7 | // IDE/Compiler: Atollic TrueStudio STM32-Lite 2.0.1
|
8 | // STM FW-Lib: 3.4.0
|
9 | //***********************************************************************************************
|
10 |
|
11 | // Includes
|
12 | #include <stddef.h>
|
13 | #include "stm32f10x.h"
|
14 | #include <string.h>
|
15 |
|
16 | #include "defines.h"
|
17 | #include "main.h"
|
18 |
|
19 | // ***********************************************************************
|
20 | // SPI Initialisierung
|
21 | // ***********************************************************************
|
22 | void init_spi_lcd (void) {
|
23 | SPI_InitTypeDef SPI_InitStructure; // SPI Struktur
|
24 |
|
25 | SPI_I2S_DeInit(SPI1);
|
26 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // SPI1 Takt freigeben
|
27 |
|
28 | // SPI1 Konfiguration
|
29 | SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; // Nur senden
|
30 | SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // SPI Master-Mode
|
31 | SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 8 Datenbits
|
32 | SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // CPOL High=Ruhezustand
|
33 | SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // CPHA 2. Flanke (L/H) gibt Daten aus
|
34 | SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // CS Chipselect per Software
|
35 | SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; // Taktfrequenz 72MHz/32 = 2,2 MHz
|
36 | SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // MSB (höherwertiges Bit) zuerst senden
|
37 | SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC (?)
|
38 | SPI_Init(SPI1, &SPI_InitStructure); // SPI initialisieren
|
39 | SPI_Cmd(SPI1, ENABLE); // SPI freigeben
|
40 | }
|
41 |
|
42 | // ***********************************************************************
|
43 | // Senden eines Bytes per SPI-Interface
|
44 | // Übergabe: byte : Datenbyte
|
45 | // ***********************************************************************
|
46 | void sendbyte_spi_lcd (unsigned char byte) {
|
47 | SPI_I2S_SendData(SPI1, byte); // Byte per SPI senden
|
48 | while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); // Warten bis Byte vollständig gesendet ist
|
49 | }
|
50 |
|
51 | // ***********************************************************************
|
52 | // Schreiben eines Zeichens an das LCD-Modul
|
53 | // Übergabe: lcd_byte : Auszugebendes Zeichen/Steuerzeichen
|
54 | // lcd_mode : 0 - Daten
|
55 | // 1 - Steuerzeichen
|
56 | // ***********************************************************************
|
57 | void write_lcd (unsigned char lcd_byte, unsigned char lcd_mode) {
|
58 | // Zeitangaben für 72 MHz und 2 Waitstates
|
59 | delay_us(200); // Pause mind. 15us bevor nächstes Zeichen gesendet werden darf
|
60 | GPIO_ResetBits(LCD_CSB); // LCD_CSB = 0;
|
61 | if (lcd_mode) GPIO_ResetBits(LCD_RS); // LCD_RS = 0 Steuerzeichen
|
62 | else GPIO_SetBits(LCD_RS); // LCD_RS = 1 Daten
|
63 | // Byte senden seriell senden (D7 D6 D5 D4 D3 D2 D1 D0)
|
64 | sendbyte_spi_lcd(lcd_byte);
|
65 | delay_us(10); // Pause (ca. 1us)
|
66 | GPIO_SetBits(LCD_CSB); // LCD_CSB = 1
|
67 | }
|
68 |
|
69 | // ***********************************************************************
|
70 | // Löschen des LCD-Display
|
71 | // ***********************************************************************
|
72 | void clear_lcd (void) {
|
73 | write_lcd(0x01,1); // Diplay löschen
|
74 | lcd.x = lcd.y = 0; // Position für Scrollfunktion auf Anfang setzen
|
75 | delay(50); // Pause
|
76 | }
|
77 |
|
78 | // ***********************************************************************
|
79 | // Ausgabe eines ASCII-Zeichen positioniert auf dem LCD-Modul
|
80 | // Übergabe: lcd_x : Spalte (0...SPALTEN_MAX-1)
|
81 | // lcd_y : Zeile (0...ZEILEN_MAX-1)
|
82 | // lcd_ascii : ASCII-Zeichen
|
83 | // ***********************************************************************
|
84 | void write_byte_lcd (unsigned char lcd_x, unsigned char lcd_y, unsigned char lcd_ascii) {
|
85 | unsigned char lcd_offset = 0;
|
86 | if (lcd_x > (SPALTEN_MAX - 1)) lcd_x = 0;
|
87 | if (lcd_y > (ZEILEN_MAX - 1)) lcd_y = 0;
|
88 | switch (lcd_y) {
|
89 | case 0: lcd_offset = 0x80; break; // Zeile 1
|
90 | case 1: lcd_offset = 0xC0; break; // Zeile 2
|
91 | default: lcd_offset = 0x80;
|
92 | };
|
93 | write_lcd(lcd_x+lcd_offset,1); // Kursorposition setzen
|
94 | write_lcd(lcd_ascii,0); // Ausgabe des ASCII-Zeichen an der Kursorposition
|
95 | }
|
96 |
|
97 | // ***********************************************************************
|
98 | // Ausgabe einer Zeichenkette positioniert auf dem LCD-Modul
|
99 | // Zeichenkette muss im SRAM liegen
|
100 | // Übergabe: lcd_x : Spalte (0...SPALTEN_MAX-1)
|
101 | // lcd_y : Zeile (0...ZEILEN_MAX-1)
|
102 | // lcd_zeichen : Adresse der auszugebenden format. Zeichenkette
|
103 | // clr_line : Löschen bis Zeilenende
|
104 | // 1 - Löschen
|
105 | // 0 - kein Löschen
|
106 | // ***********************************************************************
|
107 | void printf_lcd (unsigned char lcd_x, unsigned char lcd_y, char *lcd_zeichen, unsigned char clr_line) {
|
108 | unsigned char lcd_i;
|
109 | unsigned char lcd_offset = 0;
|
110 | if (lcd_x > (SPALTEN_MAX - 1)) lcd_x = 0;
|
111 | if (lcd_y > (ZEILEN_MAX - 1)) lcd_y = 0;
|
112 | switch (lcd_y) {
|
113 | case 0: lcd_offset = 0x80; break; // Zeile 1
|
114 | case 1: lcd_offset = 0xC0; break; // Zeile 2
|
115 | default: lcd_offset = 0x80;
|
116 | }
|
117 | write_lcd(lcd_x+lcd_offset,1); // Kursorposition setzen
|
118 | // Ausgabe der Zeichenkette ab der Kursorposition
|
119 | lcd_offset = strlen(lcd_zeichen); // Länge der Zeichenkette
|
120 | if (lcd_offset > SPALTEN_MAX) lcd_offset = SPALTEN_MAX;
|
121 | for(lcd_i = lcd_offset ; lcd_i ; lcd_i--) {
|
122 | write_lcd(*lcd_zeichen,0);
|
123 | lcd_zeichen++;
|
124 | }
|
125 | if (clr_line) {
|
126 | // Löschen bis Zeilenende
|
127 | for(lcd_i = SPALTEN_MAX - lcd_offset - lcd_x ; lcd_i ; lcd_i--) write_lcd(' ',0);
|
128 | }
|
129 | }
|
130 |
|
131 | // ***********************************************************************
|
132 | // Blinkposition auf dem LCD-Displays setzen / Blinken ein/ausschalten
|
133 | // Übergabe: lcd_x : Spalte (0...SPALTEN_MAX-1)
|
134 | // lcd_y : Zeile (0...ZEILEN_MAX-1)
|
135 | // lcd_blink : 0 - Blinken/Cursor aus
|
136 | // 1 - Blinken an
|
137 | // 2 - Cursor an
|
138 | // ***********************************************************************
|
139 | void blink_lcd (unsigned char lcd_x, unsigned char lcd_y, unsigned char lcd_blink) {
|
140 | unsigned char lcd_offset;
|
141 | write_lcd(0x0C,1); // KURSOR ausschalten
|
142 | if (lcd_x > (SPALTEN_MAX - 1)) lcd_x = 0;
|
143 | if (lcd_y > (ZEILEN_MAX - 1)) lcd_y = 0;
|
144 | switch (lcd_y) {
|
145 | case 0: lcd_offset = 0x80; break; // Zeile 1
|
146 | case 1: lcd_offset = 0xC0; break; // Zeile 2
|
147 | default: lcd_offset = 0x80;
|
148 | };
|
149 | write_lcd(lcd_x+lcd_offset,1); // Blinkposition setzen
|
150 | if (lcd_blink == 1) write_lcd(0x0D,1); // Blinken ein
|
151 | if (lcd_blink == 2) write_lcd(0x0E,1); // Cursor ein
|
152 | }
|
153 |
|
154 | // ***********************************************************************
|
155 | // Definieren eines Sonderzeichen
|
156 | // Übergabe: lcd_addr : Adresse
|
157 | // lcd_zeichen: Zeiger auf das 1. Byte der Zeichendefinition
|
158 | // ***********************************************************************
|
159 | void write_lcd_cg (unsigned char lcd_addr, char *lcd_zeichen) {
|
160 | unsigned char lcd_i;
|
161 | for(lcd_i = 0; lcd_i < 8; lcd_i++) {
|
162 | write_lcd(0x40 + lcd_addr * 8 + lcd_i,1); // CG RAM Adresse Set (01aa azzz)
|
163 | write_lcd(*lcd_zeichen,0); // Data Write 8x Pixelzeile
|
164 | lcd_zeichen++;
|
165 | }
|
166 | }
|
167 |
|
168 | // ***********************************************************************
|
169 | // Definieren von 8 Sonderzeichen
|
170 | // Übergabe: lcd_zeichen: Zeiger auf das Zeichenfeld (8x8 Byte)
|
171 | // ***********************************************************************
|
172 | void write_lcd_cg_block (char *sonderzeichenblock) {
|
173 | unsigned char lcd_i;
|
174 | for(lcd_i = 0; lcd_i < 8; lcd_i++) {
|
175 | write_lcd_cg(lcd_i, &sonderzeichenblock[lcd_i * 8]);
|
176 | }
|
177 | }
|
178 |
|
179 | // ***********************************************************************
|
180 | // Grundinitialisierung des LCD-Moduls
|
181 | // LCD wird wie im 8-Bit parallel-Mode initialisiert!
|
182 | // ***********************************************************************
|
183 | void init_lcd (void) {
|
184 | // init_spi_lcd(); // Hardware SPI Initialisierung
|
185 |
|
186 | GPIO_SetBits(LCD_CSB); // LCD_CSB = 1
|
187 | // GPIO_SetBits(LCD_SCK); // LCD_SCK = 1
|
188 | delay(500); // Wartezeit nach POWER-ON bis VCC stabil ist
|
189 | // Grundinitialisierung (SPI, wie im 8-Bit Parallel-Mode)
|
190 | write_lcd(0x39,1); // Function Set
|
191 | write_lcd(0x39,1); // Function Set (gleiches Byte nochmal senden)
|
192 | write_lcd(0x14,1); // Bias Set
|
193 | write_lcd(0x55,1); // Power Control + Kontrast Set C5,C4
|
194 | write_lcd(0x6D,1); // Follower Control
|
195 | write_lcd(0x78,1); // Kontrast Set C3,C2,C1,C0
|
196 | write_lcd(0x0C,1); // Display Set
|
197 | write_lcd(0x06,1); // Entry Mode Set
|
198 | clear_lcd(); // Display löschen
|
199 | }
|
200 |
|
201 |
|
202 |
|
203 | .....
|
204 | // Call
|
205 |
|
206 | init_spi_lcd(); // SPI-Interface für LCD konfigurieren
|
207 | init_lcd(); // LCD Initialisierung
|
208 | printf_lcd(0,0,"Test",1);
|
209 |
|
210 | ...
|