PIC TIMER0 and 7-segment multiplexing problem

Thread Starter

thejmh

Joined Jul 3, 2009
12
Hi! I'm trying to get this program work but haven't succeeded yet. I have a 3-digit common cathode 7-segment display and three transistors to turn the digits on. I'm using a PIC16F877A with a 4MHz crystal. Timer0 sets an interrupt after 1ms. I tried the multiplexing part of the code with 1ms counters written into code, without the interrupts and it worked perfectly. When I try to get the timing from TIMER0 it doesn't work. What's wrong with my code?

Rich (BB code):
PC                    EQU 02h
TRISA                EQU 85h
PORTA                EQU 05h
TRISB                EQU 86h    
PORTB                EQU 06h
TRISC                EQU 87h
PORTC                EQU 07h
TRISD                EQU 88h
PORTD                EQU 08h
TRISE                EQU 89h
PORTE                EQU 09h

STATUS              EQU 03h
TXSTA                EQU 98h
TXREG                EQU 19h
SPBRG                EQU 99h
PCLATH               EQU 0Ah
INTCON              EQU 0Bh
OPTION_REG      EQU 81h
TMR0                 EQU 01h

W_TEMP             EQU 70h
STATUS_TEMP     EQU 71h
PCLATH_TEMP     EQU 72h

BCD0                EQU 39h            ; result of binary to bcd conversion in these 3 registers.
BCD1                EQU 3Ah
BCD2                EQU 3Bh




            ORG        000h
            goto        INIT


            ORG        004h                ; Interrupt routine
            

            movwf    W_TEMP            ; Copy W to TEMP register
            swapf    STATUS,0        ; Swap status to be saved into W
            clrf        STATUS             ; bank 0, regardless of current bank, Clears IRP,RP1,RP0
            movwf    STATUS_TEMP    ; Save status to bank zero STATUS_TEMP register
            movf        PCLATH,0        ; Only required if using pages 1, 2 and/or 3
            movwf    PCLATH_TEMP    ; Save PCLATH into W
            clrf        PCLATH            ; Page zero, regardless of current page
            

; 7-SEGMENT MULTIPLEXING
        
            btfss        PORTE,0            ; Is ones transistor on?
            goto        $+6
            movlw    b'100'
            movwf    PORTE            ; Set hundreds transistor on.
            movf        BCD2,0            ; Move hundreds to 7-seg digit
            movwf    PORTC
            goto        INT_EXIT

            btfss        PORTE,1            ; Is tens transistor on?
            goto        $+6
            movlw    b'001'
            movwf    PORTE            ; Set ones transistor on.
            movf        BCD0,0            ; Move ones to 7-seg digit
            movwf    PORTC
            goto        INT_EXIT

            btfss        PORTE,2            ; Is hundreds transistor on?
            goto        $+5
            movlw    b'010'
            movwf    PORTE            ; Set tens transistor on.
            movf        BCD1,0            ; Moves tens to 7-seg digit
            movwf    PORTC
            

INT_EXIT   movf        PCLATH_TEMP,0    ; Restore PCLATH
            movwf    PCLATH            ; Move W into PCLATH
            swapf    STATUS_TEMP,0    ; Swap STATUS_TEMP register into W
            movwf    STATUS            ; Move W into STATUS register
            swapf    W_TEMP,1        ; Swap W_TEMP
            swapf    W_TEMP,0        ; Swap W_TEMP into W
            
            movlw     b'11111010'        ; FAh (=250)
            movwf    TMR0 
            bcf        INTCON,2            ; TMR0_INT
            retfie




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


INIT      bsf        STATUS,5        ; To bank 1
            movlw    b'000000'            
            movwf    TRISA            
            movlw    b'00001111'    
            movwf    TRISB        
            movlw    b'00000000'
            movwf    TRISC            
            movlw    b'00000000'
            movwf    TRISD            
            movlw    b'000'
            movwf    TRISE            

            movlw    b'001'
            movwf    PORTE            ; Sets the first digit on for multiplexing.
            
            ; SETUP TMR0

            movlw    b'01000001'        ; Also sets PORTB pull-ups
            movwf    OPTION_REG
            bcf        STATUS,5             ; return to page 0

            movlw    b'10100000'
            movwf    INTCON              ; GIE enable interrupts.
    

