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.

PIC16F84A SEVEN SEGMENT

miumiu

Newbie
Joined
May 12, 2024
Messages
2
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
13
HI GUYS, so i have a problem with my coding, i have 3 question to ask , 1)i cant make it to have a 12ms delayed without overloading, 2)how to create a reset button at pin A3 that will be used to reset the multiplexing 7-Segments, and 3)how to make this the START/ STOP switch that connected at pinA0 that can be count when we pressed and stop the stopwatch when depressed, i only can make it start but not pause, please help me, disclaimer, im still new at this

Code:
LIST P=16F84 ; PIC16F84A Configuration Bit Settings
; STILL NEEDS TO SETUP!!!!
#include <P16F84.inc>

TENS equ 0x20
UNITS equ 0x21
COUNT equ 0x22 ; New variable for counting

org 0x00 ; Reset vector
goto START

LOOKUP addwf PCL,F
retlw 0x3F ; 0
retlw 0x06 ; 1
retlw 0x5B ; 2
retlw 0x4F ; 3
retlw 0x66 ; 4
retlw 0x6D ; 5
retlw 0x7D ; 6
retlw 0x07 ; 7
retlw 0x7F ; 8
retlw 0x67 ; 9

DELAY nop
return

START bsf STATUS,RP0
clrf TRISB ; Port B as output
movlw h'09'
movwf TRISA ;makes PORTA as input
bcf STATUS,RP0

clrf TENS
clrf UNITS
clrf COUNT
call STOP

STOP: btfsc PORTA,0
call DISPLAY_NUMBER
goto STOP
return

DISPLAY_NUMBER:
movf COUNT,W ; Load COUNT into W
movwf TENS ; Store tens place
movlw 0x0A
subwf TENS,W ; Subtract 10 from TENS
btfsc STATUS,C ; If no carry (TENS >= 10)
goto INCREMENT ; Increment TENS
goto SKIP_INCREMENT

INCREMENT:
clrf TENS ; Reset TENS to 0
incf UNITS,F ; Increment UNITS
movlw 0x64 ; Check if UNITS >= 100
subwf UNITS,W
btfss STATUS,Z ; If UNITS >= 100
goto RESET_COUNT ; Reset COUNT
goto SKIP_INCREMENT
call STOP


RESSET: movlw h'00'
movwf COUNT


RESET_COUNT:
clrf COUNT ; Reset COUNT to 0
goto DISPLAY_NUMBER

SKIP_INCREMENT:
movf TENS,W
call LOOKUP
movwf PORTB ; Display tens place
bsf PORTA,1 ; Set enable pin for tens place
call DELAY ; Delay 1ms
bcf PORTA,1 ; Clear enable pin for tens place
movf UNITS,W
call LOOKUP
movwf PORTB ; Display units place
bsf PORTA,2 ; Set enable pin for units place
call DELAY ; Delay 1ms
bcf PORTA,2 ; Clear enable pin for units place
incf COUNT,F ; Increment COUNT
movlw 0x64 ; Check if COUNT >= 100
subwf COUNT,W
btfss STATUS,Z ; If COUNT >= 100
goto DISPLAY_NUMBER
clrf COUNT ; Reset COUNT to 0
goto DISPLAY_NUMBER


end
 
Last edited by a moderator:
Somewhat confusing code, I can see you are trying to multiplex digits to a display with segments on PORTB and digit selects on PORTA but what is it actually counting and what speed is it supposed to count at? In my mind, the solution to your problem is to use the hardware timer, either to advance the digit select or to advance the number you are counting. If you do that, the counter can be stopped and started with its enable bit. Can you show your schematic please, preferably as an image.

Even better would be to change the PIC to a more modern one with several timers so you can set the speed of count and multiplexing with different timers and interrupts.

Brian.
 
Somewhat confusing code, I can see you are trying to multiplex digits to a display with segments on PORTB and digit selects on PORTA but what is it actually counting and what speed is it supposed to count at? In my mind, the solution to your problem is to use the hardware timer, either to advance the digit select or to advance the number you are counting. If you do that, the counter can be stopped and started with its enable bit. Can you show your schematic please, preferably as an image.

Even better would be to change the PIC to a more modern one with several timers so you can set the speed of count and multiplexing with different timers and interrupts.

