4 bit lcd interfacing-

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi

 

I am trying to interface lcd (4 bit mode) to atmega32A, the hardware connections are as shown in the figure, as you can observe the three data pins are connected to PORTD(pin 5,6,7) and one pin is connected to PORTB(pin 3). I am new to avr and dont want to use lcd header files. My problem is; how I can address the two different data PORT pins at the same time. It is easy to address them, when the data pins are connected to a same port.  

 

Last Edited: Tue. Mar 24, 2015 - 11:18 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

akshayingle wrote:
I am new to avr ...

And do you have experience with other microcontrollers?

 

Quote:
... and dont want to use lcd header files

Why not?

 

Even if you won't use them in your final project, you should at least be studying the prior art...

 

Quote:
My problem is; how I can address the two different data PORT pins at the same time

Think about it: does the LCD know or care that all the data lines change at the "same" time...?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

and dont want to use lcd header files.

That's a real shame because this lcd.c/lcd.h combination from Peter Fleury:

 

http://homepage.hispeed.ch/peter...

 

has both 4bit and 8bit support and even lets you put each of the data pins on a different port just as you require here.

 

If nothing else at least take a look at his code to see how he achieves this.

 

BTW note that his code uses quite a clever "trick". It recognises that (for almost all the AVRs) that the DDR register is always at an address 1 less than the PORT address and the PIN register at addr-2. So given one you can work out where the others are:

#define DDR(x) (*(&x - 1))      /* address of data direction register of port x */
#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
    /* on ATmega64/128 PINF is on port 0x00 and not 0x60 */
    #define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) )
#else
	#define PIN(x) (*(&x - 2))    /* address of input register of port x          */
#endif

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for the reply

 

The reason for not using header files is to learn interfacing from the very start, I know by using header files will simplify my task

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know by using header files will simplify my task

And what crime against society did you commit that bars you from simplifying your task?

 

There is a lot going on in an LCD interface that a library like Peter's(which I use all the time) is a great learning tool as his naming conventions are extremely easy to read, and understand what is going on.  You can follow the steps taken for each command by simply looking for the parts he calls out.

 

While it is admirable that you want to learn the ins and outs at such a fundamental level, IMO you would do yourself a better service by working with a known working library that you can see the result working, then dissect it to it's individual parts.

 

I have attached a very simple Studio program that uses Peter's library for you to look at.  It will work with the mega32's internal RC oscillator so all you need is a 5 volt power source and a potentiometer for LCD contrast.  I do not have a mega32 to try it out on, but I am pretty confident you will be fine.  I'll look around for a mega 16 later when I am in the lab.

 

you must use the R/W pin on the LCD as Peter polls the busy flag IIRC.

 

I used PORTD in this example, so the pin locations are all in a row that you will need.  Here are theire call outs:

#define LCD_PORT         PORTD        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN    0            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    2            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    3            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       4            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       5            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        6            /**< pin  for Enable line     */

Jim

Attachment(s): 

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

akshayingle wrote:
The reason for not using header files is to learn interfacing from the very start

OK - so here is the process: http://www.8052.com/forum/read/1...

 

And, of course, studying the prior art 

Last Edited: Tue. Mar 24, 2015 - 11:07 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I noticed no one asked, and you did not provide the following in your OP:

 

IDE being used (Studio?)

Programmer/Debugger?

 

I am assuming C is the language of choice.

 

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There's nothing wrong with implementing HD44780 to learn about the operation of it from scratch but don't make the mistake almost everyone else who ever posts about it here seems to make. It is VITAL that you read every last detail in the datasheet. In particular it has timing diagrams that show the correct timed sequence for initialising the display into 4 bit mode then sending it commands after that. You must follow the timings given there TO THE LETTER. Every thread we see here where the LCD does not initalise properly (the usual symptom is one line of "dark boxes") is a result of those who are not following the given timing correctly. So pay particular attention to that.

 

As to how to split it across ports. You will have a routine that is being passed a 4 but nibble value to be sent to the LCD. In the simple case you would just:

void send_nibble(uint8_t data) {
  data &= 0xF; // make sure it is just 4 bits (this bit optional)
  PORTD = (PORTD & 0x0F) | (data << 4);
  then_strobe_it();
}

This is when PD7,6,5,4 are used together. So you just take "data" that is passed in. Make sure it is just 4 bits (as I say, optional) then you read PORTD and clear the top 4 bits (that's what the "& 0x0F" does) then you take data and <<4 to move it from bits 3..0 to bits 7..4 and finally you OR (|) the new value into place.

 

But in your case the bottom bit is in another port. So first consider the 3 bits that are still in PORTD (7,6,5). For those you can do almost exactly what I just showed:

void send_nibble(uint8_t data) {
  data &= 0xF; // make sure it is just 4 bits (this bit optional)
  PORTD = (PORTD & 0x1F) | (data & 0x0E) << 4);
  then_strobe_it();
}

the changes here are that you are now "keeping" 5 bits in the existing PORTD contents so the (PORTD & 0x0F) becomes (PORTD & 0x1F) and you only want the top 3 of 4 bits in "data" so I added an & 0x0E to isolate just the top 3 of 4 bits. But now you still have one bit to send to PORTB.3 so for that add:

void send_nibble(uint8_t data) {
  data &= 0xF; // make sure it is just 4 bits (this bit optional)
  PORTD = (PORTD & 0x1F) | (data & 0x0E) << 4);
  PORTB = (PORTB & 0xF7) | (data & 0x01) << 3);
  then_strobe_it();
}

