Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

My Code works in ISIS but not for real?

Status
Not open for further replies.

dons21

New Member
Hello again, the code below works on isis and it displays 0000 to 1023 depending on the voltage input of RA4 0-5v

However when I test it on my breadboard the ADC result displayed remains fixed i.e.
When I release from reset and RA4 is at 0v is will show 0000.

If I change the RA4 input to 5v (via pot) nothing happens unless I reset again and 1023 is shown.

Please point me in the right direction. (the connection on the breadboard are all ok)

Once again many thanks


Code:
;******************************************************************************
;                                                                             *
;    Filename:   7 Seg ADC 10-Bit Multiplex.asm                               *
;******************************************************************************
;					(RA2)1	18(RA1)Display 1 Enable		  _A_		  *
;					(RA3)2	17(RA0)Display 2 Enable		F|   | B      *
;		ADC Input		(RA4)3	16(RA7)Display 3 Enable		F|_G_| B	  *
;		10k to Vdd		(RA5)4	15(RA6)Display 4 Enable		E|   | C	  *
;					(VSS)5	14(VDD)				E|_ _| C	  *
;				Seg G 	(RB0)6	13(RB7)	Seg DP		    D		  *
;				Seg F 	(RB1)7	12(RB6)	Seg A								  *
;				Seg E 	(RB2)8	11(RB5)	Seg B								  *
;				Seg D 	(RB3)9	10(RB4)	Seg C 								  *
;******************************************************************************
;                                                                             *
;    Revision History:     1.0                                                *
;	 Read 10bit of ADC convert to decimal and display 0-1023 using TMR0	      *
;                                                                             *
;******************************************************************************

;------------------------------------------------------------------------------
; PROCESSOR DECLARATION
;------------------------------------------------------------------------------
	
    LIST      p=16F88              ; list directive to define processor
    #INCLUDE <P16F88.INC>          ; processor specific variable definitions
	ERRORLEVEL	0,	-302		   ; suppress bank selection messages
;------------------------------------------------------------------------------
; CONFIGURATION WORD SETUP
;------------------------------------------------------------------------------
#Define		DispThou 	PORTA,1
#Define		DispHund 	PORTA,0
#Define		DispTens 	PORTA,7
#Define		DispOnes 	PORTA,6
	

	__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_OFF & _WDT_OFF & _INTRC_IO
	__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF


		cblock	0x20				;GPR variable registers allocated contiguously
				
				W_Temp				;Temporay files for Interrupt
				S_Temp	
				PC_Temp
				NumH
				NumL
                TenK
				Thou
				Hund
				Tens
				Ones
				ThouData
				HundData
				TensData
				OnesData
				disp
		endc 

RESET	ORG		0x0000				; processor reset vector
		goto	Main		

		ORG		0x0004
INTR	movwf 	W_Temp				;Copy W to TEMP register
		swapf 	STATUS, w 			;Swap status to be saved into W
		clrf 	STATUS 				;bank 0, regardless of current bank, Clears IRP,RP1,RP0
		movwf 	S_Temp				;Save status to bank zero STATUS_TEMP register
		movf 	PCLATH, w 			;Only required if using page 1
		movf 	PC_Temp				;Save PCLATH into W
		clrf 	PCLATH 				;Page zero, regardless of current page
		

		bcf		INTCON,2			;Reset TMR0 Overflow Flag
	
		btfsc	DispOnes
		goto	Dis1	
		btfsc	DispTens
		goto	Dis4		
		btfsc	DispHund			
		goto	Dis3
		btfsc	DispThou
		goto	Dis2
	
		
Dis1	
		clrf	PORTA
		movfw	ThouData
		movwf	PORTB
		bsf		DispThou
		goto	Exit
Dis2
		clrf	PORTA
		movfw	HundData
		movwf	PORTB
		bsf		DispHund
		goto	Exit
Dis3
		clrf	PORTA
		movfw 	TensData
		movwf	PORTB
		bsf		DispTens
		goto	Exit
Dis4
		clrf	PORTA
		movfw	OnesData
		movwf	PORTB
		bsf		DispOnes
		goto	Exit