MAIN

            ; Main program here, I didn't include it this time...
 
Last edited:

SgtWookie

Joined Jul 17, 2007
22,201
Just some general thoughts....

When an interrupt occurs, consider immediately turning off interrupts while the current interrupt is being serviced; otherwise if your service routine takes longer than you thought, you'll get stuck in a loop.

Then clear the flag that caused the initial interrupt.

Then perform your interrupt service routine.

Then re-initialize the timer.

Lastly, re-enable interrupts.

Note that your MAIN portion doesn't have any statements; it should be at least branching back to MAIN. Otherwise the program counter may just run off the end of your code, and attempt to execute arbitrary data that was left from the last programming exercise.
 

Thread Starter

thejmh

Joined Jul 3, 2009
12
Thanks for your tips. I did those and also found some errors and it works now!:) But now there's a new problem. If I want to display for example 0 on ones display, then there is also very dim 0 on hundreds display, which is the next digit in multiplexing sequence. I tried messing with the timing but it didn't help.
 
Last edited:

SgtWookie

Joined Jul 17, 2007
22,201
It's because you're putting the cart before the horse. ;)

Right now, you're turning off the prior digit and turning on the new digit - the prior value is still loaded in the port.

You need to turn the prior and current digit off before loading in the new value, or you'll get "ghosting" on other digits.


1) Turn the transistor for the last digit OFF.
2) Load the port with data for the new segments to be displayed.
3) Turn the transistor for the new digit ON.
4) Return after resetting interrupt status;etc.

Also, I see you're using "goto $+6" etc.
You'll be better off to branch to labels instead of hard-coded PC offsets. As things are now, you'll have to adjust those hard-coded offsets to compensate for the instructions you'll have to add. If you'd used labels, the assembler would take care of the adjustment automatically.

Here's an example of what I'm talking about:
Rich (BB code):
; 7-SEGMENT MULTIPLEXING
        
TestOnes    btfss    PORTE,0          ; Is ones transistor on?
            goto     TestTens
            movlw    b'000'
            movwf    PORTE            ; Set all transistors off.
            movf     BCD2,0           ; Move hundreds to 7-seg digit
            movwf    PORTC
            movlw    b'100'
            movwf    PORTE            ; Set hundreds transistor on.
            goto     INT_EXIT

TestTens    btfss    PORTE,1          ; Is tens transistor on?
            goto     DispTens
            movlw    b'000'
            movwf    PORTE            ; Set all transistors off.
            movf     BCD0,0           ; Move ones to 7-seg digit
            movwf    PORTC
            movlw    b'001'
            movwf    PORTE            ; Set ones transistor on.
            goto     INT_EXIT

DispTens    movlw    b'000'           ; Displaying tens.
            movwf    PORTE            ; Set all transistors off.
            movf     BCD1,0           ; Moves tens to 7-seg digit
            movwf    PORTC
            movlw    b'010'
            movwf    PORTE            ; Set tens transistor on.
 
Last edited:

walid el masry

Joined Mar 31, 2009
132
iam so lucky iam working on the same circuit but unfortunately there is some thing wrong
i can reset only the 1st digit on number 10 of course but other 2 digits doesn't affected at all , i tested the logic of code and i guess it is fine but on testing the circuit on Proteus 7.4 i found this problem


see that my code

Rich (BB code):
    LIST P=16F876
    #INCLUDE<P16F876.INC>
    __CONFIG    _CP_OFF&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_XT_OSC
TIME EQU 0X20                   ;used to delay code
; if we have a 100 in decimal then DIG0 = 0 , DIG1 = 0 , DIG2 = 1
DIG0 EQU 0X21
DIG1 EQU 0X22
DIG2 EQU 0X23
    ORG 0X00
    GOTO INTIATION
    ORG 0X04
;INTERRUPT SUBRUTINE
    ;CLRF TIME                    ;clear delay if i want to reset delay
    CALL SCAN                    ;make a count
    BCF INTCON,INTF        ;STOP THE INTERRUPT
    BSF INTCON,GIE          ;ALLOW OTHER INTERRUPT TO BE ABLE OCCUR
    RETFIE