Brian.
hii sorry for late replied and thank you so much to reply, may i attach the question and the simple flowchart that i have been made? still a bit confuse on how to do it, an di cannot changhe my pic the schematic on proteus,

WhatsApp Image 2024-05-13 at 8.41.55 PM.jpeg


WhatsApp Image 2024-05-13 at 8.33.12 PM.jpeg
 
Last edited:
It would be wrong of me to do your homework but I can give some advice:

The task says you have to use a timer to increment the count but you didn't use one in your code. The 16F84 only has one timer TMR0 which has 8 bits and generates an interrupt as it overflows from 0xFF to 0x00.
Look closely at the "TMR0 Block Diagram" in the data sheet. What you want to do is make the output that sets the T0IF bit go high every 12mS.

We don't know what your clock frequency is but there are two sources that can make TMR0 count, either an external signal on RA4/T0CKI or the system clock divided by 4. Use the T0CS bit to select which you want to use.

Next you have to decide whether you need to pre-scale (further divide) the count signal by setting the PSA bit. If you are using the prescaler you will also have to set the PS2,PS1 and PS0 bits to set the division ratio. Don't worry about the comments about internal clock sync,you can ignore it.

You now have a signal that drives the counter in TMR0. It counts upwards but being only 8 bits wide, it rolls over to zero at the next clock after it hold 0xFF. This is important to understand because you can pre-load a value into TMR0 to reduce how many counts it takes to roll over. You might have to load it with a value after each interrupt to reset it to time the next period correctly.

When you have the timing sort out, you next have to write an ISR (Interrupt Service Routine). This is called automatically when interrupts are enabled and T0IF gets set. Refer to the data sheet for how to write an ISR, the 16F84 doesn't save some essential data when entering the ISR so you have to do it in your own code. In the ISR set a variable to say "its time to increment the digits" then restore that data you just saved then issue a RETFI instruction to end the ISR.

So far you have a routine that sets your variable every 12mS. In your main code loop read that variable and use it to call the routine that counts the digits upwards then very important - reset your variable so it is ready to use again when the next ISR occurs.

See how you get on so far and send us your new code to check.

Brian.
 
This assignment appears simple but is quite complex when implementing an actual solution.

The OP is using the Proteus simulation environment from LabCenter. This allows simulation of code that would fail to work in real hardware. It does give us some insights for acceptable choices of the system oscillator frequency and what initial setting of the configuration bits would be good enough.

This is what I created as a working solution:
Code:
;
; File:     main.asm
; Target:   PIC16f84A
; Author:   dan1138
; Date:     2024-05-18
; Compiler: MPASMWIN v5.84
; IDE:      MPLABX v5.25
;
; Description:
;
;   Stopwatch, two digit multiplexed 7-segment LED displays
;   See: https://www.edaboard.com/threads/pic16f84a-seven-segment.410963/post-1773686
;
;                           PIC16F84A
;                   +----------:_:----------+
; (Digit2)EN2 <>  1 : RA2               RA1 : 18 <> EN1(Digit1)
; (Reset)BTN2 <>  2 : RA3               RA0 : 17 <> BTN1(Start/Stop)
;             <>  3 : RA4/T0CKI        OSC1 : 16 <- 4MHz crystal
;    ICSP_VPP ->  4 : MCLR             OSC2 : 15 -> 4MHz crystal
;         GND ->  5 : GND               VDD : 14 <- 5v0
;       LED_a <>  6 : RB0/INT       PGD/RB7 : 13 <> LED_dp /ICSP_PGD
;       LED_b <>  7 : RB1           PGC/RB6 : 12 <> LED_g  /ICSP_PGC
;       LED_c <>  8 : RB2               RB5 : 11 <> LED_f
;       LED_d <>  9 : RB3               RB4 : 10 <> LED_e
;                   +-----------------------:
;                            DIP-18

    list    p=16F84A        ; Select PIC16F84A as target device
    list    n=0, c=250      ; No page breaks, support long lines in list file
    list    r=dec
    errorlevel -302         ; Suppress not in bank zero warning

#include <p16f84A.inc>

; PIC16F84A Configuration Bit Settings

 __CONFIG _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _CP_OFF
;
; Power-On-Reset entry point
;
Por_Vec    CODE   0x0000
    global  resetVec
