LIST P=16F628 ; 16F84 Runs at 4 MHz
INCLUDE "p16f628.inc"
__CONFIG h'3f10'
ERRORLEVEL -302 ; supress message because of page change
; Define Information
#DEFINE Kdata PORTB, 0
#DEFINE RS PORTB, 1
#DEFINE E PORTB, 2
#DEFINE Kclk PORTB, 3
#DEFINE SW PORTB, 4
#DEFINE wsk reg, 0
#DEFINE result reg, 1
#DEFINE cl reg, 2
#DEFINE Kerr reg, 3
#DEFINE I2C_PORT PORTB
#DEFINE I2C_SCL 6
#DEFINE I2C_SDA 5
;------ Define port pins: RB2=SDA=data, RB1=SCL=clock
;------ Pins are connected via 4.7K pullup resistors for passive control
;------ Any port pins can be used.
; RB0-RB3 are D4-D7 of LCD
; Macro
EStrobe MACRO ; Strobe the "E" Bit
bsf E
call Edelay
bcf E
call Edelay
ENDM
wait10 MACRO
btfsc Kclk
goto $-1
ENDM
wait01 MACRO
btfss Kclk
goto $-1
ENDM
trans MACRO key, ascii, sascii
movlw key
call compare
btfss result
goto $+6
movlw ascii
btfsc cl
addlw h'100'
call sendCHAR
return
ENDM
CBLOCK 20H
Temp ; a temporary variable
count ; counter
precount ; holds value for prescalar
bin ; binary number to be converted to BCD
hundreds ; BCD hundreds result
tens_and_ones ; BCD tens and ones result
reg
flags ; flag bit register
position
l1
l2
keycount
rxdata
txdata
data_out
index
_w
_status
_pclath
ENDC
org h'00' ; start at location 0
goto main ; jump over to main routine
org h'04'
goto int
;-------------------------------------------------------------------------;
; Initialize the ports ;
;-------------------------------------------------------------------------;
Init: movlw h'07'
movwf cmcon
clrf PORTA
clrf PORTB
bsf status, rp0
bcf pcon, oscf
movlw B'00000000' ; all outputs
movwf trisa
movlw B'00011001' ; RB4, input, others outputs
movwf trisb
movlw B'00100001' ; pull-ups enabled
movwf option_reg
bcf status, rp0
clrf precount
clrf reg
movlw b'10010000'
movwf intcon
movlw h'01'
movwf position
return
;-------------------------------------------------------------------------;
; Initialize the ports ;
;-------------------------------------------------------------------------;
Edelay: nop
nop
nop
nop
nop
return
;-------------------------------------------------------------------------;
; Initialize the LCD ;
;-------------------------------------------------------------------------;
initlcd:
movlw D'40'
call nmsec ; Wait 40 msecs before Reset
bcf RS ; send an 8 bit instruction
movlw 0x03 ; Reset Command
call NybbleOut ; Send the Nybble
call Dlay5 ; Wait 5 msecs before Sending Again
EStrobe
nop
nop ; Wait 244 usecs before Sending the Second Time
EStrobe
nop
nop ; Wait 244 usecs before Sending the Third Time
bcf RS ; send an 8 bit instruction
movlw 0x02 ; Set 4 Bit Mode
call NybbleOut
nop
nop
movlw 0x028 ; 4 bit, 2 Line, 5x7 font
call SendINS
movlw 0x010 ; display shift off
call SendINS
movlw 0x001 ; Clear the Display RAM
call SendINS
call Dlay5 ; Note, Can take up to 4.1 msecs
movlw 0x006 ; increment cursor
call SendINS
movlw 0x00F ; display on cursor off
call SendINS
return
;-------------------------------------------------------------------------;
; Send the character in W out to the LCD ;
;-------------------------------------------------------------------------;
int: movwf _w
swapf status, w
clrf status
movwf _status
swapf pclath, w
movwf _pclath
call getch
movlw .25
subwf position, w
btfsc status, z
call f2
movlw .49
subwf position, w
btfsc status, z
call f1
call key2ascii
bsf status, rp0
bcf pcon, oscf
bcf status, rp0
call msec250
bsf status, rp0
bsf pcon, oscf
bcf status, rp0
bcf intcon, intf
swapf _pclath, w
movwf pclath
swapf _status, w
movwf status
swapf _w, f
swapf _w, w
retfie
;-------------------------------------------------------------------------;
; Send the character in W out to the LCD ;
;-------------------------------------------------------------------------;
SendASCII
addlw '0' ; Send nbr as ASCII character
SendCHAR ; Send the Character to the LCD
bsf status, rp0
bcf pcon, oscf
bcf status, rp0
movwf Temp ; Save the Temporary Value
swapf Temp, w ; Send the High Nybble
bsf RS ; RS = 1
call NybbleOut
movf Temp, w ; Send the Low Nybble
bsf RS
call NybbleOut
bsf status, rp0
bsf pcon, oscf
bcf status, rp0
incf position, f
return
;-------------------------------------------------------------------------;
; Send an instruction in W out to the LCD ;
;-------------------------------------------------------------------------;
SendINS ; Send the Instruction to the LCD
bsf status, rp0
bcf pcon, oscf
bcf status, rp0
movwf Temp ; Save the Temporary Value
swapf Temp, w ; Send the High Nybble
bcf RS ; RS = 0
call NybbleOut
movf Temp, w ; Send the Low Nybble
bcf RS
call NybbleOut
bsf status, rp0
bsf pcon, oscf
bcf status, rp0
return
;-------------------------------------------------------------------------;
; Send the nibble in W out to the LCD ;
;-------------------------------------------------------------------------;
NybbleOut ; Send a Nybble to the LCD
movwf PORTA
EStrobe ; Strobe out the LCD Data
nop
nop
return
;-------------------------------------------------------------------------;
; Output the message on the LCD ;
;-------------------------------------------------------------------------;
OutMessage:
movwf FSR ; Point at first letter
OutLoop:
movf FSR, w ; Get pointer into W
incf FSR, f ; Set up for next letter
call shomsg ; Get character to output
iorlw 0 ; At the End of the Message?
btfsc STATUS, Z ; Skip if not at end
return ; Yes - Equal to Zero
call SendCHAR ; Output the ASCII Character
goto OutLoop ; Get the next character
;-----------------------------------------------------------------------;
; Delay routine ;
;-----------------------------------------------------------------------;
msec250:
movlw 0 ; 250 msec delay (adjusted to try and
; allow for 2.5% low loop time)
goto $+2
Dlay5: movlw 5 ; delay for 5 milliseconds
nmsec: ; delay for # msec in W on entry
nop ; each nop is 0.122 milliseconds
nop
nop ; each total loop is 8 X 0.122 = 0.976 msec
nop
addlw H'FF' ; same as subtracting 1 from W
btfss STATUS, Z ; skip if result is zero
goto nmsec ; this is 2 X 0.122 msec
return ; back to calling point
;-----------------------------------------------------------------------;
; odbior z klawiatury ;
;-----------------------------------------------------------------------;
getch: movlw .8
movwf keycount
wait10
wait01
nextb: wait10
btfss Kdata
bcf status, c
btfsc Kdata
bsf status, c
rrf rxdata, f
wait01
decfsz keycount, f
goto nextb
return
;-----------------------------------------------------------------------;
; porównanie ;
;-----------------------------------------------------------------------;
compare:
subwf rxdata, w
btfss status, z
bcf result
btfsc status, z
bsf result
return
;-----------------------------------------------------------------------;
; key2ascii ;
;-----------------------------------------------------------------------;
key2ascii:
trans h'1C', A'a'
trans h'32', A'b'
trans h'21', A'c'
trans h'23', A'd'
trans h'24', A'e'
trans h'2b', A'f'
trans h'34', A'g'
trans h'33', A'h'
trans h'43', A'i'
trans h'3B', A'j'
trans h'42', A'k'
trans h'4B', A'l'
trans h'3A', A'm'
trans h'31', A'n'
trans h'44', A'o'
trans h'4D', A'p'
trans h'15', A'q'
trans h'2D', A'r'
trans h'1B', A's'
trans h'2C', A't'
trans h'3C', A'u'
trans h'2A', A'v'
trans h'1D', A'w'
trans h'22', A'x'
trans h'35', A'y'
trans h'1A', A'z'
trans h'45', A'0'
trans h'16', A'1'
trans h'1E', A'2'
trans h'26', A'3'
trans h'25', A'4'
trans h'2E', A'5'
trans h'36', A'6'
trans h'3D', A'7'
trans h'3E', A'8'
trans h'46', A'9'
trans h'41', A','
trans h'49', A'.'
trans h'4A', A'/'
trans h'4C', A';'
trans h'52', h'27'
trans h'54', A'['
trans h'5B', A']'
trans h'0E', A'`'
trans h'4E', A'-'
trans h'55', A'='
trans h'29', A' '
return
;-----------------------------------------------------------------------;
; I2C routine ;
;-----------------------------------------------------------------------;
d5u: ;razem z CALL 5 cykli
GOTO $+1 ;2 cykle
return ;2 cykle
I2C_START ; Send the Start Bit on the I2C Bus
bsf I2C_PORT, I2C_SDA ; Make the Data Line High
goto $+1
bcf I2C_PORT, I2C_SCL ; Make the Clock Line Low
nop
bsf I2C_PORT, I2C_SCL ; Set the Clock High
CALL d5u ;5 cykli
nop
bcf I2C_PORT, I2C_SDA ; Drop the Clock Line to Go into Start Mode
CALL d5u ;5 cykli
bcf I2C_PORT, I2C_SCL ; Start Clock Train
goto $+1
return
I2C_STOP ; Send the Stop Bit to the I2C Bus
bcf I2C_PORT, I2C_SDA ; Data Line Low
CALL d5u ;5 cykli
bsf I2C_PORT, I2C_SCL ; Set the Clock Line High
CALL d5u ;5 cykli
bsf I2C_PORT, I2C_SDA ; Data goes high whil Clock is High for Stop Bit
goto $+1
bcf I2C_PORT, I2C_SCL ; Set Clock Low Again
goto $+1
nop
return
I2C_SEND ;wyslij W do I2C
MOVWF DATA_OUT
MOVLW .8
MOVWF INDEX
I2C_SEND_LOOP
RLF DATA_OUT, f
BTFSC STATUS, C ; JEDYNKA jesli nie to :pomin i ZERO
GOTO I2C_1
bcf I2C_PORT, I2C_SDA ;Ustaw 0
goto I2C_CLK
I2C_1
bsf I2C_PORT, I2C_SDA ;Ustaw 1
I2C_CLK
BSF I2C_PORT, I2C_SCL ;USTAW CLK
CALL d5u ;5 cykli
BCF I2C_PORT,I2C_SCL ;ZERUJ CLK
;drugie 5 cykli to petla :)
DECFSZ INDEX, F
GOTO I2C_SEND_LOOP
BSF I2C_PORT, I2C_SDA ;Ustawienie SDA zeby uklad mogl ACK wyslac
BSF I2C_PORT, I2C_SCL ;Takt zegara na ACK.ACK NIE jest sprawdzane
CALL d5u ;5 cykli
BCF I2C_PORT, I2C_SCL
CALL d5u ;5 cykli
RETURN
;-----------------------------------------------------------------------;
; Przycisk ;
;-----------------------------------------------------------------------;
test: btfsc sw
goto zeruj
bsf wsk
call msec250
btfsc sw
zeruj: bcf wsk
return
;-------------------------------------------------------------------------;
; The Main routine ;
;-------------------------------------------------------------------------;
main: call msec250
call Init ; initialize ports, set up timer
call initlcd ; initialize the LCD
call init2
movlw H'80'
call SendINS
bcf intcon, gie
btfsc intcon, gie
goto $-2
clrf PORTB
call I2C_START
movlw b'01110000' ;zapis
call I2C_SEND
movlw b'01100110' ;oba
call I2C_SEND
call I2C_STOP
bsf intcon, gie
goto $
end