# How to produce a frequency in khz

#### mini

##### New Member
Hello,
I am use uC PIC16F628A, how can I get or produce the frequency 9Khz with external oscilator 8mhz, my compiler is oshonsoft.

I hope someone here help me.

mini.

#### sagor1

##### Member
Have you tried the FREQOUT command? It can (according to manual) produce up to 10kHz tones for up to 10 seconds. But I have not tried it myself...
Other option would be to set up a timer with interrupt and toggle an I/O pin at the desired frequency. The higher the PIC oscillator, the better the frequency resolution would be.
Another option is to set up a PWM on the PWM pin. Read section 9.3 of the datasheet. That could be set up to run continuously I think...
If you describe your application a bit better, others may have other suggestions....

Last edited:

#### mini

##### New Member
I plan for continuously to get to 9Khz frequency at PORTBO with external oscillator 8Mhz or 20Mhz.
Could you please give me a sample according this.

Mini.

#### sagor1

##### Member
Sorry, don't have any examples. It would be trial and error in programming to get the right frequency. You have to experiment a bit to see what you can get

#### mini

##### New Member
Helo Sagor,
Is okay, advice and write is more easy than practice knowledge.
Youtube is more better than forum.

Mini.

#### dknguyen

##### Well-Known Member
Helo Sagor,
Is okay, advice and write is more easy than practice knowledge.
Youtube is more better than forum.

Mini.
It's also more easy to ask someone to write your code for you than to write it yourself. You're not asking for help. You're asking someone to do it for you.

Last edited:

#### mini

##### New Member
I have done with picbasic, I am new in oshonsoft that why i need some sample (TMRO = 20).....

#### sagor1

##### Member
Ok, here is an example of an interrupt routine that will toggle PORTB.0 at about 9kHz. The thing is, at 18k interrupts per second, there is not much time left for other main code.
Interrupt is set to 18kHz so every cycle it turns off the port, then next cycle turn the port on. two cycles give a full 9kHz square wave. At 8Mhz crystal, total time in interrupt will be 12.5uS. With an interrupt running every 55.5uS, that leaves little time for main routine. Though the main code can be long, the interrupt routine will use up about 20% of your CPU cycles.
Read the comments carefully, pick either the 8Mhz options or the 20Mhz options, not both.
The simulator seems to run this ok, but I don't have means of testing. You are on your own from here. Look for "timer tools" on the Internet, there are a few that will let you calculate the timer values.

Code:
Define CONFIG = 0x3f0a  '16f628a
'Example of 18Khz interrupt to produce 9Khz output
'actual Output is 9009Hz due To rounding errors/accuracy with 8Mhz
'actual output is 8992Hz due to rounding errors at 20Mhz

'Use 8Mhz crystal
Define CLOCK_FREQUENCY = 8.0  '8 Mhz

'Use 20 Mhz crystal
'Define CLOCK_FREQUENCY = 20.0

'Example using timer0 to set 55.5us interrupt

'for 8Mhz crystal
OPTION_REG = 0x88
TMR0 = 145
INTCON = 0xa0  'enable interrupts and timer0 interrupt

'for 20Mhz crystal:
'OPTION_REG = 0x80
'TMR0 = 117
'INTCON = 0xa0  'enable interrupts and timer0 interrupt

Enable  'Enable interrupts
loop:
'main code here
Goto loop
End

'Interrupt routine with 8Mhz takes about 9us to complete without "Save System"
'Takes about 12.5us with Save System
'With 20Mhz crystal, total time will be 5uS with Save System

On Interrupt
Save System
If INTCON.T0IF = 1 Then
INTCON.T0IF = 0
'For 8Mhz crystal
TMR0 = 145

'For 20Mhz crystal, reset to 20Mhz count:
'TMR0 = 117

Toggle PORTB.0
Endif
Resume

Last edited:

#### sagor1

##### Member
There is another way with the PWM registers, which I've never used. However, a PIC calculator (Mister E PIC Multicalc) comes up with these values to try:

Again, these are suggestions to try. The 1:1 prescaler option seems the closest to 9khz. You have to figure out the PWM registers based on the PIC you are using, and adjust values based on what you actually get in real life... For the 16F628a, read section 9.0 and 9.3 of the datasheet. The problem with PWM is that the output pin is fixed to RB3 (port B, pin 3) as pin 9 on the IC (18 pin DIP)

Last edited:

#### Pommie

##### Well-Known Member
You need a cycle every 111 clock cycles. Use a 4MHz crystal, set PR2 to 111, tmr2 to 1:1 prescaler and PWM on with CCPR1L set to 55 and you should get 9KHz on RB3.

Just follow the setup steps in section 9.3 of the data sheet.

Mike.
Edit you main code can just be an infinite loop.
Edit2, I see I was beeten to it by Sagor. Double the above figures for a 8M crystal.

#### mini

