Introduction

Stepper motors can be used in various areas of your microcontroller projects such as making robots, robotic arm, automatic door lock system etc. This tutorial will explain you construction of stepper motors (unipolar and bipolar stepper motors ), basic pricipal, different controlling types (Half step and Full step), Interfacing Techniques (using L293D or ULN2003) and programming your microcontroller in C and assembly to control stepper motor.

►Unipolar stepper motor The unipolar stepper motor has five or six wires and four coils (actually two coils divided by center connections on each coil). The center connections of the coils are tied together and used as the power connection. They are called unipolar steppers because power always comes in on this one pole.

►Bipolar stepper motor The bipolar stepper motor usually has four wires coming out of it. Unlike unipolar steppers, bipolar steppers have no common center connection. They have two independent sets of coils instead. You can distinguish them from unipolar steppers by measuring the resistance between the wires. You should find two pairs of wires with equal resistance. If you've got the leads of your meter connected to two wires that are not connected (i.e. not attached to the same coil), you should see infinite resistance (or no continuity). As already said, we will talk mostly on "Unipolar stepper motors" which is most common type of stepper motor available inthe market.A simple example of 6 lead step motor is given below and in 5 lead step motor wire 5 and 6 are joined together to make 1 wire as common.

►Working of Stepper Motor
Now lets discuss the operation pricipal of a stepper motor. When we energize a coil of stepper motor, The shaft of stepper motor (which is actually a permanent magnet) align itself according to poles of energized coil. So when motor coils are energized in a particular sequence, motor shaft tend to align itself according to pole of coils and hence rotates. A small example of energizing operation is given below.

You can see in the example, when coil "A" is energized, A north-south polarity is generated at "A+A\" as shown in the figure above and magnetic shaft automatically align itself according to the poles generated. When the next coil is energized the shaft again align itself and take a step. Hence the working pricipal.

We have seen that to make the stepper motor work, we need to energize coil in a sqeuence.

Stepper motors can be driven in two different patterns or sequences namely, • • Full Step Sequence Half Step Sequence

we will go through these sequences one by one.

►Full Step Sequence
In the full step sequence, two coils are energized at the same time and motor shaft rotates. The order in which coils has to be energized is given in the table below.

Full Mode Sequence Step
0 1 2 3

A
1 0 0 1

B
1 1 0 0

A\
0 1 1 0

B\
0 0 1 1

The working of the full mode sequence is given in the animated figure below.

►Half Step Sequence
In Half mode step sequence, motor step angle reduces to half the angle in full mode. So the angualar resolution is also increased i.e. it becomes double the angular resolution in full mode. Also in half mode sequence

As we have seen that in half mode. Half mode is usually preffered over full mode.simply divide 360 by number of steps a motor takes to complete one revolution. so step angle reduces to half. To calculate step angle. the number of steps taken by the motor to complete one revolution gets doubled.. So step angle can be calculated as. Half Mode Sequence Step 0 1 2 3 4 5 6 7 A 1 0 0 0 0 0 1 1 B 1 1 1 0 0 0 0 0 A\ 0 0 1 1 1 0 0 0 B\ 0 0 0 0 1 1 1 0 The working of the half mode sequence is given in the animated figure below. As in above examples. Table below shows the pattern of energizing the coils. ►Step Angle Step angle of the stepper motor is defined as the angle traversed by the motor in one step. Stepper Motor rotating in full mode takes 4 steps to complete a revolution.the number of steps gets doubled as that of full mode. Step Angle ø = 360° / 4 = 90° ..

Knowing stepper motor's step angle helps you calibrate the rotation of motor also to helps you move the motor to correct angular position. ►Step Sequence for 2-wire control of Unipolar stepper motor As seen in above explanation. This polarity sequence is shown in the table below. Step Sequence Step 0 1 2 3 A 1 0 0 0 A\ 0 0 1 0 B 0 1 0 0 B\ 0 0 0 1 We have now learnt most of the necessary things regarding a stepper motor. The sequence is given in the table below: 2-wire Mode Sequence Step 0 1 2 3 A 0 1 1 0 B 1 1 0 0 ►Step Sequence for Bipolar stepper motor Bipolar motor has simpler construction. Usually step angle is given in the spec sheet of thestepper motor you are using. So this way we can calculate step angle for any stepper motor.and in case of half mode step angle gets half so 45°. The stepping sequence is the same as it is for the two coils A and B. . two wires are always set to opposite polarities. Being simpler in contruction. the stepping sequence is a little complex. and the opposite polarity value is given to A\ and B\. It has two windings with no center taps and a permanent magnet at the center just like unipolar stepepr motors. with a slightly more complex circuit. In every step of the sequence. it's possible to control steppers with only two wires instead of four. as the power for both the coils has to be controlled in such a way that the polarity of the poles get reversed. Because of this. Polarity Sequence Step A 0 1 2 3 +ve -ve -ve -ve A\ -ve -ve +ve -ve B -ve +ve -ve -ve B\ -ve -ve -ve +ve The above polarity sequence can be interpreted in terms of logic levels for microcontroller by activating one coil at a time as shown in the table below.

