__16F88
__config _CONFIG1,_BODEN_OFF&_WDT_OFF&_LVP_OFF&_MCLR_OFF&_PWRTE_ON&_INTRC_IO
; I/O pin assignments
ifdef __16F88
#DEFINE PGBTN PORTB,6 ; page button (S3)
#DEFINE HDBTN PORTB,7 ; hold button (S2)
#DEFINE BLDBTN PORTA,7 ; blades button (S1)
#DEFINE RPM_IN PORTB,0 ; rpm input
#DEFINE LCD_D7 PORTA,4 ; \
#DEFINE LCD_D6 PORTB,1 ; |
#DEFINE LCD_D5 PORTB,2 ; | LCD panel
#DEFINE LCD_D4 PORTB,3 ; |
#DEFINE LCD_E PORTB,4 ; |
#DEFINE LCD_RS PORTB,5 ; /
Hi guys, newbie here. I used 16F88 as my MCU and i define the port as below:
As I need B5 as my hardware UART, i am planning to switch the LCD_RS to another port which is A6 (RA6/OSC2/CLKO),
A6 buffer type is ST and i had it ground previously. However when I changed to RA6 and reconnect LCD port...it gives weird characters on the LCD.
Is it possible to do it this way? Thank you.
;--------------------------------------------------------------------
; Main Program Starts Here!
;
Start:
clrf PORTA
clrf PORTB
bsf STATUS,RP0 ; bank 1
ifdef __16F88
movlw B'11101111' ; PortA directions (16F88)
movwf TRISA
movlw B'11000001' ; PortB directions (16F88)
movwf TRISB
movlw B'01100000' ; 4MHz internal osc (16F88)
movwf OSCCON
else
movlw B'11111111' ; PortA directions (16F870)
movwf TRISA
movlw B'00000000' ; PortB directions (16F870)
movwf TRISB
movlw B'11111111' ; PortC directions (16F870)
movwf TRISC
endif
movlw B'01010111' ; Weak pullups enabled, Timer0 src = clkout/256
movwf OPTION_REG
bcf STATUS,RP0 ; bank 0
; Set up Interrupts
clrf INTCON ; clear any pending ints
clrf PIR1
bsf INTCON,PEIE ; enable peripheral ints
bsf INTCON,GIE ; enable interrupts
; set up LCD Display
movlw 25 ; wait 500mS
call waitx20k
call LCDinit ; Set up the LCD display
call show_signon ; show signon message
movlw 50 ; wait 1 second
call waitx20k
; set up A/D convertor
bsf STATUS,RP0 ; bank 1
ifdef __16F88
movlw b'10110000' ; right-justify, ext vref (16F88)
movwf ADCON1
movlw b'00001111'
movwf ANSEL ; Analog inputs on RA0~RA3 (16F88)
else
movlw b'10001101' ; right-justify, ext vref, RA1/RA0 (16F870)
movwf ADCON1
endif
bcf STATUS,RP0 ; bank 0
movlw b'01000000' ; CLK/8
movwf ADCON0
; Start Timer0
movlw REFRESH_DELAY
movwf TMR0
; initialize variables
clrf Flags
clrf Flags2
movlw 0
movwf pagenum
clrf Page_Timer
clrf Blade_Timer
clr16 CCPR
clr16 Period
clr32 AmpSum
clr32 rpm
movlw 2
movwf NumBlades
; Set up CCP1 and Timer1 for rpm capture
clrf TMR1L
clrf TMR1H ; clear Timer1
movlw b'00100001'
movwf T1CON ; 4:1 prescaler, Timer1 ON
bcf PIR1,TMR1IF
bcf PIR1,CCP1IF ; clear Int flags
banksel PIE1
bsf PIE1,CCP1IE ; enable CCP1 Ints
bsf PIE1,TMR1IE ; enable TMR1 Ints
banksel 0
movlw b'00000111' ; capture every 16th leading edge
movwf CCP1CON ; enable Capture
ReadInputs:
clr16 Volts
clr16 Amps
clr16 Watts
movlw 64 ; 64 times oversampling
movwf Readings
NextRead:
movlw b'01000001' ; CLK/8, select RA0 (Volts), A/D on
movwf ADCON0
call wait100 ; wait 100uS to stabilize analog input
bsf ADCON0,GO_DONE ; start A/D conversion
waitv: btfsc ADCON0,GO_DONE
goto waitv ; wait until conversion Done
movf ADRESH,w
movwf Temp1
addwf Volts
bsf STATUS,RP0
movf ADRESL,w ; add 10 bit A/D result to Volts
bcf STATUS,RP0
movwf Temp2
addwf Volts+1
skpnc
incf Volts
bcf Flags,MAX_VOLTS
movf Temp1,w
xorlw b'00000011'
skpnz
bsf Flags,MAX_VOLTS ; Volts overloaded ?
movf Temp2,w
xorlw b'11111111'
skpz
bcf Flags,MAX_VOLTS
movlw b'01001001' ; CLK/8, select RA1 (Amps), A/D on
movwf ADCON0
call wait100 ; wait 100uS to stabilize analog input
bsf ADCON0,GO_DONE ; start A/D conversion
waita: btfsc ADCON0,GO_DONE
goto waita ; wait until conversion Done
movf ADRESH,w
movwf Temp1
addwf Amps
bsf STATUS,RP0
movf ADRESL,w ; get 10 bit A/D result
bcf STATUS,RP0
movwf Temp2
addwf Amps+1
skpnc
incf Amps
bcf Flags,MAX_AMPS
movf Temp1,w
xorlw b'00000011'
skpnz
bsf Flags,MAX_AMPS ; Amps overloaded ?
movf Temp2,w
xorlw b'11111111'
skpz
bcf Flags,MAX_AMPS
decfsz Readings
goto NextRead ; accumulate readings
clrc
rr16 Volts ; Volts / 2
movlw Volts
call Divx12 ; Volts / 12.8
movlw Amps
call Divx12 ; Amps / 12.8
btfsc Flags,GOT_ZERO ; have Amps been zeroed ?
goto sub_zero
get_zero:
mov16 Amps,ZeroAmps ; record zero Amps value
bsf Flags,GOT_ZERO
sub_zero:
bcf Flags,NEG_AMPS
sub16 ZeroAmps,Amps ; subtract zero value from Amps
skpnc
goto got_amps
bsf Flags,NEG_AMPS
com16 Amps ; Amps = -0 to -0.99
got_amps:
mov16 Amps,aa
mov16 Volts,bb
call Mult16 ; Watts = Volts * Amps
movi16 1000,aa
call Div32 ; Watts = Watts / 1000
subi16 500,bb
skpc ; remainder > 0.5 ?
goto store_watts
inc16 dd+2 ; yes, round up
store_watts:
mov16 dd+2,Watts
calc_Ah:
add1632 Amps,AmpSum ; AmpSum = accumulated Amps
mov32 AmpSum,dd
movi16 3600*3,aa ; 3 reads per second, 3600 seconds per hour
call Div32 ; AmpHours = AmpSum / (reads per hour)
store_Ah:
mov16 dd+2,AmpHours
; CCPR is a copy of the CCPR1 register. It is updated from the Interrupt
; routine. This may happen at any time, so we must prevent it from being
; updated while copying it. We cannot disable interrupts while copying
; because it could upset capture timing.
;
bsf Flags,LOCK_P ; lock CCPR
mov16 CCPR,Period ; get period (1/rpm)
bcf Flags,LOCK_P ; unlock CCPR
; reduce rpm jitter by averaging this and previous measurement
tst16 Period
skpz ; got good rpm ?
goto sp_good
clr16 OldPeriod ; no, old period = 0
goto sp_done
sp_good:
tst16 OldPeriod
skpnz ; got previous good rpm ?
goto sp_done ; no
mov1632 Period,dd
add1632 OldPeriod,dd
rr32 dd ; dd = (Period+OldPeriod)/2
mov16 Period,OldPeriod ; old period = current period
mov16 dd+2,Period ; Period now averaged
sp_done:
; show results on LCD screen
do_display:
movlw 6 ; 6 * 55.555mS = 3 readings per second
movwf ref_timer
display_page:
movlw 0
call Set_Cursor ; set cursor to start of line
movf pagenum,w
skpnz ; page 0 ?
goto page0
addlw -1
skpnz ; page 1 ?
goto page1
ifdef LCD8x2
; 8x2 or 16x1 display, 3 pages
addlw -1
skpnz ; page 2 ?
goto page2
page0: call Show_Volts
movlw LCDLINE2
call Set_Cursor ; "99.99V 99.99A"
call Show_Amps
goto ref_delay
page1: call Show_Watts ; "9999.9W 99.99Ah"
movlw LCDLINE2
call Show_AmpHours
goto ref_delay
page2: call Show_rpm
movlw LCDLINE2
call Set_Cursor ; "99999rpm x 9"
call Show_Blades
else
; 16x2 display, 2 pages
page0: call Show_Volts
call Show_Amps ; "99.99V 99.99A"
movlw LCDLINE2
call Set_Cursor
call Show_Watts
call Show_AmpHours ; "9999.9W 99.99Ah"
goto ref_delay
page1: call Show_Volts
call Show_Amps ; "99.99V 99.99A"
movlw LCDLINE2
call Set_Cursor
call Show_rpm ; "99999rpm x 9"
call Show_Blades
endif
; Wait 1/3 second (3 readings per second)
; Check buttons while waiting
ref_delay:
btfss INTCON,TMR0IF
goto ref_delay ; wait for Timer0 overflow (55.555mS)
movlw REFRESH_DELAY
addwf TMR0 ; recharge Timer0
bcf INTCON,TMR0IF
call page_button ; handle page button
call blade_button ; handle blades button
decfsz ref_timer
goto display_page ; 6 Timer0 overflows = 333.3mS (1/3 Second)
check_hold:
btfss HDBTN ; hold switch on ?
goto do_display ; yes, hold last readings
goto ReadInputs ; no, get new readings
END
hi,
A quick look at the code:
Code:ifdef __16F88 movlw B'1[COLOR="Red"]1[/COLOR]101111' ; PortA directions (16F88) movwf TRISA
RA6 is set as an Input
The RA5 in the previous post was a typo, should have read RA6...
OK. Though it is set as input, but it is connected to ground. Can I use it to interface with LCD_RS?
If its physically connected to ground [0v],, its not in service.
Why is it connected to ground.?
If you want to use it with your LCD, it should be connected to LCD_RS pin.?
BTW: the code you posted is incomplete,I cannot assemble it.
Because it seems like it is not being used for me, so i ground it. Now, as to move my LCD_RS from B5, i try to use A6/OSC2. Below are the complete compilable file. Thanks.
ifdef __16F88
movlw B'1[COLOR="Red"]0[/COLOR]101111' ; PortA directions (16F88)
movwf TRISA
hi,
I'll look thru the code, it will take a little while.
What you should do is to change bit6 marked in RED to a '0' and then retry writing to the LCD. [ make sure the ground isnt on RA6]
If it works OK, let me know so that I dont waste time looking thru your code.
Code:ifdef __16F88 movlw B'1[COLOR="Red"]0[/COLOR]101111' ; PortA directions (16F88) movwf TRISA
hi,
Look at these images taken from the Oshonsoft Simulator using your program.
I had to change a couple of pins around so that my Sim would run.
As the program you have is written for the 16F88, which you are using, why do you want to switch the pins about, ie: PORTA,6..???
If you wired it as per the program for the 16F88 it will work.
you can download it from Oshonsoft
Yup..i juz downloaded it..thanks
hi,
This is the edited version I used with OS.
Dont forget a Sim runs much slower than normal.
Just load into OS, set the LCD 'setup to suit' and run
The image shows the LCD settings for my version of the asm.
I see that there is modification for the pins of LCD...
is this the one u manage to run it correctly?
yes it is, OS requires the LCD data pins [4] to be either the high or low nibble of a port.
#DEFINE RPM_IN PORTA,4;;;PORTB,0 ; rpm input
Hi...
might want to know why the rpm pin is changed as well? Thanks...Code:#DEFINE RPM_IN PORTA,4;;;PORTB,0 ; rpm input
For the test, I reallocated PORTB.0 to be part of the LCD data nibble.
As the main program uses PORTB.0 on interrupt, you must reassign PORTB.0 back to RPM when you use the original program.
If you connect PORTA.6 as LCD_RS and ensure that you configure as an output the project should work in a PIC.
movlw B'10101111' ; PortA directions (16F88)
Always thought that design was a little wonky. Why break up the D4-7 LCD lines? Why not use RB1-4 and move E to RA4. As for counting RPM most might use the TMR0 input (like frequency counters do) instead of RB0. Swap S1 and LCD/RS (pullup built in). Just an odd choice of I/O allocation IMO.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?