Senin, 15 Oktober 2012

Beranda » Proteus Microcontroller Tutorial on LCD display

Proteus Microcontroller Tutorial on LCD display

This tutorial is about the programming of PIC16F84A microcontroller and LCD driven by Hitachi HD44780 LCD controller for real time simulation to display character onto the display.

The way this whole works is that an assembly program is written and then burned into the PIC microcontroller and the program directs and control the smaller LCD hardware controller HD44780. That is HD44780 is in itself a primitive machine that has its own instruction set, memory, timing and display control circuit. In order to correctly control the LCD display it is necessary to have knowledge about the functions it supports, the initialization it requires such as font size, duty cycle, 8 or 4 pin interface width, diplay on/off, cursor on/off, character shift etc, ports and pins, the size and types of memory and working of the LCD controller.

The program starts by defining constants and variables required for routines and allocating memory space for text data to be displayed. The ports type(whether inputs or outputs) of the PIC microcontroller are defined. The next step is the initialization of the LCD, that is setting up the font size, the 8 or 4 interface width, display, cursor and shift of character. Then the last step is the generation of text and transfer of text to buffer in PIC microcontroller and then finally the transfer from buffer to the DDRAM of the LCD controller which is then displayed. This transfer and display requires sending commands to the controller.

The schematic diagram that shows the interfacing between the microcontroller and the LCD controller is shown below-

Proteus Microcontroller Tutorial on LCD display

The part that has been used here are-
  •  9C08052A1002FKHFT
  • BUTTON
  • CRYSTAL
  • ERA-3YEB101V
  • LM016L
  • PIC16F84A
 The source code is provided below. To use this source code, simply double click on the microcontroller and select edit firmware option. Then copy paste the below source code. Compile it by clicking on the build icon as shown in figure and you should see compiled successfully(perhaps with minor warning which can just be ignored).

Proteus Microcontroller Tutorial on LCD display

 To run the simulation, go back to the schematic and click on the Run icon.

Proteus Microcontroller Tutorial on LCD display
Source Code:; Processor: 16F84A
;
; Description:
; Program to exercises 8-bit PIC-to-LCD interface.
; Code assumes that LCD is driven by Hitachi HD44780
; controller and that the display supports two lines
; each one with 16 characters. The wiring and base
; address of each display line is stored in #define
; statements. These statements can be edited to
; accomodate a different set-up.
; Program uses delay loops for interface timing.
; WARNING:
; Code assumes 4Mhz clock. Delay routines must be
; edited for faster clock

; Displays: Minnesota State, Mankato
;
;===========================
;        switches
;===========================
; Switches used in __config directive:
;   _CP_ON          Code protection ON/OFF    
; * _CP_OFF     
; * _PWRTE_ON     Power-up timer ON/OFF
;   _PWRTE_OFF    
;   _WDT_ON       Watchdog timer ON/OFF 
; * _WDT_OFF      
;   _LP_OSC       Low power crystal occilator
; * _XT_OSC       External parallel resonator/crystal ocillator 
;   _HS_OSC       High speed crystal resonator (8 to 10 MHz)
;                 Resonator: Murate Erie CSA8.00MG = 8 MHz  
;   _RC_OSC       Resistor/capacitor ocillator (simplest, 20% error)
; |
; |_____ * indicates setup values

;=========================
; setup and configuration
;=========================
    processor 16f84A
    include      <p16f84A.inc>
    __config  _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

;=====================================================
;                 constant definitions
;  for PIC-to-LCD pin wiring and LCD line addresses
;=====================================================
#define E_line 1       ;|
#define RS_line 2    ;| -- from wiring diagram
#define RW_line 3    ;|
; LCD line addresses (from LCD data sheet)
#define LCD_1 0x80    ; First LCD line constant
#define LCD_2 0xc0    ; Second LCD line constant
; Note: The constant that define the LCD display line
;       addresses have the high-order bit set in
;       order to faciliate the controller command
;
;=====================================================
;              variables in PIC RAM
;=====================================================
; Reserve 16 bytes for string buffer
    cblock    0x0c
    strData
    endc
; Leave 16 bytes and Continue with local variables
    cblock    0x1d        ; Start of block
    count1        ; Counter # 1
    count2        ; Counter # 2
    count3        ; Counter # 3
    pic_ad        ; Storage for start of text area
                ; (labeled strData) in PIC RAM
    J            ; counter J
    K            ; counter K
    index        ; Index into text table (also used
                ; for auxiliary storage)
    endc