3 and 4 will control the motion and direction of thestepper motor according to the step sequece programmed in the controller. ►Connecting Unipolar stepper using L293D As you see in the circuit above the four pins "Controller pin 1". Interface using L293D . Interface using ULN2003/2004 . out of them the most used interfaces are: 1.Darlington Arrays We will dicuss both connection techniques one by one. The above mentioned methods need 4 controller pins for interface.There are actually many ways you can interface a stepper motor to your controller.H-Bridge Motor Driver 2. Connecting Unipolar stepper using ULN2003/2004 .2.

Connecting Bipolar Stepper Motor As we have studied that.2. This can be done as shown in the figure below: . The circuit for 2-wire connection is shown below.3 and 4 will control the motion and direction of the stepper motor according to the step sequece sent by the controller. The step sequence for Bipolar stepper motor is same as that of unipolar stepper motors. Here in this circuit too the four pins "Controller pin 1". but we can simplify the design to make controller use less pins with the help of 2-wire connection method.As already discussed in case of L293D. The driving circuit for this require an H-Bridge as it allows the polarity of the power applied to be controlled independently. ►2-wire connection for Unipolar Stepper Motor We have seen the generally used 4-wire connection method for interfacing unipolar stepper motor. Bi-polar stepper motors has 2 different coils.

3.#4 wait2: mov r6.0 to Port 1. org 0H stepper equ P1 main: mov stepper. #0CH acall delay mov stepper. #03H acall delay mov stepper.#0FFH wait1: mov r5.wait2 ret end . Adjusting the delay will increase or decrease the speed of the motor.wait1 djnz r7. you can change it as you want. #06H acall delay mov stepper. Here just for demonstration i have taken some delay. #09H acall delay sjmp main delay: mov r7.#0FFH wait: djnz r5.Programming Full step Sequence I am assuming that stepper motor is connected at Port 1.wait djnz r6.

#08H acall delay mov stepper. #0CH acall delay mov stepper. #04H acall delay mov stepper. #06H acall delay mov stepper. #02H acall delay mov stepper. #09H acall delay sjmp main .Programming Half step Sequence main: mov stepper. #03H acall delay mov stepper. #01H acall delay mov stepper.

#01H acall delay mov stepper. #02H acall delay sjmp main . #03H acall delay mov stepper.Programming for 2-wire connection of Unipolar Stepper Motor main: mov stepper. #00H acall delay mov stepper.

#02H acall delay mov stepper.Programming for Bipolar Stepper Motor main: mov stepper. #08H acall delay mov stepper. #01H acall delay sjmp main . #04H acall delay mov stepper.

if Ton is Ttotal then Vout is Vin or say maximum. So you can see from the final equation the output voltage can be directly varied by varying the Ton value. Duty cycle of a square wave is defined as The output voltage varies with duty cycle as. measurement and communication.Pulse Width Modulation (PWM) Introduction Pulse width Modulation or PWM is one of the powerful techniques used in control systems today. Vout is also 0.. ►Basic Principal of PWM Pulse-width Modulation is achived with the help of a square wave whose duty cycle is changed to get a varying voltage output as a result of average value of waveform. Ton is the time for which the output is high and Toff is time for which output is low. If Ton is 0. Consider a square wave shown in the figure above. power control. Let Ttotal be time period of the wave such that.. A mathematical explaination of this is given below. They are not only employed in wide range of control application which includes: speed control. This was all about theory behind PWM.. Now lets take a look at the practical implementation of PWM on microcontrollers. .

PWM output pin PWM_SETUP: MOV TMOD.Idea Behind Implementation The basic idea behind PWM implementation on 8051 is using timers and switching port pin high/low at defined intervals. Start Timer RET Interrupt Service Routine TIMER_0_INTERRUPT: JB F0. we can vary the width of square wave keeping same time period of the square wave. . R7 CLR TF0 RETI HIGH_DONE: CLR section CLR MOV CLR .0 . . If F0 flag is set then we just finished the high section of the cycle so Jump to HIGH_DONE Make F0=1 to indicate start of high Make PWM output pin High Load high byte of timer with R7 (pulse width control value) Clear the Timer 0 interrupt flag Return from Interrupt to where . SETB EA . R7 MOV TH0. Clear the Timer 0 interrupt flag . The value loaded in R7 is value X as . so the value loaded into TH0 + R7 = 255 .R7. discussed above. Make PWM output pin low . Timer0 in Mode 0 MOV R7. . If for high level we load a value X in TH0 then for low level TH0 will be loaded with 255-X so that total remains as 255. the program came from F0 PWMPIN A.#00H . As we have discussed in the introduction of PWM that by changing the Ton time. Values for high and low level will be loaded in such a way that total delay remains same. A CLR TF0 RETI . . Clear C (the carry bit) so it does . the program came from SUBB A. Enable Timer 0 Interrupt SETB TR0 . A = 255 . ►Assembly Code Example Timer setup for PWM PWMPIN EQU P1. . Enable Interrupts SETB ET0 . HIGH_DONE LOW_DONE: SETB F0 section SETB PWMPIN MOV TH0. #160 . . Move FFH (255) to A . . not affect the subtraction . We will be using 8051 Timer0 in Mode 0. Set pulse width control . Make F0=0 to indicate start of low . #0FFH C . Return from Interrupt to where . . Subtract R7 from A. .

