stepper motor controller using 8051

44
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.

Transcript of stepper motor controller using 8051

Page 1: stepper motor controller using 8051

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.

Page 2: stepper motor controller using 8051

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.

Page 3: stepper motor controller using 8051

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 A B A\ B\

0 1 1 0 0

1 0 1 1 0

2 0 0 1 1

3 1 0 0 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

Page 4: stepper motor controller using 8051

the number of steps gets doubled as that of full mode. Half mode is usually preffered over full mode. Table below shows the pattern of energizing the coils.

Half Mode Sequence

Step A B A\ B\

0 1 1 0 0

1 0 1 0 0

2 0 1 1 0

3 0 0 1 0

4 0 0 1 1

5 0 0 0 1

6 1 0 0 1

7 1 0 0 0

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

►Step Angle

Step angle of the stepper motor is defined as the angle traversed by the motor in one step. To calculate step angle,simply divide 360 by number of steps a motor takes to complete one revolution. As we have seen that in half mode, the number of steps taken by the motor to complete one revolution gets doubled, so step angle reduces to half.

As in above examples, Stepper Motor rotating in full mode takes 4 steps to complete a revolution, So step angle can be calculated as...

Page 5: stepper motor controller using 8051

Step Angle ø = 360° / 4 = 90°

and in case of half mode step angle gets half so 45°.

So this way we can calculate step angle for any stepper motor. Usually step angle is given in the spec sheet of thestepper motor you are using. 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, In every step of the sequence, two wires are always set to opposite polarities. Because of this, it's possible to control steppers with only two wires instead of four, with a slightly more complex circuit. The stepping sequence is the same as it is for the two coils A and B, and the opposite polarity value is given to A\ and B\. The sequence is given in the table below:

2-wire Mode SequenceStep A B0 0 11 1 12 1 03 0 0

►Step Sequence for Bipolar stepper motor

Bipolar motor has simpler construction. It has two windings with no center taps and a permanent magnet at the center just like unipolar stepepr motors. Being simpler in contruction, the stepping sequence is a little complex, as the power for both the coils has to be controlled in such a way that the polarity of the poles get reversed. This polarity sequence is shown in the table below.

Polarity Sequence

Step A A\ B B\

0 +ve -ve -ve -ve

1 -ve -ve +ve -ve

2 -ve +ve -ve -ve

3 -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.

Step Sequence

Step A A\ B B\

0 1 0 0 0

1 0 0 1 0

2 0 1 0 0

3 0 0 0 1

We have now learnt most of the necessary things regarding a stepper motor.

There are actually many ways you can interface a stepper motor to your controller, out of them the most used interfaces are:

Page 6: stepper motor controller using 8051

1. Interface using L293D - H-Bridge Motor Driver2. Interface using ULN2003/2004 - Darlington Arrays

We will dicuss both connection techniques one by one. The above mentioned methods need 4 controller pins for interface.

►Connecting Unipolar   stepper   using L293D

As you see in the circuit above the four pins "Controller pin 1",2,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 ULN2003/2004

Page 7: stepper motor controller using 8051

As already discussed in case of L293D, Here in this circuit too the four pins "Controller pin 1",2,3 and 4 will control the motion and direction of the stepper motor according to the step sequece sent by the controller.

►2-wire connection for Unipolar Stepper Motor

We have seen the generally used 4-wire connection method for interfacing unipolar stepper motor, but we can simplify the design to make controller use less pins with the help of 2-wire connection method. The circuit for 2-wire connection is shown below.

Connecting Bipolar Stepper Motor

As we have studied that, Bi-polar stepper motors has 2 different coils. The step sequence for Bipolar stepper motor is same as that of unipolar stepper motors. The driving circuit for this require an H-Bridge as it allows the polarity of the power applied to be controlled independently. This can be done as shown in the figure below:

Page 8: stepper motor controller using 8051

Programming Full step SequenceI am assuming that   stepper motor   is connected at Port 1.0 to Port 1.3.   Adjusting   the delay will   increase   or   decrease   the speed of   the motor. Here just for demonstration i have taken some delay, you can change it as you want.

org 0H

stepper equ P1

main:        mov stepper, #0CH        acall delay        mov stepper, #06H        acall delay        mov stepper, #03H        acall delay        mov stepper, #09H        acall delay        sjmp main

delay:        mov r7,#4wait2:        mov r6,#0FFHwait1:        mov r5,#0FFHwait:        djnz r5,wait        djnz r6,wait1        djnz r7,wait2        ret        end

Page 9: stepper motor controller using 8051

Programming Half step Sequencemain:        mov stepper, #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, #03H        acall delay        mov stepper, #01H        acall delay        mov stepper, #09H        acall delay        sjmp main

Page 10: stepper motor controller using 8051

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

Page 11: stepper motor controller using 8051

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