Exit	movf 	PC_Temp, w	 		;Restore PCLATH
		movwf 	PCLATH 				;Move W into PCLATH
		swapf 	S_Temp, w	 		;Swap STATUS_TEMP register into W
		movwf 	STATUS 				;Move W into STATUS register
		swapf 	W_Temp, f 			;Swap W_TEMP
		swapf 	W_Temp, w 			;Swap W_TEMP into W

	retfie

Main	bcf		STATUS,RP0			;setbank0
	
		clrf	PORTA				;set PORTB ouputs low
		clrf	PORTB				;set PORTA ouputs low
		CLRF	OnesData
		clrf	TensData
		clrf	HundData
		clrf	ThouData
		

		bsf		STATUS,RP0			;setbank1			
		
		movlw	b'11010010'	
		movwf	OPTION_REG
		movlw	0x07
		movwf	CMCON				;turn comparators off (WAS NOT INSIDE BANK 1)	
		movlw	b'01100000'			;Set up clock speed mhz4
		movwf	OSCCON	
		movlw	b'00010000'			;set RA4 to analog 1=analog 0=digital
		movwf	ANSEL	
		movlw 	b'00000000'			;set PortB all outputs
		movwf 	TRISB				
		movlw	b'00010000'			;set port A inputs/outputs 1=input 0=output
		movwf	TRISA
		movlw	b'10100000'			;set up interrupt
		movwf	INTCON
		movlw	b'10000000'
		movwf	ADCON1				;set ADC Res format
		bcf		STATUS,RP0			;setbank0
		movlw   b'01100001'			; set ADC to RA4 enable ADC 8Tosc for TAD
		movwf	ADCON0   

	goto	START						; go to beginning of program

START	
		
 		call	ReadADC
		movf	Thou, W
		call	Table
		movwf	ThouData
		movf	Hund, W
		call	Table
		movwf	HundData
		movf	Tens, W
		Call	Table
		movwf	TensData
		movf	Ones, W
		call	Table
		movwf	OnesData

	goto    START				

;Table Data for 7 seg displays			

Table	ADDWF	PCL, f			;data table for bit pattern
	    retlw	b'01111110'		;0 -|A|B|C|D|E|F|-  
		retlw	b'00110000'		;1 -|-|B|C|-|-|-|-  
		retlw	b'01101101'		;2 -|A|B|-|D|E|-|G  
		retlw	b'01111001'		;3 -|A|B|C|D|-|-|G  
		retlw	b'00110011'		;4 -|-|B|C|-|-|F|G  
		retlw	b'01011011'		;5 -|A|-|C|D|-|F|G  
		retlw	b'01011111'		;6 -|A|-|C|D|E|F|G  
		retlw	b'01110000'		;7 -|A|B|C|-|-|-|-  
		retlw	b'01111111'		;8 -|A|B|C|D|E|F|G 
	    retlw	b'01110011'		;9 -|A|B|C|D|E|F|-
		
	return



Convert:                        ; Takes number in NumH:NumL
                                ; Returns decimal in
                                ; TenK:Thou:Hund:Tens:Ones
        swapf   NumH, w
		iorlw	B'11110000'
        movwf   Thou
        addwf   Thou,f
        addlw   0XE2
        movwf   Hund
        addlw   0X32
        movwf   Ones

        movf    NumH,w
        andlw   0X0F
        addwf   Hund,f
        addwf   Hund,f
        addwf   Ones,f
        addlw   0XE9
        movwf   Tens
        addwf   Tens,f
        addwf   Tens,f

        swapf   NumL,w
        andlw   0X0F
        addwf   Tens,f
        addwf   Ones,f

        rlf     Tens,f
        rlf     Ones,f
        comf    Ones,f
        rlf     Ones,f

        movf    NumL,w
        andlw   0X0F
        addwf   Ones,f
        rlf     Thou,f

        movlw   0X07
        movwf   TenK

        movlw   0X0A                             
