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.

Timer1 with PIC16F628a and 32.768KHz Crystal

Status
Not open for further replies.
Hey everyone.

Ok my concept is simple; generate a pulse (roughly long enough to flash an LED and see it, say 100mS?) at a fairley accurate interval of 1 second.
Been done a million times before I know, but its my first so I learning.

I have successfully generated a flashing LED, but it seems to be flashing every 2 seconds.
I can understand that my Timer1 is overflowing at 65,535 and not 32,768 counts as it is 16 bits and this probably explains the x2 flash rate but I'm not sure how to work around this.

I have:
LED on PORTB, bit 0
32.768kHz crystal on RB6 RB7
TMR1CS: 1 = External clock from pin RB6/T1OSO/T1CKI/PGC (on the rising edge) - (Timer1 Clock Source Select bit)
T1SYNC: 1 = Do not synchronize external clock input (Timer1 External Clock Input Synchronization Control bit)
T1OSCEN: 1 = Oscillator is enabled (Timer1 Oscillator Enable Control bit)
T1CKPS<1:0>: 00 = 1:1 Prescale value (Timer1 Input Clock Prescale Select bits)

Here is my code.
Code:
        LIST            P=PIC16F628A
        INCLUDE         P16F628A.INC
        __CONFIG        _CP_OFF & _CPD_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDTE_OFF & _INTOSC_OSC_NOCLKOUT 
        ERRORLEVEL      -302    ;Eliminate bank warning

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                                                                                  ;
;                                   PIC16F628A Microcontroller                                     ;
;                                            ____ ____                                             ;
;                             VREF/AN2/RA2 -| 1  - 18 |- RA1/AN1                                   ;
;                             CPM1/AN3/RA3 -| 2    17 |- RA0/AN0                                   ;
;                           CMP2/T0CKI/RA4 -| 3    16 |- RA7/OSC1/CLKIN                            ;
;                             VPP/MCLR/RA5 -| 4    15 |- RA6/OSC2/CLKOUT                           ;
;                                      VSS -| 5    14 |- VDD                                       ;
;                                  INT/RB0 -| 6    13 |- RB7/T1OSC1/PGD                            ;
;                                DT/RX/RB1 -| 7    12 |- RB6/T1OSCO/T1CLKI/PGC                     ;
;                                CK/TX/RB2 -| 8    11 |- RB5                                       ;
;                                 CCP1/RB3 -|_9____10_|- RB4/PGM                                   ;
;                                                                                                  ;
;                                                                                                  ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

CBLOCK  H'20'                           ; Commence defining following constant block at RAM address H'20'
DELAYGPR1                               ; Variable used for temporary information storage in the delay subroutines
DELAYGPR2                               ; Variable used for temporary information storage in the delay subroutines
DELAYGPR3                               ; Variable used for temporary information storage in the delay subroutines
FLAGS
ENDC

W_ISR   EQU     H'70'                   ; For context saving. Ensures GPR is accessible from any Bank. See Memory Map of 628A
S_ISR   EQU     H'71'                   ; For context saving. Ensures GPR is accessible from any Bank. See Memory Map of 628A
P_ISR   EQU     H'72'                   ; For context saving. Ensures GPR is accessible from any Bank. See Memory Map of 628A
F_ISR   EQU     H'73'                   ; For context saving. Ensures GPR is accessible from any Bank. See Memory Map of 628A



       
        ORG     H'000'                  ; Processor reset vector location. On power up, the program jumps here
        GOTO    SETUP                   ; 
       
        ORG     H'004'                  ; Interrupt vector location. When an Interrupt occurs, the program jumps here
  ; Save
        MOVWF   W_ISR                   ; Save W to W_ISR
        SWAPF   STATUS, W               ; Use SWAPF instruction so status bits don't change
        MOVWF   S_ISR                   ; Save Status to S_ISR
        CLRF    STATUS                  ; Switch to Bank 0
        MOVF    PCLATH, W               ; Move PCLATH to W register
        MOVWF   P_ISR                   ; Save PCLATH to P_ISR
        CLRF    PCLATH                  ; Force page 0
        MOVF    FSR, W                  ; Move FSR to W register
        MOVWF   F_ISR                   ; Save FSR to F_ISR
       
  ; Interrupt content
        BSF     PORTB, 0
        CALL    DELAY_100mS
        BCF     PORTB, 0
       
  ; RESTORE
        BCF     PIR1, TMR1IE            ; Clear TMR1 interrupt flag while still in Bank 0        
        MOVF    F_ISR, W                ; MOVE F_ISR to W
        MOVWF   FSR                     ; Restore FSR
        MOVF    P_ISR, W                ; MOVE P_ISR to W
        MOVWF   PCLATH                  ; Restore PCLATH
        SWAPF   S_ISR, W                ; Undo previous SWAPF, place result in W
        MOVWF   STATUS                  ; Restore STATUS
        SWAPF   W_ISR, F                ; Use SWAPF instruction so status bits don't change
        SWAPF   W_ISR, W                ; Undo previous SWAPF and restore W register
        RETFIE                          ; Return From Interrupt
       
       
