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.

Multiplexing frequency and 16F88 Code check

Status
Not open for further replies.

dons21

New Member
Its been a while since I have posted anything, but I have written some code to display the 8 bit ADC result to three 7 segment displays. It is running at 4Mhz with TMR0 pre-scaler set at 256.

so each segment is lit for 1.031ms a total display time of 3.096ms. How do I calculate the Frequency (Hz) of the display ?

Is the code a good or reasonable way to multiplex displays? Here is the main loop.
Code:
START						; Read RA0 and convert to decimal
	call           ReadADC
        movf         Hund,w          		        ; Get Hund Result
        call           Table         			; then output it     
        movwf	PORTB			        ; to PORTB
	bsf            PORTA,2     		        ; display 1 ON
	clrf	        TMR0				; Clr TMR0
w1	btfss         TMR0,2      			; wait to go low
        goto          w1					; display for 1.031ms
	bcf		PORTA,2				; display 1 OFF 
        movf         Tens,w          			; Get Tens Result
        call           Table        				; then output it    
        movwf	PORTB				; to PORTB
        bsf           PORTA,3        			; display 2 ON
	clrf	       TMR0					; Clr TMR0
w2	btfss        TMR0,2     			        ; wait to go low
        goto         w2			       		; display for 1.031ms
	bcf		PORTA,3				; display 2 OFF
        movf         Ones,w          			; Get Ones Result
        call           Table         			; then output it   
        movwf	PORTB 				; to PORTB
        bsf            PORTA,4          			; display 3 ON
	clrf	        TMR0				; Clr TMR0
w3	btfss         TMR0,2        			; wait to go low
        goto         w3					; display for 1.031ms
	bcf		PORTA,4				; display 3 OFF


goto START
 
Last edited:
No it's a poor way, because the multiplexing stops while you're reading the ADC.

Check out my tutorials (dual 7 segment and 8x8 matrix) for examples of using timer2 interrupts to do it entirely seamlessly.
 
Ok I agree it does stop to read the ADC and convert the result.

Do understand correctly that when a interrupt is triggered or called the program stops what its doing and goes to 0x004 and runs the interrupt code?

So at some point would there not be a slight pause or stop to the multiplexing whilst the interrupt reads the ADC?
 
Ok I agree it does stop to read the ADC and convert the result.

Do understand correctly that when a interrupt is triggered or called the program stops what its doing and goes to 0x004 and runs the interrupt code?

Yes, that's correct - you trigger the interrupt via a timer (timer2 is a good one to use), and that sets the multiplexing speed.

So at some point would there not be a slight pause or stop to the multiplexing whilst the interrupt reads the ADC?

No, the main code reads the ADC and writes it to GPR's ready for display, the interrupt routine just updates the display.
 
dons21,

There's nothing wrong with your method. A minor change would allow you to read the ADC during one of the display intervals instead of after all of the display intervals (assuming your ReadADC routine uses less than about 1000-usecs).

It's also worth your while to learn how to use an interrupt driven display driver.

Cheerful regards, Mike

Code:
START
        call    ReadADC         ; Read RA0 and convert to decimal
        movf    Hund,w          ; Get Hund 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     PORTA,4         ; display 3 OFF (blank display)
        movwf   PORTB           ; to PORTB
        bsf     PORTA,2         ; display 1 ON
        movf    Tens,W          ; Get Tens 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     PORTA,2         ; display 1 OFF
        movwf   PORTB           ; to PORTB
        bsf     PORTA,3         ; display 2 ON
        movf    Ones,w          ; Get Ones Result
        call    Table           ; get segment data
w3      btfss   TMR0,2          ; ~1-ms interval? yes, skip, else
        goto    w3              ; loop (wait)
        clrf    TMR0            ; reset TMR0
        bcf     PORTA,3         ; display 2 OFF
        movwf   PORTB           ; to PORTB
        bsf     PORTA,4         ; display 3 ON
        goto    START           ;
;
 