Page 12: stepper motor controller using 8051

Pulse Width Modulation (PWM)

Introduction

Pulse width Modulation or PWM is one of the powerful techniques used in control systems today. They are not only employed in wide range of control application which includes: speed control, power control, measurement and communication..

►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. A mathematical explaination of this is given below.

Consider a square wave shown in the figure above.

Ton is the time for which the output is high and Toff is time for which output is low. Let Ttotal be time period of the wave such that,

Duty cycle of a square wave is defined as 

The output voltage varies with duty cycle as...

So you can see from the final equation the output voltage can be directly varied by varying the Ton value.

If Ton is 0, Vout is also 0.

if Ton is Ttotal then Vout is Vin or say maximum.

This was all about theory behind PWM. Now lets take a look at the practical implementation of PWM on microcontrollers.

Page 13: stepper motor controller using 8051

Idea Behind Implementation

The basic idea behind PWM implementation on 8051 is using timers and switching port pin high/low at defined intervals. As we have discussed in the introduction of PWM that by changing the Ton time, we can vary the width of square wave keeping same time period of the square wave.

We will be using 8051 Timer0 in Mode 0. Values for high and low level will be loaded in such a way that total delay remains same. 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.

►Assembly Code Example

Timer setup for PWM

PWMPIN EQU P1.0         ; PWM output pinPWM_SETUP:        MOV TMOD,#00H           ; Timer0 in Mode 0        MOV R7, #160            ; Set pulse width control        ; The value loaded in R7 is value X as        ; discussed above.        SETB EA         ; Enable Interrupts        SETB ET0                ; Enable Timer 0 Interrupt        SETB TR0                ; Start Timer        RET

Interrupt Service Routine

TIMER_0_INTERRUPT:        JB F0, HIGH_DONE        ; If F0 flag is set then we just finished                                ; the high section of theLOW_DONE:                       ; cycle so Jump to HIGH_DONE        SETB F0                 ; Make F0=1 to indicate start of high section        SETB PWMPIN             ; Make PWM output pin High        MOV TH0, R7             ; Load high byte of timer with R7                                ; (pulse width control value)        CLR TF0                 ; Clear the Timer 0 interrupt flag        RETI                    ; Return from Interrupt to where                                        ; the program came fromHIGH_DONE:        CLR F0                  ; Make F0=0 to indicate start of low section        CLR PWMPIN              ; Make PWM output pin low        MOV A, #0FFH    ; Move FFH (255) to A        CLR C                   ; Clear C (the carry bit) so it does                                        ; not affect the subtraction        SUBB A, R7              ; Subtract R7 from A. A = 255 - R7.        MOV TH0, A              ; so the value loaded into TH0 + R7 = 255        CLR TF0                 ; Clear the Timer 0 interrupt flag        RETI                    ; Return from Interrupt to where                                ; the program came from

In your main program you need to call this PWM_SETUP routine and your controller will have a PWM output. Timer Interrupt service routine will take care of PWM in the background. The width of PWM can

Page 14: stepper motor controller using 8051

be changed by changing the value of R7 register. In above example I am using 160, you can choose any value from 0 to 255. 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. And the output pin can be changed to whatever pin you want.

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 this tutorial, we will discuss about character based LCDs, their interfacing with various microcontrollers, various interfaces (8-bit/4-bit), programming, special stuff and tricks you can do with these simple looking LCDs which can give a new look to your application.

For Specs and technical information HD44780 controller Click Here

►Pin Description

The most commonly used LCDs found in the market today are 1 Line, 2 Line or 4 Line LCDs which have only 1 controllerand support at most of 80 charachers, whereas LCDs supporting more than 80 characters make use of 2 HD44780 controllers.

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). Pin description is shown in the table below.

Figure 1: Character LCD type HD44780 Pin diagram

Pin No. Name Description

Pin no. 1 VSS Power supply (GND)Pin no. 2 VCC Power supply (+5V)Pin no. 3 VEE Contrast adjust

Pin no. 4 RS0 = Instruction input1 = Data input

Pin no. 5 R/W 0 = Write to LCD module

Page 15: stepper motor controller using 8051

1 = Read from LCD module

Pin no. 6 EN Enable signalPin no. 7 D0 Data bus line 0 (LSB)Pin no. 8 D1 Data bus line 1Pin no. 9 D2 Data bus line 2Pin no. 10 D3 Data bus line 3Pin no. 11 D4 Data bus line 4Pin no. 12 D5 Data bus line 5Pin no. 13 D6 Data bus line 6Pin no. 14 D7 Data bus line 7 (MSB)

Table 1: Character LCD pins with 1 Controller

Pin No. Name Description

