Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Code problems with 16F88

Status
Not open for further replies.

IMSlo

Newbie level 6
Joined
Oct 1, 2006
Messages
13
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,499
is lo or hi better porta 16f88

Can someone tell me why the attached code won't run on a 16f88 PIC. This is a simple elapsed time timer running on a timer0 interrupt and displaying the time on a 2 X 16 LCD. I downloaded the code from several places and put it together. With the minor necessary changes the code will run for days on a 16f627a. On the 88 it will run a few seconds, zero up run a few seconds, zero up and maybe even run a few minutes and zero up. It will eventually quit some times with the display showing numbers and again with the display blank. I'm at my wit's end. Please ignore the comments because they may or may not be right. Any help would be appreciated.

;******************************************************************************
; ZERO-ERROR ONE SECOND TIMER
; (Roman Black 2001, public domain, use it as you like)
;

;
;******************************************************************************


;==============================================================================
; processor defined ;
LIST p=16F88 ;tell assembler what chip we are using
include "P16F88.inc" ;include the defaults for the chip
ERRORLEVEL 0, -302 ;suppress bank selection messages


;==============================================================================
; MPLAB stuff here

LIST b=5, n=97, t=ON, st=OFF
; absolute listing tabs=5, lines=97, trim long lines=ON, symbol table=OFF

__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO

;Program Configuration Register 2
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF

LCD_PORT Equ PORTB
LCD_TRIS Equ TRISB
LCD_RS Equ 0x04 ;LCD handshake lines
LCD_RW Equ 0x06
LCD_E Equ 0x07


;==============================================================================
; Variables here

CBLOCK 0x20
sec
sec10
min
min10
hr
hr10
bres_hi ; hi byte of our 24bit variable
bres_mid ; mid byte
bres_lo ; lo byte
; (we only need 3 bytes for this system)

status_temp ; used for interrupt servicing
w_temp ; used for interrupt servicing
templcd ;temp store for 4 bit mode
templcd2
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
oldtime
ENDC


;==============================================================================
; Code here

org 0x000 ; Set program memory base at reset vector 0x000
reset
goto setup ; set up ints and port stuff

org 0x004 ; Interrupt vector, int handler code comes next.
;==============================================================================

;******************************************************************************
; INTERRUPT HANDLER (runs this code each timer0 interrupt)
;******************************************************************************
;
;------------------
int_handler
;
;------------------

;-------------------------------------------------
; first we preserve w and status register

movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register

;-------------------------------------------------
; Note! we get here every 256 instructions, we
; can now do our special one second timing system.

; This consists of three main steps;
; * subtract 256 counts from our 24bit variable
; * test if we reached the setpoint
; * if so, add 1,000,000 counts to 24bit variable and generate event.
;-------------------------------------------------
; * optimised 24 bit subtract here
; This is done with the minimum instructions.
; We subtract 256 from the 24bit variable
; by just decrementing the mid byte.

tstf bres_mid ; first test for mid==0
skpnz ; nz = no underflow needed
decf bres_hi,f ; z, so is underflow, so dec the msb

decfsz bres_mid,f ; dec the mid byte (subtract 256)

; now the full 24bit optimised subtract is done!
; this is about 4 times faster than a "proper"
; 24bit subtract.

goto int_exit ; nz, so definitely not one second yet.
; in most cases the entire int takes
; only 16 instructions.
;------------------------
; * test if we have reached one second.
; only gets here when mid==0, it MAY be one second.
; only gets to here 1 in every 256 times.
; (this is our best optimised test)
; it gets here when bres_mid ==0.

tstf bres_hi ; test hi for zero too
skpz ; z = both hi and mid are zero, is one second!
goto int_exit ; nz, so not one second yet.

;-------------------------------------------------
; Only gets to here if we have reached one second.

; now we can generate our one second event, like add
; one second to our clock or whatever.
; (in this example we toggle a led)