INTIATION
;INTERRUPT INTIATION
    MOVLW 0X90
    MOVWF INTCON           ;Enable External Interrupt & Enable Global Interrupt Gate
    MOVLW 0X47
    MOVWF OPTION_REG  ;Intrrupt Start At Falling Edge
;INTIATION PORTS
    MOVLW 0X01
    TRIS PORTB
    MOVLW 0X00
    TRIS PORTC
;MOVLW 0X09                     ;used to test program at this point on the 7 segments 
    MOVWF PORTB            ;to clear any value stored in portb after chipt boot
    MOVWF PORTC            ;to clear any value stored in portc after chipt boot
    MOVWF DIG0
    MOVWF DIG1
    MOVWF DIG2
START
    CALL DELAY
    BCF PORTC,2
    BSF PORTC,0
    BCF PORTC,1
    SWAPF DIG0,W
    MOVWF PORTB
    CALL DELAY
    BCF PORTC,0
    BSF PORTC,1
    BCF PORTC,2
    SWAPF DIG1,W
    MOVWF PORTB
    CALL DELAY
    BCF PORTC,1
    BSF PORTC,2
    BCF PORTC,0
    SWAPF DIG2,W
    MOVWF PORTB
    GOTO START
SCAN                       ;counter increment code
CDIG0                      ;CALCULATION FOR DIGIT 0
    INCF DIG0,DIG0
    MOVLW 0X0A          ;OVER FLOW TEST FOR DIGIT >9 AT COUNTING 10
    XORWF DIG0,W
    BTFSC STATUS,Z
    GOTO CDIG1;NO     ;OVER FLOW FOR DIG0 OCCUR
    GOTO FIN;YES
;----------------------------------------
CDIG1                      ;CALCULATION FOR DIGIT 1
    MOVLW 0X00
    MOVWF DIG0
    INCF DIG1,DIG1
    MOVLW 0X0A          ;OVER FLOW TEST FOR DIGIT >9 AT COUNTING 100
    XORWF DIG1,W
    BTFSC STATUS,Z
    GOTO CDIG2;NO     ;OVER FLOW FOR DIG1 OCCUR
    GOTO FIN;YES
;----------------------------------------
CDIG2                      ;CALCULATION FOR DIGIT 2
    MOVLW 0X00
    MOVWF DIG1
    INCF DIG2,DIG2
    MOVLW 0X0A          ;OVER FLOW TEST FOR DIGIT >9 AT COUNTING 1000
    XORWF DIG2,W
    BTFSC STATUS,Z
    GOTO CLR;NO         ;OVER FLOW FOR DIG2 OCCUR
    GOTO FIN;YES
;----------------------------------------
    MOVLW 0XFF
    MOVWF PORTC
CLR                          ;CALCULATION FOR OVER FLOW > 999 CONT
    MOVLW 0X00
    MOVWF DIG0
    MOVWF DIG1
    MOVWF DIG2
;----------------------------------------
FIN
;MOVLW 0XFF       ;used to test program at this point on the 7 segments
;MOVWF PORTC    ;used to test program at this point on the 7 segments
    RETURN
DELAY ;1 sec delay
    CLRF TIME
    MOVLW 0XF4
    MOVWF TMR0 
    BSF STATUS,RP0
    MOVLW 0X47
    MOVWF OPTION_REG
    BCF STATUS,RP0
WAIT 
    BTFSS INTCON,T0IF
    GOTO WAIT
    BCF INTCON,T0IF
    INCF TIME
    MOVLW 0X04
    XORWF TIME,W
    BTFSS STATUS,Z
    GOTO WAIT
    RETURN
    END
and that is the circuit i built virtually on Proteus



counter count on switch pressing which make interrupt with that and then continue the 7 segment multiplexing
 

walid el masry

Joined Mar 31, 2009
132
i intend to reduce the circuit in future by using just 1 decoder and make the multiplexing on the unused pins in portb instead of the pins of portc i used of course after solving the problem
 

millwood

Joined Dec 31, 1969
0
looks like you have enough pins on the mcu so you shouldn't use any decoder (just 7 pins to the led + 3 pins to the commons).
 

