HomeArticlesProjectsBlogContact
Articles
2 Things at Once
Colin Mitchell
Colin Mitchell
November 01, 2010
Make sure to subscribe to our newsletter and be the first to know the news.
  • PIC12F629 Data Sheet (.pdf 4,926KB)
  • Instruction Set for PIC12F629
  • blank12F629.asm template
  • PIC12F629.inc

See more projects using micros:

A micro executes a program one instruction at a time and each instruction takes 1 microsecond. The instructions can create all sorts of effects but basically the micro is doing one thing at a time.
A program can perform a small task and output a result, then perform another task and output a result very soon after the first, so they appear to be happening at the same time.
This can be called a form of multi-tasking or multiplexing and in this way large displays can be illuminated, although only a few of the pixels are being driven at any one time.
But sometimes you want to actually carry out 2 tasks AT THE SAME TIME and sometimes this cannot be done by jumping from one task to the other and back again.
For instance, you may want to time the length of a game, while the player is playing.
There is no way to multiplex these two requirements, but the PIC chip has a feature called a TIMER. This is a file or register that is used exclusively for counting pulses (cycles). These pulses can come from an external source via one of the input pins or the file can be connected to the clock inside the chip.
The timer register is actually to files and they can be connected together to create a file 16 bits long. We call the result timer1. It is made up of tmrL for the low 8 bits and tmrH for the high 8 bits.
Then we connect the input of timer1 to the clock in the micro so that it increments each time the clock advances.
Timer1 will increment in the background while the program is being executed. We have an instruction reset timer1, so that timing will commence immediately after the instruction is executed. We also have 2 instructions to load the timer1 with a value so that it will “roll-over” at a desired instant.
We can also instruct the micro to jump to a certain location “0004” each time timer1 rolls over from FFFFh to 0000h. Timer1 gets incremented and that means if you are going to load it with a value, it has to be the number of uS (counts) up to FFFFh.
Location “0004” is called the Interrupt Service location or Interrupt Service Register and at that location you can place an instruction to go to a sub-routine: isr - Interrupt Service Routine that outputs a value to a port, turns off a port-line or perform any task at all. You can also reload timer1 with a value so that the Interrupt occurs again after a desired interval.
The instructions at ISR should be kept very short so they do not interfere with the running of the main program.
What happens is this:
The micro executes the main program and all the sub-routines and when timer1 rolls-over, the micro marks the next instruction and goes to location 0004.
It carries out the instructions at 0004. At 0004 you can place an instruction to go to isr. At isr the micro comes to an instruction retfi (return from interrupt). This is the instruction that is placed at the end of the routine and tells the micro to go back the location it marked and continue. This location the micro came from can be in the middle of sub-routine or the middle of a delay routine. It does not matter, the micro will continue with the program.
The maximum length of time for timer1 is 65,536uS or about 0.06 seconds. This can be increased by adding a prescaler of 8:1 making the maximum time approx .52seconds.
The full details of how to set up timer1 to create a 20 second time-delay is shown below.
There are a number of bits in files that must be set and since this is quite complex, the best approach is to copy and past the instructions and add further code to Main and sub-routines.
Start by making sure the instructions below work, then add a few instructions at a time, while checking that everything still works.
Adding an interrupt feature like this is complex and only add a few instructions at a time.

The following program contains the instructions needed to set up Timer1. Some of the instructions are in SetUp and some are in Main.
The micro then goes to a loop in main consisting of nop’s and executes these until 20 seconds has elapsed.
The instruction just before the nops in main (bsf PIE1,0) start the timer incrementing each time the clock ticks over while it is carrying out the instructions in the program. The micro executes a program in Main and gets interrupted 39 times and goes to 0004 and isr where it decrements a file and when the file is zero, it executes a set of instructions at isr such as flashing a LED on a display.
You can turn the timer off and turn it on at any time.

