|
|
View previous topic :: View next topic |
Author |
Message |
Briany
Joined: 06 Jan 2009 Posts: 15
|
use timer0 to gen 400KHz - need help |
Posted: Tue Jan 27, 2009 10:33 pm |
|
|
hi all,
I'm trying to create a PPM ultrasonic pulse at 200KHz using timer0. So, what it's in my mind is:
- provide a character
- use timer0 as a counter to toggle a pin high and low until the character is done.
problem:
I've used 18F4431 and 16F88, but I've encountered the exact same problem: timer0 is stuck at 9.7KHz and no matter what value I've put into set_timer0(value), nothing happens. The only thing that changes the frequency is by changing the RTCC_div_#.
here's the code:
what it does at the moment is to check the frequency of the timer0. It has nothing to do with PPM. It just toggles PIN_B3, or pin9 of 16F88 to high and low so it generates a 50% duty_cycle square wave.
compiler: 4.038
Code: |
#include <16F88.h>
#fuses hs,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOWRT
#use delay(clock=20000000)
//
//#id 0x0819
//include files here..........
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
//#include <brianlcd.c>
#include <string.h>
//#include <lcd_menu.c>
//#use rs232 (baud = 115200, xmit = UART_TX, rcv = UART_RX, bits = 8, parity = N,errors)
//**************************************************************************************************************
//define global variables
//**************************************************************************************************************
int8 num;
int16 sensor1_time=0, sensor2_time=0;
int1 calc_distance = 0;
int1 PPM_flag=0, detection=0, test_timer0=0, test_timer1=0, test_timer2=0;
int8 timer_overflow=0;
//**************************************************************************************************************
//**************************************************************************************************************
//set timer0 as the 1st priority
//**************************************************************************************************************
//Timer0 interrupt routine
//**************************************************************************************************************
#int_timer0
void Timer0_isr()
{
//PPM_flag = 1;
output_bit(PIN_B3,test_timer0);
if(test_timer0==0)
test_timer0 = 1;
else
test_timer0 = 0;
}
//**************************************************************************************************************
// MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN
//**************************************************************************************************************
void main ()
{
int16 period, duty_max, duty_value;
int8 state=0;
setup_adc_ports(NO_ANALOGS); //= 0x06; //00000110 all digital to start
//****************************************************************************************
//setup timer0
//****************************************************************************************
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_BIT);
set_timer0(243);
//****************************************************************************************
//Setup interrupts
//****************************************************************************************
enable_interrupts(INT_timer0);
enable_interrupts(GLOBAL);
//Frequency = Fosc / (4 * (period+1) *postscale)
//**************************************************************************************************************
// WHILE LOOP WHILE LOOP WHILE LOOP WHILE LOOP WHILE LOOP WHILE LOOP WHILE LOOP WHILE LOOP WHILE LOOP WHILE LOOP
//**************************************************************************************************************
while (1)
{
}
} |
|
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: use timer0 to gen 400KHz - need help |
Posted: Tue Jan 27, 2009 11:00 pm |
|
|
Setting Timer 0 has nothing to do with the frequency with which Timer 0 interrupts occur. You call set_timer0() just once during setup. From that point on, Timer 0 counts up and overflows from 0xff to 0x00. On each overflow, you get an interrupt where you toggle the output pin. But Timer 0 does not reload that initial value again. It just continues counting up from 0x00. If you want to change the frequency, you will have to set Timer 0 every time in the interrupt routine. But this won't work for you either because 400,000 interrupts per second means 2.5 usec. per interrupt. That's only 12.5 instruction times. That is not enough to get into the interrupt, do something, at get back out.
You have a better chance of generating the signal you want using Timer 2 and PWM. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
Briany
Joined: 06 Jan 2009 Posts: 15
|
Re: use timer0 to gen 400KHz - need help |
Posted: Tue Jan 27, 2009 11:09 pm |
|
|
RLScott wrote: | Setting Timer 0 has nothing to do with the frequency with which Timer 0 interrupts occur. You call set_timer0() just once during setup. From that point on, Timer 0 counts up and overflows from 0xff to 0x00. On each overflow, you get an interrupt where you toggle the output pin. But Timer 0 does not reload that initial value again. It just continues counting up from 0x00. If you want to change the frequency, you will have to set Timer 0 every time in the interrupt routine. But this won't work for you either because 400,000 interrupts per second means 2.5 usec. per interrupt. That's only 12.5 instruction times. That is not enough to get into the interrupt, do something, at get back out.
You have a better chance of generating the signal you want using Timer 2 and PWM. |
great thanks. But I have a question: how did you figure out it's 12.5 instruction times? and what is the minimum instruction times needed for timer0, timer1 and timer2 @ 20MHz?
do you mean that I have to set_timer0(243) before the timer0_isr() ends?
Code: |
#int_timer0
void Timer0_isr()
{
//PPM_flag = 1;
output_bit(PIN_B3,test_timer0);
if(test_timer0==0)
test_timer0 = 1;
else
test_timer0 = 0;
set_timer0(243);
} |
If this is correct, I'll move this to timer2 and test it out. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
Briany
Joined: 06 Jan 2009 Posts: 15
|
|
Posted: Wed Jan 28, 2009 3:11 am |
|
|
thanks for the links PCM.
I've another question.
Since PWM via CCP is the only way to generate high frequency, and that I already have 18F4431 with hardware PWM built in it, can I use those to generate 200KHz data stream using that PIC? I've been playing around with the single shot feature, but I don't know how to set it to trigger every time I want it to fire.
I'm trying to create a PPM pulse, without using the CCP pins. I'm reserving the CCP pins for receiving part, and I want to keep the circuit as simple as possible. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Wed Jan 28, 2009 7:18 am |
|
|
Briany wrote: |
...I'm trying to create a PPM pulse, without using the CCP pins. I'm reserving the CCP pins for receiving part, and I want to keep the circuit as simple as possible. |
OK, if you must generate 200 kHz without using the CCP module, another option is to generate it using software:
Code: |
PulseCount = 150; //..total number of pulses generated
#ASM
goto PulseGenTop ; skip over the delay subroutine
DelayShort:
nop
nop
nop
nop
nop
return
PulseGenTop:
bsf PORTB,3
call DelayShort ; 1.8 uSec
nop
nop
bcf PORTB,3
call DelayShort ; 1.8 uSec
decfsz PulseCount,f
goto PulseGenTop
#ENDASM
|
If you use this method you will have to know in advance how many pulses you want to generate, you must have interrupts disabled, and your software is totally tied up doing this so it can't do anything else while it is generating a pulse stream. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
Briany
Joined: 06 Jan 2009 Posts: 15
|
|
Posted: Wed Jan 28, 2009 10:18 pm |
|
|
thanks a lot RLScott!
I have one last question.
is it possible to set up the hardware PWM off of a 18F4431 and set it to single shot mode to do that?
I've encountered problems with the single shot mode and wasn't able to get it to do the pulse generation. 200KHz is still an awfully lot of time for the PIC. I'm trying to experiment with all of the available methods in my hand.
The best way is to have my software running for something else, because I'll have UART running, but I think the most important thing is to have an accurate pulse generation, which I might have now (just logged on and hasn't tested the code yet). |
|
|
|
|
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
|