; The other thing we need to do is add 1,000,000 counts
; to our 24bit variable and start all over again.
;-------------------------------------------------
; Add the 1,000,000 counts first.
; One second = 1,000,000 = 0F 42 40 (in hex)

; As we know hi==0 and mid==0 this makes it very fast.
; This is an optimised 24bit add, because we can
; just load the top two bytes and only need to do
; a real add on the bottom byte. This is much quicker
; than a "proper" 24bit add.

movlw 0x0F ; get msb value
movwf bres_hi ; load in msb

movlw 0x42 ; get mid value
movwf bres_mid ; load in mid

movlw 0x40 ; lsb value to add
addwf bres_lo,f ; add it to the remainder already in lsb
skpnc ; nc = no overflow, so mid is still ok

incf bres_mid,f ; c, so lsb overflowed, so inc mid
; this is optimised and relies on mid being known
; and that mid won't overflow from one inc.

; that's it! Our optimised 24bit add is done,
; this is roughly twice as quick as a "proper"
; 24bit add.
;-------------------------
; now we do the "event" that we do every one second.

; Note! for this example we toggle a led, which
; will give a flashing led which is on for a second
; and off for a second.
; Add your own code here for your one second event.

; Note! My led is on porta,3
; your led may be on a different pin.
; movlw b'00001000' ; mask for bit 3
; xorwf PORTB,f ; toggle PORTA,bit3 (toggle the led)

movlw sec ; point at sec register
movwf FSR
newdigit: incf INDF, f ; current digit up one
movlw sec ; get difference between sec and FSR
subwf FSR, W
call sethi ; use to get high limit + 1
subwf INDF, W ; reached that number yet?
btfss STATUS, Z ; skip over if yes
goto int_exit ; else exit isr
clrf INDF ; set current digit to 0
incf FSR, f ; point at next digit
goto newdigit ; no, increment the next digit


;-------------------------------------------------
; now our one second event is all done, we can exit the
; interrupt handler.
;-------------------------------------------------
; finally we restore w and status registers.
; also clears TMRO int flag now we are finished.
int_exit
BCF INTCON,2 ; reset the tmr0 interrupt flag
bcf STATUS,Z
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents

retfie ; return from interrupt

;------------------------------------------------------------------------------
;-------------------------------------------------------------------------;
; High limit + 1 of digits at position W ;
;-------------------------------------------------------------------------;
sethi:
addwf PCL, f
dt H'A',H'6',H'A',H'6',H'A',H'A'



;******************************************************************************
; SETUP (runs this only once at startup)
;******************************************************************************


;
;------------------
setup ; goto label
;------------------

movlw B'01100000' ; 4Mhz = B'01100000'
banksel OSCCON
movwf OSCCON
banksel 0
;Wait until osc stabilizes
lp:
btfss OSCCON, 2
goto lp


;-------------------------------------------------
; Note! 16F84 version.
; Note! here we set up peripherals and port directions.
; this will need to be changed for different PICs.
;-------------------------------------------------
; OPTION setup
movlw b'00001000' ;

; -------x ;
; Note! We set the prescaler to the wdt, so timer0


; has NO prescaler and will overflow every 256
; instructions and make an interrupt.
;


banksel OPTION_REG ; go proper reg bank
movwf OPTION_REG ; load data into OPTION_REG
banksel 0 ; back to normal bank 0
;-------------------------------------------------
; PORTB pins direction setup
; 1=input, 0=output
clrf PORTB ;
;
movlw b'00000000' ; all 8 portb are outputs
;
banksel TRISB ; go proper reg bank
movwf TRISB ; send mask to portb
banksel 0 ; back to normal reg bank
;-------------------------------------------------
; PORTA pins direction setup
; 1=input, 0=output
clrf PORTA ;
;
movlw b'00000000' ; all 5 porta are outputs,
; (with 16F84 porta only has lower 5 bits)
;
banksel TRISA ; go proper reg bank
movwf TRISA ; send mask to porta
banksel 0 ; back to normal reg bank
;-------------------------------------------------
; INTCON setup
;
; for this code example, we enable the timer0
; overflow interrupt.
;
; enable interrupts last
; interrupt setup
movlw b'11100000' ; GIE=on TOIE=on (timer0 overflow int)
; bsf INTCON,7
; bsf INTCON,6
; bsf INTCON,5
banksel INTCON
movwf INTCON
banksel 0
clrf sec
clrf sec10
clrf min
clrf min10
clrf hr
clrf hr10

