Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[AVR] LCD 4bit code not working

Status
Not open for further replies.

milan.rajik

Banned
Joined
Apr 1, 2013
Messages
2,524
Helped
540
Reputation
1,078
Reaction score
524
Trophy points
1,393
Activity points
0
My LCD 4bit code is not working in hardware. Why ? I am using IAR EW AVR 6.60.1 licensed Compiler, ATMega1284 @ 8 MHz external clock and mikroElektronika's EasyAVR v7 development board. I am attaching my IAR AVR project. LCD code is correct because I use that code in other compilers. I think the problem is with
Code:
Delay_us()
and
Code:
Delay_ms()
functions. How to make a proper Delay function which gives exact delay based on clock frequency ?

IAR EW AVR Code


Code C - [expand]
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
#define F_OSC 8000000
 
#include <iom1284.h>
#include <intrinsics.h>
 
#define _LCD_FIRST_ROW          0x80     //Move cursor to the 1st row
#define _LCD_SECOND_ROW         0xC0     //Move cursor to the 2nd row
#define _LCD_THIRD_ROW          0x94     //Move cursor to the 3rd row
#define _LCD_FOURTH_ROW         0xD4     //Move cursor to the 4th row
#define _LCD_CLEAR              0x01     //Clear display
#define _LCD_RETURN_HOME        0x02     //Return cursor to home position, returns a 
                                         //shifted display to its original position.
                                         //Display data RAM is unaffected.
#define _LCD_CURSOR_OFF         0x0C     //Turn off cursor
#define _LCD_UNDERLINE_ON       0x0E     //Underline cursor on
#define _LCD_BLINK_CURSOR_ON    0x0F     //Blink cursor on
#define _LCD_MOVE_CURSOR_LEFT   0x10     //Move cursor left without changing 
                                         //display data RAM
#define _LCD_MOVE_CURSOR_RIGHT  0x14     //Move cursor right without changing 
                                         //display data RAM
#define _LCD_TURN_ON            0x0C     //Turn Lcd display on
#define _LCD_TURN_OFF           0x08     //Turn Lcd display off
#define _LCD_SHIFT_LEFT         0x18     //Shift display left without changing 
                                         //display data RAM
#define _LCD_SHIFT_RIGHT        0x1E     //Shift display right without changing 
                                         //display data RAM
void Delay_us(unsigned int uSec);
void Delay_ms(unsigned int mSec);
 
void LCD_Cmd(char out_char);
void LCD_Chr(char row, char column, char out_char);
void LCD_Chr_Cp(char out_char);
void LCD_Init();
void LCD_Out(char row, char col, char *text);
void LCD_Out_Cp(char *text);
 
void Delay_us(unsigned int uSec) {
  unsigned int i = 0;
  
  while(uSec != 0) {
    for(i = 0; i < 250; i++);
    
    uSec--;    
  }
}
 
void Delay_ms(unsigned int mSec) {
  unsigned int i = 0;
  
  while(mSec != 0) {
    for(i = 0; i < 2000; i++);
    
    mSec--;    
  }
}
 
#define EN_DELAY 100
#define LCD_STROBE {LCD_EN = 1; Delay_us(EN_DELAY); LCD_EN = 0; Delay_us(EN_DELAY);};
 
#define LCD_RS PORTA_Bit2
#define LCD_EN PORTD_Bit6
#define LCD_D4 PORTC_Bit4
#define LCD_D5 PORTC_Bit5
#define LCD_D6 PORTC_Bit6
#define LCD_D7 PORTC_Bit7
 
#define LCD_RS_Direction DDRA_Bit2
#define LCD_EN_Direction DDRD_Bit6
#define LCD_D4_Direction DDRC_Bit4
#define LCD_D5_Direction DDRC_Bit5
#define LCD_D6_Direction DDRC_Bit6
#define LCD_D7_Direction DDRC_Bit7
 
void LCD_Cmd(char out_char) {
 
    LCD_RS = 0;
 
    LCD_D4 = (out_char & 0x10)?1:0;
    LCD_D5 = (out_char & 0x20)?1:0;
    LCD_D6 = (out_char & 0x40)?1:0;
    LCD_D7 = (out_char & 0x80)?1:0;
    LCD_STROBE
    LCD_D4 = (out_char & 0x01)?1:0;
    LCD_D5 = (out_char & 0x02)?1:0;
    LCD_D6 = (out_char & 0x04)?1:0;
    LCD_D7 = (out_char & 0x08)?1:0;
    LCD_STROBE
 
    if(out_char == 0x01)Delay_ms(2);
}
 