SETUP  ; This routine sets up the Microcontroller's Inputs and Outputs
        MOVLW   H'07'                   ; Turn Comparators off and enable pins for I/O functions
        MOVWF   CMCON                   ;
        BSF     STATUS, RP0             ; Bank 1
        MOVLW   B'00010000'             ; 
        MOVWF   TRISA                   ;
       
        MOVLW   B'11000000'             ; 
        MOVWF   TRISB                   ; 
        BCF     STATUS, RP0             ; Bank 0
       
        CLRF    PORTA                   ;
        CLRF    PORTB                   ;
        CLRF    FLAGS                   ;
       
       
TIMER_1_SETUP
        MOVLW   B'00001110'             ;               R/W-POR State   Bit Name: Bit Description - Setting
        MOVWF   T1CON                   ;   -------0    R/W-0           TMR1ON: Timer1 On bit (0 = Stops Timer1)
                                        ;   ------1-    R/W-0           TMR1CS: Timer1 Clock Source Select bit (1 = External clock from pin RB6/T1OSO/T1CKI/PGC (on the rising edge))
                                        ;   -----1--    R/W-0           T1SYNC: Timer1 External Clock Input Synchronization Control bit (1 = Do not synchronize external clock input)
                                        ;   ----1---    R/W-0           T1OSCEN: Timer1 Oscillator Enable Control bit (1 = Oscillator is enabled)                                        
                                        ;   --00----    R/W-0           T1CKPS<1:0>: Timer1 Input Clock Prescale Select bits (00 = 1:1 Prescale value)
                                        ;   00------    R/W-0           Unimplemented: Read as ‘0’
       
CONFIGURE_INTERRUPT
        BSF     INTCON, GIE             ; Enable Global Interrupts
        BSF     INTCON, PEIE            ; Enable Peripheral Interrupts
        BSF     STATUS, RP0             ; Bank 1
        BSF     PIE1, TMR1IE            ; Enable TMR1IE - TMR1 Overflow Interrupt Enable bit
        BCF     STATUS, RP0             ; Bank 0
        CLRF    PIR1                    ; Clear Peripheral Interrupt Flags
        BSF     T1CON, TMR1ON           ; Start TMR1
       
LOOP_PROG
        NOP                             ; Do nothing 
        GOTO    LOOP_PROG


       

DELAY_100mS  ; Actual delay = 0.1 seconds = 100000 cycles
        MOVLW   0X1F                    ;
        MOVWF   DELAYGPR1               ;
        MOVLW   0X4F                    ;
        MOVWF   DELAYGPR2               ;
DELAY_100mS_0
        DECFSZ  DELAYGPR1, F            ;
        GOTO    $+2                     ;
        DECFSZ  DELAYGPR2, F            ;
        GOTO    DELAY_100mS_0           ; 
        GOTO    $+1                     ; 99998 CYCLES
        RETURN                          ; 4 cycles (including call)


END                                     ; Directive 'end of program'
 