Pin no. 1 D7 Data bus line 7 (MSB)Pin no. 2 D6 Data bus line 6Pin no. 3 D5 Data bus line 5Pin no. 4 D4 Data bus line 4Pin no. 5 D3 Data bus line 3Pin no. 6 D2 Data bus line 2Pin no. 7 D1 Data bus line 1Pin no. 8 D0 Data bus line 0 (LSB)

Pin no. 9 EN1Enable signal for row 0 and 1 (1stcontroller)

Pin no. 10R/W0 = Write to LCD module1 = Read from LCD module

Pin no. 11RS0 = Instruction input1 = Data input

Pin no. 12VEE Contrast adjustPin no. 13VSS Power supply (GND)Pin no. 14VCC Power supply (+5V)

Pin no. 15EN2Enable signal for row 2 and 3 (2ndcontroller)

Pin no. 16NC Not ConnectedTable 2: Character LCD pins with 2 Controller

Usually these days you will find single controller LCD modules are used more in the market. So in the tutorial we will discuss more about the single controller LCD, the operation and everything else is same for the double controller too. Lets take a look at the basic information which is there in every LCD.

Page 16: stepper motor controller using 8051

DDRAM - Display Data RAM

Display data RAM (DDRAM) stores display data represented in 8-bit character codes. Its extended capacity is 80 X 8 bits, or 80 characters. The area in display data RAM (DDRAM) that is not used for display can be used as general data RAM. So whatever you send on the DDRAM is actually displayed on the LCD. For LCDs like 1x16, only 16 characters are visible, so whatever you write after 16 chars is written in DDRAM but is not visible to the user.

Figures below will show you the DDRAM addresses of 1 Line, 2 Line and 4 Line LCDs.

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 - Character Generator ROM

Now you might be thinking that when you send an ascii value to DDRAM, how the character is displayed on LCD? so the answer is CGROM. 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). It can generate 208 5 x 8 dot character patterns and 32 5 x 10 dot character patterns. Userdefined character patterns are also available by mask-programmed ROM.

Page 17: stepper motor controller using 8051

Figure 5: LCD characters code map for 5x8 dots

Page 18: stepper motor controller using 8051

Figure 6: LCD characters code map for 5x10 dots

As you can see in both the code maps, the character code from 0x00 to 0x07 is occupied by the CGRAM characters or the user defined characters. If user want to display the fourth custom character then the code to display it is 0x03 i.e. when user send 0x03 code to the LCD DDRAM then the fourth user created charater or patteren will be displayed on the LCD.

►CGRAM - Character Generator RAM

As clear from the name, CGRAM area is used to create custom characters in LCD. In the character generator RAM, the user can rewrite character patterns by program. For 5 x 8 dots, eight character patterns can be written, and for 5 x 10 dots, four character patterns can be written. 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.

►BF - Busy Flag

Busy Flag is an status indicator flag for LCD. When we send a command or data to the LCD for processing, this flag is set (i.e BF =1) and as soon as the instruction is executed successfully this flag is cleared (BF = 0). This is helpful in producing and exact ammount of delay. for the LCD processing.

Page 19: stepper motor controller using 8051

To read Busy Flag, the condition RS = 0 and R/W = 1 must be met and The MSB of the LCD data bus (D7) act as busy flag. 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.

►Instruction Register (IR) and Data Register (DR)

There are two 8-bit registers in HD44780 controller Instruction and Data register. Instruction register corresponds to theregister where you send commands to LCD e.g LCD shift command, LCD clear, LCD address etc. and Data register is used for storing data which is to be displayed on LCD. when send the enable signal of the LCD is asserted, 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.Data Register is not only used for sending data to DDRAM but also for CGRAM, the address where you want to send the data, is decided by the instruction you send to LCD.

Commands and Instruction set

Only the instruction register (IR) and the data register (DR) of the LCD can be controlled by the MCU. Before starting theinternal operation of the LCD, control information is temporarily stored into these registers to allow interfacing with various MCUs, which operate at different speeds, or various peripheral control devices. The internal operation of the LCD is determined by signals sent from the MCU. These signals, which include register selection signal (RS), read/write signal (R/W), and the data bus (DB0 to DB7), make up the LCD instructions (Table 3). There are four categories of instructionsthat: 

Designate LCD functions, such as display format, data length, etc. Set internal RAM addresses Perform data transfer with internal RAM Perform miscellaneous functions

Page 20: stepper motor controller using 8051

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.

No. Instruction Hex Decimal

1 Function Set: 8-bit, 1 Line, 5x7 Dots 0x30 482 Function Set: 8-bit, 2 Line, 5x7 Dots 0x38 563 Function Set: 4-bit, 1 Line, 5x7 Dots 0x20 324 Function Set: 4-bit, 2 Line, 5x7 Dots 0x28 405 Entry Mode 0x06 66 Display off Cursor off 0x08 8

Page 21: stepper motor controller using 8051

(clearing display without clearing DDRAM content)