Last edited:
Thanks for all your input.

Mike,

Thanks for the insight with your code. It gave me another way to think about how to write asm code. As previously I would do things in order. i.e get segment data, enable display, wait etc. I like the way W is pre loaded ready for the next display.

I will try an interrupt routine and post it when its done.

Many Thanks

Don
 
Hi Don,

I forgot to mention that your refresh rate is approximately 320-Hz ... frequency is the reciprocal of the period, which in this case is the time it takes to refresh all three displays ---> 1 / (3 * 0.00103)

Mike
 
Last edited:
My Interrupt code 4x 7Segment Displays

Well after reading how to setup TMR0 interrupt on overflow here is my interrupt test code. The save/restore W, STATUS and PCLATH is from the 16F88 data sheet example.

The PIC is running at 4Mhz, with TMR0 interrupt on overflow enabled and a prescaler of 8. The interrupt should be called every 2048 instruction cycles (256*8)=2048

The code does not do anything else there is a just a goto start loop in the main
program.

Is there anything else I should or should not be doing with the interrupt code?

Thanks Don

Code:
#Define		DispThou 	PORTA,1
#Define		DispHund 	PORTA,0
#Define		DispTens 	PORTA,7
#Define		DispOnes 	PORTA,6
	

	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
		movwf 	S_Temp		;Save status 
		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	DispThou
		goto	Hunds
		btfsc	DispHund				
		goto	Tens
		btfsc	DispTens
		goto	Ones
		btfsc	DispOnes
		goto	Thous
		
Thous	
		clrf	        PORTA
		movlw	b'01011111' ;display test digit
		movwf	PORTB
		bsf		DispThou
		goto	Exit
Hunds
		clrf	        PORTA
		movlw	b'00110000' ;display test digit
		movwf	PORTB
		bsf		DispHund
		goto	Exit
Tens
		clrf	        PORTA
		movlw 	b'01111001' ;display test digit
		movwf	PORTB
		bsf		DispTens
		goto	Exit
Ones
		clrf	        PORTA
		movlw	b'01110011' ;display test digit
		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
 
Well after reading how to setup TMR0 interrupt on overflow here is my interrupt test code. The save/restore W, STATUS and PCLATH is from the 16F88 data sheet example.

The PIC is running at 4Mhz, with TMR0 interrupt on overflow enabled and a prescaler of 8. The interrupt should be called every 2048 instruction cycles (256*8)=2048

The code does not do anything else there is a just a goto start loop in the main
program.

Is there anything else I should or should not be doing with the interrupt code?

If you check my tutorials as I said before you will see what needs to be done - and TMR2 is a far better option to use than TMR0.
 
If you check my tutorials as I said before you will see what needs to be done - and TMR2 is a far better option to use than TMR0.
Hi Nigel,

I did check your tutorials. I was not ignoring your advice, just thought I would use TMR0 thats all. I dont just want to go copying code so I thought I would try with TMR0, learn along the way etc.

To interrupt with TMR2 I think you set another register to the value you want it to overflow? Why is TMR2 a better option?
 
Last edited:
Hi Nigel,

I did check your tutorials. I was not ignoring your advice, just thought I would use TMR0 thats all. I dont just want to go copying code so I thought I would try with TMR0, learn along the way etc.

To interrupt with TMR2 I think you set another register to the value you want it to overflow? Why is TMR2 a better option?

TMR0 is the crudest of timers, I suspect it's only still there for compatibility with older programmes. TMR2 does what a timer should do, easily, accurately - and does "what it says on the tin".

This is only a crude inaccurate application anyway, but it's as well to use a more useful timer so as to get used to it.
 
Welcome to the Forum where the biggest challenge is filtering out qualified advice from personal preferences, garbage, and voodoo (lol).

There's nothing wrong with using Timer 0. All of the timers have their advantages and disadvantages in various situations.

Off to school for me... Cheerful regards, Mike
 
Status
Not open for further replies.

Latest threads

Back
Top