The additional line here takes what is already in PORTB and retains everything but bit 3 (that's what & 0xF7 does). The new value for bit3 on PORTB is then ORd into place by taking "data" and just isolating the bottom bit (& 0x01) and then shifting this 3 places (<<3) to move it to the bit3 position in PORTB.

 

So that should be pretty much what you require to split the 4 bits of "data" to PD7..5 and PB3.

 

(of course life (and code) is a lot simpler if you get your hardware guy to just wire four adjacent port bits to the LCD in the first place!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

this lcd.c/lcd.h combination from Peter Fleury .. has both 4bit and 8bit support

Well, no, not really. The only 8 bit support that it has is for a memory-mapped LCD. Normal 8 bit support for arbitrary port/pin configurations is not supported.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is pretty trivial to add 8-bit support.

 

It is also fairly pointless.   You only need a 4-bit bus for the LCD to be fully operational.

 

Personally,   I would start with proven code and then study how it works.

If you are determined to roll your own code,   see if you can re-implement the proven code from scratch.

 

After all,  this is how you learn how to solve mathematics problems at school.

The textbook or teacher shows you the method.    If you want to be able to answer under examination conditions,   you do plenty of example exercises until you have confidence that you understand the method.

 

Young Einsteins might be able to skip the 'teacher' step.    Most people learn stuff at school.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

this lcd.c/lcd.h combination from Peter Fleury .. has both 4bit and 8bit support

But this is still a true statement of fact isn't it? I didn't claim the 8bit had assignable individual pins. I simply said Fleury has both 4bit and 8bit support. It does. For the OP's purpose it further has pin assignable 4 bit support.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks JIm for the reply

 

I am using C language and a GCC compiler and cygwin environment, and a avr doper for programming.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have you tried a Google search for 'LCD Programming Examples'? 

 

In the US the very first hit is: http://web.alfredstate.edu/weimandn/programming/lcd/ATmega328/LCD_code_gcc_4d.html and if you poke around a bit on that site you will find several more examples.  Most of those examples provide for the implementation of any LCD line on any I/O pin. 

 

I can vouch for the code when run on an ATmega328, I assume it won't have to be much different for an ATmega32A.

 

Don

Last Edited: Thu. Mar 26, 2015 - 02:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi

 

suppose I have a 8 bit data eg. 0100 1100 , and I want to send it to data pins of 4 bit lcd (kindly refer to pin diagram from my first post at the top), If all the data pins are from the same port then its fine but

since the 3 pins are from PORTD and last pins is from PORTB, how I will send this 8 bit data to these pins (I understand that for 4 bit lcd you have to send this data 2 times, i.e. higher nibble first and lower nibble next and keeping enable pin transition from high to low), but as higher nibble(0100), the MSB (0) will be send to PORTB.3, and the rest (100) needs to be send to PORTD.5,6,7 respectively. Now how are going to separate these individual bits, so that they can be send to the respective pin locations of avr. Once we are able to send these individual bits at the right pins then rest of the interfacing is not difficult.

I think we need a variable (unsigned char) to store the higher nibble and perform logical operation to get desired bit and then send this bit to their locations.

 

thanks all for your previous posts. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

akshayingle wrote:
how are going to separate these individual bits, so that they can be send to the respective pin locations of avr.

Cliff has already showed you how to do this in comment #8http://www.avrfreaks.net/comment...

 

It's just a basic application of the standard 'C' shift & mask bitwise operations. It doesn't really have anything specifically to do with LCDs or AVRs - you would do exactly the same in any situation when you wanted to extract a bitfield from a larger word...

Last Edited: Thu. Mar 26, 2015 - 08:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

akshayingle wrote:

...  Now how are going to separate these individual bits, so that they can be send to the respective pin locations of avr. Once we are able to send these individual bits at the right pins then rest of the interfacing is not difficult ...

 

You might get some ideas from the example code I linked to in my previous post (#13).

 

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But this is still a true statement of fact isn't it?

Technically true, but misleading. It is only available for a limited number of AVRs (the ones with external SRAM interface), and the mega32A that the OP is using isn't one of them.

I didn't claim the 8bit had assignable individual pins.

 You may not have stated it explicitly, but it could certainly be implied by your statement:

has both 4bit and 8bit support and even lets you put each of the data pins on a different port just as you require here. 

 

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
It's just a basic application of the standard 'C' shift & mask bitwise operations. It doesn't really have anything specifically to do with LCDs or AVRs - you would do exactly the same in any situation when you wanted to extract a bitfield from a larger word...

 

As, for example, here (also by Cliff, as it happens): http://www.avrfreaks.net/comment...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If it is possible to set an output pin hi or lo under computer control, and it is possible to look at a data byte and determine which bits are hi and lo, then it follows by some corrolary of boolean logic that one should be able to set any 4 or 8 output pins anywhere on the avr according to the bits set in a random data byte to be sent.

This task can be programmed using c, basic, pascal, forth, assembler, fortran, ada, and any other procedural language that I cant recall while sitting at a keyboard. If this is Just Too Hard to do, one could get a serial lcd. Sort of the same problem.... read the lcd datasheet to see what commands have to be sent in which order to init the lcd controller, then send those commands using the serial port.

 

Imagecraft compiler user

Last Edited: Fri. Mar 27, 2015 - 02:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can tell a horse where the water is (twice) but you can't make him go there.

 

Don