Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

LCD hd44780 met ATMEL M32

Pagina: 1
Acties:

  • kippy
  • Registratie: September 2004
  • Laatst online: 21-11 13:02
Nu het vakantie is vond ik dat ik toch maar een beetje moet gaan hobbyen. Ik heb een 2 x 20 regel LCD aangesloten op een ATMEL M32. Ik krijg em alleen niet goed aan de praat en kan niet vinden waar de fout zit.

Ik programeer in IAR. en het LCD is goed aangeloten. Dus het zit em in de code, maar ik zie niet waar.
(edit) ook wel handig om te weten ik gebruik de 4bit mode.


code:
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
// Aanslutingen
// PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0
// E   R/W REG x   D7  D6  D5  D4
#define LCD PORTB

void LCDE(void)
{
    LCD = LCD | 0x80;
    __delay_cycles(50000);
    LCD = LCD & ~0x80;
};

void LCDRSON(void)
{
    LCD = LCD | 0x20;
    __delay_cycles(500);
};

void LCDRSOFF(void)
{
    LCD = LCD & ~0x20;
    __delay_cycles(500);
};

void LCDRON(void)
{
    LCD = LCD | 0x40;
};

void LCDWON(void)
{
    LCD = LCD & ~0x40;
};

void LCDWRITE(char b)
{
    char a = LCD;
    char c;
    c = (a & 0xF0) | (b & 0x0F);
    LCD = c;
    LCDE();
    b = __swap_nibbles(b);  //Swaps bit 0-3 with bit 4-7
    c = (a & 0xF0) | (b & 0x0F);
    LCD = c;
    LCDE();
};

void LCDLETTER(char b)
{

    char a = LCD;
    char c;
    c = (a & 0xF0) | (b & 0x0F);
    LCD = c;
    LCDRSON();
    LCDE();
    LCDRSOFF();
    b = __swap_nibbles(b);  //Swaps bit 0-3 with bit 4-7
    c = (a & 0xF0) | (b & 0x0F);
    LCD = c;
    LCDRSON();
    LCDE();
    LCDRSOFF();
};

int LCDINIT(void)
{
    // Aanslutingen
    // PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0
    // E   R/W REG x   D7  D6  D5  D4
    // 8   4   2   1   8   4   2   1
    DDRB = 0xFF;
    LCD = 0x00;
    LCDWON();
    LCD = LCD | 0x03;   //8bit
    LCDE();
    LCD = LCD | 0x03;   //8bit
    LCDE();
    LCD = LCD | 0x03;   //8bit
    LCDE();
    LCD = LCD | 0x02;   //4bit
    LCDE();
    LCDWRITE(0x28);
    LCDWRITE(0x08);
    LCDWRITE(0x0c);
    LCDWRITE(0x01);
    LCDWRITE(0x06);
    __delay_cycles(30000);
    LCDLETTER('A');
    LCDLETTER('B');
    LCDLETTER('C');

    return 0;
};


(edit 2) ik zie trouwens wel dat men LCD wel een clear command krijgt. Maar ik krijg geen tekst.

[ Voor 17% gewijzigd door kippy op 12-07-2006 19:16 ]


  • kippy
  • Registratie: September 2004
  • Laatst online: 21-11 13:02
Ok na nog wat verder klungelen en de initializatie zonder funkties geschreven te hebben werkt het. Ga nog wel een goede funkties der voor maken. Voor de liefhebbers een goede 4 bit init.

code:
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
#define LCD PORTB

void LCDE(void)
{
    LCD = LCD | 0x80;
    __delay_cycles(500);
    LCD = LCD & ~0x80;
};

void LCDRSON(void)
{
    LCD = LCD | 0x20;
    __delay_cycles(500);
};

void LCDRSOFF(void)
{
    LCD = LCD & ~0x20;
    __delay_cycles(500);
};

void LCDREADB(void)
{
    LCD = LCD | 0x40;
};

void LCDWRITEB(void)
{
    LCD = LCD & ~0x40;
};

void LCDWRITE(char b)
{

};

void LCDLETTER(char b)
{

};