7 Display on Cursor on 0x0E 148 Display on Cursor off 0x0C 129 Display on Cursor blinking 0x0F 1510 Shift entire display left 0x18 2412 Shift entire display right 0x1C 3013 Move cursor left by one character 0x10 1614 Move cursor right by one character 0x14 20

15Clear Display (also clear DDRAM content)

0x01 1

16Set DDRAM address or coursor position on display

0x80+add* 128+add*

17Set CGRAM address or set pointer to CGRAM location

0x40+add** 64+add**

Table 4: Frequently used commands and instructions for LCD

* DDRAM address given in LCD basics section see Figure 2,3,4** CGRAM address from 0x00 to 0x3F, 0x00 to 0x07 for char1 and so on..

The table above will help you while writing programs for LCD. But after you are done testing with the table 4, i recommend you to use table 3 to get more grip on working with LCD and trying your own commands. In the next section of the tutorial we will see the initialization with some of the coding examples in C as well as assembly.

LCD Initialization

Before using the LCD for display purpose, LCD has to be initialized either by the internal reset circuit or sending set of commands to initialize the LCD. It is the user who has to decide whether an LCD has to be initialized by instructions or byinternal reset circuit. we will dicuss both ways of initialization one by one.

Initialization by   internal   Reset Circuit

An internal reset circuit automatically initializes the HD44780U when the power is turned on. The following instructions are executed during the initialization. The busy flag (BF) is kept in the busy state until the initialization ends (BF = 1). The busy state lasts for 10 ms after VCC rises to 4.5 V.

Display clear Function set:

DL = 1; 8-bit interface dataN = 0; 1-line displayF = 0; 5 x 8 dot character font

Display on/off control:D = 0; Display offC = 0; Cursor offB = 0; Blinking off

Entry mode set:I/D = 1; Increment by 1S = 0; No shift

Page 22: stepper motor controller using 8051

Note: If the electrical characteristics conditions listed under the table Power Supply Conditions Using Internal Reset Circuit are not met, the internal reset circuit will not operate normally and will fail to initialize the HD44780U. For such a case, initial-ization must be performed by the MCU as explained in the section, Initializing by Instruction.

As mentioned in the Note, there are certain condtions that has to be met, if user want to use initialization by internal reset circuit. These conditions are shown in the Table 5 below.

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.

Figure 7: Internal Power Supply reset

Now the problem with the internal reset circuit is, it is highly dependent on power supply, 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.e. Initialization by instruction is used and is recommended most of the time.

Initialization by   instructions

Initializing LCD with instructions is really simple. Given below is a flowchart that describles the step to follow, to initialize the LCD.

Page 23: stepper motor controller using 8051

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 - Using 8-bit interface2) Delay 20ms3) Send command 0x30 - 8-bit interface4) Delay 20ms5) Send command 0x30 - 8-bit interface6) Delay 20ms7) Send Function set - see Table 4 for more information8) Display Clear command9) Set entry mode command - explained below

The first 3 commands are usually not required but are recomended when you are using 4-bit interface. So you can program the LCD starting from step 7 when working with 8-bit interface. 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).

LCD Entry modeFrom Table 3 in command section, you can see that the two bits decide the entry mode for LCD, these bits are:a) I/D - Increment/Decrement bitb) S - Display shift.

Page 24: stepper motor controller using 8051

With these two bits we get four combinations of entry mode which are 0x04,0x05,0x06,0x07 (see table 3 in LCD Commandsection). So we get different results with these different entry modes. Normally entry mode 0x06 is used which is No shift and auto incremement. I recommend you to try all the possible entry modes and see the results, I am sure you will be surprised.

Programming example for LCD Initialization

CODE:

LCD_data equ P2    ;LCD Data portLCD_D7   equ P2.7  ;LCD D7/Busy FlagLCD_rs   equ P1.0  ;LCD Register SelectLCD_rw   equ P1.1  ;LCD Read/WriteLCD_en   equ P1.2  ;LCD Enable

LCD_init:         mov   LCD_data,#38H  ;Function set: 2 Line, 8-bit, 5x7 dots         clr   LCD_rs         ;Selected command register         clr   LCD_rw         ;We are writing in instruction register         setb  LCD_en         ;Enable H->L         clr   LCD_en         acall LCD_busy       ;Wait for LCD to process the command         mov   LCD_data,#0FH  ;Display on, Curson blinking command         clr   LCD_rs         ;Selected instruction register         clr   LCD_rw         ;We are writing in instruction register         setb  LCD_en         ;Enable H->L         clr   LCD_en         acall LCD_busy       ;Wait for LCD to process the command         mov   LCD_data,#01H  ;Clear LCD         clr   LCD_rs         ;Selected command register         clr   LCD_rw         ;We are writing in instruction register         setb  LCD_en         ;Enable H->L         clr   LCD_en         acall LCD_busy       ;Wait for LCD to process the command         mov   LCD_data,#06H  ;Entry mode, auto increment with no shift         clr   LCD_rs         ;Selected command register         clr   LCD_rw         ;We are writing in instruction register         setb  LCD_en         ;Enable H->L         clr   LCD_en         acall LCD_busy       ;Wait for LCD to process the command         ret                  ;Return from routine