Timer Interrupt service routine will take care of PWM in the background. we will discuss about character based LCDs. various interfaces (8-bit/4-bit). LCD interfacing with Microcontrollers Introduction The most commonly used Character based LCDs are based on Hitachi's HD44780 controller or other which are compatible with HD44580. In above example I am using 160. Pin description is shown in the table below. For Specs and technical information HD44780 controller Click Here ►Pin Description The most commonly used LCDs found in the market today are 1 Line. Most LCDs with 1 controller has 14 Pins and LCDs with 2 controller has 16 Pins (two pins are extra in both for back-light LED connections). programming. R7 = 0 will give you o/p 0V approx and R7 = 255 will give you 5V approx You can also make use of Timer1 if you want. In this tutorial. 2 Line or 4 Line LCDs which have only 1 controllerand support at most of 80 charachers. special stuff and tricks you can do with these simple looking LCDs which can give a new look to your application. And the output pin can be changed to whatever pin you want. Figure 1: Character LCD type HD44780 Pin diagram Pin No. 2 VCC Pin no. 5 R/W Power supply (GND) Power supply (+5V) Contrast adjust 0 = Instruction input 1 = Data input 0 = Write to LCD . 1 VSS Pin no. you can choose any value from 0 to 255. Name Description Pin no.In your main program you need to call this PWM_SETUP routine and your controller will have a PWM output. The width of PWM can be changed by changing the value of R7 register. 3 VEE Pin no. 4 RS Pin no. their interfacing with various microcontrollers. whereas LCDs supporting more than 80 characters make use of 2 HD44780 controllers.

5 Pin no. 10 R/W 1 = Read from LCD module 0 = Instruction input Pin no. 12 Pin no. Lets take a look at the basic information which is there in every LCD. 11 Pin no. the operation and everything else is same for the double controller too. 9 Pin no. 9 EN1 st (1 controller) 0 = Write to LCD module Pin no. 10 Pin no. 8 Data bus line 7 (MSB) Data bus line 6 Data bus line 5 Data bus line 4 Data bus line 3 Data bus line 2 Data bus line 1 Data bus line 0 (LSB) Enable signal for row 0 and 1 Pin no. 12 VEE Contrast adjust Pin no. Name Description Pin no. 14 EN D0 D1 D2 D3 D4 D5 D6 D7 module 1 = Read from LCD module Enable signal Data bus line 0 (LSB) Data bus line 1 Data bus line 2 Data bus line 3 Data bus line 4 Data bus line 5 Data bus line 6 Data bus line 7 (MSB) Table 1: Character LCD pins with 1 Controller Pin No.Display Data RAM . 13 VSS Power supply (GND) Pin no. 15 EN2 nd (2 controller) Pin no. 6 Pin no. 3 Pin no. 11 RS 1 = Data input Pin no. 1 Pin no. 4 Pin no.Pin no. DDRAM . So in the tutorial we will discuss more about the single controller LCD. 14 VCC Power supply (+5V) Enable signal for row 2 and 3 Pin no. 6 Pin no. 13 Pin no. 8 Pin no. 2 Pin no. 16 NC Not Connected Table 2: Character LCD pins with 2 Controller D7 D6 D5 D4 D3 D2 D1 D0 Usually these days you will find single controller LCD modules are used more in the market. 7 Pin no. 7 Pin no.

It can generate 208 5 x 8 dot character patterns and 32 5 x 10 dot character patterns. The character generator ROM generates 5 x 8 dot or 5 x 10 dot character patterns from 8-bit character codes (see Figure 5 and Figure 6 for more details). Userdefined character patterns are also available by mask-programmed ROM. or 80 characters. The area in display data RAM (DDRAM) that is not used for display can be used as general data RAM. Figure 2: DDRAM Address for 1 Line LCD Figure 3: DDRAM Address for 2 Line LCD Figure 4: DDRAM Address for 4 Line LCD ►CGROM . So whatever you send on the DDRAM is actually displayed on the LCD. so whatever you write after 16 chars is written in DDRAM but is not visible to the user. only 16 characters are visible. how the character is displayed on LCD? so the answer is CGROM. Its extended capacity is 80 X 8 bits.Character Generator ROM Now you might be thinking that when you send an ascii value to DDRAM. For LCDs like 1x16.Display data RAM (DDRAM) stores display data represented in 8-bit character codes. 2 Line and 4 Line LCDs. Figures below will show you the DDRAM addresses of 1 Line. .

Figure 5: LCD characters code map for 5x8 dots .

Figure 6: LCD characters code map for 5x10 dots As you can see in both the code maps. When we send a command or data to the LCD for processing. In the character generator RAM. for the LCD processing. the character code from 0x00 to 0x07 is occupied by the CGRAM characters or the user defined characters. For 5 x 8 dots. If user want to display the fourth custom character then the code to display it is 0x03 i. the user can rewrite character patterns by program. four character patterns can be written. . ►CGRAM . and for 5 x 10 dots. CGRAM area is used to create custom characters in LCD. Later in this tutorial i will explain how to use CGRAM area to make custom character and also making animations to give nice effects to your application.Busy Flag Busy Flag is an status indicator flag for LCD. when user send 0x03 code to the LCD DDRAM then the fourth user created charater or patteren will be displayed on the LCD. this flag is set (i. This is helpful in producing and exact ammount of delay. ►BF .e. eight character patterns can be written.e BF =1) and as soon as the instruction is executed successfully this flag is cleared (BF = 0).Character Generator RAM As clear from the name.