;*******************************
;;Interrupt Routine.asm
;  1-11-2010
;*******************************

    ;for  16F628 microcontroller


    __Config    _cp_off & _lvp_off & _pwrte_on
        & _wdt_off & _intRC_osc_noclkout & _mclre_off

    ;for 12F629 microcontroller

     __CONFIG   _MCLRE_OFF & _CP_OFF
        & _WDT_OFF & _INTRC_OSC_NOCLKOUT


;****************************************************************
; variables - names and files
;****************************************************************


        ;Files start at 20h

_20Secs     equ 20h ;file for counting up to 20 seconds

;****************************************************************
;Equates
;****************************************************************
status      equ 0x03
cmcon       equ 0x1F
rp1     equ 0x06
rp0     equ 0x05

z       equ 0x02


;****************************************************************
;Beginning of program
;****************************************************************


Start   org 0x00    ;program starts at location 000
    goto    SetUp
    nop
    nop     ;NOPs to get past reset vector address
    org 4
    goto    isr

SetUp   bsf status,rp0
    movlw   b'10000000';
    movwf   OPTION_REG  ; x000 0000 x=1 = weak pull-ups disabled
    bcf status,rp0      ;select programming area - bank0
    movlw   b'00000000' ;6,7=0 disables all interrupts
    movwf   INTCON      ;until we want timing to commence.
    movlw   07h     ;Turn comparators off
    movwf   cmcon
    movlw   .39
    movwf   _20Secs
    goto    Main


;interrupt service routine

isr nop
    bsf status,rp0  ;Bank 1
    bsf PIE1,0  ;,0 1=enables TMR1 interrupt
    bcf status,rp0  ;bank 0
    bcf PIR1,0  ;clear TMR1 overflow flag
    bsf INTCON,7    ;This instruction is needed HERE!!!
    bsf INTCON,6    ;1=enable all peripheral interrupts
    decfsz  _20Secs,f   ;creates 20Sec delay for each game.
    retfie
    bcf PIE1,0  ;,0 0=disables TMR1 interrupt
    bcf INTCON,6    ;0=disable all peripheral interrupts
    nop     ;put instructions here such as to produce a
    nop     ;digit on a display to show 20 seconds
    nop     ;has elapsed.
    goto    SetUp


;*************************************
;* Main             *
;*************************************

Main            ;at the instruction bsf PIE1,0 timer1 starts
            ;incrementing and the micro goes to
            ;0004 and isr to decrement_20Secs file
            ;39 times  39 x .53sec = 20 seconds.


;
;The following instructions start Timer1 to count 39 loops of .53 seconds
;to produce a total delay of 20 seconds. This is done on the background while the
;main program is being executed:
;

    bsf status,rp0  ;Bank 1
    movlw   b'10000000' ;
    movwf   OPTION_REG  ; x000 0000 x=1= weak pull-ups disabled
    bcf status,rp0  ;bank 0

    movlw   b'11000000' ;b'11000000'
    movwf   INTCON      ;,0  1=RB port change interrupt flag
                ;,1  1=RB0 interrupt occurred
    ;bcf    INTCON,2    ;1=TMR0 overflowed. Clear overflow flag
    ;bcf    INTCON,3    ;1=enable RB port change interrupt
    ;bcf    INTCON,4    ;1=enable RB external interrupt
    ;bsf    INTCON,5    ;1=enable TMR0 overflow (interrupt)
    ;bcf    INTCON,6    ;1=enable all peripheral interrupts
    ;bsf    INTCON,7    ;1=enable all unmasked interrupts

    movlw   b'00110101' ;b'00110001'
    movwf   T1CON       ;,7  not used
                ;,6 0=Timer1 is ON
                ;,5,4  11=8 prescale (max) 01=1:2
                ;,3 bit ignored
                ;,2 This MUST BE SET!!!!!!
                ;,1 0=int clock
                ;,0 1=enable timer1

    bcf PIR1,0      ;clear TMR1 overflow flag
    clrf    TMR1L       ;clear the Timer1 low register
    clrf    TMR1H       ;clear the Timer1 high register
                ;Timer0 is not used
                ; will go to isr when overflow in TMR1
                ;0.52 sec when prescaler=1:8  524,288uS

    bsf status,rp0  ;Bank 1 (Must use Bank1)
    bsf PIE1,0      ;,0 1=enables TMR1 interrupt
    bcf status,rp0  ;bank 0