LCD Initialization

Before using the LCD for display purpose, LCD has to be initialized either by the internal reset circuit or sending set of commands to initialize the LCD. It is the user who has to decide whether an LCD has to be initialized by instructions or byinternal reset circuit. we will dicuss both ways of initialization one by one.

Initialization by   internal   Reset Circuit

Page 25: stepper motor controller using 8051

An internal reset circuit automatically initializes the HD44780U when the power is turned on. The following instructions are executed during the initialization. The busy flag (BF) is kept in the busy state until the initialization ends (BF = 1). The busy state lasts for 10 ms after VCC rises to 4.5 V.

Display clear Function set:

DL = 1; 8-bit interface dataN = 0; 1-line displayF = 0; 5 x 8 dot character font

Display on/off control:D = 0; Display offC = 0; Cursor offB = 0; Blinking off

Entry mode set:I/D = 1; Increment by 1S = 0; No shift

Note: If the electrical characteristics conditions listed under the table Power Supply Conditions Using Internal Reset Circuit are not met, the internal reset circuit will not operate normally and will fail to initialize the HD44780U. For such a case, initial-ization must be performed by the MCU as explained in the section, Initializing by Instruction.

As mentioned in the Note, there are certain condtions that has to be met, if user want to use initialization by internal reset circuit. These conditions are shown in the Table 5 below.

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.

Page 26: stepper motor controller using 8051

Figure 7: Internal Power Supply reset

Now the problem with the internal reset circuit is, it is highly dependent on power supply, 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.e. Initialization by instruction is used and is recommended most of the time.

Initialization by   instructions

Initializing LCD with instructions is really simple. Given below is a flowchart that describles the step to follow, to initialize the LCD.

Page 27: stepper motor controller using 8051

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 - Using 8-bit interface2) Delay 20ms3) Send command 0x30 - 8-bit interface4) Delay 20ms5) Send command 0x30 - 8-bit interface6) Delay 20ms7) Send Function set - see Table 4 for more information8) Display Clear command9) Set entry mode command - explained below

The first 3 commands are usually not required but are recomended when you are using 4-bit interface. So you can program the LCD starting from step 7 when working with 8-bit interface. 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).

LCD Entry modeFrom Table 3 in command section, you can see that the two bits decide the entry mode for LCD, these bits are:a) I/D - Increment/Decrement bitb) S - Display shift.

Page 28: stepper motor controller using 8051

With these two bits we get four combinations of entry mode which are 0x04,0x05,0x06,0x07 (see table 3 in LCD Commandsection). So we get different results with these different entry modes. Normally entry mode 0x06 is used which is No shift and auto incremement. I recommend you to try all the possible entry modes and see the results, I am sure you will be surprised.

Programming example for LCD Initialization

CODE:

LCD_data equ P2    ;LCD Data portLCD_D7   equ P2.7  ;LCD D7/Busy FlagLCD_rs   equ P1.0  ;LCD Register SelectLCD_rw   equ P1.1  ;LCD Read/WriteLCD_en   equ P1.2  ;LCD Enable

LCD_init:         mov   LCD_data,#38H  ;Function set: 2 Line, 8-bit, 5x7 dots         clr   LCD_rs         ;Selected command register         clr   LCD_rw         ;We are writing in instruction register         setb  LCD_en         ;Enable H->L         clr   LCD_en         acall LCD_busy       ;Wait for LCD to process the command         mov   LCD_data,#0FH  ;Display on, Curson blinking command         clr   LCD_rs         ;Selected instruction register         clr   LCD_rw         ;We are writing in instruction register         setb  LCD_en         ;Enable H->L         clr   LCD_en         acall LCD_busy       ;Wait for LCD to process the command         mov   LCD_data,#01H  ;Clear LCD         clr   LCD_rs         ;Selected command register         clr   LCD_rw         ;We are writing in instruction register         setb  LCD_en         ;Enable H->L         clr   LCD_en         acall LCD_busy       ;Wait for LCD to process the command         mov   LCD_data,#06H  ;Entry mode, auto increment with no shift         clr   LCD_rs         ;Selected command register         clr   LCD_rw         ;We are writing in instruction register         setb  LCD_en         ;Enable H->L         clr   LCD_en         acall LCD_busy       ;Wait for LCD to process the command         ret                  ;Return from routine

Reading the busy Flag

As discussed in the previous section, there must be some delay which is needed to be there for LCD to successfullyprocess the command or data. 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, which is recomended. 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 is best suited for every application.