Oh by the way, I know it isn't good practice to spend longer than needed inside the ISR (like calling a delay from inside), and I was using a flag and checking the flag in normal program loop to flash and delay the LED, but for simplicity and just to get it working i deleted that and will fix that later.
It's a very simple program and the delay should execute well and truly before the Timer1 overflow occurs again.
 
I simply inserted this into the ISR and seems to have done the trick.
Code:
        MOVLW   B'10000000'
        MOVWF   TMR1H

I assume TMR1 doesn't need to be stopped because when i update TMR1H manually inside the ISR, the TMR has just overflowed and it will be 256 counts of TMR1L before TMR1H is changed (or incremented to 00000001). And this is 256 counts at 32kHz so way slower that the chips instruction cycle execution time so I guess it doesn't need to be stopped.
 
Exactly, there are situations where you might want to stop the timer or be careful about the order you load the values, the number of cycles it takes, what happens if the clock changes right as you load the register, but if all you are doing is making a light flash once per second it doesn't really matter if you are off by a few ten thousandths of a second here or there.
 
Oh thanks Mike!
If only I'd have known that was in existence. Although having to think about it and write it line for line myself is probably more beneficial to me. And that is pretty much what I've got running.

It's been ticking away for 17hrs : 12min :30secs and its still counting within the second. The stop watch on my phone and the LED is flashing a little out of sync now but still within a second.
I'll let it run for 24 hours and check how far out it is..
 
Hi Jake,

I hope you're well.

I'm happy to see you're still enjoying PIC assembly language programming. Speaking of which, have you sampled and tried any of the more recent "enhanced mid-range" PIC devices like the 18 pin 16F1826, 16F1827, 16F1847, or 20 pin 16F1829? They're really quite nice. I especially like auto context save/restore for interrupts, access to WREG like on 18F devices, and dual FSRs which can be used to read ROM as well as RAM. Other features, like the BRW (branch W) instruction for tables and indirect access to RAM in a linear address space, are quite handy too. You really should try them, if you haven't already.

After many years of experimenting with PIC devices, I never used a 32768 Hz crystal with the Timer1 low power oscillator until just recently. It worked quite well and I designed and built a relatively simple 4-digit single chip 24-hour clock project (pictured below) which is posted on another forum.

Nice to see you again.

Cheerful regards, Mike

4-digit-2-jpg.85557
 

Attachments

  • 4-Digit #2.jpg
    4-Digit #2.jpg
    77.7 KB · Views: 1,878
If you write to the counter then you'll probably introduce errors, I've used a watch xtal on timer1 a few times, one project has a cursor led that flashes every second, I just count I think bit 15 of timer1, it toggles at 2hz, every 2 cycles is one second, you just need to use up a register location for a counter, then your led will keep very accurate sync with the clock on your 'phone.
 
Hey mike! It's nice to know my absence was noticed. Just been caught up with other things that's all. But I've really been missing it, so I'm back....

Anyway that's a nice little project you have there, I am just signing up (or resetting my password because my email is already in use... ??????) on all about circuits so I can download the source code. You've taught me a lot through this forum and I'm sure there are many more valuable things I can learn from analyzing your simple clock code.

My simple 1-sec interval led flashing code has been running for 7 days now, or 168 hours. I have it hooked up to a cd4040 12-bit counter. (it has wrapped around 147 times with the remainder displayed on my most recent mini project; a 16-bit binary in, decimal out converted). It is about 4 seconds slow. Which is pretty good I think.. only about 3 minutes a year i guess.. I just have 2 fixed value 22pf caps coupled to it.

In regards to the enhanced mid-range, no I haven't yet. I haven't know any different from the standard mid range. I will make sure to pick some up on my next electronics parts purchase.

dr pepper, I can see what you mean about writing to the counter register, the datasheet states to be cautious about this too. But for this simple program where interrupts trigger the led flash after a TMR1 overflow, the counter has just overflowed and a write to the upper register shouldn't be an issue. But I understand more caution may be need in more complex programs.
 
after resetting my password at all about circuits..
Code:
Welcome, jakeselectronics.
You last visited: 10-06-2008 at 08:01 PM
There you go, I was already a member. I probably just signed up so I could view some attachments one time haha..
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top