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 | 1/11/10
|
|