int LCDINIT(void)
{
    // Aanslutingen
    // PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0
    // E   R/W REG x   D7  D6  D5  D4
    // 8   4   2   1   8   4   2   1
    DDRB = 0xFF;
    LCD = 0x00;
    LCDWRITEB();
    LCD = 0x03;   //8bit
    LCDE();
    __delay_cycles(3000);
    LCD = 0x03;   //8bit
    LCDE();
    __delay_cycles(3000);
    LCD = 0x03;   //8bit
    LCDE();
    __delay_cycles(3000);
    LCD = 0x02;   //4bit
    LCDE();
    __delay_cycles(3000);
    LCD = 0x02;
    LCDE();
    LCD = 0x08;
    LCDE();
    LCD = 0x00;
    LCDE();
    LCD = 0x08;
    LCDE();
    LCD = 0x00;
    LCDE();
    LCD = 0x01;
    LCDE();
    __delay_cycles(30000);
    LCD = 0x00;
    LCDE();
    LCD = 0x0C;
    LCDE();
    LCD = 0x00;
    LCDE();
    LCD = 0x06;
    LCDE();

    //Char A
    LCD = 0x04;
    LCDRSON();
    LCDE();
    LCD = 0x01;
    LCDRSON();
    LCDE();
    LCDRSOFF();

    //Char B
    LCD = 0x04;
    LCDRSON();
    LCDE();
    LCD = 0x02;
    LCDRSON();
    LCDE();
    LCDRSOFF();

    return 0;
};

  • Vuikie
  • Registratie: December 2003
  • Laatst online: 09:35
Mag ik alleen vragen waarom je de init 3 keer in 8 bit stuurt?

Ik ben zelf een assembler progger maar als je de 00101000 code 1 keer in 8 en 1 keer in 4 bit stuurt is ook genoeg, bij mij in elkgeval wel.

  • kippy
  • Registratie: September 2004
  • Laatst online: 21-11 13:02
Wat ik in alle datasheets heb gelezen moest het 3 keer. Zal nog wel eens met 1 keer proberen.

  • Vuikie
  • Registratie: December 2003
  • Laatst online: 09:35
dit is de code die ik heb gebruikt:

code:
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
;****************************************
;*Naam      :LCD controller voor het    *
;*           Trein Controller systeem   *
;*                                      *
;*Auteur    :Arjan Vuik                 *
;*                                      *
;*Platform  :Atmel AT90S2313            *
;*                                      *
;*IDE       :AVR Studio 4               *
;*                                      *
;*Taal      :Assembler                  *
;****************************************

.device     AT90S2313
.include    "2313def.inc"

;Definities
.def    char    =r0     ;hier worden de letters van het boot message in gezet voor dat ze weggeschreven worden naar het LCD.
.def    id      =r1     ;register om de chip ID in op te slaan. Dit moet nu nog van te voren ingesteld worden, maar het is de bedoeling dat dit automatisch word.
.def    null    =r2     ;nul register
.def    een     =r3     ;1 register
.def    wreg    =r16    ;werk register
.def    lcddata =r17    ;LCD data/instructie opslag register
.def    lwreg   =r18    ;LCD werk register
.def    nibble1 =r19    ;Data bestaat uit 24bit die worden verzonden in 3 nibbles van 8 bit, eerste nibble is altijd het chip ID.
.def    nibble2 =r20    ;tweede nibble. Is altijd een LCD instructie, als er geen instructie is worden er alleen maar nullen gstuurd.
.def    nibble3 =r21    ;derde nibble. Is altijd LCD data, als er geen data is worden er alleen nullen gestuurd.
;.def   spare   =r22    ;HEY ik heb nog een register over!
.def    teller  =r23    ;teller registers
.def    teller1 =r24    ;
.def    teller2 =r25    ;

;equals

;stuurlijnen
.equ    E       = PB2   ;controll lijnen voor LCD
.equ    RS      = PB0
.equ    COMM    = PD0   ;communicatie poort.
;PB4-PB7 zitten aan D4-D7 van de LCD

;commando's
.equ    clr_lcd = 0b00000001    ;clear LCD
.equ    hm_lcd  = 0b00000010    ;Cursor home
.equ    set_lcd8= 0b00100000    ;8bit functie settings
.equ    set_lcd4= 0b00101000    ;4bit functie settings van lcd(4bit, 2/4 regels)
.equ    lcd_on  = 0b00001100    ;LCD aan zetten, cursor verborgen
.equ    entry   = 0b00000110    ;Cursor verschuift

        
;Vector tabel
.cseg

.org    $00
        rjmp    main                ; reset vector

;main program

main:
    ldi     wreg, RAMEND
    out     SPL, wreg

    rcall   init

    ldi     wreg, set_lcd8      ;Het set_lcd commando moet 2 keer verzonden worden
    rcall   write_com8          ;1 keer in 8 bit,

    ldi     lwreg, set_lcd4
    rcall   write_com           ;en 1 keer in 4 bit.
    
    ldi     lwreg, lcd_on
    rcall   write_com

    ldi     lwreg, clr_lcd
    rcall   write_com
    rcall   wacht1
    rcall   wacht1
    rcall   wacht1

    ldi     lwreg, entry
    rcall   write_com