walid el masry

Joined Mar 31, 2009
132
you are wright but think if you can use the port c to do another job then you can understand the importance of wasted 3 pin of it except that i have reduced the pcb to take smaller size
 

SgtWookie

Joined Jul 17, 2007
22,201
The 7448 has built-in pull-up resistors. You don't need resistors on the outputs.
On the other hand, you DO need resistors to limit current on the bases of Q1 through Q3; I suggest 1k Ohms.

You don't seem to be doing any multiplexing in your code; just incrementing the counters.
You'll need to turn the current display off via portc, move the new digit's data to display into portb, and then turn the new digit on in portc.

It is not necessary to use the large font size for your text. The regular font works just fine.
 

walid el masry

Joined Mar 31, 2009
132


The 7448 has built-in pull-up resistors. You don't need resistors on the outputs.
i miss it and it will make it smaller

you DO need resistors to limit current on the bases of Q1 through Q3; I suggest 1k Ohms.
you are wright but in simulation every thing works fine :):)

You don't seem to be doing any multiplexing in your code; just incrementing the counters.
i do the multiplexing but i found Proteus can't handle time smaller than this in code (200mSEC) but in real life at (1mSEC) or smaller it works fine
and multiplexing code

Rich (BB code):
START
    CALL DELAY        ;multiplexing delay
    BCF PORTC,2       ;turn third display off
    BSF PORTC,0       ;turn first display on
    BCF PORTC,1       ;ensure turning second display off
    SWAPF DIG0,W
    MOVWF PORTB       ;move the vaule to displayed on PORTB
;--------------------------------------
    CALL DELAY        ;multiplexing delay
    BCF PORTC,0       ;turn first display off
    BSF PORTC,1       ;turn second display on
    BCF PORTC,2       ;ensure turning third display off
    SWAPF DIG1,W
    MOVWF PORTB       ;move the vaule to displayed on PORTB
;--------------------------------------
    CALL DELAY        ;multiplexing delay
    BCF PORTC,1       ;turn second display off
    BSF PORTC,2       ;turn third display on
    BCF PORTC,0       ;ensure turning first display off
    SWAPF DIG2,W
    MOVWF PORTB       ;move the vaule to displayed on PORTB
    GOTO START
It is not necessary to use the large font size for your text. The regular font works just fine.
i agree with you :):):)
 

walid el masry

Joined Mar 31, 2009
132
that is improved one but i use the common anode but let us discuss the common cathode code up there

and for multiplexing i used the code
MOVLW B'XXXXXXXX'
MOVWF PORTB

from
thejmh , it reduce code

 
Last edited:

millwood

Joined Dec 31, 1969
0
10k for r1/r2/r3 may be too much.

the LED will likely take 3-5ma each to light up. so that means a total of 35ma if all segments are lit up.

the LEDs will also have a forward drop of about 1.5 - 2v, at least. plus one Vbe, you are talking about a base current of only (5-2-.7)/10k=.2ma. with a beta of 100 for small signal transistors, that means those transistors can source about 20ma. a little bit on the low side.

I would use 1k resistors instead.
 

millwood

Joined Dec 31, 1969
0
this is what I have, in a similar set-up. it is a 16f628a driving 3 7-segments. programmed in picc-lite / hi-tide.

Rich (BB code):
#include <htc.h>

