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
<!-- // TODO FIX ME - add the form input and javascript back in -->
Quick Links
Legal Stuff
Social Media