;Regel 1 ophalen uit tabel1:

    ldi     teller,20
    ldi     ZL,LOW(tabel1*2)    ;Z pointer naar tabel 1 laten wijzen
    ldi     ZH,HIGH(tabel1*2)

    ldi     lwreg, 0x80         ;REGEL 1!!!
    rcall   write_com           ;En regel 1 commando wegschrijven naar LCD

;tekst op scherm zetten
    rcall   tloop               ;tekst op scherm zetten             

;Regel 2 op halen uit tabel2:
    ldi     teller,20
    ldi     ZL,LOW(tabel2*2)    ;Z pointer naar tabel 2 laten wijzen.
    ldi     ZH,HIGH(tabel2*2)

    ldi     lwreg, 0xC0         ;REGEL 2!!!
    rcall   write_com           ;regel 2 commando wegschrijven naar LCD

;tekst op scherm zetten
    rcall   tloop               ;tekst op scherm zetten

;Regel 3 op halen uit tabel 3:
    ldi     teller,20
    ldi     ZL,LOW(tabel3*2)
    ldi     ZH,HIGH(tabel3*2)

    ldi     lwreg, 0x94         ;REGEL 3!!!
    rcall   write_com           ;Regel 3 commando wegschrijven naar LCD

;tekst op scherm zetten
    rcall   tloop               ;tekst op scherm zetten

ncloop:
    ;Is init bit aanwezig?
    ldi     teller, 7
    sbic    PORTD,COMM          ;nee? Ga verder met de loop.
    rjmp    comminit            ;Ja? ga naar het binnen halen van de nibbles

contl:
;Regel 4:
    ldi     teller,20
    ldi     ZL,LOW(tabel4*2)
    ldi     ZH,HIGH(tabel4*2)

    ldi     lwreg, 0xD4         ;REGEL..... 4???
    rcall   write_com           ;Regel 4 commando wegschrijven naar LCD

;tekst op scherm zetten
    rcall   tloop               ;tekst op scherm zetten

    rcall   langwacht
    rcall   langwacht
    rcall   wacht2


;Regel 4 geen connectie:
    ldi     teller,20
    ldi     ZL,LOW(tabel5*2)
    ldi     ZH,HIGH(tabel5*2)

    ldi     lwreg, 0xD4         ;weer regel 4?
    rcall   write_com           ;Regel 4 commando wegschrijven naar LCD

;tekst op scherm zetten
    rcall   tloop               ;tekst op scherm zetten

    rcall   langwacht
    rcall   langwacht
    rcall   wacht2
    rjmp    ncloop

loop:
    sbic    PORTD,COMM
    rjmp    comminit
    rjmp    loop

tloop:                          ;loop om tekst op het scherm te zetten.
    lpm
    mov     lwreg, char
    rcall   write_char

    inc     ZL
    brcc    nocarry
    inc     ZH

nocarry:
    dec     teller
    brne    tloop
    ret

;Init routine
init:
    ldi     wreg, 0b11111111    ;poort B is output
    out     DDRB, wreg
    ldi     wreg, 0b00000000
    out     PORTB, wreg         ;alle poorten 0
    ldi     wreg, 0b00000000    ;poort D is input
    out     DDRD, wreg

    ldi     wreg, 0
    mov     null, wreg          ;null register moet wel nul zijn.
    ldi     wreg, 1
    mov     een, wreg           ;een register moet wel 1 zijn.
    ldi     wreg, 4             ;Id's 4 tot 6 zijn voor lcd controllers
    mov     id, wreg            ;deze controller krijgt nu id 3
    ret

;commando routine 8 bit
write_com8:
    out     PORTB, wreg

    cbi     PORTB,RS
    sbi     PORTB,E

    nop
    nop
    nop

    cbi     PORTB,E

    rcall   wacht2
    rcall   wacht2
    rcall   wacht2
    ret

;commando routine 4 bit
write_com:
    mov     lcddata, lwreg
    cbr     lwreg,0b00001111

    mov     wreg, lwreg
    out     PORTB, wreg

    sbi     PORTB,E

    cbi     PORTB,E

    mov     lwreg, lcddata
    cbr     lwreg, 0b11110000

    swap    lwreg
    mov     wreg, lwreg
    out     PORTB, wreg

    sbi     PORTB,E

    cbi     PORTB,E

    rcall   wacht2
    rcall   wacht2
    rcall   wacht2
    ret