There are four categories of instructionsthat: • Designate LCD functions. and the data bus (DB0 to DB7). the address where you want to send the data. Data Register is not only used for sending data to DDRAM but also for CGRAM. and Data register is used for storing data which is to be displayed on LCD. Set internal RAM addresses Perform data transfer with internal RAM Perform miscellaneous functions • • • . LCD address etc. These signals.g LCD shift command. make up the LCD instructions (Table 3). Instruction register corresponds to theregister where you send commands to LCD e. is decided by the instruction you send to LCD. LCD clear. which include register selection signal (RS).To read Busy Flag. control information is temporarily stored into these registers to allow interfacing with various MCUs. Commands and Instruction set Only the instruction register (IR) and the data register (DR) of the LCD can be controlled by the MCU. ►Instruction Register (IR) and Data Register (DR) There are two 8-bit registers in HD44780 controller Instruction and Data register. The internal operation of the LCD is determined by signals sent from the MCU. data length. the data on the pins is latched in to the data register and data is then moved automatically to the DDRAM and hence is displayed on the LCD. When BF = 1 means LCD is busy and will not accept next command or data and BF = 0 means LCD is ready for the next command or data to process. which operate at different speeds. Before starting theinternal operation of the LCD. etc. when send the enable signal of the LCD is asserted. such as display format. read/write signal (R/W). or various peripheral control devices. the condition RS = 0 and R/W = 1 must be met and The MSB of the LCD data bus (D7) act as busy flag.

5x7 Dots Function Set: 4-bit.Table 3: Command and Instruction set for LCD type HD44780 Although looking at the table you can make your own commands and test them. Below is a breif list of useful commands which are used frequently while working on the LCD. 1 Line. 1 Line. 2 Line. 2 Line. 5x7 Dots Entry Mode Display off Cursor off 0x30 0x38 0x20 0x28 0x06 0x08 48 56 32 40 6 8 . 5x7 Dots Function Set: 4-bit. No. Instruction Hex Decimal 1 2 3 4 5 6 Function Set: 8-bit. 5x7 Dots Function Set: 8-bit.

The busy flag (BF) is kept in the busy state until the initialization ends (BF = 1). 1-line display F = 0. No shift • • • Note: If the electrical characteristics conditions listed under the table Power Supply Conditions Using Internal Reset Circuit are not met. Blinking off Entry mode set: I/D = 1. initial-ization must be performed by the MCU as explained in the section.. .5 V. 5 x 8 dot character font Display on/off control: D = 0. 0x00 to 0x07 for char1 and so on. Display off C = 0. The following instructions are executed during the initialization. LCD has to be initialized either by the internal reset circuit or sending set of commands to initialize the LCD. we will dicuss both ways of initialization one by one. In the next section of the tutorial we will see the initialization with some of the coding examples in C as well as assembly.3. Initialization by internal Reset Circuit An internal reset circuit automatically initializes the HD44780U when the power is turned on. the internal reset circuit will not operate normally and will fail to initialize the HD44780U. LCD Initialization Before using the LCD for display purpose. It is the user who has to decide whether an LCD has to be initialized by instructions or byinternal reset circuit. For such a case. Increment by 1 S = 0. But after you are done testing with the table 4. 8-bit interface data N = 0. Cursor off B = 0. i recommend you to use table 3 to get more grip on working with LCD and trying your own commands.4 ** CGRAM address from 0x00 to 0x3F. The table above will help you while writing programs for LCD.7 8 9 10 12 13 14 15 16 17 (clearing display without clearing DDRAM content) Display on Cursor on Display on Cursor off Display on Cursor blinking Shift entire display left Shift entire display right Move cursor left by one character Move cursor right by one character Clear Display (also clear DDRAM content) Set DDRAM address or coursor position on display Set CGRAM address or set pointer to CGRAM location 0x0E 0x0C 0x0F 0x18 0x1C 0x10 0x14 0x01 14 12 15 24 30 16 20 1 0x80+add* 128+add* 0x40+add** 64+add** Table 4: Frequently used commands and instructions for LCD * DDRAM address given in LCD basics section see Figure 2. • Display clear Function set: DL = 1. The busy state lasts for 10 ms after VCC rises to 4. Initializing by Instruction.

e. So usually the second menthod i. Initialization by instruction is used and is recommended most of the time. Figure 7: Internal Power Supply reset Now the problem with the internal reset circuit is. . there are certain condtions that has to be met.As mentioned in the Note. Table 5: Power Supply condition for Internal Reset circuit Figure 7 shows the test condition which are to be met for internal reset circuit to be active. to initialize the LCD. These conditions are shown in the Table 5 below. Given below is a flowchart that describles the step to follow. to meet this critical power supply conditions is not hard but are difficult to achive when you are making a simple application. Initialization by instructions Initializing LCD with instructions is really simple. if user want to use initialization by internal reset circuit. it is highly dependent on power supply.