;============================================================
;                           program
;============================================================
        org        0      ; start at address
        goto    main
; Space for interrupt handlers
    org        0x08

main:
    movlw    b'00000000' ; All lines to output
    tris    PORTA        ; in port A
    tris    PORTB        ; and port B
    movlw    b'00000000' ; All outputs ports low
    movwf    PORTA
    movwf    PORTB
; Wait and initialize HD44780
    call    delay_5ms        ; Allow LCD time to initialize itself
    call    initLCD        ; Then do forced initialization
    call    delay_5ms        ; (Wait probably not necessary)
; Store base address of text buffer in PIC RAM
    movlw    0x0c        ; Start address of text buffer
    movwf    pic_ad        ; to local variable
;======================
;   first LCD line
;======================
; Store 16 blanks in PIC RAM, starting at address stored
; in variable pic_ad
    call    blank16
; Call procedure to store ASCII characters for message
; in text buffer
    movlw    d'3'        ; Offset into buffer
    call    storeMN
; Set DDRAM address to start of first line
    call     line1
; Call procedure to display 16 characters in LCD
    call    display16
;========================
;   second LCD line
;========================
    call    delay_125mcs    ; Wait for termination
    call    blank16        ; Blank buffer
; Call procedure to store ASCII characters for message
; in text buffer
    movlw    d'1'        ; Offset into buffer
    call    storeUniv
    call    line2        ; DDRAM address of LCD line 2
    call    display16
;=======================
;       done!
;=======================
loopHere:
    goto    loopHere  ;done

;************************************************************
;                  INITIALIZE LCD PROCEDURE
;************************************************************
initLCD
; Initialization for Densitron LCD module as follows:
;    8-bit interface
;   2 display lines of 16 characters each
;   cursor on
;   left-to-right increment
;   cursor shift right
;   no display shift
;***********************|
;     COMMAND MODE      |
;***********************|
    bcf        PORTA,E_line    ; E line low
    bcf        PORTA,RS_line    ; RS line low for command
    bcf        PORTA,RW_line   ; Write mode
    call    delay_125mcs        ;delay 125 microseconds
;***********************|
;     FUNCTION SET      |
;***********************|
    movlw    0x38    ; 0 0 1 1 1 0 0 0 (FUNCTION SET)
                    ;     | | | |__ font select:
                    ;     | | |    1 = 5x10 in 1/8 or 1/11 dc
                    ;     | | |    0 = 1/16 dc
                    ;     | | |___ Duty cycle select
                    ;     | |      0 = 1/8 or 1/11
                    ;     | |      1 = 1/16 (multiple lines)
                    ;     | |___ Interface width
                    ;     |      0 = 4 bits
                    ;     |      1 = 8 bits
                    ;     |___ FUNCTION SET COMMAND
    movwf    PORTB    ;0011 1000
    call    pulseE    ;pulseE and delay

;***********************|
;    DISPLAY OFF        |
;***********************|
    movlw    0x08    ; 0 0 0 0 1 0 0 0 (DISPLAY ON/OFF)
                    ;         | | | |___ Blink character at cursor
                    ;         | | |      1 = on, 0 = off
                    ;         | | |___ Curson on/off
                    ;         | |      1 = on, 0 = off
                    ;         | |____ Display on/off
                    ;         |       1 = on, 0 = off
                    ;         |____ COMMAND BIT

    movwf    PORTB
    call    pulseE    ;pulseE and delay

;***********************|
; DISPLAY AND CURSOR ON |
;***********************|
    movlw    0x0e    ; 0 0 0 0 1 1 1 0 (DISPLAY ON/OFF)
                    ;         | | | |___ Blink character at cursor
                    ;         | | |      1 = on, 0 = off
                    ;         | | |___ Curson on/off
                    ;         | |      1 = on, 0 = off
                    ;         | |____ Display on/off
                    ;         |       1 = on, 0 = off
                    ;         |____ COMMAND BIT
    movwf    PORTB
    call    pulseE    ;pulseE and delay

;***********************|
;    ENTRY MODE SET     |
;***********************|
    movlw    0x06    ; 0 0 0 0 0 1 1 0 (ENTRY MODE SET)
                    ;           | | |___ display shift
                    ;           | |      1 = shift
                    ;           | |      0 = no shift
                    ;           | |____ cursor increment mode
                    ;           |       1 = left-to-right
                    ;           |       0 = right-to-left
                    ;           |___ COMMAND BIT
    movwf    PORTB    ;00000110
    call    pulseE