Main2   nop     ;the micro will loop around these nop's until 20 seconds
    nop     ;has expired.
    nop
                nop
    goto    Main2

    End

The PIC micro can sometimes do 2 things at the same time, such as produce
3Hz and 23Hz on pins GP4 and GP5 but the instructions can be very long and complex.
The following is a program to produce 3Hz and 23Hz:


;*******************************
;;3Hz and 23Hz.asm
;*******************************
;Producing 3Hz at GP4 and 23Hz at GP5 at the same time.



cycle

    movlw    30h
    xorwf    gpio,1    ;to toggle GP4 GP5 (say ON)
    movlw    .7
    movwf    loops
    call     delay
    call     delay
    call     delay
    movlw    10h
    xorwf    gpio,1    ;to toggle GP4 3.5 times
    decfsz   loops,1
    goto     $-6
    call     delay
    call     delay
    movlw    20h
    xorwf    gpio,1    ;to toggle GP5 for 23Hz (off)
    call     delay
    movlw    10h
    xorwf    gpio,1    ;to toggle GP4 4 times
    movlw    .7
    movwf    loops
    call     delay
    call     delay
    call     delay
    movlw    10h
    xorwf    gpio,1    ;to toggle GP4 7.5 times
    decfsz   loops,1
    goto     $-6
    call     delay
    movlw    20h
    xorwf    gpio,1    ;to toggle GP5 (ON)
    call     delay
    call     delay
    movlw    10h
    xorwf    gpio,1    ;to toggle GP4 8 times
    movlw    .7
    movwf    loops
    call     delay
    call     delay
    call     delay
    movlw    30h
    xorwf    gpio,1    ;to toggle GP4 11.5 times GP5 (off)
    decfsz   loops,1
    goto     $-6
    movlw    .7
    movwf    loops
    call     delay
    call     delay
    call     delay
    movlw    10h
    xorwf    gpio,1    ;to toggle GP4 15 times
    decfsz   loops,1
    goto     $-6
    call     delay
    call     delay
    movlw    20h
    xorwf    gpio,1    ;to toggle GP5 (ON)
    call     delay
    movlw    10h
    xorwf    gpio,1    ;to toggle GP4 15.5 times
    movlw    .7
    movwf    loops
    call     delay
    call     delay
    call     delay
    movlw    10h
    xorwf    gpio,1    ;to toggle GP4 19 times
    decfsz   loops,1
    goto     $-6
    call     delay
    movlw    20h
    xorwf    gpio,1    ;to toggle GP5 (off)
    call     delay
    call     delay
    movlw    10h
    xorwf    gpio,1    ;to toggle GP4 19.5 times
    movlw    .6
    movwf    loops
    call     delay
    call     delay
    call     delay
    movlw    30h
    xorwf    gpio,1    ;to toggle GP4  22.5 times
    decfsz   loops,1
    goto     $-6
    call     delay
    call     delay
    call     delay
    goto     cycle where GP4 = 23 times and GP5 (ON)



delay    ;7246uS

    movlw    .8
    movwf    fileA
    movlw    .225
    movwf    fileB
    nop
    decfsz   fileB,1
    goto      $-2
    decfsz   fileA,1
    goto      $-4
    retlw    00

This can be simplified by using timer1 to produce the 3Hz and 23Hz while the Main program is performing another task.

;************************************************************************************
;;Interrupt Routine.asm
;Original code written by:  Mosaic Trinidad,W.I.   BSc, Industrial Eng.







