PIC24_DOG
DOGM_S.C
gehe zur Dokumentation dieser Datei
1 // ********************************************************************
2 // Demoprogramm
3 // Inhalt: LCD (DOG-M 081/162/163) mit (ST7036 Controller) ansteuern,
4 // 5V/3V Variante, mit selbst definierten Zeichen im RAM, SPI-Ansteuerung seriell
5 // LCD-Controller: ST7036 kompatibel
6 // Stand: 18.04.2008, Autor: Matthias Kahnt, Url: pro-51.eltra-tec.de
7 // SDCC-Version: M-IDE-51/SDCC 2.8.0
8 // AT89C51ED2: --code-loc 0x0000 --iram-size 256 --xram-loc 0x0000 --xram-size 0x0700
9 // AT89S8253: --code-loc 0x0000 --iram-size 256
10 // ********************************************************************
11 // Für 8051-Microcontroller, z.B. AT89C51ED2 oder AT89S8253
12 // Frequenz: 11.0592 MHz
13 // Code-Speicherbedarf: ca. 1.3kByte, keine XRAM-Verwendung
14 // Das Programm verwendet nur 8051/52 Standard-SFRs und wurde
15 // mit dem AT89C51ED2 auf dem PRO-51 System getestet.
16 // ********************************************************************
17 // Die Programmfunktionen dürfen für private Nutzung verwendet und
18 // verändert werden. Für gewerbliche Nutzung ist die Zustimmung
19 // des Autors erforderlich. Die Nutzung erfolgt auf eigene Gefahr.
20 // Für eventuell entstehende Schäden wird keine Haftung übernommen.
21 // ********************************************************************
22 
23 #include "at89c51ed2.h" // Register des AT89C51ED2
24 //#include "at89s8253.h" // Register des AT89S8253
25 #include <string.h> // Stingfunktionen
26 
27 // Typendefinition
28 typedef unsigned char byte;
29 typedef unsigned int word;
30 typedef unsigned long dword;
31 
32 // Hardware PINs, bitte anpassen
33 #define LCD_ON P1_4
34 #define LCD_RS P3_7
35 #define LCD_SCL P2_6
36 #define LCD_DATA P2_7
37 //#define LCD_CSB (CS-Signal: wird im Bsp. nicht verwendet)
38 
39 // Displaytyp, bitte anpassen
40 #define SPALTEN 16
41 #define ZEILEN 3
42 #define SPANNUNG 5
43 
44 // Tabelle für 8 selbst definierte Sonderzeichen
45 byte code sonderzeichen[] = {
46  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F, // 00-07 Zeichen an Adresse 0
47  0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F, // 08-15 Zeichen an Adresse 1
48  0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F, // 16-23 Zeichen an Adresse 2
49  0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F, // 32-39 Zeichen an Adresse 3
50  0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F, // 40-47 Zeichen an Adresse 4
51  0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F, // 48-55 Zeichen an Adresse 5
52  0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F, // 56-63 Zeichen an Adresse 6
53  0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F // 64-71 Zeichen an Adresse 7
54 };
55 
56 // Tabelle der DOG-M Initialisierung
57 byte code lcd_init_code[] = {
58  0x31,0x1C,0x51,0x6A,0x74, // 00-04 DOG-M 081 5V
59  0x31,0x14,0x55,0x6D,0x7C, // 05-09 DOG-M 081 3V
60  0x39,0x1C,0x52,0x69,0x74, // 10-14 DOG-M 162 5V
61  0x39,0x14,0x55,0x6D,0x78, // 15-19 DOG-M 162 3V
62  0x39,0x1D,0x50,0x6C,0x77, // 20-24 DOG-M 163 5V
63  0x39,0x15,0x55,0x6E,0x72 // 25-29 DOG-M 163 3V
64 };
65 
66 // Tabelle der DOG-M Zeilenanfangsadressen
68  0x00,0x00,0x00, // 00-02 DOG-M 081
69  0x00,0x40,0x40, // 03-05 DOG-M 162
70  0x00,0x10,0x20 // 06-08 DOG-M 163
71 };
72 
73 // ********************************************************************
74 // Verzögerungsschleife für kurze Zeit
75 // Zeit: Wartezeit in [zeit]
76 // 1 = 20us
77 // 2 = 28us
78 // 3 = 36us u.s.w. (gilt für 11.0952MHz)
79 // 255 = ca. 2ms
80 // ********************************************************************
81 void delay_us(byte zeit) {
82 byte zaehler;
83  for ( zaehler = zeit; zaehler; zaehler-- ) {
84  _asm nop; _endasm;
85  }
86 }
87 
88 // ********************************************************************
89 // Verzögerungsschleife für lange Zeit
90 // Zeit: Wartezeit in [zeit]
91 // 1 = ca. 10ms
92 // 2 = ca. 20ms
93 // 3 = ca. 30ms u.s.w.
94 // 255 = ca. 2,5s (gilt für 11.0952MHz)
95 // ********************************************************************
96 void delay(byte zeit) {
97 byte zaehler;
98  for (zaehler = zeit; zaehler; zaehler--) {
99  delay_us(255); // dauert ca. 2ms
100  delay_us(255); // dauert ca. 2ms
101  delay_us(255); // dauert ca. 2ms
102  delay_us(255); // dauert ca. 2ms
103  delay_us(255); // dauert ca. 2ms
104  }
105 }
106 
107 // ***********************************************************************
108 // Schreiben eines Zeichens an das LCD-Modul
109 // seriell Soft-SPI Mode, 3/4 Draht Interface
110 // Übergabe: lcd_byte : Auszugebendes Zeichen/Steuerzeichen
111 // lcd_mode : 0 - Daten
112 // 1 - Steuerzeichen
113 // ***********************************************************************
114 void write_lcd(byte lcd_byte, bit lcd_mode) {
115 byte stelle;
116  // Pause bevor nächstes Zeichen gesendet werden darf
117  delay_us(5); // Pause mind. 26,3us
118  // LCD_CSB = 0;
119  if (lcd_mode) LCD_RS = 0; // Steuerzeichen
120  else LCD_RS = 1; // Daten
121  // Byte senden seriell senden, H-Bit zuerst (Bit 8 7 6 5 4 3 2 1 0)
122  for ( stelle = 0x80; stelle; stelle >>= 1 ) {
123  LCD_DATA = lcd_byte & stelle;
124  LCD_SCL = 0;
125  LCD_SCL = 1;
126  }
127  // LCD_CSB = 1;
128 }
129 
130 // ***********************************************************************
131 // Definieren eines Sonderzeichen
132 // Übergabe: lcd_addr : Adresse
133 // lcd_zeichen: Zeiger auf das 1. Byte der Zeichendefinition
134 // ***********************************************************************
135 void write_lcd_cg(byte lcd_addr, byte *lcd_zeichen) {
136 byte lcd_i;
137  write_lcd(0x38,1); // Function Set DL=1 N=1 DH=0 IS2=0 IS1=0 IS Table 0
138  for(lcd_i = 0; lcd_i < 8; lcd_i++) {
139  write_lcd(0x40 + lcd_addr * 8 + lcd_i,1); // CG RAM Adresse Set (01aa azzz)
140  write_lcd(*lcd_zeichen,0); // Data Write 8x Pixelzeile
141  lcd_zeichen++;
142  }
143  write_lcd(0x39,1); // Function Set DL=1 N=1 DH=0 IS2=0 IS1=1 IS Table 1
144 }
145 
146 // ***********************************************************************
147 // Definieren von 8 Sonderzeichen
148 // Übergabe: lcd_zeichen: Zeiger auf das Zeichenfeld (8x8 Byte)
149 // ***********************************************************************
150 void write_lcd_cg_block(byte *sonderzeichenblock) {
151 byte lcd_i;
152  for(lcd_i = 0; lcd_i < 8; lcd_i++) {
153  write_lcd_cg(lcd_i, &sonderzeichenblock[lcd_i * 8]);
154  }
155 }
156 
157 // ***********************************************************************
158 // Löschen des LCD-Display
159 // und Kursor auf Position 0,0 setzen
160 // ***********************************************************************
161 void clear_lcd(void) {
162  write_lcd(0x01,1);
163  delay(20);
164 }
165 
166 // ***********************************************************************
167 // Ausgabe eines ASCII-Zeichen positioniert auf dem LCD-Modul
168 // Übergabe: lcd_x : Spalte (0...SPALTEN-1)
169 // lcd_y : Zeile (0...ZEILEN-1)
170 // lcd_ascii : ASCII-Zeichen
171 // ***********************************************************************
172 void write_byte_lcd(byte lcd_x, byte lcd_y, byte lcd_ascii) {
173 byte lcd_offset = 0;
174  if (lcd_x > (SPALTEN - 1)) lcd_x = 0;
175  if (lcd_y > (ZEILEN - 1)) lcd_y = 0;
176  switch (lcd_y) {
177  case 0: lcd_offset = lcd_zeilen_adresse[(ZEILEN - 1) * 3]; break; // Zeile 1
178  case 1: lcd_offset = lcd_zeilen_adresse[(ZEILEN - 1) * 3 + 1]; break; // Zeile 2
179  case 2: lcd_offset = lcd_zeilen_adresse[(ZEILEN - 1) * 3 + 2]; break; // Zeile 3
180  };
181  write_lcd(0x80 + lcd_x + lcd_offset,1); // Kursorposition setzen
182  write_lcd(lcd_ascii,0); // Ausgabe des ASCII-Zeichen an der Kursorposition
183 }
184 
185 // ***********************************************************************
186 // Ausgabe einer Zeichenkette positioniert auf dem LCD-Modul
187 // Übergabe: lcd_x : Spalte (0...SPALTEN-1)
188 // lcd_y : Zeile (0...ZEILEN-1)
189 // lcd_zeichen : Adresse der auszugebenden format. Zeichenkette
190 // clr_line : Löschen bis Zeilenende
191 // 1 - Löschen
192 // 0 - kein Löschen
193 // ***********************************************************************
194 void printf_lcd(byte lcd_x, byte lcd_y, byte *lcd_zeichen, bit clr_line) {
195 byte lcd_i;
196 byte lcd_offset = 0;
197  if (lcd_x > (SPALTEN - 1)) lcd_x = 0;
198  if (lcd_y > (ZEILEN - 1)) lcd_y = 0;
199  switch (lcd_y) {
200  case 0: lcd_offset = lcd_zeilen_adresse[(ZEILEN - 1) * 3]; break; // Zeile 1
201  case 1: lcd_offset = lcd_zeilen_adresse[(ZEILEN - 1) * 3 + 1]; break; // Zeile 2
202  case 2: lcd_offset = lcd_zeilen_adresse[(ZEILEN - 1) * 3 + 2]; break; // Zeile 3
203  }
204  write_lcd(0x80 + lcd_x + lcd_offset,1); // Kursorposition setzen
205  // Ausgabe der Zeichenkette ab der Kursorposition
206  lcd_offset = strlen(lcd_zeichen); // Länge der Zeichenkette
207  if (lcd_offset > SPALTEN) lcd_offset = SPALTEN;
208  for(lcd_i = lcd_offset; lcd_i; lcd_i--) {
209  write_lcd(*lcd_zeichen,0); lcd_zeichen++;
210  }
211  if (clr_line) {
212  // Löschen bis Zeilenende
213  for(lcd_i = SPALTEN - lcd_offset - lcd_x; lcd_i; lcd_i--)
214  write_lcd(' ',0);
215  }
216 }
217 
218 // ***********************************************************************
219 // Blinkposition/Cursor auf dem LCD-Displays setzen
220 // Übergabe: lcd_x : Spalte (0...SPALTEN-1)
221 // lcd_y : Zeile (0...ZEILEN-1)
222 // lcd_blink : 0 - Blinken/Cursor aus
223 // 1 - Blinken an
224 // 2 - Cursor an
225 // ***********************************************************************
226 void blink_lcd(byte lcd_x, byte lcd_y, byte lcd_blink) {
227 byte lcd_offset = 0;
228  write_lcd(0x0C,1); // KURSOR ausschalten
229  if (lcd_x > (SPALTEN - 1)) lcd_x = 0;
230  if (lcd_y > (ZEILEN - 1)) lcd_y = 0;
231  switch (lcd_y) {
232  case 0: lcd_offset = lcd_zeilen_adresse[(ZEILEN - 1) * 3]; break; // Zeile 1
233  case 1: lcd_offset = lcd_zeilen_adresse[(ZEILEN - 1) * 3 + 1]; break; // Zeile 2
234  case 2: lcd_offset = lcd_zeilen_adresse[(ZEILEN - 1) * 3 + 2]; break; // Zeile 3
235  };
236  write_lcd(0x80 + lcd_x + lcd_offset,1); // Blinkposition setzen
237  if (lcd_blink == 1) write_lcd(0x0D,1); // Blinken ein
238  if (lcd_blink == 2) write_lcd(0x0E,1); // Cursor ein
239 }
240 
241 
242 // ***********************************************************************
243 // Grundinitialisierung des LCD-Moduls in SPI-Mode (seriell)
244 // ***********************************************************************
245 #pragma save
246 #pragma disable_warning 126
247 void init_lcd(void) {
248 byte offset;
249  LCD_ON = 1; // LCD Beleuchtung einschalten
250  delay(5); // ca. 50ms Wartezeit nach dem Einschalten
251  offset = (ZEILEN - 1) * 10; // Offset = 00, 10, 20
252  if (SPANNUNG != 5) offset += 5; // Offset = 05, 15, 25
253  // Grundinitialisierung (SPI, wie im 8-Bit parallel-Mode)
254  write_lcd(lcd_init_code[offset],1); // Function Set
255  write_lcd(lcd_init_code[offset],1); // Function Set (gleiches Byte nochmal senden)
256  write_lcd(lcd_init_code[offset + 1],1); // Bias Set
257  write_lcd(lcd_init_code[offset + 2],1); // Power Control + Kontrast Set C5,C4
258  write_lcd(lcd_init_code[offset + 3],1); // Follower Control
259  write_lcd(lcd_init_code[offset + 4],1); // Kontrast Set C3,C2,C1,C0
260  write_lcd(0x0C,1); // Display Set
261  write_lcd(0x06,1); // Entry Mode Set
262  clear_lcd(); // Display löschen
263 }
264 #pragma restore
265 
266 // ********************************************************************
267 // Hauptprogramm
268 // ********************************************************************
269 void main (void) {
270  init_lcd();
271  write_lcd_cg_block(sonderzeichen); // Sonderzeichen definieren
272  // Ausgabebeispiel für 3 zeiliges Display
273  printf_lcd(0,0,"LCD-Basic's",1); // Einschaltmeldung
274  printf_lcd(0,1,"DOG-M 163 ST7036",1);
275  printf_lcd(0,2,"V1 18.04.2008",1);
276  delay(200); // Pause ca. 2s
277  printf_lcd(0,2,"CGRAM:",1); // Sonderzeichen ausgeben
278  write_byte_lcd(7,2,0);
279  write_byte_lcd(8,2,1);
280  write_byte_lcd(9,2,2);
281  write_byte_lcd(10,2,3);
282  write_byte_lcd(11,2,4);
283  write_byte_lcd(12,2,5);
284  write_byte_lcd(13,2,6);
285  write_byte_lcd(14,2,7);
286  delay(200); // Pause ca. 2s
287  printf_lcd(0,2,"SPI seriell Mode",1);
288  blink_lcd(15,2,1);
289  while(1);
290 }
unsigned int word
Definition: DOGM_S.C:29
#define LCD_DATA
Definition: DOGM_S.C:36
#define LCD_SCL
Definition: DOGM_S.C:35
unsigned char byte
Definition: DOGM_S.C:28
void main(void)
Definition: DOGM_S.C:269
void clear_lcd(void)
Definition: DOGM_S.C:161
void delay_us(byte zeit)
Definition: DOGM_S.C:81
#define SPANNUNG
Definition: DOGM_S.C:42
void init_lcd(void)
Definition: DOGM_S.C:247
#define LCD_RS
Definition: DOGM_S.C:34
byte code lcd_zeilen_adresse[]
Definition: DOGM_S.C:67
void write_lcd(byte lcd_byte, bit lcd_mode)
Definition: DOGM_S.C:114
void delay(byte zeit)
Definition: DOGM_S.C:96
void printf_lcd(byte lcd_x, byte lcd_y, byte *lcd_zeichen, bit clr_line)
Definition: DOGM_S.C:194
void blink_lcd(byte lcd_x, byte lcd_y, byte lcd_blink)
Definition: DOGM_S.C:226
byte code sonderzeichen[]
Definition: DOGM_S.C:45
#define ZEILEN
Definition: DOGM_S.C:41
void write_lcd_cg(byte lcd_addr, byte *lcd_zeichen)
Definition: DOGM_S.C:135
#define LCD_ON
Definition: DOGM_S.C:33
byte code lcd_init_code[]
Definition: DOGM_S.C:57
void write_byte_lcd(byte lcd_x, byte lcd_y, byte lcd_ascii)
Definition: DOGM_S.C:172
unsigned long dword
Definition: DOGM_S.C:30
void write_lcd_cg_block(byte *sonderzeichenblock)
Definition: DOGM_S.C:150
#define SPALTEN
Definition: DOGM_S.C:40