Code to drive an LCD and a serial routine so that serial data can be displayed.
;************************************************************************** ; LC001.ASM ; ; PROGRAM: Simple LCD project ; ; DESCRIPTION: ; ; AUTHOR: Douglas Rice ; Copyright 2000 ; ; Crystal: 4MHz ; ; I/O used:- ; ; ; Port B is used for the LCD ; INCLUDE "p16F84.inc" ; ;************************************************************************** LIST P=16F84, R=DEC __idlocs 0x1234 __config _XT_OSC&_PWRTE_ON & _WDT_OFF ; NOEXPAND cblock 0x0c endc ;-------------------------------------------------------------------------- ; Sec 1. Equates and Constants ;-------------------------------------------------------------------------- ; The General Purpose Registers start at the end of the ; Special Purpose Registers. ; IPMentState values ; in normal running or in time setting modes ; ; DoTimeSlice bits ; these bits are set to schedule a timer chain event DTsS4event EQU 0 ; DTsSevent EQU 1 DTsMevent EQU 2 DTSTriggered EQU 3 ; a capture should take place DTsTurnOff EQU 4 DTsMeasFreq EQU 5 DTsDispFreq EQU 6 DTsDispCount EQU 7 ; IPtrigMenu DTSWaitForEdge EQU 0 ; if set, then wait for 0 to 1 edge on PA0 DTSSingle EQU 1 ; IPtrigMenu DTSFast EQU 0 ;-------------------------------------------------------------------------- ; Sec 1.1 Button and LED ;-------------------------------------------------------------------------- BUTTON_RS232 EQU 0 ; EDG - Bottom Buttom BUTTON_DOWN EQU 6 ; EDG - Bottom Buttom BUTTON_UP EQU 7 ; TRIG - Middle Button LCDnumSamples EQU 40 ; PORTA binary values ;-------------------------------------------------------------------------- ; Sec 1.2 Button and LED ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; Sec 2.0 Variables ;-------------------------------------------------------------------------- ; Variables start 0x0C ; ; Variables for FlashLED ( FL ) process ; ; DoTimeSlice Bits, to schedule, set bit cblock DoTimeSlice IPnew IPlast IPbuttonEvent IPnewFast IPlastFast IPbuttonEventUp IPtrigMenu LCDAnalSpeed LCDcnt3 LCDgetCharFlag LCDbase LCDbaseCnt CLtmr4sec RSloopCnt RSdata RSdell endc ; *********** I/O EQUATES ************** PORTA EQU 5 ; 5 BITS PA0 EQU 0 PA1 EQU 1 PA2 EQU 2 PA3 EQU 3 PA4 EQU 4 PORTB EQU 6 PB0 EQU 0 ; Serial In PB1 EQU 1 PB2 EQU 2 PB3 EQU 3 PB4 EQU 4 PB5 EQU 5 PB6 EQU 6 PB7 EQU 7 RS232tx EQU PA0 ; Serial Out RS232rx EQU PB0 ; Serial In buildLCD_HD44780 TEST_STRADDLE MACRO START if high( $ ) != high( START ) Error "Table straddles Page Boundary " + Start endif endm ;-------------------------------------------------------------------------- ; Sec 3. Program Code ;-------------------------------------------------------------------------- ORG 0 GOTO Start ORG 4 RETFIE GOTO Intrtn ;-------------------------------------------------------------------------- ; Sec 3.1 Main Program Init Code ;-------------------------------------------------------------------------- Start CALL LCDdelaylong CALL LCDdelaylong CALL LCDdelaylong ; Enable Interupts MOVLW H'00' MOVWF INTCON ; Set up PortB:7 as output. BSF STATUS, RP0 MOVLW 0XF0 MOVWF TRISB MOVLW 0xFF ; Make PORTA 3:0 INPUTS. MOVWF TRISA BCF STATUS, RP0 CLRF DoTimeSlice ; Change Prescaler CLRWDT ; Configure Tmr 0 BSF STATUS,RP0 ; Set up prescaller for 8192 / 16 = 512 ticks perseconds. MOVLW 0x0 + 2 ; For Tmr0 0=/2, 1=/4, 2=/8,3=/16 MOVWF OPTION_REG BCF STATUS,RP0 CALL LCDstart MOVLW LCDCurLeftLower CALL LCDwrtCmd CLRF LCDbase CLRF IPbuttonEvent CLRF IPbuttonEventUp GOTO MainLoop ;-------------------------------------------------------------------------- ; Sec 3.2 Main Program ;-------------------------------------------------------------------------- MainLoop ; Enable Interupts ; Disable Interupts MLdisableInt CALL CLtimeslice CALL IPtimesliceFast ; test for rising edge BTFSC IPbuttonEventUp,BUTTON_RS232 ; RS232 input start CALL IPrs232 ; test for button presses BTFSC IPbuttonEvent,BUTTON_UP ; On BUTTON_RATE Press CALL IPupPressed BTFSC IPbuttonEvent,BUTTON_DOWN ; On BUTTON_RATE Press CALL IPdownPressed GOTO MainLoop ;-------------------------------------------------------------------------- ; Sec 3.3 Jump Table for running or time setting mode ;-------------------------------------------------------------------------- LCDInit ; We run this from the toggle state and ; Prevent update of time display on second ticks. RETURN include "lcd4mhz.inc" ; the code below must be kept together. LCDgetByte ; we should have set up PCLATH ; and reset LCDgetCharFlag ; BCF LCDPortB,LCDgetCharFlag MOVLW high $ MOVWF PCLATH MOVFW LCDstrPtr; ; INCF LCDstrPtr,f ; ADDWF PCL,f MOVWF PCL LCDstrs LCDstrLFast ;equ $ - LCDstrs DT "del" GOTO LCDgetByteEnd2 ; now print out 4 blanks LCDstrLCont ;equ $ - LCDstrs DT "C " GOTO LCDgetByteEnd1 LCDstrLContEdge ;equ $ - LCDstrs DT "C_- " GOTO LCDgetByteEnd1 LCDstrLSingle ;equ $ - LCDstrs DT "S " GOTO LCDgetByteEnd1 LCDstrLSingleEdge ;equ $ - LCDstrs DT "S_- " GOTO LCDgetByteEnd1 LCDstrLFreq ;equ $ - LCDstrs DT "Freq" GOTO LCDgetByteEnd1 LCDstrLTime ;equ $ - LCDstrs DT "Time LCD001.asm" GOTO LCDgetByteEnd1 LCDLastStr TEST_STRADDLE LCDgetByte ; Jump into these to select how many spaces printed ; at the end, so that 9 chars are printed. LCDgetByteEnd0 DECF LCDeraseCnt,f LCDgetByteEnd1 DECF LCDeraseCnt,f LCDgetByteEnd2 DECF LCDeraseCnt,f LCDgetByteEnd3 DECF LCDeraseCnt,f LCDgetByteEnd4 DECF LCDeraseCnt,f LCDgetByteEnd5 DECF LCDeraseCnt,f LCDgetByteEnd6 BSF LCDPortB,LCDgetCharFlag CLRF LCDstrPtr DECFSZ LCDstrPtr,f NOP RETURN ;-------------------------------------------------------------------------- ; Sec 4. Subroutines, procedures and functions ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; Sec 4.1 Button Poll Routine ;-------------------------------------------------------------------------- IPtimeslice ; --_____ button press ; ----___ ; __----- /IPnew ; ----___ IPlast ; __--___ ; ; ; ; This reads all Port B inputs and looks for Press MOVFW IPnew MOVWF IPlast MOVFW PORTB MOVWF IPnew ; IP last contains new setting, IPlast contains previous ; look for falling edges COMF IPnew,W ANDWF IPlast,W ; now force IPbuttonEvent bits to high for new pressed button ; the service routine should reset the bit to clear the event. IORWF IPbuttonEvent,F RETURN IPtimesliceFast ; Look for rising edges MOVFW IPnewFast MOVWF IPlastFast MOVFW PORTB MOVWF IPnewFast COMF IPlastFast,W ANDWF IPnewFast,W IORWF IPbuttonEventUp,F RETURN ;-------------------------------------------------------------------------- ; Sec 4.2 ;-------------------------------------------------------------------------- IPupPressed BCF IPbuttonEvent,BUTTON_UP MOVLW LCDCurLeftLower CALL LCDwrtCmd MOVLW 0x10 MOVWF LCDbaseCnt IPupPressed1 MOVFW LCDbase CALL LCDwrtChar INCF LCDbase,f DECFSZ LCDbaseCnt GOTO IPupPressed1 MOVLW LCDCurLeftLower CALL LCDwrtCmd return IPdownPressed BCF IPbuttonEvent,BUTTON_DOWN MOVLW LCDCurLeftLower CALL LCDwrtCmd MOVLW 0x10 MOVWF LCDbaseCnt IPdownPressed1 MOVFW LCDbase CALL LCDwrtChar DECF LCDbase,f DECFSZ LCDbaseCnt GOTO IPdownPressed1 MOVLW LCDCurLeftLower CALL LCDwrtCmd return IPrs232 BCF IPbuttonEventUp,BUTTON_RS232 GOTO RS232in ;-------------------------------------------------------------------------- ; Sec 4.3 Clock Chain Routine ;-------------------------------------------------------------------------- CLtimeslice ; BTFSS INTCON,T0IF RETURN ; TMR0 timeout BCF INTCON,T0IF BSF DoTimeSlice,DTsS4event CALL IPtimeslice RETURN ;-------------------------------------------------------------------------- ; Sec 4.6 Event Handler Routine - Buttons ;-------------------------------------------------------------------------- ; come here and combine the current state and the current event to index into ; the state jump table. ; IPtrigMenuJT MOVLW high $ MOVWF PCLATH MOVFW IPtrigMenu ANDLW 0x03 ADDWF PCL,f ; set choice State Table - limited to 2 states and two events RETLW LCDstrLCont RETLW LCDstrLContEdge RETLW LCDstrLSingle RETLW LCDstrLSingleEdge TEST_STRADDLE IPtrigMenuJT DTSTriggered EQU 3 ; a capture should take place DTsTurnOff EQU 4 DTsMeasFreq EQU 5 DTsDispFreq EQU 6 DTsDispCount EQU 7 ;-------------------------------------------------------------------------- ; Sec 4.7 Serial Input Routine ;-------------------------------------------------------------------------- ;************************************************** RS232in ; spin for a start bit ; CLRWDT ; BTFSS PORTB,RS232rx ; GOTO RS232in CALL Delay6 CALL Delay5 movlw 8 movwf RSloopCnt RS232inL0 ; BTFSC PORTB,RS232rx ; GOTO RS232inL1 ; BSF STATUS,C ; GOTO RS232inL2 ;RS232inL1 BCF STATUS,C ;RS232inL2 RRF RSdata,F MOVFW PORTB ANDLW 1<< RS232rx ; mask off bit ADDLW -1<< RS232rx ; use ripple carry to move into C RRF RSdata,F CALL Delay5 DECFSZ RSloopCnt,f goto RS232inL0 ; test for Stop bit COMF RSdata,f MOVFW RSdata ADDLW -0x0D SKPNZ GOTO RSfoundCR ADDLW 0x0D CALL LCDwrtChar RETURN RSfoundCR MOVLW LCDCurLeftLower CALL LCDwrtCmd RETURN Delay5 ; RETURN ; NOP NOP MOVLW 0x1E MOVWF RSdell Delay51 DECFSZ RSdell ; 1 GOTO Delay51 ; 2 clk CLRWDT RETURN ;*************** ; Delay 0x0F * 3 ticks of 4Mhz ~= 45us Delay6 ; RETURN ; MOVLW 0x0F MOVLW 0x08 ; shorten delay as edge detector takes about 22 us MOVWF RSdell Delay61 DECFSZ RSdell GOTO Delay61 CLRWDT RETURN ;-------------------------------------------------------------------------- ; Sec 5.0 Interrupt Routines ;-------------------------------------------------------------------------- Intrtn ; Which Interupt ? ; No Context Save in these routines. ; BTFSC INTCON,2 ; GOTO IntTmr0 ; BTFSC INTCON,1 ; GOTO Intfint ; BTFSC INTCON,0 ; GOTO IntRbport IntTmr0 ; BCF INTCON,2 RETFIE Intfint ; BCF INTCON,1 ; RETFIE IntRbport ; BCF INTCON,0 RETFIE ;-------------------------------------------------------------------------- ; Program End ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; EEPROM data ;-------------------------------------------------------------------------- ORG 0x2100 ; first 2 on and off are general ones DE 0x24,0x00 ; 4 cblock LastVar endc END
;************************************************************************** ; ; ; LCD4MHZ.inc LCD code to drive an epson SED1200 ( 32Khz clk ) or Hitachi HD44780 ( 4Mhz clk) ; ; Description: Drives EPSON EA-C20017AR based upon Epson ; SED1200F if buildLCDsed1200 defined ; ; Drives Hitachi HD44780 based Modules if if buildLCD_hd44780 defined ; ; Common Procedures:- ; LCDwrtStr - display a String into 10 byte window starting at 0x80. ; LCDdispByte - display byte as two hex nibbles ; LCDwrtChar - write Char to module ; LCDwrtCmd - write CMD to module ; ; Cursor addres 0x80 is line 1 on both modules ; Cursor addres 0xC0 is line 2 on both modules. ; ; On SED1200 line 1 is left 10 Chars ; On SED1200 line 2 is Right10 Chars ; ; Treat the two sides separately, as two lines ; ; On HD557840 line 1 is top line ; On HD557840 line 2 is bottom line ; ; LCDstart - Initilizes Module ; ;Define one of these to select the module in main file. ; ; buildLCDsed1200 ; buildLCD_HD44780 ; ; ; Author: Doug Rice ; ; ; ; ;************************************************************************** ;-------------------------------------------------------------------------- ; Sec 3.3 LCD routines stuff ;-------------------------------------------------------------------------- cblock LCDtemp ; LCDcnt ; LCDnibble ; LCDPortB ; image of port B for unused bits LCDeraseCnt ; LCDstrPtr ; endc ;-------------------------------------------------------------------------- ; Sec 3.3.4.2 LCD procedures LCD string write displayes ;-------------------------------------------------------------------------- ifdef buildLCDgetByte LCDgetByte ; we should have set up PCLATH ; When LCDstrPtr gets to 0xFF MOVLW high $ MOVWF PCLATH MOVFW LCDstrPtr; ADDWF PCL,f LCDstrs LCDstrLTime equ $ - LCDstrs DT "Hello" GOTO LCDgetByteEnd4 ; now print out 4 blanks LCDstrLblank equ $ - LCDstrs DT " " GOTO LCDgetByteEnd6 LCDstrLOff equ $ - LCDstrs DT "OFF" GOTO LCDgetByteEnd6 LCDstrLOn equ $ - LCDstrs DT "ON " GOTO LCDgetByteEnd6 LCDstrLOnp equ $ - LCDstrs DT "ON+" GOTO LCDgetByteEnd6 LCDLastStr IF 0 != ( high ( LCDLastStr ) - high ( LCDgetByte ) ) Error "String Table straddles Page Boundary " ENDIF ; Jump into these to select how many spaces printed ; at the end, so that 9 chars are printed. LCDgetByteEnd0 DECF LCDeraseCnt,f LCDgetByteEnd1 DECF LCDeraseCnt,f LCDgetByteEnd2 DECF LCDeraseCnt,f LCDgetByteEnd3 DECF LCDeraseCnt,f LCDgetByteEnd4 DECF LCDeraseCnt,f LCDgetByteEnd5 DECF LCDeraseCnt,f LCDgetByteEnd6 CLRF LCDstrPtr DECF LCDstrPtr,f RETURN endif ; buildLCDgetByte ;-------------------------------------------------------------------------- ; Sec 3.3.4.3 LCD procedures LCD string write displayes ;-------------------------------------------------------------------------- LCDwrtStr ; W contains the string offset MOVWF LCDstrPtr; ; Erase upto 6 chars at end of string MOVLW 0x06 MOVWF LCDeraseCnt ; position cursor at left on line 1. ; erase old display MOVLW LCDCurLeft0 ; 0x80 CALL LCDwrtCmd GOTO LCDwrtStr1 LCDwrtStr0 CALL LCDwrtChar LCDwrtStr1 CALL LCDgetByte INCFSZ LCDstrPtr,f GOTO LCDwrtStr0 GOTO LCDwrtStrFlush ; write 10 chars to blank rest of right LCDwrtStrFlush ; W contains the number of Chars to flush LCDwrtStrLoop DECFSZ LCDeraseCnt,f GOTO LCDwrtStrLoop1 RETURN LCDwrtStrLoop1 MOVLW 0x20 CALL LCDwrtChar GOTO LCDwrtStrLoop ;-------------------------------------------------------------------------- ; Sec 3.3.4 LCD procedures ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; Sec 3.3.4.1 LCD procedures - Multi entry display procedure for commands, nibbles,bytes,chars ;-------------------------------------------------------------------------- LCDdispByte MOVWF LCDnibble ; Display top nipple SWAPF LCDnibble,w CALL LCDwrtDecNibble ; Display bottom nipple MOVFW LCDnibble CALL LCDwrtDecNibble RETURN LCDwrtCmd BCF LCDPortB,LCDbitA0 GOTO LCDwrtByte LCDwrtDecNibble ; currently only displays 0..9, A..F ANDLW 0x0F ADDLW 0x06 ; is it A..F, if so trigger a digit overflow SKPNDC ADDLW 7; subtract 10, then add 'A'-'0' ADDLW 0x30-6 ; Subtract extra 6 added to cause DC LCDwrtChar BSF LCDPortB,LCDbitA0 ifdef buildLCD_HD44780 ;You don't need to read the busy line on the display. ; ;PORT B Display LCD Pin ;DB7 DB7 14 ;DB6 DB6 13 ;DB5 DB5 12 ;DB4 DB4 11 ;DB3 E 6 ; R/W gnd 5 ;DB2 RS 4 ; V0 Vlcd 3 ; Vss 0 2 ; Vdd +5 1 ;R/W ==X====================x==== ;RS ____________________________ 0 for CMD, 1 for DATA ;E ____/----\____/-----\_______ ;DB ==X=========X==========X==== ; MSN LSN ; define bits - these need to be defined for the HD44780 chip ;LCDbitCS EQU 1 ; PORTB:1 ;LCDbitWR EQU 3 ; PORTB:3 ;LCDbitCLK EQU 3 ; PORTB:3 or OSC Out LCDbitE EQU 3 LCDbitRS EQU 2 LCDbitA0 EQU LCDbitRS ; RS - PORTB:2 ; sometimes used for bit number LCDCurOff EQU 0x0C ; DisplayOn, Cursor Off, Blink Off LCDCurOn EQU 0x0F ; DisplayOn, Cursor On, Blink On LCDCurLeft0 EQU 0x80 ; display 80,..,89,C0..C9 ; top LCDCurRight0 EQU 0xC0 ; left LCDCurLeftLower EQU 0xC0 ; left LCDwrtByte ; assume that the A0 line is correctly set, ; Byte to be displayed is in W ; SED1200 LCD chip ; CS ----________------------------------------------------ ; WR,CLK-----__--__------_-_-_-_--_-_-_-_--_-_-_-_--_-_-_-_--- ; DB,A0 ---x====x====x---------------------------------------- ; HD44780 LCD chip ;R/W ==X====================x==== ;RS ____________________________ 0 for CMD, 1 for DATA ;E ____/----\____/-----\_______ ;DB ==X=========X==========X==== ; MSN LSN ; Assumes:- ; LCD_DB0..3 connected to PORTB:4..7 ; R/~w connected to Gnd. ; R/S,E are equated, but connected to PORTB ; on exit PORTB<4:7> are left as inputs, so that they can ; be used for the keyboard/buttons. MOVWF LCDtemp ; set up PORTB<0:3> to Outputs,PORTB<4:7> to Outputs MOVLW 0x00 ; This is only required if MOVWF PORTB ; The MS nibble is used as BSF STATUS, RP0 ; inputs when reading buttons. MOVLW 0x01 ; MOVWF TRISB ; BCF STATUS, RP0 ; BTFSC LCDPortB, LCDbitA0 ; set RS line early BSF PORTB,LCDbitA0 BTFSS LCDPortB, LCDbitA0 ; set BCF PORTB,LCDbitA0 ; set up to write top nibble, then pulse WR MOVFW LCDtemp ANDLW 0xF0 ; assumes DB0..DB3 is MSB BTFSC LCDPortB, LCDbitRS ; set IORLW 1 << LCDbitRS MOVWF PORTB BSF PORTB,LCDbitE NOP BCF PORTB,LCDbitE ; set up to write bottom nibble, then pulse WR SWAPF LCDtemp,w ANDLW 0xF0 ; assumes DB0..DB3 is MSB BTFSC LCDPortB, LCDbitA0 ; set IORLW 1 << LCDbitRS MOVWF PORTB BSF PORTB,LCDbitE NOP BCF PORTB,LCDbitE NOP ; set up PORTB<0:3> to Outputs,PORTB<4:7> to Inputs BSF STATUS, RP0 ; MOVLW 0xF1 ; MOVWF TRISB ; BCF STATUS, RP0 ; ; Run a little delay to allow the instructions to take place. MOVLW 20 ; MOVLW 1 MOVWF LCDtemp ; Hold CS high and pulse WR low at least 16 times ; Now pulse CLK low 16 times to execute command LCDloop ; BCF PORTB,LCDbitCLK NOP NOP ; BSF PORTB,LCDbitCLK DECFSZ LCDtemp,f GOTO LCDloop RETURN LCDdelay ; 1.79 ms delay MOVLW 255 MOVWF LCDtemp LCDdelay1 GOTO $+1 GOTO $+1 DECFSZ LCDtemp,f GOTO LCDdelay1 RETURN LCDdelaylong ; 1.79 ms delay CLRF LCDtemp LCDdelaylong1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 DECFSZ LCDtemp,f GOTO LCDdelaylong1 RETURN ;-------------------------------------------------------------------------- ; Sec 3.3.4.2 LCD procedures - Initilization ;-------------------------------------------------------------------------- LCDstart ; Minimum reset instructions: ; System Reset,Line Select(2),Display On ; set up for LCD commands ; wlcdCmd($33); ; wlcdCmd($32); ; wlcdCmd($28); { 4 bit, 2 line, 5x7 display } ; wlcdCmd($01); { Clear Display } ; wlcdCmd($0F); { $0F - Display On,CursorOn,Blink } ; wlcdCmd($C9); { set dd address } MOVLW 0x33 ; 40us force to 8 bit mode, from any mode CALL LCDwrtCmd MOVLW 0x32 ; 40us force to 4 bit mode CALL LCDwrtCmd MOVLW 0x28 ; 40us 4 bit, 2 line, 5x7 display CALL LCDwrtCmd MOVLW 0x01 ; Clear display CALL LCDwrtCmd CALL LCDdelay MOVLW 0x0F ; Display On,Cursor On,Blink CALL LCDwrtCmd MOVLW 0x80 MOVLW 10 MOVWF LCDcnt ; Now actually display something MOVLW LCDstrLTime CALL LCDwrtStr RETURN ;To know wwhich nibble is being sent initilize to 8 bit then ;go into 4 bit mode and keep track of each nibble sent ; ;If using 4 bit interface only use the DB4 to DB7 pins. ;The 8 bits comands to convert to 4 bits mode do not care ;about the 4 LSB. ; ;With R/W =0 and RS=0: ; ;0x01 ;clear display 82us @250Hz ;0x02 ;return home 82us @250Hz ;0x04 ;EntryModeSet 40us @250Hz ; 0x01 ; S 1 = shift ; 0x02 ; I/D 1= increment/0=decrement ;0x08 ;Display ON/OFF 40us @250Hz ; 0x01 ; B Blink ; 0x02 ; C Cursor On ; 0x04 ; D Display On ;0x10 ;Cursor and Display Shift 40us @250Hz ; 0x04 ; s/c Shift Display/ 0=shift Cursor ; 0x08 ; r/l Shift Right,0=shift left ;0x20 ;Function Set 40us @250Hz ; 0x04 ; F 5x10 dots /5x7dots ; 0x08 ; N 2lines /1lines ; 0x10 ; DL 8bits interface /4 bits interface. ;0x40 ;Set CG RAM address 40us @250Hz ;0x80 ;Set DD RAM address; 40us @250Hz ;With R/W =0 and RS=1: ;write data to CG or DD ;With R/W =1 and RS=1: ;Read data from CG or DD ; ;Send the commands below to Initilize. ;First mop up any 4 bit commands, and convert to 8 bit, ;either from 4 bit mode or 8 bit mode. ;Then from 8 bit node move to 4 bit mode. ;Then issue 4 bit commands. ; wlcdCmd($33); 8 bit mode - could be in 4 bit mode ; wlcdCmd($32); 8 bit mode - could be in 4 bit mode ; wlcdCmd($28); 4 bit mode, 2 lines 5x7 dots ; wlcdCmd($01); Clear Display could take 1.6ms ; wlcdCmd($0F); $0F - Display On,CursorOn,Blink ; wlcdCmd($C9); set dd address ;You don't need to read the busy line on the display. ; ;PORT B Display LCD Pin ;DB7 DB7 14 ;DB6 DB6 13 ;DB5 DB5 12 ;DB4 DB4 11 ;DB3 E 6 ; R/W gnd 5 ;DB2 RS 4 ; V0 Vlcd 3 ; Vdd +5 2 ; Vss 0 1 endif ifdef buildLCDsed1200 ; ; ;================================================================ ;this needs to be changed ; ; ;-------------------------------------------------------------------------- ; Sec 3.3.1 LCD introduction - SED1200F ;-------------------------------------------------------------------------- ;LCD Information ;================== ; ;Having brought a number of displays for a bargin price, and finding that the ;information provided was inadequate, this document summarizes what has been ;found out. ; ; ;Epson EA-C20017AR ;================== ; ;20 char by one line. ; ;The display appears to be based on an SED1200F controller. ; ;Pin Connections when looking at display, contacts on left. ; ; 1 +5V 2 Gnd |------------------| ; 3 Vlcd 4 Clk | | ; 5 -CS 6 A0 | DISPLAY 20x1 | ; 7 -WR 8 -RD | - | ; 9 DB3 10 DB2 | | ; 11 DB1 12 DB0 |------------------ ; ; Display is 20 x 1 ; Suggested values for single line mode , 10 x 1 repeated 10 x 1. ; ; + 5V Pin 1 ; | ; [ ] 10k ohm ; | ;Vlcd Pin 3 ; | ; [ ] 3k ohm ; | ; GND ; ; ; For proper operation run the display as two line mode. ; ; ; Initialization. leaves random characters. ; ; CMD, System Reset 0,0x10 ; CMD, DISPLAY ON 0,0x0D ; CMD, Line Select-On 0,0x13 ; CMD, Cursor Home 0,0x80 ; DATA,0x20 ;-------------------------------------------------------------------------- ; Sec 3.3.2 LCD command equates ;-------------------------------------------------------------------------- ; ; SED 1200F config commands A0=0 ; LCDsetCurDirInc EQU 0x04 LCDsetCurDirDec EQU 0x05 LCDCurInc EQU 0x06 LCDCurDec EQU 0x07 LCDCurBlock EQU 0x09 LCDCurUL EQU 0x08 LCDCurConst EQU 0x0A LCDCurBlink EQU 0x0B LCDCurDispOff EQU 0x0C LCDCurDispOn EQU 0x0D LCDCurOff EQU 0x0E LCDCurOn EQU 0x0F LCDSysReset EQU 0x10 LCD1line EQU 0x12 LCD2line EQU 0x13 LCDCurX0Y0 EQU 0x80 ; display has two halfs of 10 chars each LCDCurX1Y0 EQU 0xC0 ; LCDCurLeft0 EQU 0x80 ; display 80,..,89,C0..C9 LCDCurRight0 EQU 0xC0 ; LCDCgRamAddr EQU 0x20 LCDCgRamData EQU 0x40 ;-------------------------------------------------------------------------- ; Sec 3.3.3 LCD control line / hardware to port mapping equates ;-------------------------------------------------------------------------- ; define binary Mask for bits LCD_CS EQU 2 ; PORTB:1 LCD_WR EQU 8 ; PORTB:3 LCD_CLK EQU 8 ; PORTB:3 or OSC Out LCD_A0 EQU 4 ; PORTB:2 ; sometimes used for bit number ; define bits LCDbitCS EQU 1 ; PORTB:1 LCDbitWR EQU 3 ; PORTB:3 LCDbitCLK EQU 3 ; PORTB:3 or OSC Out LCDbitA0 EQU 2 ; PORTB:2 ; sometimes used for bit number LCDwrtByte ; assume that the A0 line is correctly set, ; Byte to be displayed is in W ; ; CS ----________------------------------------------------ ; WR,CLK-----__--__------_-_-_-_--_-_-_-_--_-_-_-_--_-_-_-_--- ; DB,A0 ---x====x====x---------------------------------------- ; Assumes:- ; LCD_DB0..3 connected to PORTB:4..7 ; RD connected to +5 ; WR,CS,A0,CLK are equated, but connected to PORTB ; on exit PORTB<4:7> are left as inputs, so that they can ; be used for the keyboard/buttons. MOVWF LCDtemp ; set up PORTB<0:3> to Outputs,PORTB<4:7> to Outputs MOVLW 0xFF ; This is only required if MOVWF PORTB ; The MS nibble is used as BSF STATUS, RP0 ; inputs when reading buttons. MOVLW 0x01 ; MOVWF TRISB ; BCF STATUS, RP0 ; BTFSC LCDPortB, LCDbitA0 ; set A0 line early BSF PORTB,LCDbitA0 BTFSS LCDPortB, LCDbitA0 ; set BCF PORTB,LCDbitA0 ; set up to write top nibble, then pulse WR MOVFW LCDtemp IORLW 0x0F ; -CS,-A0,-WR BTFSS LCDPortB, LCDbitA0 ; set ANDLW ~LCD_A0 MOVWF PORTB BCF PORTB,LCDbitCS BCF PORTB,LCDbitWR NOP BSF PORTB,LCDbitWR ; set up to write bottom nibble, then pulse WR SWAPF LCDtemp,w IORLW 0x0F ; -CS,-A0,-WR BTFSS LCDPortB, LCDbitA0 ; set ANDLW ~(LCD_A0 | LCD_CS) ANDLW ~LCD_CS MOVWF PORTB BCF PORTB,LCDbitWR NOP NOP BSF PORTB,LCDbitWR NOP NOP BSF PORTB,LCDbitCS ; set up PORTB<0:3> to Outputs,PORTB<4:7> to Inputs BSF STATUS, RP0 ; MOVLW 0xF1 ; MOVWF TRISB ; BCF STATUS, RP0 ; MOVLW 20 ; MOVLW 1 MOVWF LCDtemp ; Hold CS high and pulse WR low at least 16 times ; Now pulse CLK low 16 times to execute command LCDloop BCF PORTB,LCDbitCLK NOP NOP BSF PORTB,LCDbitCLK DECFSZ LCDtemp,f GOTO LCDloop ; set up PORTB<0:3> to Outputs,PORTB<4:7> to Inputs BSF STATUS, RP0 ; MOVLW 0xF1 ; MOVWF TRISB ; BCF STATUS, RP0 ; RETURN ;-------------------------------------------------------------------------- ; Sec 3.3.4.2 LCD procedures - Initilization ;-------------------------------------------------------------------------- LCDstart ; Minimum reset instructions: ; System Reset,Line Select(2),Display On ; set up for LCD commands ; CMD, System Reset 0,0x10 ; CMD, DISPLAY ON 0,0x0D ; CMD, Line Select 2 ; CMD, Cursor On 0,0x0F ; CMD, Cursor Dir 0,0x04 ; CMD, Cursor Blink off 0,0x0A ; CMD, Cursor Home 0,0x80 ; DATA,0x20 BCF PORTA,LCDA0 ; LCD system reset MOVLW 0x10 CALL LCDwrtCmd ; LCD Display On MOVLW 0x0D CALL LCDwrtCmd ; LCD Set 2 Line Mode MOVLW 0x13 CALL LCDwrtCmd ; LCD Display On MOVLW 0x0D CALL LCDwrtCmd ; LCD Cursor Home MOVLW 0x80 CALL LCDwrtCmd MOVLW 10 MOVWF LCDcnt ; now write some characters LCDloop1 MOVLW 0x20 CALL LCDwrtChar DECFSZ LCDcnt,f GOTO LCDloop1 ; LCD Cursor Home MOVLW 0xC0 CALL LCDwrtCmd MOVLW 10 MOVWF LCDcnt LCDloop2 MOVLW 0x20 CALL LCDwrtChar DECFSZ LCDcnt,f GOTO LCDloop2 LCDloop2A ; Now actually display something MOVLW LCDstrLTime CALL LCDwrtStr RETURN endif ;buildLCDsed1200 ; ; ;======================================================================= ; ; ;: Symbols that need to be defined differently for different LCD chips ;RT003.ASM 390 : (LCDstart) ;LCD.INC 151 : (LCDbitA0) ; check the sense ;LCD.INC 152 : (LCDwrtByte) ;RT003.ASM 803 : (LCDCurOn) ;RT003.ASM 812 : (LCDCurOff) ;RT003.ASM 680 : (LCDCurRight0) ;LCD.INC 104 : (LCDCurLeft0) ;-------------------------------------------------------------------------- ; END OF FILE ;--------------------------------------------------------------------------
Strap GPIO3 low for serial.
Strap GPIO3 high to allow A/D0 bit5 to be copied to GPIO5.
;********************************************************** ;* dm002.asm ;********************************************************** ;* This program configures the A/D Module to convert on ;* A/D channels and outputs the results serial at 32K ;********************************************************** list p=12f675 ; Include file, change directory if needed include "p12f675.inc" __idlocs 0x1234 __config _PWRTE_ON & _WDT_OFF & _BODEN_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF cblock 0x20 ; variables used for context saving w_temp status_temp ADrh ADrl ADcnt SRtxTemp SRtxCnt SRout SRdel cnt1 cnt2 cnt3 endc ; Start at the reset vector org 0x000 ; goto test goto Init test movlw 0 movwf cnt1 movlw 1 movwf cnt2 test1 incf cnt1,f incf cnt2,f movfw cnt1 xorwf cnt2,w andlw 0x88 movwf cnt3 goto test1 Init org 0x010 banksel 0x3FF CALL 0x3FF MOVWF OSCCAL banksel TRISIO BSF STATUS, RP0 ; movlw 0xCF movlw 0xDF MOVWF TRISIO ; Set output high to start Measurement BCF STATUS, RP0 movlw 0x0D call SRtxChar movlw 0x0A call SRtxChar movlw 0x0D call SRtxChar movlw 0x0A call SRtxChar movlw 0x55 call SRtxChar movlw 0xAA call SRtxChar movlw ' ' call SRtxChar movlw 'A' call SRtxChar movlw '/' call SRtxChar movlw 'D' call SRtxChar movlw ' ' call SRtxChar movlw '(' call SRtxChar movlw '8' call SRtxChar movlw '7' call SRtxChar movlw '6' call SRtxChar movlw ')' call SRtxChar movlw ' ' call SRtxChar movlw 0x55 call SRtxChar movlw 0xAA call SRtxChar movlw 0x0D call SRtxChar movlw 0x0A call SRtxChar ; goto Init Start ; output p(,ad0,ad1,ad2,ad3,ad5,); movlw 0x0D call SRtxChar movlw 0x0A call SRtxChar movlw 'p' call SRtxChar movlw '(' call SRtxChar movlw ',' call SRtxChar movlw 0 << 2 call ADconvert call LDled movlw 1 << 2 call ADconvert movlw 2 << 2 call ADconvert movlw 3 << 2 call ADconvert ; movlw ',' ; call SRtxChar movlw ')' call SRtxChar movlw ';' call SRtxChar goto Start ;Do it again ADconvert ; W contains the channel in bit 5-3 banksel ADCON0 addlw B'00000001' ;Fosc/8, A/D enabled movwf ADCON0 banksel ANSEL movlw B'00010111' ;Fosc/8, A/D enabled movwf ANSEL banksel OPTION_REG movlw B'10000111' ;TMR0 prescaler, 1:256 movwf OPTION_REG banksel ADCON0 movlw 0x80 | 2 ;Left justify,5 analog channel addwf ADCON0,f ;VDD and VSS references banksel GPIO banksel INTCON Main ; goto StartConvert ; btfss INTCON,T0IF ;Wait for Timer0 to timeout ; goto Main ; bcf INTCON,T0IF ; ; use PORTA 4 as a delay. ; ;Vdd - [ Rt ] + [ R ] - pin RA4 ; ; C ; | ; gnd ; ; make RA4 an output to discharge C ; then make it an input ; Wait for C to Charge, then proceed. ; StartConvert bcf PIR1,ADIF banksel ADCON0 bsf ADCON0,GO ;Start A/D conversion Wait btfss PIR1,ADIF ;Wait for conversion to complete goto Wait nop nop movfw ADRESH movwf ADrl ; now output the value in Hex swapf ADrl,W ;Write A/D result to GPIO call SRwrtHexNibble movf ADrl,W ;Write A/D result to GPIO call SRwrtHexNibble banksel ADRESL movfw ADRESL banksel ADrl movwf ADrl swapf ADrl,W ;Write A/D result to GPIO call SRwrtHexNibble movf ADrl,W ;Write A/D result to GPIO call SRwrtHexNibble movlw ',' call SRtxChar return SRwrtHexNibble ; currently only displays 0..9, A..F ANDLW 0x0F ADDLW 0x06 ; is it A..F, if so trigger a digit overflow SKPNDC ADDLW 7; subtract 10, then add 'A'-'0' ADDLW 0x30-6 ; Subtract extra 6 added to cause DC MOVWF SRout GOTO SRtxChar SRtxChar ; test GPIO bit 3 to see if serial out or LED out ; GPIO bit 3 must be low BTFSC GPIO,3 RETURN ; ;Output Start Bit ;Output LSB first ;use TxOnBit equ 5 movwf SRtxTemp comf SRtxTemp,f BCF GPIO,TxOnBit MOVLW ~( 3 << TxOnBit ) ; TRIS GPIO BSF STATUS, RP0 MOVWF TRISIO ; Set output high to start Measurement BCF STATUS, RP0 ; 1200 baud output ; move the char into SRtxtemp, it is destroyed. ;Start Bit BSF GPIO,TxOnBit GOTO $+1 call delay movlw TxOnBit movwf SRtxCnt GOTO $+1 SRtxCharLp1 ; This outputs two bits at a time ; this takes 6.5 cycles each ; After start bit, which is 1, then test each bit ; I need to set PA:0 to same as LSB SRtxTemp ; this compares PA:0 with SRtxTemp so see if it needs toggling ; The xorwf PORTA,f causes the bit to be toggled if required. ; Toggle bit if next bit is different RRF SRtxTemp,f movfw STATUS andlw 1 << C ; mask off bit addlw ( 1 << TxOnBit) -1 ; shift bit by using a ripple carry xorwf GPIO,W andlw 0x1 << TxOnBit xorwf GPIO,f ;t+6,19 GOTO $+1 call delay RRF SRtxTemp,f movfw STATUS andlw 1 << C addlw ( 1 << TxOnBit) -1 xorwf GPIO,W andlw 0x1 << TxOnBit xorwf GPIO,f ;t+11,24 GOTO $+1 call delay decfsz SRtxCnt goto SRtxCharLp1 GOTO $+1 GOTO $+1 call delay BCF GPIO,TxOnBit GOTO $+1 GOTO $+1 RETURN delay nop movlw 0x03 movwf SRdel delay1 decfsz SRdel goto delay1 return ;--------------------------- ; LD process ;--------------------------- LDled ; test GPIO bit 3 to see if serial out or LED out BTFSS GPIO,3 RETURN banksel ADRESL movfw ADRESL movwf ADrl banksel GPIO bcf GPIO,5 BTFSC ADrl,5 bsf GPIO,5 return org 0x3FD RETLW 0x6C RETLW 0x6C RETLW 0x6C end