void LCD_Chr(char row, char column, char out_char) {
 
    switch(row){
 
        case 1:
        LCD_Cmd(0x80 + (column - 1));
        break;
        case 2:
        LCD_Cmd(0xC0 + (column - 1));
        break;
        case 3:
        LCD_Cmd(0x94 + (column - 1));
        break;
        case 4:
        LCD_Cmd(0xD4 + (column - 1));
        break;
    }
 
    LCD_RS = 1;
 
    LCD_D4 = (out_char & 0x10)?1:0;
    LCD_D5 = (out_char & 0x20)?1:0;
    LCD_D6 = (out_char & 0x40)?1:0;
    LCD_D7 = (out_char & 0x80)?1:0;
    LCD_STROBE
 
    LCD_D4 = (out_char & 0x01)?1:0;
    LCD_D5 = (out_char & 0x02)?1:0;
    LCD_D6 = (out_char & 0x04)?1:0;
    LCD_D7 = (out_char & 0x08)?1:0;
    LCD_STROBE
}
 
void LCD_Chr_Cp(char out_char) {
 
    LCD_RS = 1;
 
    LCD_D4 = (out_char & 0x10)?1:0;
    LCD_D5 = (out_char & 0x20)?1:0;
    LCD_D6 = (out_char & 0x40)?1:0;
    LCD_D7 = (out_char & 0x80)?1:0;
    LCD_STROBE
 
    LCD_D4 = (out_char & 0x01)?1:0;
    LCD_D5 = (out_char & 0x02)?1:0;
    LCD_D6 = (out_char & 0x04)?1:0;
    LCD_D7 = (out_char & 0x08)?1:0;
    LCD_STROBE
}
 
 
void LCD_Init() {
 
    LCD_RS = 0;
    LCD_EN = 0;
    LCD_D4 = 0;
    LCD_D5 = 0;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_RS_Direction = 1;
    LCD_EN_Direction = 1;
    LCD_D4_Direction = 1;
    LCD_D5_Direction = 1;
    LCD_D6_Direction = 1;
    LCD_D7_Direction = 1;
    
    Delay_ms(30);
 
    LCD_D4 = 1;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    Delay_ms(10);
 
    LCD_D4 = 1;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    Delay_ms(10);
 
    LCD_D4 = 1;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    Delay_ms(10);
 
    LCD_D4 = 0;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    Delay_ms(10);
 
    LCD_Cmd(0x28);
    LCD_Cmd(0x06);
}
 
void LCD_Out(char row, char col, char *text) {
    while(*text)
         LCD_Chr(row, col++, *text++);
}
 
void LCD_Out_Cp(char *text) {
    while(*text)
         LCD_Chr_Cp(*text++);
}
 
int main( void )
{
  DDRA = 0xFF;
  DDRB = 0xFF;
  DDRC = 0xFF;
  DDRD = 0xFF;
  
  PORTA = 0x00;
  PORTB = 0x00;
  PORTC = 0x00;
  PORTD = 0x00;
  
  
  LCD_Init();
  LCD_Cmd(_LCD_CURSOR_OFF);
  LCD_Cmd(_LCD_CLEAR);
  LCD_Out(1,1,"LCD 4bit");
  LCD_Out(2,1,"IAR EW AVR");
    
  while(1) {    
    
  }
  
  //return 0;
}

 

u havnt declared the values for m_Sec and u_sec anywhere in the code
 

uSec amd mSec are function parameters. In the
Code:
Delay_us()
and
Code:
Delay_ms()
function calls I am passing the values to them.
 

i dont understand ur code bro, in the function if u r passing the value of the i to u_sec or m_sec then everything goes wrong, because u used the condition m_sec!=0, while u initialized the i by i=0; so here goest first satisfaction that i or m_sec gets = to 0, if the i isnt variable whose value is getting passed to m_sec then m_sec has no value.. everything seems wrong..
 

Hello!

How to make a proper Delay function which gives exact delay based on clock frequency ?

One way to do it is to use an oscilloscpe to measure the delay you can achieve.
By the way, don't use hard coded variables. #define the values.

Example:


Code C - [expand]
1
2
3
4
5
6
7
8
#define MILLISECOND  2500
 
void delay(uint16 ms) {
    volatile uint16 i, j;
    for(i = 0 ; i < ms ; ++i) {
        for(j = 0 ; j < MILLISECOND ; ++j);
    }
}



In the case you don't have any measurement means, use a LED and write this (pseudo code)


Code C - [expand]
1
2
3
4
while(1) {
    ToggleLed();
    Delay(1000);
}



If your LED switches every second, then it's fine. If it's too fast, increase MILLISECOND, if it's too
slow, decrease it. You can use your watch. If the LED changes about 60 times per minute, then
you're quite close.

Another way to do it is to read the processor specs and try to find out how many clocks are needed
for 1 loop. By the way, when using MSP430, the IAR compiler tells you how many clocks are needed
when debugging step by step. For MSP430, it's about 10. In this case, if your clock is 8 MHz, then
the loop frequency will be 800 kHz. So if you set up MILLISECOND as 800, you LED will change at
exactly one second.

Last, you can use a timer (that's what they are made for).

Dora.
 

well, the delays required are given in the datasheet... in my assembly language i used decimal 200 ad chked lcd and it worked then i started decreasing the value so i get proper deay decimal that wthe lcd works on.. the matter is that i hav the confusion in the functions M-sec and u_sec....
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top