#define S0	RA0
#define S1	RA1
#define S2	RA2
#define LED	PORTB
#define SEG_A	(ON<<0)
#define SEG_B	(ON<<1)
#define SEG_C	(ON<<2)
#define SEG_D	(ON<<3)
#define SEG_E	(ON<<4)
#define SEG_F	(ON<<5)
#define SEG_G	(ON<<6)
#define ON	1
#define OFF	0
#define Chr_0	SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F
#define Chr_1	        SEG_B | SEG_C                              
#define Chr_2	SEG_A | SEG_B |         SEG_D | SEG_E |         SEG_G
#define Chr_3	SEG_A | SEG_B | SEG_C | SEG_D |                 SEG_G
#define Chr_4	        SEG_B | SEG_C |                 SEG_F | SEG_G
#define Chr_5	SEG_A |         SEG_C | SEG_D |         SEG_F | SEG_G
#define Chr_6	SEG_A |         SEG_C | SEG_D | SEG_E | SEG_F | SEG_G
#define Chr_7	SEG_A | SEG_B | SEG_C                                
#define Chr_8	SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G
#define Chr_9	SEG_A | SEG_B | SEG_C | SEG_D |         SEG_F | SEG_G
#define Chr_A	SEG_A | SEG_B | SEG_C |         SEG_E | SEG_F | SEG_G
#define Chr_B	SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G
#define Chr_C	SEG_A |                 SEG_D | SEG_E | SEG_F | SEG_G
#define Chr_D	SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F         
#define Chr_E	SEG_A |                 SEG_D | SEG_E | SEG_F | SEG_G
#define Chr_F	SEG_A |                         SEG_E | SEG_F | SEG_G
#define Disp_0	LED=Chr_0
#define Disp_1	LED=Chr_1
#define Disp_2	LED=Chr_2
#define Disp_3	LED=Chr_3
#define Disp_4	LED=Chr_4
#define Disp_5	LED=Chr_5
#define Disp_6	LED=Chr_6
#define Disp_7	LED=Chr_7
#define Disp_8	LED=Chr_8
#define Disp_9	LED=Chr_9
#define Disp_A	LED=Chr_A
#define Disp_B	LED=Chr_B
#define Disp_C	LED=Chr_C
#define Disp_D	LED=Chr_D
#define Disp_E	LED=Chr_E
#define Disp_F	LED=Chr_F
#define DELAY	1000000

__CONFIG( XT & WDTDIS & PWRTDIS & BORDIS & LVPDIS & UNPROTECT );

void mcu_init(void) {
//initialize the mcu
	CMCON=0x07;	//turn off coomparators;
	TRISA=0x00;	//turn port A to output
	TRISB=0x00;	//turn port b to output
	OPTION=0b00000000;	//disable PortB pull-up.
//	INTCON=0x00;		//disable interrupts
//	RCSTA=0x00;	//disable usart
}

void delay(long int dly) {
	for(; dly==0; dly--)
		;
}

void display_chr(char chr) {
	switch (chr) {
	case '0':	Disp_0; break;
	case '1':	Disp_1; break;
	case '2':	Disp_2; break;
	case '3':	Disp_3; break;
	case '4':	Disp_4; break;
	case '5':	Disp_5; break;
	case '6':	Disp_6; break;
	case '7':	Disp_7; break;
	case '8':	Disp_8; break;
	case '9':	Disp_9; break;
	case 'A':	Disp_A; break;
	case 'B':	Disp_B; break;
	case 'C':	Disp_C; break;
	case 'D':	Disp_D; break;
	case 'E':	Disp_E; break;
	case 'F':	Disp_F; break;
	}
}


void main(void)
{
	int i;
	const char *str="02A";
	mcu_init();
	while (1){
		//TODO Auto-generated main function
		display_chr('4');
		S0=0; delay(DELAY); S0=1;
		display_chr('5');
		S1=0; delay(DELAY); S1=1;
		display_chr('A');
		S2=0; delay(DELAY); S2=1;
	}
}
you can write a function to display a string and then it will be mostly done!
 

walid el masry

Joined Mar 31, 2009
132
yes you are 100% wright in real life
but in simulation it doesn't matter every thing works fine
but what am asking for is the logic of the code cause i think it must work fine
but when i tried to simulate it , it just increment the 1st display and reset it on over flow but nothing happen for the other displays

see that is the code for the above circuit

Rich (BB code):
    LIST P=16F876
    #INCLUDE<P16F876.INC>
    __CONFIG    _CP_OFF&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_XT_OSC
TIME EQU 0X20                   ;used to delay code
; if we have a 100 in decimal then DIG0 = 0 , DIG1 = 0 , DIG2 = 1
DIG0 EQU 0X21
DIG1 EQU 0X22
DIG2 EQU 0X23
    ORG 0X00
    GOTO INTIATION
    ORG 0X04
;INTERRUPT SUBRUTINE
    ;CLRF TIME                    ;clear delay if i want to reset delay
    CALL SCAN                    ;make a count
    BCF INTCON,INTF        ;STOP THE INTERRUPT
    BSF INTCON,GIE          ;ALLOW OTHER INTERRUPT TO BE ABLE OCCUR
    RETFIE