Lb1:
        addwf   Ones,f
        decf    Tens,f
        btfss   3,0
        goto   Lb1
Lb2:
        addwf   Tens,f
        decf    Hund,f
        btfss   3,0
        goto   Lb2
Lb3:
        addwf   Hund,f
        decf    Thou,f
        btfss   3,0
        goto   Lb3
Lb4:
        addwf   Thou,f
        decf    TenK,f
        btfss   3,0
        goto   Lb4

	retlw	0x00

ReadADC
		movf	ADRESH,w
		movwf	NumH
		bsf		STATUS,RP0
		movf	ADRESL,w
		bcf		STATUS,RP0
		movwf	NumL
		call	Convert
		bsf		ADCON0,2
		
	return



	END
 
hi Don,
Your program runs OK in the Oshonsoft simulator.
It appears to me that the refresh rate and execution time for the display is so long that the readadc subr is not being called in a real PIC.
 
His OSCCON is wrong it should be some thing like this OSCCON = 01100010 or 0x62
 
Last edited:
be80be
His OSCCON is wrong it should be some thing like this OSCCON = 01100010 or 0x62

I just tried that, but it made no difference. :-(

I don`t know where I have gone wrong I thought it might be a bad chip. However the code below does the same without using an Interrupt. It works well.

Code:
;******************************************************************************
;                                                                             *
;    Filename:   7 Seg ADC 10-Bit Multiplex.asm                               *
;******************************************************************************
;						(RA2)1	18(RA1)Display 1 Enable			  _A_		  *
;						(RA3)2	17(RA0)Display 2 Enable			F|   | B      *
;		ADC Input		(RA4)3	16(RA7)Display 3 Enable			F|_G_| B	  *
;		10k to Vdd		(RA5)4	15(RA6)Display 4 Enable			E|   | C	  *
;						(VSS)5	14(VDD)							E|_ _| C	  *
;				Seg G 	(RB0)6	13(RB7)	Seg DP				   	   D		  *
;				Seg F 	(RB1)7	12(RB6)	Seg A								  *
;				Seg E 	(RB2)8	11(RB5)	Seg B								  *
;				Seg D 	(RB3)9	10(RB4)	Seg C 								  *
;******************************************************************************
;                                                                             *
;    Revision History:     1.0                                                *
;	 Read 8bit of ADC convert to decimal and display 0-1023			          *
;                                                                             *
;******************************************************************************

;------------------------------------------------------------------------------
; PROCESSOR DECLARATION
;------------------------------------------------------------------------------
	
    LIST      p=16F88              ; list directive to define processor
    #INCLUDE <P16F88.INC>          ; processor specific variable definitions
	ERRORLEVEL	0,	-302		   ; suppress bank selection messages
;------------------------------------------------------------------------------
; CONFIGURATION WORD SETUP
;------------------------------------------------------------------------------
#Define	DispThou	PORTA,1
#Define	DispHund	PORTA,0
#Define	DispTens	PORTA,7
#Define	DispOnes	PORTA,6
	

	__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_OFF & _WDT_OFF & _INTRC_IO
	__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF


		cblock	0x20						;GPR variable registers allocated contiguously
				NumH
				NumL
                TenK
				Thou
				Hund
				Tens
				Ones
			endc 

RESET	ORG		0x0000				; processor reset vector
		
		bcf		STATUS,RP0			;setbank0
		clrf 	ADRESH
		CLRF	PORTA				;set PORTB ouputs low
		CLRF	PORTB				;set PORTA ouputs low
		clrf	TMR0
		clrf	Ones				;clear GPRs
		clrf	Tens
		clrf	Hund
		clrf	TenK
		clrf	Thou
		clrf	NumH
		clrf	NumL
		bsf		STATUS,RP0			;setbank1			
		
		movlw	b'11010111'	
		movwf	OPTION_REG
		movlw	0x07
		movwf	CMCON				;turn comparators off (WAS NOT INSIDE BANK 1)	
		movlw	b'01100000'			;Set up clock speed mhz4
		movwf	OSCCON	
		movlw	b'00010000'			;set RA2 to analog 1=analog 0=digital
		movwf	ANSEL	
		movlw 	b'00000000'			;set PortB all outputs
		movwf 	TRISB				
		movlw	b'00010000'			;set port A inputs/outputs 1=input 0=output
		movwf	TRISA
		movlw	b'10000000'
		movwf	ADCON1				;set ADC Res format
		bcf		STATUS,RP0			;setbank0
		movlw   b'01100001'			; set ADC to RA4 enable ADC 8Tosc for TAD
		movwf	ADCON0   
	
		
		goto	START						; go to beginning of program

START
        call    ReadADC         ; Read RA0 and convert to decimal
        movf    Thou,w          ; Get thou Result
        call    Table           ; get segment data
w1      btfss   TMR0,2          ; ~1-ms interval? yes, skip, else
        goto    w1              ; loop (wait)
        clrf    TMR0            ; reset TMR0
        bcf     DispOnes         ; display 3 OFF (blank display)
        movwf   PORTB           ; to PORTB
        bsf     DispThou		;PORTA,1         ; display 1 ON (thous)
        movf    Hund,w          ; Get hund Result
        call    Table           ; get segment data
w2      btfss   TMR0,2          ; ~1-ms interval? yes, skip, else
        goto    w2              ; loop (wait)
        clrf    TMR0            ; reset TMR0
        bcf     DispThou		;PORTA,1         ; display 1 OFF thous
        movwf   PORTB           ; to PORTB
        bsf     DispHund		;PORTA,0         ; display 2 ON
        movf	Tens,w
		call	Table
w3		btfss   TMR0,2
		goto	w3
		clrf	TMR0
		bcf		DispHund
		movwf	PORTB		
		bsf		DispTens
		movf    Ones,w          ; Get Ones Result
		call    Table           ; get segment data
w4      btfss   TMR0,2          ; ~1-ms interval? yes, skip, else
        goto    w4              ; loop (wait)
        clrf    TMR0            ; reset TMR0
        bcf     DispTens         ; display 2 OFF;;;;;;;;;;;;;;;;;;;;;;
        movwf   PORTB           ; to PORTB
        bsf     DispOnes         ; display 3 ON
        

goto    START           ;				





			

Table	ADDWF	PCL, f			;data table for bit pattern
	    retlw	b'01111110'		;0 -|A|B|C|D|E|F|-  
		retlw	b'00110000'		;1 -|-|B|C|-|-|-|-  
		retlw	b'01101101'		;2 -|A|B|-|D|E|-|G  
		retlw	b'01111001'		;3 -|A|B|C|D|-|-|G  
		retlw	b'00110011'		;4 -|-|B|C|-|-|F|G  
		retlw	b'01011011'		;5 -|A|-|C|D|-|F|G  
		retlw	b'01011111'		;6 -|A|-|C|D|E|F|G  
		retlw	b'01110000'		;7 -|A|B|C|-|-|-|-  
		retlw	b'01111111'		;8 -|A|B|C|D|E|F|G 
	    retlw	b'01110011'		;9 -|A|B|C|D|E|F|-
		
	return

;This routine downloaded from http://www.piclist.com
Convert:                        ; Takes number in NumH:NumL
                                ; Returns decimal in
                                ; TenK:Thou:Hund:Tens:Ones
        swapf   NumH, w
		iorlw	B'11110000'
        movwf   Thou
        addwf   Thou,f
        addlw   0XE2
        movwf   Hund
        addlw   0X32
        movwf   Ones

        movf    NumH,w
        andlw   0X0F
        addwf   Hund,f
        addwf   Hund,f
        addwf   Ones,f
        addlw   0XE9
        movwf   Tens
        addwf   Tens,f
        addwf   Tens,f

        swapf   NumL,w
        andlw   0X0F
        addwf   Tens,f
        addwf   Ones,f

        rlf     Tens,f
        rlf     Ones,f
        comf    Ones,f
        rlf     Ones,f

        movf    NumL,w
        andlw   0X0F
        addwf   Ones,f
        rlf     Thou,f

        movlw   0X07
        movwf   TenK

        movlw   0X0A                             
Lb1:
        addwf   Ones,f
        decf    Tens,f
        btfss   3,0
        goto   Lb1
Lb2:
        addwf   Tens,f
        decf    Hund,f
        btfss   3,0
        goto   Lb2
Lb3:
        addwf   Hund,f
        decf    Thou,f
        btfss   3,0
        goto   Lb3
Lb4:
        addwf   Thou,f
        decf    TenK,f
        btfss   3,0
        goto   Lb4

        retlw	0x00
ReadADC	
		movf	ADRESH,w
		movwf	NumH
		bsf		STATUS,RP0
		movf	ADRESL,w
		bcf		STATUS,RP0
		movwf	NumL
		call	Convert
		bsf		ADCON0,2			;start adc conversion

		return
	END
 
Last edited:
I haven't looked over all the code, but I do see one glaring problem at the bottom of your code.

You are setting the go/done bit in ADCON0, but you are returning from the call most likely before it is done. At a 4mhz clock, it only has 1us to finish the reading properly, which I don't think it can do. You need to poll the go/done bit like this:

Code:
BSF          ADCON0,2   ;set the go done bit
BTFSC      ADCON0,2   ;see if the reading is done, when done the ADC will clear the Go/Done bit
GOTO       $ -1            ;if still set, go back and keep testing
RETURN
 
Last edited:
This
Code:
                movlw	b'01100000'			;Set up clock speed mhz4
		movwf	OSCCON
Should be this you need to
Note 1: Bit resets to ‘0’ with Two-Speed Start-up mode and LP, XT or HS selected as the
oscillator mode.
Code:
                movlw	b'01101010'			;Set up clock speed mhz4
		movwf	OSCCON
 
Last edited:
Burt that got it going.
movlw b'01101010' ;Set up clock speed mhz4
movwf OSCCON

I did how ever try to recreate the problem but putting b'01100000' back into OSCCON made no difference it still continued to work.

Do you ever get any gremlins in the PIC MCU? As I think I had one :)

Now its working I can try and refine the code.

Cheers
 
To wannaBinventor
You are setting the go/done bit in ADCON0, but you are returning from the call most likely before it is done. At a 4mhz clock, it only has 1us to finish the reading properly, which I don't think it can do. You need to poll the go/done bit like this:

Thanks for the info on polling I have seen it before though. Do you think I should be setting the GO/DONE bit more often as when I test it in MPLAB SIM and place a Breakpoint on the BSF ADCON0,2 line.

It is set, between 222uS and 267uS depending how it take to convert the ADC result from binary to decimal.
 
Last edited:
Hi all, I thought that the problem with my code was the 16f88 playing up. As the code would work once. ie once programmed and released from reset it would work. Remove the power then reconnect it the 7seg displays showed nothing. I would have to reprogram the chip again!

Even though the code worked in the simulators

The problem was with the Intterupt

Code:
		ORG		0x0004
INTR	movwf 	W_Temp				;Copy W to TEMP register
		swapf 	STATUS, w 			;Swap status to be saved into W
		clrf 	STATUS 				;bank 0, regardless of current bank, Clears IRP,RP1,RP0
		movwf 	S_Temp				;Save status to bank zero STATUS_TEMP register
		[COLOR="red"]movf 	PCLATH, w 			;Only required if using page 1
		movf 	PC_Temp				;Save PCLATH into W
		clrf 	PCLATH 				;Page zero, regardless of current page[/COLOR]
		

		bcf		INTCON,2			;Reset TMR0 Overflow Flag
	
		btfsc	DispOnes
		goto	Dis1	
		btfsc	DispTens
		goto	Dis4		
		btfsc	DispHund			
		goto	Dis3
		btfsc	DispThou
		goto	Dis2
	
		
Dis1	
		clrf	PORTA
		movfw	ThouData
		movwf	PORTB
		bsf		DispThou
		goto	Exit
Dis2
		clrf	PORTA
		movfw	HundData
		movwf	PORTB
		bsf		DispHund
		goto	Exit
Dis3
		clrf	PORTA
		movfw 	TensData
		movwf	PORTB
		bsf		DispTens
		goto	Exit
Dis4
		clrf	PORTA
		movfw	OnesData
		movwf	PORTB
		bsf		DispOnes
		goto	Exit


Exit	[COLOR="red"]movf 	PC_Temp, w	 		;Restore PCLATH
		movwf 	PCLATH 				;Move W into PCLATH[/COLOR]
		swapf 	S_Temp, w	 		;Swap STATUS_TEMP register into W
		movwf 	STATUS 				;Move W into STATUS register
		swapf 	W_Temp, f 			;Swap W_TEMP
		swapf 	W_Temp, w 			;Swap W_TEMP into W

	retfie


Once I had removed the lines of code highlighted in red every thing worked as expected.

Don
 
I think the 2nd line is supposed to be movwf PC_Temp, otherwise u are defaulting to a movf PC_Temp,f

Not protecting PCLATH can cause problems if your code uses ANY non page 0 codespace.


And simulators aren't perfect.

I ran out of bank 0 gpr for a large project, so I started 'scavenging' bytes from unused bank 0 peripheral ram. Tx1Reg, 0x19 in a 16f886 appears unused in the sim. BUT 'occasionally' corrupts any variable in it in the real h'ware. Was kinda tuff to hunt down as it was erratic.


On the matter of the go/done bit waiting 45uS loop. Well...that's cool if u can afford the wait. But if u have 5 ADC to do...that adds up. especially if u are running a 4 digit 7 segment display sweep.

Without getting into interrupts, u can mod your ADC loop by using a global ADC counter gpr. The gpr tracks which ADC value is being sampled....and this permits an immediate return to the regular code. On the next loop, the global ADC gpr is incremented and this selects the next adc item. But b4 the next adc is sampled the last ADC value is taken from ADRESH/L and saved. This works well when your main program loop exceeds 45uS, Reset the gpr counter when the 'final' adc item is done in the sequence to restart the process.

Code:
	movf ADCtrak,w; into wreg, so if adctrak = 3....the ladder points to tps.
	skpnz
	goto Sample_oxy
	addlw .255 ; reduce by 1 ,but don't store in adctrak.
	skpnz
	goto Sample_pres
	addlw .255; reduce by 1
	skpnz
	goto Sample_volts
	addlw .255; reduce by 1
	skpnz
	goto Sample_tps
	addlw .255; reduce by 1
	skpnz
	goto Sample_baro
	addlw .255; reduce by 1
	skpnz
	goto Sample_store; this is for saving the last activated sample. no new sample is triggered.
	clrf ADCtrak ; reset counter if value ># of samples done.

	
Sample_oxy; sample the oxy sensor.
	
	
	banksel ADCON0
	;ADCON0, ADRESH is in current bank 0 of 16f886
	bsf ADCON0,ADON ; enable ADC
	call acqdel ; 13uS channel select delay
	bsf ADCON0,GO ; get sample of o2 Volts
	incf ADCtrak,f; point counter to next sample.
	return; to main code

Sample_pres; b4 doing this sample save the last sample (oxydata) into correct variable.
getadc;	
        btfsc ADCON0,GO;  test Go/Done bit for acq. Do this  in case code returns here b4 45uS sampling is complete.
	goto getadc ; wait until sampling is complete.
	movf ADRESH,w ; get 8 MSBs of data
	movwf Oxydata
;********Next ADC acq****************
	bsf ADCON0,2 ; select ch1 , An1
	call acqdel ; 13uS channel select delay
	bsf ADCON0,GO ; get sample of pressure
        incf ADCtrak,f; point counter to next sample.
        return; to main code
 
Last edited:
I think the 2nd line is supposed to be movwf PC_Temp, otherwise u are defaulting to a movf PC_Temp,f

Hi Mosaic

I agree it should be movwf! I will test it on hardware when I have time. But Im 100% sure that the missing w was the cause.

Cheers


UPDATE

The code does work on the H'ware :)
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top