;-------------------------------------------------
; Note! Now the hardware is set up we need to load the
; first count for one second into our 24bit bres variable.
;-------------------------------------------------
; Note! This example uses 4 MHz clock, which is
; 1,000,000 counts per second.
;
; We require a 1 second period, so we must load
; 1,000,000 counts each time.
; 1,000,000 = 0F 42 40 (in hex)
;
; We also need to add 256 counts for the first time,
; so we just add 1 to the mid byte.
; Check mid overflow if needed.

; here we load the 24bit variable.
movlw 0x0F ; get msb value
movwf bres_hi ; put in hi

movlw 0x42 +1 ; get mid value (note we added 1 to it)
movwf bres_mid ; put in mid

movlw 0x40 ; get lsb value
movwf bres_lo ; put in mid

;call LCD_Init


; now setup is complete, we can start execution.
;-------------------------------------------------
goto main ; start main program

;------------------------------------------------------------------------------
;Initialise LCD
LCD_Init call Delay100 ;wait for LCD to settle

movlw 0x20 ;Set 4 bit mode
call LCD_Cmd

movlw 0x28 ;Set display shift
call LCD_Cmd

movlw 0x06 ;Set display character mode
call LCD_Cmd

movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd ;Set cursor off

call LCD_Clr ;clear display

retlw 0x00
; command set routine
LCD_Cmd movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high

movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00

LCD_CharD addlw 0x30 ;add 0x30 to convert to ASCII
LCD_Char movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high

movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00

LCD_Line1 movlw 0x80 ;move to 1st row, first column
call LCD_Cmd
retlw 0x00

LCD_Line2 movlw 0xc0 ;move to 2nd row, first column
call LCD_Cmd
retlw 0x00

LCD_Line1W addlw 0x80 ;move to 1st row, column W
call LCD_Cmd
retlw 0x00

LCD_Line2W addlw 0xc0 ;move to 2nd row, column W
call LCD_Cmd
retlw 0x00

LCD_CurOn movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00

LCD_CurOff movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00

LCD_Clr movlw 0x01 ;Clear display
call LCD_Cmd
retlw 0x00

;LCD_HEX movwf tmp1
; swapf tmp1, w
; andlw 0x0f
; call HEX_Table
; call LCD_Char
; movf tmp1, w
; andlw 0x0f
; call HEX_Table
; call LCD_Char
; retlw 0x00

Delay255 movlw 0xff ;delay 255 mS
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay5 movlw 0x05 ;delay 5.000 ms (4 MHz clock)
d0 movwf count1
d1 movlw 0xC7 ;delay 1mS
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0

decfsz count1 ,f
goto d1
retlw 0x00

Pulse_e bsf LCD_PORT, LCD_E
nop
bcf LCD_PORT, LCD_E
retlw 0x00

;end of LCD routines

DispTime
MOVLW 0x04
CALL LCD_Line1W
movf hr10,w
CALL LCD_CharD
movf hr,w
CALL LCD_CharD
MOVLW ":"
CALL LCD_Char
movf min10,w
CALL LCD_CharD
movf min,w
CALL LCD_CharD
MOVLW ":"
CALL LCD_Char
movf sec10,10
CALL LCD_CharD
movf sec,w
CALL LCD_CharD
RETURN



;*****************************************************************************


