#include ;#include "banks.inc" ; This header file defines configurations, registers, and other useful ; bits of information for the PIC18F4550 microcontroller. These names ; are taken to match the data sheets as closely as possible. CONFIG WDT = OFF; Disable watchdog timer CONFIG MCLRE = ON; MCLEAR Pin on CONFIG DEBUG = OFF; disable Debug Mode CONFIG LVP = OFF; Low-Voltage programming disabled CONFIG FOSC = HSPLL_HS; HS oscillator, PLL enabled, HS used by USB CONFIG PBADEN = OFF; PORTB<4:0> pins are configured as digital I/O on Reset CONFIG VREGEN = ON ; USB voltage regulator enabled CONFIG PLLDIV = 5 ; PLL prescaler Divide by 5 (20 MHz oscillator input) CONFIG USBDIV = 2 ; USB clock source comes from the 96 MHz PLL divided by 2 CONFIG CP0 = ON ; Code Protect CONFIG CP1 = ON CONFIG CP2 = ON CONFIG CPB = ON ; Boot Sect Code Protect CONFIG CPD = OFF ; EEPROM Data Protect CONFIG WRT0 = OFF ; Table Write Protect CONFIG WRT1 = OFF CONFIG WRT2 = OFF CONFIG WRTB = ON ; Boot Table Write Protest ;--------------------test1b.ASM------------------------ ; robot test - checks function of forward movement ;for the pic18f4550 20Mhz -> 4Mhz -> 100Mhz processor ;------------------------------------------------------ ; Edwin Armstrong AKA (efa) ;------------------------------------------------------ ; 03/10/09 Modified code to work with pic 18F4550 procesor (efa) ; 01/24/10 Added test code for LCD (efa) ;------------------------------------------------------ list p=18f4550 ;------------------------------------------------------- ; setup equates for ram memory -- Pic16f648: 0x20 to 0x7F (in bank 0), 0xA0 to 0xEF (in bank 1), ; 0x120 to 0x16F (in bank 2). 256 total ram count equ 0x20 ocount equ 0x21 ncount equ 0x22 ncount1 equ 0x23 ncount2 equ 0x24 ncount3 equ 0x25 seconds equ 0x26 tenths equ 0x27 sens equ 0x28 ;sensor status flag rt_sens, etc. LCD_tmp1 equ 0x29 ;---------------------------- LCD defines -------------------------------- ; see post includes for LCD control, at bottom of program... ; LCD and port defines #DEFINE LCD_D4 PORTA, 0 #DEFINE LCD_D5 PORTA, 1 #DEFINE LCD_D6 PORTA, 2 #DEFINE LCD_D7 PORTA, 3 #DEFINE LCD_RS PORTA, 4 ; Register Select, 0 = Command, 1 = Data #DEFINE LCD_E PORTA, 5 ; enable, strobe from 1 to 0 to send data ;--------------------- special registers and flags ------------------ porta equ PORTA portb equ PORTB portc equ PORTC portd equ PORTD w equ 0 f equ 1 FSR equ 04h EStrobe MACRO ; Strobe the "E" Bit BSF LCD_E call wait_ms ; wait 1 ms BCF LCD_E call wait_ms ; wait 1 ms ENDM ;-------------------------------------------------------------------------- ; org 0x800 ;reset starting address 00 goto begin org 0x804 ; define the interrupt, starts at 0x804 goto begin ; not currently used, just goto begin ;=================================================================== begin ; Initialize and setup processor to do work ; movlw 0x0F ; turn off A to D off for port A, all pin are digital movwf ADCON1 movlw 0x00 ; load w with 0000 0000 - controls input/output MOVWF TRISA ; movlw 0x00 ; load w with 0000 0000 - controls input/output MOVWF TRISD ; ; movlw 0x32 ; load w with 0011 0010 MOVWF TRISC ; ; bcf INTCON, GIE ;disable interrupts MOVLW 0x07 ; turn comparators off and MOVWF CMCON ; enable pins for I/O functions ;**************** Clear Variables ********************* clrf sens ; clear sensors status flags ;-------------------------- Do an LCD test -------------------------------- CALL LCD_init ; Init the LCD loop1 MOVLW 'I' CALL LCD_wrtData MOVLW ' ' CALL LCD_wrtData MOVLW 'a' CALL LCD_wrtData MOVLW 'm' CALL LCD_wrtData MOVLW ' ' CALL LCD_wrtData MOVLW 'A' CALL LCD_wrtData MOVLW 'l' CALL LCD_wrtData MOVLW 'i' CALL LCD_wrtData MOVLW 'v' CALL LCD_wrtData MOVLW 'e' CALL LCD_wrtData MOVLW ' ' CALL LCD_wrtData MOVLW ':' CALL LCD_wrtData MOVLW '-' CALL LCD_wrtData MOVLW ')' CALL LCD_wrtData sleep ; no loop, just put the cpu to sleep ;------------------------------------------------------- ; LCD_init:: Initialize LCD, set it to 4bit mode ; 02/06/10 (efa) ;------------------------------------------------------- LCD_init: bcf LCD_RS ; Enter command mode, Register Select, 0 = Command, 1 = Data movlw 0x30 ; force to 8 bit mode, send upper nibble call LCD_wrtCMD_nibble call wait_ms; movlw 0x30 ; force to 8 bit mode, send upper nibble call LCD_wrtCMD_nibble call wait_ms; movlw 0x30 ; force to 8 bit mode, send upper nibble call LCD_wrtCMD_nibble call wait_ms; movlw 0x20 ; force to 4 bit mode, send upper nibble call LCD_wrtCMD_nibble call pause; ; wait 10 ms ; **** Now that we are in 4bit mode, send data a nibble at a time **** MOVLW 0x28 ; set to 4 bit, 2 line, 5x7 display call LCD_wrtCMD MOVLW 0x08 ; Don't shift display, hide cursor CALL LCD_wrtCMD MOVLW 0x01 ; clear and home cursor CALL LCD_wrtCMD MOVLW 0x06 ; set sursor movement to the right CALL LCD_wrtCMD ; MOVLW 0x80 ; move cursor to line 1, home on left ; CALL LCD_wrtCMD MOVLW 0x0F ; turn on display w/ blinking cursor CALL LCD_wrtCMD RETURN ;;============================================================ ; Send an instruction byte (command) to the LCD ;;============================================================ LCD_wrtCMD: BCF LCD_RS ; RS low = Command mode CALL LCDsendByte ; Send the instruction byte RETURN ;;============================================================ ; Send a character to the LCD ;;============================================================ LCD_wrtData: BSF LCD_RS ; RS high = character data CALL LCDsendByte ; Send the character RETURN ;;============================================================ ; Send an instruction byte (command) to the LCD ;;============================================================ LCD_wrtCMD_nibble: BCF LCD_RS ; RS low = Command mode movwf LCD_tmp1 ;;***************** do the upper nibble ****************** BCF LCD_D7 ; Clear data bits BCF LCD_D6 BCF LCD_D5 BCF LCD_D4 BTFSC LCD_tmp1, 7 ; Load high nibble BSF LCD_D7 BTFSC LCD_tmp1, 6 BSF LCD_D6 BTFSC LCD_tmp1, 5 BSF LCD_D5 BTFSC LCD_tmp1, 4 BSF LCD_D4 EStrobe ; strobe the E bit to send data call wait_ms ; Short delay for instruction to settle RETURN ;;============================================================ ; LCDsendByte:: Send a byte to the LCD, assumes RS already set ;;============================================================ LCDsendByte: MOVWF LCD_tmp1 ; Store byte in LCD_tmp1 ;;***************** do the upper nibble ****************** BCF LCD_D7 ; Clear data bits BCF LCD_D6 BCF LCD_D5 BCF LCD_D4 BTFSC LCD_tmp1, 7 ; Load high nibble BSF LCD_D7 BTFSC LCD_tmp1, 6 BSF LCD_D6 BTFSC LCD_tmp1, 5 BSF LCD_D5 BTFSC LCD_tmp1, 4 BSF LCD_D4 EStrobe ; strobe the E bit to send data ;;***************** do the lower nibble ****************** BCF LCD_D7 ; Clear data bits BCF LCD_D6 BCF LCD_D5 BCF LCD_D4 BTFSC LCD_tmp1, 3 ; Load low nibble BSF LCD_D7 BTFSC LCD_tmp1, 2 BSF LCD_D6 BTFSC LCD_tmp1, 1 BSF LCD_D5 BTFSC LCD_tmp1, 0 BSF LCD_D4 EStrobe ; strobe the E bit to send data RETURN ;;=========================================================== ;------------------------------------------------------- ; wait:: subroutine to "wait" for up to 255 seconds. ; Wait routine uses "pause" and variable "seconds" ; 01/31/10 (efa) - calibrated (+/- .1%) ;------------------------------------------------------- wait movwf seconds ; wait for 1-255 seconds incf seconds,f ; start 1 second back... s_loop movlw 0x0a ;max value inner counter movwf ncount1 ;load value inner counter decfsz seconds,f ; --ncount goto start ; pause for a time return ; subroutine return start movlw 0x01 ; load 1/10 seconds to wait in w movwf tenths ; load w value to seconds call wait_10 ; pause for .1 seconds decfsz ncount1,f ; --ncount1 goto start ; inner1 loop goto s_loop ; go back to s_loop ;------------------------------------------------------- ; wait_10:: subroutine to "wait" for up to 255 (1/10) seconds. ; Wait routine uses "pause" and variable "seconds" ; 01/31/10 (efa) - calibrated ;------------------------------------------------------- wait_10 movwf tenths ; wait for 1-255 (1/10) seconds incf tenths,f ; start 1 second back... s_loop1 movlw 0x0a ;max value inner counter movwf ncount2 ;load value inner counter decfsz tenths,f ; --ncount goto start1 ; pause for a time return ; subroutine return start1 call pause ; pause for .01 seconds decfsz ncount2,f ; --ncount1 goto start1 ; inner1 loop goto s_loop1 ; go back to s_loop ;------------------------------------------------------- ; pause:: subroutine to pause for 1/100 second ; To decrease pause decrease max value in outer loop ; 01/31/10 (efa) - calibrated ;------------------------------------------------------- pause movlw 0x0a ;max value outer counter (10) movwf ncount3 ;load value outer counter outer1 call wait_ms ; no operation, just a delay decfsz ncount3,f ; --ocount goto outer1 ; outer loop return ; subroutine return ;------------------------------------------------------- ; wait_ms:: subroutine to wait for 1/1000 second ; To decrease pause decrease max value in outer loop ; 1/30/10 (efa) calibrated ;------------------------------------------------------- wait_ms movlw 0x18 ;max value outer counter () movwf ocount ;load value outer counter outer movlw 0x7b ;max value inner counter movwf ncount ;load value inner counter inner nop ; no operation, just a delay decfsz ncount,f ; --ncount goto inner ; inner loop decfsz ocount,f ; --ocount goto outer ; outer loop return ; subroutine return ;------------------------------------------------------- ;------------------------------------------------------- ;; Final post-code includes ;; INCLUDE "lcd_4bit.inc" end