Steps to read busy flag

Page 29: stepper motor controller using 8051

when we send the command, 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.

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..

Ports used are same as the previous example

LCD_busy:         setb   LCD_D7        ;Make D7th bit of LCD data port as i/p         setb   LCD_en        ;Make port pin as o/p         clr    LCD_rs        ;Select command register         setb   LCD_rw        ;we are readingcheck:         clr    LCD_en        ;Enable H->L         setb   LCD_en         jb     LCD_D7,check  ;read busy flag again and again till it becomes 0         ret                  ;Return from busy routine

The above routine will provide the necessary delay for the instructions to complete. If you dont want to read the busy flag you can simply use a delay routine to provide the a specific ammount of delay. A simple delay routine for the LCD is given below.

CODE:LCD_busy:         mov  r7,#50Hback:         mov  r6,#FFH         djnz r6,$         djnz r7,back         ret                  ;Return from busy routine

Sending Commands to LCD

To send commands we simply need to select the command register. Everything is same as we have done in the initialization routine. But we will summarize the common steps and put them in a single subroutine. 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.

CODE:;Ports used are same as the previous example;Routine to send command to LCD

LCD_command:

Page 30: stepper motor controller using 8051

         mov   LCD_data,A     ;Move the command to LCD port         clr   LCD_rs         ;Selected command register         clr   LCD_rw         ;We are writing in instruction register         setb  LCD_en         ;Enable H->L         clr   LCD_en         acall LCD_busy       ;Wait for LCD to process the command         ret                  ;Return from busy routine

; Usage of the above routine; A will carry the command for LCD; e.g. we want to send clear LCD command;; mov   a,#01H         ;01H is command for clearing LCD; acall LCD_command    ;Send the command

Setting cursor position on LCDTo set the cursor position on LCD, we need to send the DDRAM address...

CODE:

Bit7  6   5   4   3   2   1   0 1   AD6 AD5 AD4 AD3 AD2 AD1 AD0

The seventh bit is always 1, and bit 0 to 7 are DDRAM address (See the introduction section of LCD). so if you want to put the cursor on first position the address will be '0000000B' in binary and 7th bit is 1. so address will be 0x80, so for DDRAM all address starts from 0x80.

For 2 line and 16 character LCD. The adress from 0x80 to 0x8F are visible on first line and 0xC0 to 0xCF is visible on second line, rest of the DDRAM area is still available but is not visible on the LCD, if you want to check this thing, then simply put a long sting greater than 16 character and shift the entire display, you will see all the missing character coming from the back.. this way you can make scrolling line on LCD (see more on shifting display in commands section).

Below is an example for setting cursor position on LCD.

CODE:;We are placing the cursor on the 4th position;so the DDRAM address will be 0x03;and the command will be 0x80+0x03 = 0x83mov a,#83H           ;load the commandacall LCD_command    ;send command to LCD

Page 31: stepper motor controller using 8051

Sending Data to LCD

To send data we simply need to select the data register. Everything is same as the command routine. Following are the steps:

Move data to LCD port 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.

CODE:;Ports used are same as the previous example;Routine to send data (single character) to LCD

LCD_senddata:         mov   LCD_data,A     ;Move the command to LCD port         setb  LCD_rs         ;Selected data register         clr   LCD_rw         ;We are writing         setb  LCD_en         ;Enable H->L         clr   LCD_en         acall LCD_busy       ;Wait for LCD to process the data         ret                  ;Return from busy routine

; Usage of the above routine; A will carry the character to display on LCD; e.g. we want to print A on LCD;; mov   a,#'A'         ;Ascii value of 'A' will be loaded inaccumulator; acall LCD_senddata   ;Send data

Now you have seen that its really easy to send command and data to LCD. Now what if we have a string to send to LCD? how we are going to do that?

Is simple, we will store the LCD string in the ROM of controller and call the string character by character. A simple exmple is shown below.

CODE:;Sending string to LCD Example

LCD_sendstring:         clr   a                 ;clear Accumulator for any previous data         movc  a,@a+dptr         ;load the first character inaccumulator         jz    exit              ;go to exit if zero         acall lcd_senddata      ;send first char

Page 32: stepper motor controller using 8051

         inc   dptr              ;increment data pointer         sjmp  LCD_sendstring    ;jump back to send the next characterexit:         ret                     ;End of routine

; Usage of the above routine; DPTR(data pointer) will carry the address; of string to send to LCD.; e.g. we want to print "LCD Tutorial" on LCD then;; mov   dptr,#my_string   ;my_string is the label where the string is stored; acall LCD_sendstring    ;Send string;; To store a string..; my_string:; DB   "LCD Tutorial", 00H; 00H indicate that string is finished.

CGRAM and Character Building