;character routine 4 bit
write_char:
    mov     lcddata, lwreg
    cbr     lwreg,0b00001111

    mov     wreg, lwreg
    out     PORTB, wreg

    sbi     PORTB,RS
    sbi     PORTB,E

    cbi     PORTB,E
    cbi     PORTB,RS
        
    mov     lwreg, lcddata
    cbr     lwreg, 0b11110000

    swap    lwreg
    mov     wreg, lwreg
    out     PORTB, wreg

    sbi     PORTB,RS
    sbi     PORTB,E

    cbi     PORTB,E
    cbi     PORTB,RS

    rcall   wacht2
    rcall   wacht2
    rcall   wacht2
    ret

;communicatie routine

comminit:                       ;Routine voor het wachten tot de init bit down wordt.
    sbic    PORTD,COMM
    rjmp    comminit
    ldi     teller, 7 

cnibble1:                       ;het binnen halen van de eerste nibble
    nop                         ;1Cl
    dec     teller              ;1Cl

    sbr     nibble1, 0b00000001 ;Maak bit 0 van nibble1 hoog
    sbis    PORTD,COMM          ;Sla volgende commando over als comm poort hoog is
    cbr     nibble1, 0b00000001 ;Maak bit 0 van nibble 1 laag
                                ;3Cl
    rol     nibble1             ;1Cl

    brne    cnibble1            ;1/2Cl
    ldi     teller, 7           ;1Cl: Als de BRNE niet springt word het met deze toch 8Cl


cnibble2:                       ;het binnen halen van het tweede nibble
    nop                         
    dec     teller              

    sbr     nibble2, 0b00000001
    sbis    PORTD,COMM
    cbr     nibble2, 0b00000001

    rol     nibble2
 
    brne    cnibble2
    ldi     teller, 7

cnibble3:                       ;het binnen halen van het derde nibble
    nop                         
    dec     teller              

    sbr     nibble3, 0b00000001
    sbis    PORTD,COMM
    cbr     nibble3, 0b00000001

    rol     nibble3

    brne    cnibble3
    ldi     teller, 7

    cpse    nibble1, id         ;is het mijn id?
    rjmp    loop                ;nee? ga (terug) naar de main loop

verw1:
    cp      nibble2, null       ;Staat er een instructie in nibble2?
    brne    instructie          ;nee? ga dan verder
verw2:
    cp      nibble3, null       ;Staat er data in nibble3?
    brne    data                ;Nee? Ga dan verder
    rjmp    loop                ;niks te doen, dus we gaan terug naar de main loop.

instructie:
    mov     lwreg, nibble2
    rcall   write_com
    rjmp    verw2

data:
    mov     lwreg, nibble3
    rcall   write_char
    rjmp    loop            

;lange wacht routine
wacht1:
    ldi     teller1,9
retour1:
    ldi     teller2,110
retour2:
    nop
    nop
    nop
    nop
    dec     teller2
    brne    retour2
    dec     teller1
    brne    retour1
    ret

;korte wacht routine
wacht2:
    ldi     teller1, 30
retourk1:
    nop
    nop

    dec     teller1
    brne    retourk1
    ret

;hele lange wacht routine   
langwacht:
    ldi     teller, 100
lwacht:
    rcall   wacht1
    rcall   wacht1
    rcall   wacht1
    rcall   wacht1
    rcall   wacht1
    dec     teller
    brne    lwacht
    ret

tabel1:
    .db "Display versie:     "

tabel2:
    .db "V0.04 90S2312  10MHZ"

tabel3:
    .db "Main controller:    "

tabel4:
    .db "Geen communicatie   "

tabel5:
    .db "met Main controller!"


Er zit hier ook heel veel code in die jij niet nodig hebt want dit komt uit een groter (Nog te testen) project maar het LCD gedeelte werkt. Dit heb ik getest met mijn STK500 en een HD44780 4*20 LCD

Deze code is geschreven voor een AT90S2313, maar ik heb deze code ook gebruikt bij een tiny2313 door alleen de include te veranderen en bij een ATmega8535 door ook de stack correct te initialiseren dus jouw'n M32 zou ook geen probleem moeten zijn lijkt mij.

-edit- de 8bit init heb ik 0b00100000 van gemaakt zodat de stuurlijnen niet overschreven zouden worden.

Ik zie trouwens dat jij C programmeerd... ik hoop dat jij wat van mijn assembler code snap.

[ Voor 3% gewijzigd door Vuikie op 19-07-2006 19:07 ]