Using 8-bit interface 2) Delay 20ms 3) Send command 0x30 .Figure 8: Flow chart for LCD initialization As you can see from the flow chart.see Table 4 for more information 8) Display Clear command 9) Set entry mode command .8-bit interface 6) Delay 20ms 7) Send Function set . 1) Send command 0x30 . . LCD Entry mode From Table 3 in command section.8-bit interface 4) Delay 20ms 5) Send command 0x30 .Increment/Decrement bit b) S .explained below The first 3 commands are usually not required but are recomended when you are using 4-bit interface..Display shift. Function set command depends on what kind of LCD you are using and what kind of interface you are using (see Table 4 in LCD Command section). So you can program the LCD starting from step 7 when working with 8-bit interface. these bits are: a) I/D . you can see that the two bits decide the entry mode for LCD.. the LCD is initialized in the following sequence.

So we get different results with these different entry modes.Selected instruction register clr LCD_rw .#06H .Enable H->L clr LCD_en acall LCD_busy .7 . 8-bit. I recommend you to try all the possible entry modes and see the results.2 . I am sure you will be surprised.0x07 (see table 3 in LCD Commandsection). The following instructions are . Initialization by internal Reset Circuit An internal reset circuit automatically initializes the HD44780U when the power is turned on.Selected command register clr LCD_rw .Function set: 2 Line. LCD has to be initialized either by the internal reset circuit or sending set of commands to initialize the LCD.Selected command register clr LCD_rw .Wait for LCD to process the command ret . Programming example for LCD Initialization CODE: LCD_data equ P2 .Wait for LCD to process the command mov LCD_data. Normally entry mode 0x06 is used which is No shift and auto incremement. we will dicuss both ways of initialization one by one.Clear LCD clr LCD_rs .#0FH .0x05. It is the user who has to decide whether an LCD has to be initialized by instructions or byinternal reset circuit.LCD Enable LCD_init: mov LCD_data.We are writing in instruction register setb LCD_en .0 .Return from routine LCD Initialization Before using the LCD for display purpose.Enable H->L clr LCD_en acall LCD_busy . auto increment with no shift clr LCD_rs .LCD D7/Busy Flag LCD_rs equ P1.With these two bits we get four combinations of entry mode which are 0x04.Wait for LCD to process the command mov LCD_data.#01H .Selected command register clr LCD_rw .0x06. 5x7 dots clr LCD_rs .Enable H->L clr LCD_en acall LCD_busy .We are writing in instruction register setb LCD_en .Wait for LCD to process the command mov LCD_data.Enable H->L clr LCD_en acall LCD_busy .#38H .1 .We are writing in instruction register setb LCD_en . Curson blinking command clr LCD_rs .Display on.LCD Register Select LCD_rw equ P1.We are writing in instruction register setb LCD_en .LCD Read/Write LCD_en equ P1.Entry mode.LCD Data port LCD_D7 equ P2.

Increment by 1 S = 0. . Cursor off B = 0. The busy flag (BF) is kept in the busy state until the initialization ends (BF = 1). No shift • • • Note: If the electrical characteristics conditions listed under the table Power Supply Conditions Using Internal Reset Circuit are not met. The busy state lasts for 10 ms after VCC rises to 4. the internal reset circuit will not operate normally and will fail to initialize the HD44780U. 5 x 8 dot character font Display on/off control: D = 0. For such a case. Blinking off Entry mode set: I/D = 1. 1-line display F = 0. if user want to use initialization by internal reset circuit. initial-ization must be performed by the MCU as explained in the section. Initializing by Instruction.5 V. • Display clear Function set: DL = 1. 8-bit interface data N = 0. there are certain condtions that has to be met. Display off C = 0. Table 5: Power Supply condition for Internal Reset circuit Figure 7 shows the test condition which are to be met for internal reset circuit to be active. As mentioned in the Note.executed during the initialization. These conditions are shown in the Table 5 below.

Figure 7: Internal Power Supply reset Now the problem with the internal reset circuit is. to meet this critical power supply conditions is not hard but are difficult to achive when you are making a simple application. So usually the second menthod i. Initialization by instructions Initializing LCD with instructions is really simple. . it is highly dependent on power supply. Initialization by instruction is used and is recommended most of the time. Given below is a flowchart that describles the step to follow. to initialize the LCD.e.

. .see Table 4 for more information 8) Display Clear command 9) Set entry mode command .Using 8-bit interface 2) Delay 20ms 3) Send command 0x30 .8-bit interface 6) Delay 20ms 7) Send Function set .8-bit interface 4) Delay 20ms 5) Send command 0x30 .explained below The first 3 commands are usually not required but are recomended when you are using 4-bit interface.Display shift.. these bits are: a) I/D . So you can program the LCD starting from step 7 when working with 8-bit interface.Increment/Decrement bit b) S . Function set command depends on what kind of LCD you are using and what kind of interface you are using (see Table 4 in LCD Command section).Figure 8: Flow chart for LCD initialization As you can see from the flow chart. the LCD is initialized in the following sequence. 1) Send command 0x30 . you can see that the two bits decide the entry mode for LCD. LCD Entry mode From Table 3 in command section.