##### New Member
Helo,
Sagor : Thank you so much for the sample code, I tried it on simulation for 8Mhz external crystal I get 9,009 Khz or 9009 Hz, which I encrease the TMRO to 161 from 145.
Mike : I will tried as well as your advice, anyway thank you to for you.

I am really new in the Oshonsoft, I bought that compiler PIC16IDE and PIC18 Basic Compiler.

Mini.

#### sagor1

##### Member
Helo,
Sagor : Thank you so much for the sample code, I tried it on simulation for 8Mhz external crystal I get 9,009 Khz or 9009 Hz, which I encrease the TMRO to 161 from 145.
Mike : I will tried as well as your advice, anyway thank you to for you.

I am really new in the Oshonsoft, I bought that compiler PIC16IDE and PIC18 Basic Compiler.

Mini.
I would not change the 145 for TMR0 to 161 in real life. The simulator has timing issues, and the 145 should produce the proper 9.009 kHz frequency. If you want to get closer to 9.000 kHz, you would have to find a crystal frequency that gives a closer result. That would be trial and error, pure guessing what crystal to use.
TMR0 is used for the interrupt routing. The PWM example uses TMR2 internally.

#### ronsimpson

##### Well-Known Member
http://www.micro-examples.com/public/microex-navig/doc/097-pwm-calculator.html
With timers you can have 9009.01 and 8968.61 hz.
If you set the counter to give you 9009.01 for 4 times then reload and get 1 time of 8968.6, then a frequency counter will measure 9000.93.
While this sounds strange it is common trick to get a frequency you can not divide to.
With a little math we should get much closer.

#### sagor1

##### Member
Just a note, if one gets a 3.6Mhz or 7.200Mhz or 18Mhz crystal, you can get exactly 9.000 khz output with the PWM method....

#### mini

##### New Member
Hi Sagor,
Today I just tested the project to real hardware, please see on picture attached.
As well as you saying that TMRO not changing to 161, I measure it to frequency counter it will be around 7936 Hz or 7,936 Khz for TMRO 145, it will be around 90911 Hz if I put the value to 161 for TMRO.

At a moment I don't have a crystal for those 3.6Mhz, 7.2Mhz or 18Mhz, last night I checking to online store, I prefer for crystal 7.2Mhz and 18Mhz, those crystal are easy I found in store than 3.6Mhz.

As you saying with the PWM method :
PR2 = 62
T2CON.TMR2ON = 1
CCP1CON.2 = 1
T2CON.2 = 1
PWMduty 2, 0
Please let you explain do with the PWM..., Thank you.

Mini.

#### Nigel Goodwin

##### Super Moderator
It's all very 'clever' trying to get an accurate frequency by using timers or PWM, but if you do it with a simple software loop you can get far better accuracy with little effort - no messing about with silly crystal frequencies, you can get accuracy to one clock cycle, so for a 4MHz clock accuracy to 1uS.

#### sagor1

##### Member
I find your results strange, according to the documentation. Are you sure you are running off the external 8Mhz crystal, in HS mode (not XT)? Did you check the input crystal frequency from the crystal to confirm it is running at 8Mhz? Some crystals can be known to be bad. Is there the required 30pF capacitors on each crystal lead to ground? (30pF can be anywhere from 22pF to over 50pF, depending on board/make). In some cases, the board expects you to insert the caps. Hard to see in your picture if there are caps or not, they may be underneath.
I don't doubt your experiment results, you can clearly see the frequency output. It is just that it does not match what all the calculations say it should be. Mind you, using TMR0 means you are trying the interrupt method. If there is anything else running interrupts, that can throw the timings off. Also, make sure you are not mixing up decimal and hex values.

Try this site:
http://www.micro-examples.com/public/microex-navig/doc/097-pwm-calculator.html
and see what the register values should be. Results are in binary (8 bits), so you can insert those directly. It shows the code in C, but you can use those values in Oshonsoft.
Other sites:
http://eng-serve.com/pic/pic_pwm.html

The tool I use on my computer as a timer calculation program can be downloaded from:

#### Nigel Goodwin

##### Super Moderator
Are you sure you are running off the external 8Mhz crystal, in HS mode (not XT)?
Does that make any difference?, and in any case 8MHz is a bit 'in the middle' of XT and HS anyway - and personally I've never found it makes any difference at all, and I've certainly forgotten to change the setting sometimes when changing crystals

From what I can gather the HS setting just reduces the drive level, as 20MHz crystals can be a little fragile, and there's a potential slight change of damaging it with the higher XT drive levels.

#### sagor1

##### Member
True Nigel. I was just wondering about his overall hardware setup...
To MINI: if you insist on staying with the interrupt routines, and use that 161 for TMR0, you can probably slow down that 9091kHz frequency by adding a NOP instruction in the actual interrupt routine to slow that frequency down. Then measure again. Keep adding NOPs until you get real close to that 9000Hz. Not sure how good an idea that is, but no harm trying it.