本篇是修改Microchip W201 Workshop教材(download)中的Lab 2,
主要是因為該篇的內容是以APP001 REV1的發展板做為平台,
然而APP001 REV2的電路的Laylout已經有一些變化,
因此我做了一些修改, 將教材中Lab 2的程式也能使用在APP001 REV2發展板上.
程式內容
該程式包含3個檔案: lab2.asm , lcd.asm , 16f877i.lkr
我們只需修改lcd.asm, 內容如下 :
;
list p=16f877
#include <p16f877.inc>
;
; Defines for I/O ports that provide LCD data & control
; PORTB.0 - PORTB.3 are Data Pins for LCD Module
; PORTB.4 is E Control Signal for LCD ---> APP001 REV2的E是由PORTA.2控制
; PORTB.5 is RS Control Signal for LCD ---> APP001 REV2的RS是由PORTD.4控制
; PORTC.2 is BackLight Control pin for LCD Module
;
global InitLCD
global putcLCD
global clrLCD
global L1homeLCD
global L2homeLCD
global SendCmd
global PutHexLCD
global Hex2ASCII
;
LCD_DATA equ PORTD (更改後的程式碼) ;;;LCD_DATA equ PORTB (更改前的程式碼)
LCD_CNTL equ PORTA (更改後的程式碼) ;;;LCD_CNTL equ PORTB (更改前的程式碼)
; Defines for I/O pins that provide LCD control
RS equ 4 (更改後的程式碼) ;;;RS equ 5 (更改前的程式碼)
RW equ 5 (更改後的程式碼) ;;;E equ 4 (更改前的程式碼)
E equ 2 (更改後的程式碼)
; LCD Module commands
DISP_ON EQU 0x00C ; Display on
DISP_ON_C EQU 0x00E ; Display on, Cursor on
DISP_ON_B EQU 0x00F ; Display on, Cursor on, Blink cursor
DISP_OFF EQU 0x008 ; Display off
CLR_DISP EQU 0x001 ; Clear the Display
ENTRY_INC EQU 0x006 ;
ENTRY_INC_S EQU 0x007 ;
ENTRY_DEC EQU 0x004 ;
ENTRY_DEC_S EQU 0x005 ;
DD_RAM_ADDR EQU 0x080 ; Least Significant 7-bit are for address
DD_RAM_UL EQU 0x080 ; Upper Left coner of the Display
;
; Directs linker to provide 4 variables in GPR memory
UDATA
Byte RES 1
Byte1 RES 1
Count RES 1
Count1 RES 1
W_BUFR RES 1
Hex_Bfr RES 1
;
PROG1 CODE
;*******************************************************************
;* The LCD Module Subroutines *
;* Command sequence for 2 lines of 5x16 characters *
;*******************************************************************
InitLCD
BANKSEL TRISD (更改後的程式碼) ;;;BANKSEL TRISB (更改前的程式碼)
movlw 0x00 (更改後的程式碼) ;;;movlw 0xc0 ; Initialize inputs/outputs for LCD (更改前的程式碼)
movwf TRISD (更改後的程式碼) ;;;movwf TRISB (更改前的程式碼)
movlw 0x85 (更改後的程式碼) ;;;
movwf ADCON1 (更改後的程式碼) ;;;RA0/RA1/RA3:Analog input, others: Digital I/O
movlw 0x0B (更改後的程式碼) ;;;
movwf TRISA (更改後的程式碼) ;;;
BANKSEL LCD_DATA
clrf LCD_DATA ; Clear LCD data & control bits
clrf LCD_CNTL (更改後的程式碼) ;;;
;
movlw .50 ; Power=On delay 50mS
Call Delay_MS
;
movlw 0x02 ; Init for 4-bit interface
call Send_4bit
movlw .10 ; Delay 10 mS
Call Delay_MS
;
movlw b'00000011' ; Fully Initial LCD module
call Send_4bit ; Sent '0011' data 4 time
movlw .5 ; Delay 5mS
Call Delay_MS
movlw b'00000011'
call Send_4bit
call Delay_1MS ; Delay 1mS
movlw b'00000011'
call Send_4bit
movlw b'00000010'
call Send_4bit
movlw b'00101000' ; Set 2 lines & 5 x 7 dots
call SendCmd
movlw DISP_ON ; Turn display on (0x0C)
call SendCmd
movlw ENTRY_INC ; Configure cursor movement
call SendCmd
movlw DD_RAM_ADDR ; Set writes for display memory
call SendCmd
return
;
;*******************************************************************
;*SendChar - Sends character to LCD *
;*This routine splits the character into the upper and lower *
;*nibbles and sends them to the LCD, upper nibble first. *
;*******************************************************************
putcLCD
banksel Byte
movwf Byte ; Save WREG in Byte variable
call Delay_1MS
swapf Byte,W ; Write upper nibble first
andlw 0x0f
movwf LCD_DATA
bsf LCD_DATA, RS (更改後的程式碼) ;;;bsf LCD_CNTL, RS ; Set for data (更改前的程式碼)
bcf LCD_DATA, RW (更改後的程式碼) ;;;
bsf LCD_CNTL, E ; Clock nibble into LCD
bcf LCD_CNTL, E
movf Byte,W ; Write lower nibble last
andlw 0x0f
movwf LCD_DATA
bsf LCD_DATA, RS (更改後的程式碼) ;;;bsf LCD_CNTL, RS ; Set for data (更改前的程式碼)
bcf LCD_DATA, RW (更改後的程式碼) ;;;
bsf LCD_CNTL, E ; Clock nibble into LCD
bcf LCD_CNTL, E
return
;
;*********************************************************************
;* To put the HEX value to LCD Display ,,
;* High nibble first than Low nibble
;* Input : W Reg.
;*********************************************************************
PutHexLCD
banksel W_BUFR
movwf W_BUFR ; Save W Register !!
swapf W_BUFR,W ; High nibble first !!
call Hex2ASCII
call putcLCD
;
movf W_BUFR,W
call Hex2ASCII
call putcLCD
return
;
;******************************************************************
;* Convert a low nibble to ASCII code
;* Input : W Reg.
;* Output: W Reg.
;******************************************************************
Hex2ASCII
andlw 0x0f ; Mask Bit 4 to 7
movwf Hex_Bfr
sublw .09
btfsc STATUS,C ; If W less than A (C=1) --> only add 30h
goto Add_W_30
Add_W_37 movlw 0x37
goto Hex_cont
Add_W_30 movlw 0x30
Hex_cont addwf Hex_Bfr,W ; The correct ASCII code for this char !!
return
;
;*******************************************************************
;* SendCmd - Sends command to LCD *
;* This routine splits the command into the upper and lower *
;* nibbles and sends them to the LCD, upper nibble first. *
;*******************************************************************
SendCmd
banksel Byte
movwf Byte ; Save WREG in Byte variable
call Delay_1MS
swapf Byte,W ; Send upper nibble first
andlw 0x0f
movwf LCD_DATA
bcf LCD_DATA,RS (更改後的程式碼) ;;;bcf LCD_CNTL,RS ; Clear for command (更改前的程式碼)
bcf LCD_DATA,RW (更改後的程式碼) ;;;
bsf LCD_CNTL,E ; Clock nibble into LCD
bcf LCD_CNTL,E
movf Byte,W ; Write lower nibble last
Send_4bit andlw 0x0f
movwf LCD_DATA
bcf LCD_DATA,RS (更改後的程式碼) ;;;bcf LCD_CNTL,RS ; Clear for command (更改前的程式碼)
bcf LCD_DATA,RW
bsf LCD_CNTL,E ; Clock nibble into LCD
bcf LCD_CNTL,E
return
;
;*******************************************************************
;* clrLCD - Clear the contents of the LCD *
;*******************************************************************
clrLCD
movlw CLR_DISP ; Send the command to clear display
call SendCmd
movlw .4 (更改後的程式碼) ;;; Delay 4mS
Call Delay_MS ;;;
return
;
;*******************************************************************
;* L1homeLCD - Moves the cursor to home position on Line 1 *
;*******************************************************************
L1homeLCD
movlw DD_RAM_ADDR|0x00 ; Send command to move cursor to
call SendCmd ; home position on line 1
return
;*******************************************************************
;* L2homeLCD - Moves the cursor to home position on Line 2 *
;*******************************************************************
L2homeLCD
movlw DD_RAM_ADDR|0x40 (更改後的程式碼) ;;;movlw DD_RAM_ADDR|0x28 ; Send command to move cursor to (更改前的程式碼)
call SendCmd ; home position on line 2
return
;*******************************************************************
;* Delay - Generic LCD delay (1.024mS @ 4MHz) *
;* Since the microcontroller can not read the busy flag of the *
;* LCD, a specific delay needs to be executed between writes to *
;* the LCD. *
;*******************************************************************
Delay_1MS ; 2 cycles for call
clrf Count ; 1 cycle to clear counter variable
Dloop
nop
decfsz Count,F ; These two instructions provide a
goto Dloop ; (256 * 3) -1 cycle count
return ; 2 cycles for return
;
;*******************************************************************
;* Delay - 1mS base delay *
;* input : W Reg. *
;* *
;*******************************************************************
Delay_MS
movwf Count1
;
DLop1 call Delay_1MS
decfsz Count1,F
goto DLop1
return
;
END