;  1-11-2010
;***********************************************************************************

    ;for  PIC12F629 and 16F628 microcontrollers
        list p=12f629,

        __CONFIG _WDT_OFF &_INTRC_OSC_NOCLKOUT
        &_BODEN_ON &_CP_OFF &_PWRTE_ON

W_TEMP      Equ 0x20
STATUS_TEMP Equ 0x21
Timebase3   Equ 0x22
Timebase23  Equ 0x23

    org     000     ;reset vector
    goto    start   ;go to beginning of program

    org  0x004 ;interrupt vector location
    goto isr   ;go to interrupt service routine
    org 0020
;context save - save the value in w and status file
isr movwf   W_TEMP      ;copy W to temp register, could be in either bank
    swapf   STATUS,W    ;swap status to be saved into W
    bcf     STATUS,RP0  ;change to bank 0 regardless of current bank
    movwf   STATUS_TEMP     ;save status to bank 0 register

    bcf     PIR1,0          ; clr Timer1 Int flag
    movlw   63h     ;Timer1 must be loaded with 65536-14493 = 51043
                ;refer to converter below to obtain the
                ;hex value for tmrL and tmrH = c763
    movwf   tmr1L
    movlw   c7h
    movwf   tmr1H
;do time base ticks
    incf    Timebase3,f
    incf    Timebase23,f
    movlw   .3      ; test for 1/3 of 69Hz (23Hz)
    subwf   Timebase23,w
    btfsc   status,z
    goto    Next_timebase
    clrf    Timebase23
    movlw   b'00100000'
    xorwf   GPIO,f      ;toggle GP5 at 23Hz
Next_timebase;
    movlw   .23         ;test for 1/23 of 69Hz (3hz)
    subwf   Timebase3,w
    btfsc   status,z
    goto    ISRDONE
    clrf    Timebase3
    movlw   b'00010000'
    xorwf   GPIO,f      ;toggle GP4 at 3Hz

ISRDONE; restore context
    swapf   STATUS_TEMP,W   ;swap STATUS_TEMP into W, bank to original state
    movwf   STATUS      ;move W into STATUS register
    swapf   W_TEMP,F    ;swap W_TEMP
    swapf   W_TEMP,W    ;swap W_TEMP into W
    retfie          ;return to Main from interrupt


start
    clrf    GPIO        ;Init GPIO
    movlw   07h         ;Set GP<2:0> to
    movwf   CMCON       ;digital IO
    bsf     STATUS,RP0  ;Bank 1
    movlw   b'00001111'     ;Sets inputs and outputs
    movwf   TRISIO      ;
    bcf     STATUS,RP0  ;Bank 0

;Setup Tmr1 interrupt

; 1000,000/69 = 14493 ticks required for interrupt for a 69Hz base.
; 65536-14493 = 51043 => preload this into TMR1L/H for 14493 ticks for interrupt.
    movlw   63h
    movwf   tmr1L
    movlw   c7h
    movwf   tmr1H
    bsf status,rp0  ;Bank 1 (Must use Bank1)
    bsf PIE1,0      ;,0 1=enables TMR1 interrupt
    bcf status,rp0      ;bank 0
    bsf     INTCON,6        ;peripheral interrupt enable
    bsf     INTCON,7        ;generate interrupt enable.
    movlw   b'00000101'     ;timer1 setup bits, with 1:1 prescale
    movwf   T1CON       ;start timer1 running on a 1,000,000 ticks/sec
                ;filling TMR1L, TMR1H (65536)before interrupt occurs
    goto    Main

Main    nop
    goto Main   ;loop until interrupt occurs

    END

Hexadecimal to Decimal to Binary Converter

<!-- // TODO FIX ME - add the form input and javascript back in -->

Colin Mitchell

Colin Mitchell

Expertise

electronics
writing
PIC-Chips

Social Media

instagramtwitterwebsite

Related Posts

TODO
Transistor Test
© 2021, All Rights Reserved.

Quick Links

Advertise with usAbout UsContact Us

Social Media