resetVec:
    goto    main

;
;   Data space use by interrupt handler to save context
Isr_Data    UDATA_SHR
;
    GLOBAL  WREG_save,STATUS_save,PCLATH_save
    GLOBAL  Segments
;
WREG_save:      res     1
STATUS_save:    res     1
PCLATH_save:    res     1
Segments:       res     2
;
;   Interrupt vector and handler
Isr_Vec CODE    0x0004
    GLOBAL  IsrVec
;
IsrVec:
    movwf   WREG_save
    swapf   STATUS,W
    movwf   STATUS_save
    movf    PCLATH,W
    movwf   PCLATH_save
;
IsrHandler:
    btfsc   INTCON,TMR0IE
    btfss   INTCON,TMR0IF
    goto    TMR0_Exit
TMR0_ISR:
    bcf     INTCON,TMR0IF
    banksel PORTB
    clrf    PORTB

    clrw
    btfsc   PORTA,2
    movlw   0x02
    btfsc   PORTA,1
    movlw   0x04
    iorlw   0
    skpnz
    movlw   0x02
    xorwf   PORTA,W
    xorwf   PORTA,F
 
    btfsc   PORTA,2
    movf    Segments+1,W
    btfsc   PORTA,1
    movf    Segments+0,W

    movwf   PORTB
TMR0_Exit:
;
IsrExit:
    movf    PCLATH_save,W
    movwf   PCLATH
    swapf   STATUS_save,W
    movwf   STATUS
    swapf   WREG_save,F
    swapf   WREG_save,W
    retfie                      ; Return from interrupt
 

;objects in bank 0 memory, note PIC16F84 does not have banked memory
MainData    UDATA_SHR
    GLOBAL  T0_Sample,TicksInTenthSecCount,TenthSecondCountBCD
    GLOBAL  SW_Flags
    GLOBAL  BTN_sample,BTN_stable,BTN_change,BTN_bounce

T0_Sample:      res     1
#define T0_COUNTS_PER_TICK 125
#define TICKS_PER_TENTH_SEC 25
TicksInTenthSecCount: res   1
TenthSecondCountBCD:  res   2
#define SW_Reset      SW_Flags,0
#define SW_RESET_MASK 0x01
#define SW_Start      SW_Flags,1
#define SW_START_MASK 0x02
SW_Flags:       res     1
#define DEBOUNCE_COUNT  2
#define BTN1_POSITION   0
#define BTN1_MASK       0x01
#define BTN2_POSITION   1
#define BTN2_MASK       0x02
BTN_sample:     res     1
BTN_stable:     res     1
BTN_change:     res     1
BTN_bounce:     res     1

MainCode    CODE
main:
    clrf    INTCON
    BANKSEL TRISB
    movlw   0x00
    movwf   TRISB
    movlw   0x09                ; RA0,RA3 inputs
    movwf   TRISA
    movlw   0x84                ; TMR0 clock source Fosc/4, TMR0 prescale 1:32
    movwf   OPTION_REG

    banksel TMR0
    clrf    TMR0
    clrf    T0_Sample
    movlw   TICKS_PER_TENTH_SEC
    movwf   TicksInTenthSecCount
    clrf    TenthSecondCountBCD+0
    clrf    TenthSecondCountBCD+1
    clrf    Segments+0
    clrf    Segments+1
    bcf     INTCON,TMR0IF
    bsf     INTCON,TMR0IE       ; enable 7-segment display multiplexing
    bsf     INTCON,GIE

    clrf    BTN_sample
    clrf    BTN_stable
    clrf    BTN_change
    clrf    BTN_bounce
    clrf    SW_Flags
AppLoop:
    movf    T0_Sample,W
    subwf   TMR0,W
    sublw   T0_COUNTS_PER_TICK
    skpnc
    goto    AppLoop
    movlw   T0_COUNTS_PER_TICK
    addwf   T0_Sample,F
;
; debounce switches
    call    BTN_Poll
    iorlw   0
    skpnz
    goto    Count4msTicks

    movf    BTN_stable,W
    andwf   BTN_change,F
    btfsc   BTN_change,BTN2_POSITION
    bsf     SW_Reset
    movlw   SW_START_MASK
    btfsc   BTN_change,BTN1_POSITION
    xorwf   SW_Flags,F
    clrf    BTN_change

