;************************************************** ; Pic by example ; LCDTERM.ASM ; ; (c) 2001, Sergio Tanzilli ; http://www.tanzilli.com ;************************************************** PROCESSOR 16F84 RADIX DEC INCLUDE "P16F84.INC" ;Suppress the following MPASM warning message [# 302]: ;"Register in operand not in bank 0. Ensure that bank bits are correct" ERRORLEVEL -302 ;Flag configuration __CONFIG 3FF1H ;RS232 lines TX equ 0 ;Tx data RX equ 1 ;Rx data ;LCD Control lines LCD_RS equ 2 ;Register Select LCD_E equ 3 ;Enable ;LCD data line bus LCD_DB4 equ 4 ;LCD data line DB4 LCD_DB5 equ 5 ;LCD data line DB5 LCD_DB6 equ 6 ;LCD data line DB6 LCD_DB7 equ 7 ;LCD data line DB7 ;********************************************************************** ; Clock frequency related constant (4 MHz) ;********************************************************************** BIT_DELAY equ 23 ;Bit delay a 9600 bps ;********************************************************************** ; MACRO - Delay subroutine with watch dog timer clearing ; ; Macro parameters: ; ; VALUE: Delay obtained = ((VALUE-1)*4+5)*(1/(Fosc/4)) ; ;********************************************************************** DELAY MACRO VALUE LOCAL REDO movlw VALUE movwf TmpRegister REDO clrwdt ;Clear watch dog timer decfsz TmpRegister,F goto REDO ENDM ;********************************************************************** ; FILE REGISTER ;********************************************************************** ORG 0CH ;Register used by LCD subroutines tmpLcdRegister res 2 ;Register used by msDelay subroutine and DELAY macro msDelayCounter res 2 TmpRegister res 1 ;Register used by RS232 subroutines ShiftReg res 1 ;Shift register BitCount res 1 ;Bit counter ;Cursor location xCurPos res 1 yCurPos res 1 putTempReg res 1 ;Reset Vector ;********************************************************************** ; RESET VECTOR ;********************************************************************** ORG 00H Start bsf STATUS,RP0 ;Swap to register bank 1 movlw 00011111B ;Sets the whole PORTA as input movwf TRISA movlw 11111111B ;Sets the whole PORTB as input movwf TRISB bcf PORTA,TX ;Sets TX line as output bcf PORTB,LCD_DB4 ;Sets LCD data and control lines as output bcf PORTB,LCD_DB5 bcf PORTB,LCD_DB6 bcf PORTB,LCD_DB7 bcf PORTB,LCD_E bcf PORTB,LCD_RS bcf STATUS,RP0 ;Swap to register bank 0 ;LCD inizialization call LcdInit ;Put terminal cursor on 0,0 position clrf xCurPos clrf yCurPos ;Wait until receives a start bit from RS232 line MainLoop btfsc PORTA,RX ;Received a start bit ? goto MainLoop ;No, wait. call RxChar ;Yes, read the byte on receiving... CheckFormFeed movlw 12 xorwf ShiftReg,W btfss STATUS,Z goto _CheckFormFeed clrf xCurPos clrf yCurPos call LcdClear goto MainLoop _CheckFormFeed movf ShiftReg,W call putchar goto MainLoop ;********************************************************************** ; Delay subroutine ; ; W = Requested delay time in ms (clock = 4MHz) ;********************************************************************** msDelay movwf msDelayCounter+1 clrf msDelayCounter+0 ; 1 ms (about) internal loop msDelayLoop nop decfsz msDelayCounter+0,F goto msDelayLoop nop decfsz msDelayCounter+1,F goto msDelayLoop return ;********************************************************************** ; Put a char to xCurPos, yCurPos position on LCD ; ; W = Char to show ; xCurPos = x position ; yCurPos = y position ; ; xCurPos and yCurPos will be increase automaticaly ;********************************************************************** putchar movwf putTempReg swapf yCurPos,W iorwf xCurPos,W call LcdLocate movf putTempReg,W call LcdSendData incf xCurPos,F movlw 16 xorwf xCurPos,W btfss STATUS,Z goto moveLcdCursor clrf xCurPos incf yCurPos,F movlw 2 xorwf yCurPos,W btfss STATUS,Z goto moveLcdCursor clrf yCurPos moveLcdCursor swapf yCurPos,W iorwf xCurPos,W call LcdLocate return ;********************************************************************** ; Init LCD ; This subroutine must be called before each other lcd subroutine ;********************************************************************** LcdInit movlw 30 ;Wait 30 ms call msDelay ;**************** ; Reset sequence ;**************** bcf PORTB,LCD_RS ;Set LCD command mode ;Send a reset sequence to LCD bsf PORTB,LCD_DB4 bsf PORTB,LCD_DB5 bcf PORTB,LCD_DB6 bcf PORTB,LCD_DB7 bsf PORTB,LCD_E ;Enables LCD movlw 5 ;Wait 5 ms call msDelay bcf PORTB,LCD_E ;Disables LCD movlw 1 ;Wait 1ms call msDelay bsf PORTB,LCD_E ;Enables LCD movlw 1 ;Wait 1ms call msDelay bcf PORTB,LCD_E ;Disables LCD movlw 1 ;Wait 1ms call msDelay bsf PORTB,LCD_E ;Enables E movlw 1 ;Wait 1ms call msDelay bcf PORTB,LCD_E ;Disables E movlw 1 ;Wait 1ms call msDelay bcf PORTB,LCD_DB4 bsf PORTB,LCD_DB5 bcf PORTB,LCD_DB6 bcf PORTB,LCD_DB7 bsf PORTB,LCD_E ;Enables LCD movlw 1 ;Wait 1ms call msDelay bcf PORTB,LCD_E ;Disabled LCD movlw 1 ;Wait 1ms call msDelay ;Set 4 bit data bus length movlw 28H; call LcdSendCommand ;Entry mode set, increment, no shift movlw 06H; call LcdSendCommand ;Display ON, Curson ON, Blink OFF movlw 0EH call LcdSendCommand ;Clear display call LcdClear return ;********************************************************************** ; Clear LCD ;********************************************************************** LcdClear ;Clear display movlw 01H call LcdSendCommand movlw 2 ;Wait 2 ms call msDelay ;DD RAM address set 1st digit movlw 80H; call LcdSendCommand return ;********************************************************************** ; Locate cursor on LCD ; W = D7-D4 row, D3-D0 col ;********************************************************************** LcdLocate movwf tmpLcdRegister+0 movlw 80H movwf tmpLcdRegister+1 movf tmpLcdRegister+0,W andlw 0FH iorwf tmpLcdRegister+1,F btfsc tmpLcdRegister+0,4 bsf tmpLcdRegister+1,6 movf tmpLcdRegister+1,W call LcdSendCommand return ;********************************************************************** ; Send a data to LCD ;********************************************************************** LcdSendData bsf PORTB,LCD_RS call LcdSendByte return ;********************************************************************** ; Send a command to LCD ;********************************************************************** LcdSendCommand bcf PORTB,LCD_RS call LcdSendByte return ;********************************************************************** ; Send a byte to LCD by 4 bit data bus ;********************************************************************** LcdSendByte ;Save value to send movwf tmpLcdRegister ;Send highter four bits bcf PORTB,LCD_DB4 bcf PORTB,LCD_DB5 bcf PORTB,LCD_DB6 bcf PORTB,LCD_DB7 btfsc tmpLcdRegister,4 bsf PORTB,LCD_DB4 btfsc tmpLcdRegister,5 bsf PORTB,LCD_DB5 btfsc tmpLcdRegister,6 bsf PORTB,LCD_DB6 btfsc tmpLcdRegister,7 bsf PORTB,LCD_DB7 bsf PORTB,LCD_E ;Enables LCD movlw 1 ;Wait 1ms call msDelay bcf PORTB,LCD_E ;Disabled LCD movlw 1 ;Wait 1ms call msDelay ;Send lower four bits bcf PORTB,LCD_DB4 bcf PORTB,LCD_DB5 bcf PORTB,LCD_DB6 bcf PORTB,LCD_DB7 btfsc tmpLcdRegister,0 bsf PORTB,LCD_DB4 btfsc tmpLcdRegister,1 bsf PORTB,LCD_DB5 btfsc tmpLcdRegister,2 bsf PORTB,LCD_DB6 btfsc tmpLcdRegister,3 bsf PORTB,LCD_DB7 bsf PORTB,LCD_E ;Enables LCD movlw 1 ;Wait 1ms call msDelay bcf PORTB,LCD_E ;Disabled LCD movlw 1 ;Wait 1ms call msDelay return ;************************************************************************** ; Send a character on RS232 ; (9600 baud,8 data bit, 1 stop bit, No parity) ; ; Input: W = Character to send ;************************************************************************** TxChar movwf ShiftReg movlw 8 ;Data lenght movwf BitCount bcf PORTA,TX ;Send start bit nop nop nop nop nop nop nop DELAY BIT_DELAY ;Tx loop TxLoop btfss ShiftReg,0 goto TxLo nop bsf PORTA,TX goto cTx TxLo bcf PORTA,TX goto cTx cTx nop rrf ShiftReg,F DELAY BIT_DELAY decfsz BitCount,F goto TxLoop nop nop nop nop bsf PORTA,TX ;Stop bit DELAY BIT_DELAY DELAY 2 nop bsf PORTA,TX DELAY BIT_DELAY DELAY 2 return ;************************************************************************** ; Receive a character from RS232 ; (9600 baud,8 data bit, 1 stop bit, No parity) ; ; Return code: ; ; ShiftReg: Received character ;************************************************************************** RxChar clrf ShiftReg movlw 8 ;Data lenght movwf BitCount DELAY BIT_DELAY+BIT_DELAY/2 ;Wait 1.5 bit ;Loop di lettura dei bit dati wDB btfss PORTA,RX goto RxBitL RxBitH nop bsf STATUS,C goto RxShift RxBitL bcf STATUS,C goto RxShift RxShift nop rrf ShiftReg,F DELAY BIT_DELAY decfsz BitCount,F goto wDB return END