;***********************|
; CURSOR/DISPLAY SHIFT  |
;***********************|
    movlw    0x14    ; 0 0 0 1 0 1 0 0 (CURSOR/DISPLAY SHIFT)
                       ;       | | | |_|___ don't care
                    ;       | |_|__ cursor/display shift
                    ;       |       00 = cursor shift left
                    ;       |       01 = cursor shift right
                    ;       |       10 = cursor and display
                    ;       |            shifted left
                    ;       |       11 = cursor and display
                    ;       |            shifted right
                    ;       |___ COMMAND BIT
    movwf    PORTB    ;0001 1111
    call    pulseE

;***********************|
;   CLEAR DISPLAY       |
;***********************|
    movlw    0x01    ; 0 0 0 0 0 0 0 1 (CLEAR DISPLAY)
                    ;               |___ COMMAND BIT
    movwf    PORTB    ;0000 0001
;
    call    pulseE
    call    delay_5ms    ;delay 5 milliseconds after init
    return
;************************************************************
;               DELAY AND PULSE PROCEDURES
;************************************************************
;=======================
;  Procedure to delay
;   42 microseconds
;=======================
delay_125mcs
    movlw    D'42'            ; Repeat 42 machine cycles
    movwf    count1            ; Store value in counter
repeat
    decfsz    count1,f           ; Decrement counter
    goto    repeat            ; Continue if not 0
    return                    ; End of delay   
;------------------------------------------------------------
;=======================
;  Procedure to delay
;   5 milliseconds
;=======================
delay_5ms
    movlw    D'41'            ; Counter = 41
    movwf    count2            ; Store in variable
delay
    call    delay_125mcs        ; Delay
    decfsz    count2,f        ; 40 times = 5 milliseconds
    goto    delay
    return                ; End of delay
;========================
;     pulse E line
;========================
pulseE
    bsf        PORTA,E_line    ;pulse E line
    bcf        PORTA,E_line
    call    delay_125mcs        ;delay 125 microseconds
    return

;=============================
;   long delay sub-routine
;     (for debugging)
;=============================
long_delay
        movlw    D'200'    ; w = 200 decimal
        movwf    J        ; J = w
jloop:    movwf    K        ; K = w
kloop:    decfsz    K,f        ; K = K-1, skip next if zero
        goto     kloop
        decfsz    J,f        ; J = J-1, skip next if zero
        goto    jloop
        return
;=============================
;   LCD display procedure
;=============================
; Sends 16 characters from PIC buffer with address stored
; in variable pic_ad to LCD line previously selected
display16:
; Set up for data
    bcf        PORTA,E_line    ; E line low
    bsf        PORTA,RS_line    ; RS line low for control
    call    delay_125mcs        ; Delay
; Set up counter for 16 characters
    movlw    D'16'            ; Counter = 16
    movwf    count3   
; Get display address from local variable pic_ad
    movf    pic_ad,w        ; First display RAM address to W
    movwf    FSR                ; W to FSR
getchar:
    movf    INDF,w            ; get character from display RAM
                            ; location pointed to by file select
                            ; register
    movwf    PORTB
    call    pulseE    ;send data to display   
; Test for 16 characters displayed
    decfsz    count3,f          ; Decrement counter
    goto    nextchar        ; Skipped if done
    return
nextchar:
    incf    FSR,f            ; Bump pointer
    goto    getchar
;========================
;     blank buffer
;========================
; Procedure to store 16 blank characters in PIC RAM
; buffer starting at address stored in the variable
; pic_ad
blank16:
    movlw    D'16'        ; Setup counter
    movwf    count1
    movf    pic_ad,w    ; First PIC RAM address
    movwf    FSR            ; Indexed addressing
    movlw    0x20        ; ASCII space character
storeit:
    movwf    INDF        ; Store blank character in PIC RAM
                        ; buffer using FSR register
    decfsz    count1,f      ; Done?
    goto    incfsr        ; no
    return                ; yes
incfsr:
    incf    FSR,f        ; Bump FSR to next buffer space
    goto    storeit

;========================
; Set address register
;    to LCD line 1
;========================
; ON ENTRY:
;         Address of LCD line 1 in constant LCD_1
line1:
    bcf        PORTA,E_line     ; E line low
    bcf        PORTA,RS_line    ; RS line low, set up for control
    call    delay_125mcs        ; delay 125 microseconds