#01H . which is recomended. auto increment with no shift clr LCD_rs .LCD Data port LCD_D7 equ P2. .Wait for LCD to process the command ret . I recommend you to try all the possible entry modes and see the results.We are writing in instruction register setb LCD_en .We are writing in instruction register setb LCD_en .7 .Return from routine Reading the busy Flag As discussed in the previous section.LCD Read/Write LCD_en equ P1.0x06.Selected command register clr LCD_rw . Steps to read busy flag when we send the command.Display on.With these two bits we get four combinations of entry mode which are 0x04. Curson blinking command clr LCD_rs . Normally entry mode 0x06 is used which is No shift and auto incremement. The reason to use busy flag is that delay produced is almost for the exact amount of time for which LCD need to process the time. So we get different results with these different entry modes.Enable H->L clr LCD_en acall LCD_busy .Function set: 2 Line.#06H .Wait for LCD to process the command mov LCD_data.Enable H->L clr LCD_en acall LCD_busy . there must be some delay which is needed to be there for LCD to successfullyprocess the command or data.0x07 (see table 3 in LCD Commandsection). 8-bit.LCD Enable LCD_init: mov LCD_data.We are writing in instruction register setb LCD_en .Enable H->L clr LCD_en acall LCD_busy .Selected instruction register clr LCD_rw .Selected command register clr LCD_rw .0 . 5x7 dots clr LCD_rs .#38H . I am sure you will be surprised.#0FH .Entry mode.LCD D7/Busy Flag LCD_rs equ P1.We are writing in instruction register setb LCD_en .1 . the BF or D7th bit of the LCD becomes 1 and as soon as the command is processed the BF = 0. Following are the steps to be kept in mind while reading the Busy flag.0x05. Programming example for LCD Initialization CODE: LCD_data equ P2 .2 .Enable H->L clr LCD_en acall LCD_busy . So is best suited for every application.Selected command register clr LCD_rw . So this delay can be made either with a delay loop of specified time more than that of LCD process time or we can read the busy flag.Wait for LCD to process the command mov LCD_data.LCD Register Select LCD_rw equ P1.Wait for LCD to process the command mov LCD_data.Clear LCD clr LCD_rs .

• • • • Select command register Select read operation Send enable signal Read the flag So following the above steps we can write the code in assembly as below.Select command register setb LCD_rw .#FFH djnz r6.A ..Make D7th bit of LCD data port as i/p setb LCD_en .#50H back: mov r6.Ports used are same as the previous example . CODE: . If you dont want to read the busy flag you can simply use a delay routine to provide the a specific ammount of delay.check .Move the command to LCD port clr LCD_rs .read busy flag again and again till it becomes 0 ret . Following are the steps: • Move data to LCD port select command register select write operation send enable signal wait for LCD to process the command • • • • Keeping these steps in mind we can write LCD command routine as. A simple delay routine for the LCD is given below.Selected command register clr LCD_rw .we are reading check: clr LCD_en . CODE: LCD_busy: mov r7. But we will summarize the common steps and put them in a single subroutine.We are writing in instruction register setb LCD_en .$ djnz r7.back ret .Enable H->L setb LCD_en jb LCD_D7. Ports used are same as the previous example LCD_busy: setb LCD_D7 .Make port pin as o/p clr LCD_rs .Enable H->L . Everything is same as we have done in the initialization routine.Return from busy routine The above routine will provide the necessary delay for the instructions to complete.Routine to send command to LCD LCD_command: mov LCD_data.Return from busy routine Sending Commands to LCD To send commands we simply need to select the command register.

you will see all the missing character coming from the back. mov a.clr LCD_en acall LCD_busy . Below is an example for setting cursor position on LCD. rest of the DDRAM area is still available but is not visible on the LCD. if you want to check this thing.#83H .load the command acall LCD_command . we need to send the DDRAM address. . so if you want to put the cursor on first position the address will be '0000000B' in binary and 7th bit is 1. acall LCD_command .Return from busy routine .Wait for LCD to process the command ret . this way you can make scrolling line on LCD (see more on shifting display in commands section). Everything is same as the command routine. CODE: Bit7 6 5 4 3 2 1 0 1 AD6 AD5 AD4 AD3 AD2 AD1 AD0 The seventh bit is always 1. we want to send clear LCD command .and the command will be 0x80+0x03 = 0x83 mov a..so the DDRAM address will be 0x03 . Usage of the above routine .send command to LCD Sending Data to LCD To send data we simply need to select the data register. A will carry the command for LCD . For 2 line and 16 character LCD. and bit 0 to 7 are DDRAM address (See the introduction section of LCD). so for DDRAM all address starts from 0x80. so address will be 0x80.Send the command Setting cursor position on LCD To set the cursor position on LCD. Following are the steps: • Move data to LCD port ..01H is command for clearing LCD .#01H . The adress from 0x80 to 0x8F are visible on first line and 0xC0 to 0xCF is visible on second line. then simply put a long sting greater than 16 character and shift the entire display.We are placing the cursor on the 4th position . e.g. CODE: ..

Now what if we have a string to send to LCD? how we are going to do that? Is simple.Move the command to LCD port setb LCD_rs .Ports used are same as the previous example . A will carry the character to display on LCD .Return from busy routine .load the first character inaccumulator jz exit . Usage of the above routine . Usage of the above routine . e.jump back to send the next character exit: ret . A simple exmple is shown below. CODE: .go to exit if zero acall lcd_senddata .increment data pointer sjmp LCD_sendstring . .Selected data register clr LCD_rw . e.Ascii value of 'A' will be loaded inaccumulator .#'A' .send first char inc dptr .Routine to send data (single character) to LCD LCD_senddata: mov LCD_data.Wait for LCD to process the data ret .select data register • select write operation • send enable signal • wait for LCD to process the data • Keeping these steps in mind we can write LCD command routine as.End of routine .clear Accumulator for any previous data movc a. we want to print "LCD Tutorial" on LCD then .Sending string to LCD Example LCD_sendstring: clr a . acall LCD_senddata . . DPTR(data pointer) will carry the address . we will store the LCD string in the ROM of controller and call the string character by character. we want to print A on LCD . CODE: .Send data Now you have seen that its really easy to send command and data to LCD.Enable H->L clr LCD_en acall LCD_busy .We are writing setb LCD_en . of string to send to LCD.A .g.g. mov a.@a+dptr .

