|
|
View previous topic :: View next topic |
Author |
Message |
girichavana
Joined: 21 Oct 2008 Posts: 17
|
33Khz square wave generation with PIC16F676 |
Posted: Tue Oct 21, 2008 3:24 am |
|
|
Hello everybody,
I am new to this forum. Presently I am using CCS PCH for programming my PIC16F676. Mine is the purely time based project, is this compiler is suitable ? If so how can I program my timers to get 33 KHz frequency wave ? Here I want to use the internal 4Mhz oscillator.
thanks and regards |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: 33Khz square wave generation with PIC16F676 |
Posted: Tue Oct 21, 2008 5:20 am |
|
|
Set up Timer 2 so that it is clocked by the Fosc/4 (1 MHz), and set its period to 30. Set the duty cycle (CCPR1L) to 15. Then you will get a 50% duty cycle PWM signal at 33.33 kHz. But I think you will need to use the PCM compiler for the 16F series. The PCH compiler is for the 18F series. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
girichavana
Joined: 21 Oct 2008 Posts: 17
|
|
Posted: Sat Oct 25, 2008 1:27 am |
|
|
Thanks for ur replay,
Sorry for my mistake, actually I am using PCM compiler. You suggested that to use the Timer 2, but its not there in PIC16f676 . Can i use the Timer1? |
|
|
Ttelmah Guest
|
|
Posted: Sat Oct 25, 2008 3:18 am |
|
|
Not really.
Unfortunately, it'll be more complex on this chip. Timer2, has the nice ability for you to program the count where it resets. This allows you to generate quite accurate timings for jobs like this. On the 676, you are going to have to do the job 'in software'. A lot depends on what else you want to do with the chip?. If you only want a 33KHz waveform, with nothing else going on, then the 'simplest' solution, is just:
Code: |
#include <16F676.h>
#device adc=8
#FUSES NOWDT,INTRC,NOPROTECT,BROWNOUT,NOMCLR,NOCPD,PUT,BANDGAP_HIGH
#use delay(clock=4000000)
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
setup_comparator(NC_NC);
setup_vref(FALSE);
while (TRUE) {
output_high(PIN_A0);
delay_us(11);
output_low(PIN_A0);
delay_us(9);
}
}
|
This will give 33.33KHz, on pin A0.
You can do it with a timer, by but the arithmetic involved (you will have to add a count to the timer, or read it an perform a subtraction), makesit likely you will 'miss counts', since there is not a lot of time available between pulses....
Best Wishes |
|
|
girichavana
Joined: 21 Oct 2008 Posts: 17
|
|
Posted: Sun Oct 26, 2008 12:07 am |
|
|
Thanks,
Your code is working properly, but my application includes some
other tasks. So here I want to use the Timer0 interrupt for this.
I want to calculate the Timer0 loadable value to get a certain frequency.
Regards |
|
|
Ttelmah Guest
|
|
Posted: Sun Oct 26, 2008 3:19 am |
|
|
You are not going to have any time.
The pulse width needed for each half cycle, is only _15_ instructions. You can simply run timer0, directly off the master clock (DIV_1), and add 241 to it, when it's interrupt flag is set. By the time you have done this, cleared the flag, and start waiting for it to set again, you are going to be running out of instruction.
You can save work, if you can accept a pulse, rather than a square wave. You then add 226 to the timer, and just pulse the output high, then one cycle latter, low. You then have 28 machine instructions to do things, till the next pulse is needed. Still not enough for anything much. Also, use the 'fast_io' mode, since this will save a couple of instructions on each change to the output.
To do other things, you really need to be clocking a lot faster. Clock the chip at 24MHz, and you have 182 instructions between leading edges (if you can accept a pulse output), for a 32967Hz output. Much better.
Alternatively, use a chip that does have a PWM output. The waveform, can then be generated by the hardware, leaving you time to do your other jobs.
Best Wishes |
|
|
girichavana
Joined: 21 Oct 2008 Posts: 17
|
|
Posted: Sun Oct 26, 2008 7:14 am |
|
|
The following is the code that i have written. I have simulated this by using the PROTEUS. But it is giving 6kHz. I tested with oscilloscope also. The result is same.
#include <16F676.h>
#fuses NOWDT,INTRC,NOPROTECT,BROWNOUT,NOMCLR,NOCPD,PUT
#use delay(clock=4000000,type=internal)
#int_timer0
void timer0interrupt()
{
output_toggle(PIN_C4);
set_timer0(0xF1);
}
//=========main======
void main()
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);
setup_timer_0(RTCC_INTERNAL);
set_timer0(0xF1);
while(1)
{
}
} |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Sun Oct 26, 2008 9:34 am |
|
|
girichavana wrote: | The following is the code that i have written. I have simulated this by using the PROTEUS. But it is giving 6kHz. I tested with oscilloscope also. The result is same.
|
Were you expecting 33kHz maybe? That is impossible. You are setting Timer 0 to 0xF1 because maybe you think it will take 15 more ticks to make 0x00, and that will cause the next interrupt. But you are forgetting that a lot of time went by from the previous overflow to where you are setting Timer 0. If you are seeing a 6 kHz waveform, then the time between transitions is now 83 uSec, where you wanted to see 15 uSec. The extra 68 uSec probably came from the time it takes the CCS interrupt handler to determine that Timer 0 was the source plus the time it took to toggle the output bit. That could easily add up to 68 uSec. If you want to make it faster, then write your own global interrupt handler and access the Timer 0 and PORTC registers directly instead of using CCS functions. But even if you do that, you will never get the output to 33 kHz, as Ttelmah so clearly showed in his last posting. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
Ttelmah Guest
|
|
Posted: Sun Oct 26, 2008 9:44 am |
|
|
Exactly.
You will get closer, if instead of physically interrupting, you _test_ the interrupt bit, and then add the offset, rather than just loading it, but I doubt if even like this, you will have more than one or two instructions 'in hand'. Certainly no time to actually do anything else.
I have posted about using polling of the interrupt bit inside the main code, as an alternative to an actual interrupt on several occassions. A search should find some stuff about this.
Best Wishes |
|
|
girichavana
Joined: 21 Oct 2008 Posts: 17
|
|
Posted: Tue Oct 28, 2008 8:38 am |
|
|
Thanks,
I got the 33khz with the ASM. How can I include the ASM routine in the CCS C ?
Regards |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Tue Oct 28, 2008 10:30 am |
|
|
girichavana wrote: | Thanks,
I got the 33khz with the ASM. How can I include the ASM routine in the CCS C ?
Regards |
Use the #ASM / #ENDASM directives. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|