Use assembly instructions and internal oscillator LFINTOSC...This example is actually a sequel to the previous one. It deals with a bit more complicated problem... The idea is to make LEDs on PORTB blink slowly. It can be done by setting delay parameter to be large in the Delay function. But there is also another, more efficient way to do it. You remember that this microcontroller has a built-in oscillator LFINTOSC which operates at the frequency of 31kHz? Now, it’s time to give it a try. The program starts with the do-until loop and remains herein for 20 cycles. After each iteration, 100mS delay is provided, which is reflected as a relatively fast PORTB LEDs blinking. When the program exits this loop, the microcontroller starts using the LFINTOSC oscillator as a clock signal source. LEDs blink much slower now, even though the program executes the same do-while loop with 10 times shorter delay. To demonstrate one potentionally dangerous situation here, control bits are activated by assembly instructions. Simply put, when entering or exiting an assembly sequence in the program, the compiler doesn’t save data on the currently active RAM bank, which means that in this program section, bank selection depends on SFR registers in use. When switching back to the program section written in Basic, the control bits RP0 and RP1 must return the state they had before entering the assembly sequence. In this case, the saveBank auxiliary variable is used to save the state of these two bits.
'Header ********************************************* program example_2 ' Program name dim k as byte ' Variable k is of byte type dim saveBank as byte ' Variable saveBank is of byte type main: ' Start of program k = 0 ' Initial value of variable k ANSEL = 0 ' All I/O pins are configured as digital ANSELH = 0 PORTB = 0 ' All PORTB pins are set to 0 TRISB = 0 ' PORTB pins are configured as outputs do PORTB = not PORTB ' Invert PORTB logic state Delay_ms(100) ' 100mS delay k = k+1 ' Increment k by 1 loop until k=20 ' Remain in loop while k<20 k=0 ' Reset variable k saveBank = STATUS and %01100000 ' Save the state of bits RP0 and RP1 ' (bits 5 and 6 of the STATUS register) asm ' Start of assembly sequence bsf STATUS,RP0 ' Select memory bank containing bcf STATUS,RP1 ' the OSCCON register bcf OSCCON,6 ' Select internal oscillator LFINTOSC bcf OSCCON,5 ' with a frequency of 31KHz bcf OSCCON,4 bsf OSCCON,0 ' Microcontroller uses internal oscillator end asm ' End of assembly sequence STATUS = STATUS and %10011111 ' Bits RP0 and RP1 return their original state STATUS = STATUS or saveBank do PORTB = not PORTB ' Invert PORTB logic state Delay_ms(10) ' 10 mS delay k = k+1 ' Increment k by 1 loop until k=20 ' Remain in loop while k<20 stay_here: goto stay_here ' Endless loop end.You have noticed that the clock signal source is changed on the fly. If you want to make sure of it, remove quartz crystal prior to switching the microcontroller on. The microcontroller will not start to operate because the Config Word loaded with the program requires the quartz crystal to be provided. If you remove this crystal later on during an operation, nothing will happen, that is to say it will not affect the operation of the microcontroller at all.