As already explained, all character based LCD of type HD44780 has CGRAM area to create user defined patterns. For making custom patterns we need to write values to the CGRAM area defining which pixel to glow. These values are to be written in the CGRAM adress starting from 0x40. If you are wondering why it starts from 0x40? Then the answer is given below.

Bit 7 is 0 and Bit 6 is 1, due to which the CGRAM adress command starts from 0x40, where the address of CGRAM (Acg) starts from 0x00. CGRAM has a total of 64 Bytes. 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), where as when LCD is working in 5x10 dots, you can define 4 user defined patterns.

Lets take an of bulding a custom pattern. 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, bit value is 1 if pixel is glowing and bit value is 0 if pixel is off. The final 7 values are loaded to the CGRAM one by one. As i said there are 8 rows for each pattern, so last row is usually left blank (0x00) for the cursor. If you are not using cursor then you can make use of that 8th row also. so you get a bigger pattern.

To explain the above explaination in a better way. I am going to take an example. Lets make a "Bell" pattern as shown below.

Now we get the values for each row as shown.

  Bit:     4 3 2 1 0 - Hex  Row1: 0 0 1 0 0 - 0x04  Row2: 0 1 1 1 0 - 0x0E

Page 33: stepper motor controller using 8051

  Row3: 0 1 1 1 0 - 0x0E  Row4: 0 1 1 1 0 - 0x0E  Row5: 1 1 1 1 1 - 0x1F  Row6: 0 0 0 0 0 - 0x00  Row7: 0 0 1 0 0 - 0x04  Row8: 0 0 0 0 0 - 0x00

We are not using row 8 as in our pattern it is not required. if you are using cursor then it is recommended not to use the 8th row. Now as we have got the values. We just need to put these values in the CGRAM. You can decided which place you want to store in. Following is the memory map for custom patterns in CGRAM.

Memory Map

Pattern No. CGRAM Address (Acg)1 0x00 - 0x072 0x08 - 0x0F3 0x10 - 0x174 0x18 - 0x1F5 0x20 - 0x276 0x28 - 0x2F7 0x30 - 0x378 0x38 - 0x3F

We can point the cursor to CGRAM address by sending command, which is 0x40 + CGRAM address (For more informationplease see Table 4 in commands section). Lets say we want to write the Bell pattern at second pattern location. So we send the command as 0x48 (0x40 + 0x08), and then we send the pattern data. Below is a small programming example to do this.

CODE:;LCD Ports are same as discussed in previous sections

LCD_build:         mov   A,#48H         ;Load the location where we want to store         acall LCD_command    ;Send the command         mov   A,#04H         ;Load row 1 data         acall LCD_senddata   ;Send the data         mov   A,#0EH         ;Load row 2 data         acall LCD_senddata   ;Send the data         mov   A,#0EH         ;Load row 3 data         acall LCD_senddata   ;Send the data         mov   A,#0EH         ;Load row 4 data         acall LCD_senddata   ;Send the data         mov   A,#1FH         ;Load row 5 data         acall LCD_senddata   ;Send the data         mov   A,#00H         ;Load row 6 data         acall LCD_senddata   ;Send the data         mov   A,#04H         ;Load row 7 data         acall LCD_senddata   ;Send the data         mov   A,#00H         ;Load row 8 data         acall LCD_senddata   ;Send the data         ret                  ;Return from routine

Page 34: stepper motor controller using 8051

The above routine will create bell character at pattern location 2. To display the above generated pattern on LCD, simply load the pattern location (0,1,2,...7) and call the LCD_senddata subroutine. Now we can also write the above routine in C as...

CODE://LCD Ports are same as discussed in previous sectionsvoid LCD_build(){        LCD_command(0x48);       //Load the location where we want to store        LCD_senddata(0x04);      //Load row 1 data        LCD_senddata(0x0E);      //Load row 2 data        LCD_senddata(0x0E);      //Load row 3 data        LCD_senddata(0x0E);      //Load row 4 data        LCD_senddata(0x1F);      //Load row 5 data        LCD_senddata(0x00);      //Load row 6 data        LCD_senddata(0x04);      //Load row 7 data        LCD_senddata(0x00);      //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, we were dealing with 8-bit mode. Now we are going to learn how to use LCD in 4-bit mode. There are many reasons why sometime we prefer to use LCD in 4-bit mode instead of 8-bit. One basic reason is lesser number of pins are needed to interface LCD.

In 4-bit mode the data is sent in nibbles, first we send the higher nibble and then the lower nibble. To enable the 4-bit mode of LCD, we need to follow special sequence of initialization that tells the LCD controller that user has selected 4-bit mode of operation. We call this special sequence as resetting the LCD. Following is the reset sequence 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 - for 8-bit and 0x20 for 4-bit) Wait for 1mS