; Set to second display line
    movlw    LCD_1            ; Address and command bit
    movwf    PORTB
    call    pulseE            ; Pulse and delay
; Set RS line for data
    bsf        PORTA,RS_line    ; Setup for data
    call    delay_125mcs        ; Delay
    return
;========================
; Set address register
;    to LCD line 2
;========================
; ON ENTRY:
;         Address of LCD line 2 in constant LCD_2
line2:
    bcf        PORTA,E_line    ; E line low
    bcf        PORTA,RS_line    ; RS line low, setup for control
    call    delay_125mcs        ; delay
; Set to second display line
    movlw    LCD_2            ; Address with high-bit set
    movwf    PORTB
    call    pulseE            ; Pulse and delay
; Set RS line for data
    bsf        PORTA,RS_line    ; RS = 1 for data
    call    delay_125mcs        ; delay
    return

;===============================
;  first text string procedure
;===============================
storeMN:
; Procedure to store in PIC RAM buffer the message
; contained in the code area labeled msg1
; ON ENTRY:
;         variable pic_ad holds address of text buffer
;         in PIC RAM
;         w register hold offset into storage area
;         msg1 is routine that returns the string characters
;         an a zero terminator
;         index is local variable that hold offset into
;         text table. This variable is also used for
;         temporary storage of offset into buffer
; ON EXIT:
;         Text message stored in buffer
;
; Store offset into text buffer (passed in the w register)
; in temporary variable
    movwf    index        ; Store w in index
; Store base address of text buffer in FSR
    movf    pic_ad,w    ; first display RAM address to W
    addwf    index,w        ; Add offset to address
    movwf    FSR            ; W to FSR
; Initialize index for text string access
    movlw    0            ; Start at 0
    movwf    index        ; Store index in variable
; w still = 0
get_msg_char:
    call    msg1        ; Get character from table
; Test for zero terminator
    andlw    0x0ff
    btfsc    STATUS,Z    ; Test zero flag
    goto    endstr1        ; End of string
; ASSERT: valid string character in w
;         store character in text buffer (by FSR)
    movwf    INDF        ; store in buffer by FSR
    incf    FSR,f        ; increment buffer pointer
; Restore table character counter from variable
    movf    index,w        ; Get value into w
    addlw    1            ; Bump to next character
    movwf    index        ; Store table index in variable
    goto    get_msg_char    ; Continue   
endstr1:
    return

; Routine for returning message stored in program area
msg1:
    addwf    PCL,f        ; Access table
    retlw    'M'
    retlw    'i'
    retlw    'n'
    retlw    'n'
    retlw    'e'
    retlw    's'
    retlw    'o'
    retlw    't'
    retlw    'a'
    retlw    0

;=================================
;   second text string procedure
;=================================
storeUniv:
; Processing identical to procedure StoreMSU
    movwf    index        ; Store w in index
; Store base address of text buffer in FSR
    movf    pic_ad,0    ; first display RAM address to W
    addwf    index,0        ; Add offset to address
    movwf    FSR            ; W to FSR
; Initialize index for text string access
    movlw    0            ; Start at 0
    movwf    index        ; Store index in variable
; w still = 0
get_msg_char2:
    call    msg2        ; Get character from table
; Test for zero terminator
    andlw    0x0ff
    btfsc    STATUS,Z    ; Test zero flag
    goto    endstr2        ; End of string
; ASSERT: valid string character in w
;         store character in text buffer (by FSR)
    movwf    INDF        ; Store in buffer by FSR
    incf    FSR,f        ; Increment buffer pointer
; Restore table character counter from variable
    movf    index,w        ; Get value into w
    addlw    1            ; Bump to next character
    movwf    index        ; Store table index in variable
    goto    get_msg_char2    ; Continue   
endstr2:
    return

; Routine for returning message stored in program area
msg2:
    addwf    PCL,f        ; Access table
    retlw    'S'
    retlw    't'
    retlw    'a'
    retlw    't'
    retlw    'e'
    retlw    ','
    retlw    0x20
    retlw    'M'
    retlw    'a'
    retlw    'n'
    retlw    'k'
    retlw    'a'
    retlw    't'
    retlw    'o'
    retlw    0

    end






Tidak ada komentar:

Posting Komentar

Diberdayakan oleh Blogger.