INTIATION
;INTERRUPT INTIATION
    MOVLW 0X90
    MOVWF INTCON           ;Enable External Interrupt & Enable Global Interrupt Gate
    MOVLW 0X47
    MOVWF OPTION_REG  ;Intrrupt Start At Falling Edge
;INTIATION PORTS
    MOVLW 0X01
    TRIS PORTB
    MOVLW 0X00
    TRIS PORTC
;MOVLW 0X09                     ;used to test program at this point on the 7 segments 
    MOVWF PORTB            ;to clear any value stored in portb after chipt boot
    MOVWF PORTC            ;to clear any value stored in portc after chipt boot
    MOVWF DIG0
    MOVWF DIG1
    MOVWF DIG2
START
    CALL DELAY
    SWAPF DIG0,W
    MOVWF PORTB
    COMF PORTB,PORTB
    BCF PORTB,3
    BSF PORTB,1
    CALL DELAY
    SWAPF DIG1,W
    MOVWF PORTB
    COMF PORTB,PORTB
    BCF PORTB,1
    BSF PORTB,2
    CALL DELAY
    SWAPF DIG2,W
    MOVWF PORTB
    COMF PORTB,PORTB
    BCF PORTB,2
    BSF PORTB,3
    GOTO START
SCAN                       ;counter increment code
CDIG0                      ;CALCULATION FOR DIGIT 0
    INCF DIG0,DIG0
    MOVLW 0X0A          ;OVER FLOW TEST FOR DIGIT >9 AT COUNTING 10
    XORWF DIG0,W
    BTFSC STATUS,Z
    GOTO CDIG1;NO     ;OVER FLOW FOR DIG0 OCCUR
    GOTO FIN;YES
;----------------------------------------
CDIG1                      ;CALCULATION FOR DIGIT 1
    MOVLW 0X00
    MOVWF DIG0
    INCF DIG1,DIG1
    MOVLW 0X0A          ;OVER FLOW TEST FOR DIGIT >9 AT COUNTING 100
    XORWF DIG1,W
    BTFSC STATUS,Z
    GOTO CDIG2;NO     ;OVER FLOW FOR DIG1 OCCUR
    GOTO FIN;YES
;----------------------------------------
CDIG2                      ;CALCULATION FOR DIGIT 2
    MOVLW 0X00
    MOVWF DIG1
    INCF DIG2,DIG2
    MOVLW 0X0A          ;OVER FLOW TEST FOR DIGIT >9 AT COUNTING 1000
    XORWF DIG2,W
    BTFSC STATUS,Z
    GOTO CLR;NO         ;OVER FLOW FOR DIG2 OCCUR
    GOTO FIN;YES
;----------------------------------------
    MOVLW 0XFF
    MOVWF PORTC
CLR                          ;CALCULATION FOR OVER FLOW > 999 CONT
    MOVLW 0X00
    MOVWF DIG0
    MOVWF DIG1
    MOVWF DIG2
;----------------------------------------
FIN
;MOVLW 0XFF       ;used to test program at this point on the 7 segments
;MOVWF PORTC    ;used to test program at this point on the 7 segments
    RETURN
DELAY ;1 sec delay
    CLRF TIME
    MOVLW 0XF4
    MOVWF TMR0 
    BSF STATUS,RP0
    MOVLW 0X47
    MOVWF OPTION_REG
    BCF STATUS,RP0
WAIT 
    BTFSS INTCON,T0IF
    GOTO WAIT
    BCF INTCON,T0IF
    INCF TIME
    MOVLW 0X04
    XORWF TIME,W
    BTFSS STATUS,Z
    GOTO WAIT
    RETURN
    END
 

walid el masry

Joined Mar 31, 2009
132
that is the code of increment

Rich (BB code):
SCAN                       ;counter increment FUNCTION
CDIG0                      ;CALCULATION FOR DIGIT 0 (1st display)
    INCF DIG0,DIG0     ;increment 1st display
    MOVLW 0X0A          ;OVER FLOW TEST FOR DIGIT >9 AT COUNTING 10
    XORWF DIG0,W
    BTFSC STATUS,Z
    GOTO CDIG1;NO     ;OVER FLOW FOR DIG0 OCCUR
    GOTO FIN;YES