The busy flag will only be valid after the above reset sequence. Usually we do not use busy flag in 4-bit mode as we have to write code for reading two nibbles from the LCD. Instead we simply put a certain ammount of delay usually 300 to 600uS. This delay might vary depending on the LCD you are using, as you might have a different crystal frequency on which LCD controller is running. So it actually depends on the LCD module you are using. So if you feel any problem running the LCD, simply try to increase the delay. This usually works. For me about 400uS works perfect.

►LCD connections in 4-bit Mode

Page 35: stepper motor controller using 8051

Above is the connection diagram of LCD in 4-bit mode, where we only need 6 pins to interface an LCD. D4-D7 are the data pins connection and Enable and Register select are for LCD control pins. We are not using Read/Write (RW) Pin of the LCD, as we are only writing on the LCD so we have made it grounded permanently. If you want to use it.. then you may connect it on your controller but that will only increase another pin and does not make any big difference. Potentiometer RV1 is used to control the LCD contrast. The unwanted data pins of LCD i.e. 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. As i already explained in 4-bit mode data is sent nibble by nibble, first we send higher nibble and then lower nibble. This means in both command and data sending function we need to saperate the higher 4-bits and lower 4-bits.

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, In the next section we will take a look at the programming microcontroller to control LCD in 4-bit mode.

4-bit Initialization

Initialization of LCD is completed only after the reset sequence and basic initialization commands. We have alreadydiscussed about the reset sequence of the lcd in the previous section. So lets look at the programming now...

►Assembly Program

CODE:;In this whole 4-bit tutorial LCD is connected to;my controller in following way...;D4 - P3.0;D5 - P3.1;D6 - P3.2

Page 36: stepper motor controller using 8051

;D7 - P3.3;EN - P3.7;RS - P3.5

        lcd_port equ P3         ;LCD connected to Port3        en equ P3.7             ;Enable connected to P3.7        rs equ P3.5             ;Register select to P3.5       lcd_reset:                  ;LCD reset sequence        mov lcd_port, #0FFH        mov delay,#20           ;20mS delay        acall delayms        mov lcd_port, #83H      ;Data = 30H, EN = 1, First Init        mov lcd_port, #03H      ;Data = 30H, EN = 0        mov delay,#15           ;Delay 15mS        acall delayms        mov lcd_port, #83H      ;Second Init, Data = 30H, EN = 1        mov lcd_port, #03H      ;Data = 30H, EN = 0        mov delay,#5            ;Delay 5mS        acall delayms        mov lcd_port, #83H      ;Third Init        mov lcd_port, #03H        mov delay,#5            ;Delay 5mS        acall delayms        mov lcd_port, #82H      ;Select Data width (20H for 4bit)        mov lcd_port, #02H      ;Data = 20H, EN = 0        mov delay,#5            ;Delay 5mS        acall delayms        ret

lcd_init:        acall lcd_reset         ;Call LCD Reset sequence        mov a,#28H              ;4-bit, 2 line, 5x7 dots        acall lcd_cmd           ;Call LCD command        mov a,#0CH              ;Display ON cursor OFF        acall lcd_cmd           ;Call LCD command        mov a,#06H              ;Set entry mode (Auto increment)        acall lcd_cmd           ;Call LCD command        mov a,#80H              ;Bring cursor to line 1        acall lcd_cmd           ;Call LCD command        ret

Sending command/Data to LCD in 4-bit mode

►Assembly Program

CODE:lcd_cmd:                  ;LCD command Routine        mov temp,a            ;Save a copy of command to temp        swap a                ;Swap to use higher nibble        anl a,#0FH            ;Mask the first four bits        add a,#80H            ;Enable = 1, RS = 0        mov lcd_port,a        ;Move it to lcd port        anl a,#0FH            ;Enable = 0, RS = 0

Page 37: stepper motor controller using 8051

        mov lcd_port,a        ;Move to lcd port

        mov a,temp            ;Reload the command from temp        anl a,#0FH            ;Mask first four bits        add a,#80H            ;Enable = 1        mov lcd_port,a        ;Move to port        anl a,#0FH            ;Enable = 0        mov lcd_port,a        ;Move to lcd port

        mov delay,#1          ;delay 1 ms        acall delayms        ret

lcd_dat:                  ;LCD data Routine        mov temp,a            ;Keep copy of data in temp        swap a                ;We need higher nibble        anl a,#0FH            ;Mask first four bits        add a,#0A0H           ;Enable = 1, RS = 1        mov lcd_port,a        ;Move to lcd port        nop        clr en                ;Enable = 0

        mov a,temp            ;Reload the data from temp        anl a,#0FH            ;we need lower nibble now        add a,#0A0H           ;Enable = 1, RS = 1        mov lcd_port,a        ;Move to lcd port        nop        clr en                ;Enable = 0

        mov delay,#1          ;Delay 1mS        acall delayms        ret