my_string: . We just need to put these values in the CGRAM. Bit 7 is 0 and Bit 6 is 1. Bit: 4 3 2 1 0 . due to which the CGRAM adress command starts from 0x40. These values are to be written in the CGRAM adress starting from 0x40. acall LCD_sendstring . I am going to take an example. so you get a bigger pattern.0x0E Row3: 0 1 1 1 0 . so last row is usually left blank (0x00) for the cursor. For making custom patterns we need to write values to the CGRAM area defining which pixel to glow. Now we get the values for each row as shown.0x04 Row8: 0 0 0 0 0 . bit value is 1 if pixel is glowing and bit value is 0 if pixel is off. where as when LCD is working in 5x10 dots. When you are using LCD as 5x8 dots in function set then you can define a total of 8 user defined patterns (1 Byte for each row and 8 rows for each pattern). mov dptr. 00H .0x0E Row4: 0 1 1 1 0 . DB "LCD Tutorial".my_string is the label where the string is stored . where the address of CGRAM (Acg) starts from 0x00. 00H indicate that string is finished. If you are wondering why it starts from 0x40? Then the answer is given below..Hex Row1: 0 0 1 0 0 . The final 7 values are loaded to the CGRAM one by one.Send string . CGRAM and Character Building As already explained. As i said there are 8 rows for each pattern.#my_string .0x04 Row2: 0 1 1 1 0 .0x00 Row7: 0 0 1 0 0 . Following is the memory map for custom patterns in CGRAM. . . Lets make a "Bell" pattern as shown below. if you are using cursor then it is recommended not to use the 8th row.0x0E Row5: 1 1 1 1 1 . If you are not using cursor then you can make use of that 8th row also. To explain the above explaination in a better way.0x00 We are not using row 8 as in our pattern it is not required.. you can define 4 user defined patterns. Lets take an of bulding a custom pattern. . You can decided which place you want to store in. all character based LCD of type HD44780 has CGRAM area to create user defined patterns. Now as we have got the values.0x1F Row6: 0 0 0 0 0 . . All we have to do is make a pixel-map of 7x5 and get the hex or decimal value or hex value for each row. To store a string. CGRAM has a total of 64 Bytes.

...0x07 2 0x08 .Send the data mov A.Send the command mov A. So we send the command as 0x48 (0x40 + 0x08).0x0F 3 0x10 .#00H . which is 0x40 + CGRAM address (For more informationplease see Table 4 in commands section).#0EH . and then we send the pattern data.Load row 4 data acall LCD_senddata .Send the data mov A.0x3F We can point the cursor to CGRAM address by sending command.0x27 6 0x28 .LCD Ports are same as discussed in previous sections LCD_build: mov A.Send the data ret ..Load row 5 data acall LCD_senddata .Load row 2 data acall LCD_senddata . CODE: //LCD Ports are same as discussed in previous sections void LCD_build(){ . To display the above generated pattern on LCD.0x1F 5 0x20 .Send the data mov A.#00H .Send the data mov A.0x17 4 0x18 .#04H .2.Load the location where we want to store acall LCD_command .Load row 1 data acall LCD_senddata . CODE: .1.Send the data mov A.Load row 7 data acall LCD_senddata .. simply load the pattern location (0. Now we can also write the above routine in C as.Return from routine The above routine will create bell character at pattern location 2.#0EH .#04H .#48H .#0EH .Send the data mov A. CGRAM Address (Acg) 1 0x00 .Load row 8 data acall LCD_senddata .0x2F 7 0x30 . Lets say we want to write the Bell pattern at second pattern location.#1FH .7) and call the LCD_senddata subroutine.Load row 6 data acall LCD_senddata .Memory Map Pattern No.Send the data mov A. Below is a small programming example to do this.0x37 8 0x38 .Load row 3 data acall LCD_senddata .