;----------------------------------------
CDIG1                      ;CALCULATION FOR DIGIT 1 (2nd display)
    MOVLW 0X00        ;reset 1st display due to over flow
    MOVWF DIG0
    INCF DIG1,DIG1     ;increment 2nd display
    MOVLW 0X0A          ;OVER FLOW TEST FOR DIGIT >9 AT COUNTING 100
    XORWF DIG1,W
    BTFSC STATUS,Z
    GOTO CDIG2;NO     ;OVER FLOW FOR DIG1 OCCUR
    GOTO FIN;YES
;----------------------------------------
CDIG2                      ;CALCULATION FOR DIGIT 2 (3rd display)
    MOVLW 0X00        ;reset 2nd display due to over flow
    MOVWF DIG1
    INCF DIG2,DIG2       ;increment 3rd display
    MOVLW 0X0A          ;OVER FLOW TEST FOR DIGIT >9 AT COUNTING 1000
    XORWF DIG2,W
    BTFSC STATUS,Z
    GOTO CLR;NO         ;OVER FLOW FOR DIG2 OCCUR
    GOTO FIN;YES
;----------------------------------------
    MOVLW 0XFF
    MOVWF PORTC
CLR                          ;CALCULATION FOR OVER FLOW > 999 CONT
    MOVLW 0X00          ;reset 3rd display due to over flow
    MOVWF DIG0
    MOVWF DIG1
    MOVWF DIG2
;----------------------------------------
FIN
    RETURN
 

SgtWookie

Joined Jul 17, 2007
22,201
Now that you've changed to a common anode, and replaced the 7448 with a 7447, you'll have to add the resistors back in (one per the 7447's current sink), value depends on Vf and current desired per segment. The NPN transistors should be replaced with PNP transistors. The base resistors should be anywhere from 330 Ohms to 1k Ohms.

In your code, I don't know why you're performing a COMF PortB,PortB (inverting all bits) and then individually setting/clearing bits.

You should instead be:
1) Turning off the previously lit segment.
2) Moving the new value to be displayed into the port.
3) Turning on the new segment.
4) Delaying.

In your interrupt service routine, you should first turn off interrupts, THEN call scan, and then turn interrupts back on.
 

walid el masry

Joined Mar 31, 2009
132
I don't know why you're performing a COMF PortB,PortB (inverting all bits)
you are wright it was stupid step of me

and then individually setting/clearing bits
i do it to do multiplexing on RB1,RB2,RB3

You should instead be:
1) Turning off the previously lit segment.
2) Moving the new value to be displayed into the port.
3) Turning on the new segment.
4) Delaying.
i corrected the code to this sequence

Rich (BB code):
START
    BCF PORTB,3
    SWAPF DIG0,W
    MOVWF PORTB
    BSF PORTB,1
    CALL DELAY
    BCF PORTB,1
    SWAPF DIG1,W
    MOVWF PORTB
    BSF PORTB,2
    CALL DELAY
    BCF PORTB,2
    SWAPF DIG2,W
    MOVWF PORTB
    BSF PORTB,3
    CALL DELAY
    GOTO START
In your interrupt service routine, you should first turn off interrupts, THEN call scan, and then turn interrupts back on.
Rich (BB code):
;INTERRUPT SUBRUTINE
    ;CLRF TIME                    ;clear delay if i want to reset delay
    BCF INTCON,GIE          ;DENAY OTHER INTERRUPT TO BE ABLE OCCUR
    CALL SCAN                    ;make a count
    BCF INTCON,INTF        ;STOP THE INTERRUPT
    BSF INTCON,GIE          ;ALLOW OTHER INTERRUPT TO BE ABLE OCCUR
    RETFIE
in the end no thing just the 1st display which work with me

here the project files if any one want to check it him self

http://rapidshare.com/files/254248062/7_segment.rar.html
or
http://www.2shared.com/file/6638073/ca3d7c42/7_segment.html

and i will include link to Proteus 7
 
Top