;
; Process reset state
    btfss   SW_Reset
    goto    Count4msTicks
    clrf    TenthSecondCountBCD+0
    clrf    TenthSecondCountBCD+1
    bcf     SW_Reset
    bcf     SW_Start
Count4msTicks:
;
; count 4ms ticks
    decfsz  TicksInTenthSecCount,F
    goto    AppLoop
    movlw   TICKS_PER_TENTH_SEC
    movwf   TicksInTenthSecCount

;
; Show seconds
    swapf   TenthSecondCountBCD+0,W
    call    Lookup7seg
    xorwf   Segments+0,W
    andlw   0x7F
    xorwf   Segments+0,F
;
; Show tens of seconds
    movf    TenthSecondCountBCD+1,W
    call    Lookup7seg
    xorwf   Segments+1,W
    andlw   0x7F
    xorwf   Segments+1,F
;
; Process start state
    btfss   SW_Start
    goto    AppLoop
;
; count tenths of seconds in a packed 4-digit BCD array, LSD first
;
    incf    TenthSecondCountBCD+0,W
    addlw   0x06
    btfsc   STATUS,DC
    goto    IncBCD_CarryD0
    addlw   -0x06
    goto    IncBCD_B0done
IncBCD_CarryD0:
    addlw   0x60
    btfsc   STATUS,C
    goto    IncBCD_CarryD1
    addlw   -0x60
IncBCD_B0done:
    movwf   TenthSecondCountBCD+0
    goto    IncBCD_done
IncBCD_CarryD1:
    movwf   TenthSecondCountBCD+0
    incf    TenthSecondCountBCD+1,W
    addlw   0x06
    btfsc   STATUS,DC
    goto    IncBCD_CarryD2
    addlw   -0x06
    goto    IncBCD_B1done
IncBCD_CarryD2:
    addlw   0x60
    btfsc   STATUS,C
    goto    IncBCD_CarryD3
    addlw   -0x60
    goto    IncBCD_B1done
IncBCD_CarryD3:
    nop
IncBCD_B1done:
    movwf   TenthSecondCountBCD+1
IncBCD_done:
    goto    AppLoop
;
; poll buttons
; Returns: WREG = 0, no buttons changed
;          WREG = 1, buttons changed
BTN_Poll:
    clrw
    btfsc   PORTA,0
    iorlw   BTN1_MASK
    btfsc   PORTA,3
    iorlw   BTN2_MASK
    xorwf   BTN_sample,W
    skpnz
    goto    BTN_debounce
    xorwf   BTN_sample,F
    movlw   DEBOUNCE_COUNT
    movwf   BTN_bounce
    retlw   0
BTN_debounce:
    movf    BTN_bounce,F
    skpnz
    goto    BTN_debounce_done
    decfsz  BTN_bounce,F
    retlw   0
BTN_debounce_done:
    movf    BTN_sample,W
    xorwf   BTN_stable,W
    skpnz
    retlw   0
    iorwf   BTN_change,F
    xorwf   BTN_stable,F
    retlw   1
;
; Look up BCD to 7-segments
;
Lookup7seg:
    andlw   0x0F
    movwf   PCLATH
    xorlw   HIGH(BCD2SEG)
    xorwf   PCLATH,F
    xorwf   PCLATH,W
    addlw   LOW(BCD2SEG)
    skpnc
    incf    PCLATH,F
    movwf   PCL

BCD2SEG:
    retlw 0x3F  ; 0
    retlw 0x06  ; 1
    retlw 0x5B  ; 2
    retlw 0x4F  ; 3
    retlw 0x66  ; 4
    retlw 0x6D  ; 5
    retlw 0x7D  ; 6
    retlw 0x07  ; 7
    retlw 0x7F  ; 8
    retlw 0x67  ; 9
    retlw 0     ; A
    retlw 0     ; b
    retlw 0     ; C
    retlw 0     ; d
    retlw 0     ; E
    retlw 0     ; F

    END
Note that I tested this with the MPLABX v5.25 simulator. This is a crap tool but it's what I have to work with.
 

Attachments

  • 16F84A_stopwatch.zip
    197.5 KB · Views: 7
Last edited:

LaTeX Commands Quick-Menu:

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top