;******************************************************************************
; MAIN (main program loop)
;******************************************************************************
;
;------------------
main ; goto label
;------------------
call LCD_Init
;-------------------------------------------------
; Note! This example uses the timer0 overflow interrupt.
; This will interrupt our main program every 256 instructions
; and do the one second timer system.
;-------------------------------------------------
main_loop ;
movf oldtime, W ; is oldtime the same as sec?
subwf sec, W
btfsc STATUS, Z ; if not, skip over next instruction
goto main_loop ; else continue checking
call DispTime ; sec has changed, display the time
movf sec, W ; make sec and oldsec the same
movwf oldtime

; or calls to the main program pieces.
; The interrupt does all the one second timer stuff.
; stuff
; stuff
; stuff
; stuff

;-------------------------------------------------
goto main_loop ; keep running the main code.

;------------------------------------------------------------------------------


;==============================================================================
end ; no code after this point.
;==============================================================================
 

16f88 porta

sounds like something to do with your reset or clock system

check crystal caps values
if your using a breadboard/veroboard remove the caps as the board will load the crystal too much as it has capacitance also
 

I don't have any caps nor crystal. I'm using internal clock on the PIC. All I have on the breadboard is a voltage regulator, the PIC and a LCD.
 

Thanks for the help.
I installed caps as shown in the sketch below. I don't know if this is the proper installation or not. They had no effect on my problem.

32_1164126605.JPG
 

Hi,

That diagram looks weird to me. Just make sure you have a 0.1uf cap connected from VDD to VSS (+5v to GND) near your PIC. For the F88 thats from pins 14 and 5. The cap doesn't (or shouldn't) have a polarity so either way around would do.
And I'm sure the -5v in that diagram is a mistake, that would mean you're running your PIC from -5 to +5v, and PIC don't like running off 10v :D

Also, MCLR (the global reset pin). You could have an internal pull up on this pin, so you can use MCLR as a regular I/O. Or, just pull this pin high with a 4.7K- 22k resistor to +5V. Either way, it needs to be pulled high.

An 'intermitent' problem is usually down to noise triggering the reset, or a dodgy power supply. I've built a few PIC circuits on stripboard, and using the internal osc is the only way really...as an external xtal oscillator is pulled off frequency on basic stripboard (quick and dirty). I can't see anything immediately wrong with your code, and skimmed over it for bank selection (always gets me in my code) but it is a bit messy. I realise that copy/pasting doesn't always keep the formatting but I noticed a couple of case where you've got the name of a subroutine with an instruction right after it on the same line...surely MPLAB would kick up a fuss? And I see 'lp:', I didn't know colons could be used in labels.

Anyway, could well be a software problem, it might be worth writing a very simle test program for your hardware setup. Same settings just without the 'timer' code. Still set up your I/O's on the tris registers, and your internal osc, but maybe make a basic delay for an LED or two, just to see if its working ok. I must say, some of that indirect addressing is quite complicated and it can be easy to lose track of just what exactly you are putting in the FSR, beware.

Buriedcode.
 

the main prob is the config string doesnt specify the osc config
so if i remember it defaults to external i/o mplab or crystal hs
if you dont define it

its a clock prob for sure

the code looks fine and here runs in proteus uses 54% cpu and dosnt crash
and steps code fine for five hours or so i left it on for last night

proteus refused to set the clock from code
so i know its a config issue for sure
 

Thanks for the reply Buriedcode.
The diagram, I am learning is weird, I don't know much about electronics and really didn't know how to connect the caps.
I justed connected one the way you suggested with still no results. I really don't think the power supply is the problem because as I stated in my original post a 627a will run for days without missing a beat. I think there is a timer or some setting that I am missing that's causing the problem. Some of the code is pretty complicated I certainly didn't write it as I said before I copied it but it runs fine on the 627a.

Thanks again for the reply.
 

VSMVDD,
Apparently I didn't notice your reply earlier. The first config statement does contain a clock setting I think it is INTOS_IO. The clock is further configured in the OSCCON register. It's configured for 4 mhz.

I have cleaned the code up and I will try to attsach it as a zipped .asm file. Maybe it will be a little easier to read.
 

VSMVDD,

I meant to ask you in last post and forgot.

What is proteus? It sounds like it might be a simulator.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top