So if you feel any problem running the LCD.LCD_command(0x48). LCD_senddata(0x1F). One basic reason is lesser number of pins are needed to interface LCD. ►LCD connections in 4-bit Mode . This delay might vary depending on the LCD you are using. To enable the 4-bit mode of LCD.          Wait for abour 20mS Send the first init value (0x30) Wait for about 10mS Send second init value (0x30) Wait for about 1mS Send third init value (0x30) Wait for 1mS Select bus width (0x30 . LCD_senddata(0x0E). } //Load the location where we want to store //Load row 1 data //Load row 2 data //Load row 3 data //Load row 4 data //Load row 5 data //Load row 6 data //Load row 7 data //Load row 8 data LCD interfacing with Microcontrollers tutorial .4-bit Mode ►Introduction Till now whatever we discussed in the previous part of ths LCD tutorial. There are many reasons why sometime we prefer to use LCD in 4-bit mode instead of 8-bit. So it actually depends on the LCD module you are using. LCD_senddata(0x04). we were dealing with 8-bit mode. as you might have a different crystal frequency on which LCD controller is running. LCD_senddata(0x0E).for 8-bit and 0x20 for 4-bit) Wait for 1mS The busy flag will only be valid after the above reset sequence. Instead we simply put a certain ammount of delay usually 300 to 600uS. We call this special sequence as resetting the LCD. For me about 400uS works perfect. Following is the reset sequence of LCD. LCD_senddata(0x0E). LCD_senddata(0x04). first we send the higher nibble and then the lower nibble. In 4-bit mode the data is sent in nibbles. Usually we do not use busy flag in 4-bit mode as we have to write code for reading two nibbles from the LCD. simply try to increase the delay. This usually works. Now we are going to learn how to use LCD in 4-bit mode. LCD_senddata(0x00). we need to follow special sequence of initialization that tells the LCD controller that user has selected 4-bit mode of operation. LCD_senddata(0x00).

. We have alreadydiscussed about the reset sequence of the lcd in the previous section. then you may connect it on your controller but that will only increase another pin and does not make any big difference.my controller in following way... Potentiometer RV1 is used to control the LCD contrast.0 .1 .P3.D4 . If you want to use it.Above is the connection diagram of LCD in 4-bit mode. We are not using Read/Write (RW) Pin of the LCD..2 .In this whole 4-bit tutorial LCD is connected to . This means in both command and data sending function we need to saperate the higher 4-bits and lower 4-bits. ►Assembly Program CODE: .P3. where we only need 6 pins to interface an LCD. As i already explained in 4-bit mode data is sent nibble by nibble. D4-D7 are the data pins connection and Enable and Register select are for LCD control pins.P3. D0-D3 are connected to ground. . ►Sending data/command in 4-bit Mode We will now look into the common steps to send data/command to LCD when working in 4-bit mode. So lets look at the programming now.. The unwanted data pins of LCD i.D5 .D6 . In the next section we will take a look at the programming microcontroller to control LCD in 4-bit mode. The common steps are:       Mask lower 4-bits Send to the LCD port Send enable signal Mask higher 4-bits Send to LCD port Send enable signal We are done with the theory part now. first we send higher nibble and then lower nibble. 4-bit Initialization Initialization of LCD is completed only after the reset sequence and basic initialization commands.e. as we are only writing on the LCD so we have made it grounded permanently.

#5 .20mS delay acall delayms mov lcd_port.Delay 15mS acall delayms mov lcd_port.Set entry mode (Auto increment) .3 .5 lcd_reset: .P3.Data = 30H. EN = 1.Enable connected to P3.Call LCD Reset sequence .Third Init mov lcd_port.Display ON cursor OFF .RS . First Init mov lcd_port.#5 .Call LCD command .Enable = 1.Delay 5mS acall delayms mov lcd_port.D7 .#0CH acall lcd_cmd mov a.Enable = 0.Move it to lcd port anl a. #83H . Data = 30H.a .LCD connected to Port3 . #03H mov delay.LCD command Routine mov temp. EN = 0 mov delay.7 . RS = 0 mov lcd_port.#0FH .a .a .Call LCD command .#28H acall lcd_cmd mov a. EN = 0 mov delay.#06H acall lcd_cmd mov a.Call LCD command .#15 .Data = 30H.Data = 20H.Register select to P3.Delay 5mS acall delayms ret lcd_init: acall lcd_reset mov a. #82H .Mask the first four bits add a. #83H .LCD reset sequence mov lcd_port.#5 .P3.#0FH .Second Init.P3.#20 .Swap to use higher nibble anl a. #03H . 5x7 dots . #0FFH mov delay.Data = 30H.5 .Save a copy of command to temp swap a .#80H . #03H .7 . EN = 0 mov delay..#80H acall lcd_cmd ret . EN = 1 mov lcd_port. 2 line.5 lcd_port equ P3 en equ P3.4-bit.Bring cursor to line 1 .EN .Call LCD command Sending command/Data to LCD in 4-bit mode ►Assembly Program CODE: lcd_cmd: .Move to lcd port . #02H . RS = 0 mov lcd_port. #83H .7 rs equ P3.Select Data width (20H for 4bit) mov lcd_port.Delay 5mS acall delayms mov lcd_port.

#0A0H .Move to lcd port nop clr en .Enable = 1.We need higher nibble anl a.Delay 1mS .Mask first four bits .Enable = 0 .#1 acall delayms ret .#0FH mov lcd_port. RS = 1 mov lcd_port.Enable = 0 mov a.LCD data Routine mov temp.#0FH .Enable = 0 mov delay.a .Mask first four bits add a.Reload the command from temp .Enable = 1 .a .we need lower nibble now add a.Enable = 1.Move to lcd port .a mov delay.#80H mov lcd_port.Keep copy of data in temp swap a .#0FH .mov a.Move to port .Move to lcd port nop clr en .#0A0H .delay 1 ms lcd_dat: .temp .#0FH add a. RS = 1 mov lcd_port.a .a anl a.#1 acall delayms ret .Reload the data from temp anl a.temp anl a.

Sign up to vote on this title
UsefulNot useful