|
|
View previous topic :: View next topic |
Author |
Message |
Guest
|
Timer_2 + calculation problem |
Posted: Tue Aug 22, 2006 6:30 am |
|
|
I really didn't want to send this question but i have totaly no clue how to solve this questions... This is extended part of some topic written before.
Code: |
#include <16F917.h>
#fuses EC_IO,BROWNOUT, PUT
#use delay(clock=8000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include "picdem2LCD.c"
void main()
{
byte freqValue;
lcd_init();
printf(lcd_putc,"\n Start:");
while( TRUE ) {
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 24, 1); // 20 khZ
setup_timer_2(T2_DIV_BY_1, 30, 1); // 24,8 khZ --> 25
setup_timer_2(T2_DIV_BY_1, 36, 1); // 29,6 khz --> 30
setup_timer_2(T2_DIV_BY_1, 43, 1); // 35,2 kHz --> 35
setup_timer_2(T2_DIV_BY_1, 49, 1); // 40 kHz
setup_timer_2(T2_DIV_BY_1, 55, 1); // 44,8 kHz --> 45
setup_adc(adc_clock_internal);
set_adc_channel(0);
freqValue=read_adc();
set_pwm1_duty(freqValue);
//sleep(); for one minute
printf(lcd_putc,"\n\rFreq:%d",freqValue);
delay_ms(500);
}
}
/*
Datasheet:
The timer will continue to run during Sleep and can generate an interrupt-on-overflow, which will wake-up the processor. However, special precautions in software are needed to read/write the timer (see Section 6.5.1 “Reading and Writing Timer1 in Asynchronous Counter Mode”).
Reading TMR1H or TMR1L, while the timer is running from an external asynchronous clock, will ensure a valid read (taken care of in hardware). However, the user should keep in mind that reading the 16-bit timer in two 8-bit values itself, poses certain problems, since the timer may overflow between the reads.
Sleep mode does not shut off the LP oscillator operation (i.e., if the INTOSC oscillator runs the microcontroller, and T1OSCEN = 1 (TMR1 is running from the LP oscillator), then the LP oscillator will continue to run during Sleep mode.
Questions and problems :
-1). Im using rs232 connection but for now i want to test it on picdem lcd.
0.) Are those freq. calculations correct?
1.) How to read/display correct freq. measure? Becuse i get "Freq= 0" on the lcd.
2.) I have to light the LED cca each 1 minute, and in sleep time. The only way to make this work is with timer2, but i dont know how.
3.) So it's like... cycle,sleep,blink,cycle,sleep,blink...
4.) I dont know how to wake him up cca 1 minute after sleep. It looks like that i have to do this thru watchdog ?
*/
|
|
|
|
Ttelmah Guest
|
|
Posted: Tue Aug 22, 2006 8:45 am |
|
|
First, Timer2, _only_ runs in sleep, if it is used as an asynchronous timer (having it's own external clock). All the modes you show, will have the timer stopping, when sleep is executed.
All the timings are wrong. The formula, is:
((osc/4)/prescale)/(terminal count+1)
So for the first line, (8000000/4)/1/(24+1)=80000
Next, you _must_ pause between selecting the ADC channel, and triggering the conversion. The ADC input, behaves as a fairly large capacitor (depends on the PIC, but typically between 100, and 200pF), in series with a resistor of usually a couple of Kohms. It takes several uSec, for the capacitor to charge to the voltage selected, and this has to happen before you trigger the conversion.
Remember also, that the maximum value you can select as a pulse width, is only 4* to maximum count on the timer, and to get this '4*', the value being fed into the pwm_duty command, _must_ be a 'long'.
You cannot pause for a minute (with any accuracy), without either an external oscillator, or an external clock.
Best Wishes |
|
|
Guest Guest
|
|
Posted: Wed Aug 23, 2006 3:04 am |
|
|
Code: | #include <16F917.h>
#fuses XT,BROWNOUT,NOPROTECT,PUT
#use delay(clock=8000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include "picdem2LCD.c"
void main()
{
long freqValue,count;
short mode;
lcd_init();
mode = 0;
count=0;
while( TRUE ) {
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 132, 1); // 15,03 khZ --> 15
setup_timer_2(T2_DIV_BY_1, 99, 1); // 20 khZ
setup_timer_2(T2_DIV_BY_1, 79, 1); // 25 khZ
setup_timer_2(T2_DIV_BY_1, 65, 1); // 30,03 khz --> 30
setup_timer_2(T2_DIV_BY_1, 56, 1); // 35,08 kHz --> 35
setup_timer_2(T2_DIV_BY_1, 49, 1); // 40 kHz
setup_timer_2(T2_DIV_BY_1, 43, 1); // 45,4 kHz --> 45
setup_adc(adc_clock_internal);
set_adc_channel(0);
freqValue=read_adc();
set_pwm1_duty(freqValue);
printf(lcd_putc,"\n\rFreq:%X",freqValue);
if(mode==1)
sleep();
count++;
delay_ms(200);
}
}
/*
Hardware:
I added 8MhZ external oscilator to project board.
Software:
Changed the timer calculations, fuses and variable type.
Questions:
1.) Next, you _must_ pause between selecting the ADC channel, and triggering the conversion.
** You meen like delay_ms or something else ?
2.)You cannot pause for a minute (with any accuracy), without either an external oscillator, or an external clock
** OK. Now that this problem is fix, there are still questions like:
I have to enter sleep ( maybe by setting bits? ) and i have to count for a minute. Becuse i am in the sleep i can use only timer 2 for seconds counting and for getting out of sleep, or ?
*/ |
|
|
|
Ttelmah Guest
|
|
Posted: Wed Aug 23, 2006 10:02 am |
|
|
You need to feed the oscillator to something that can wake the chip. T1OSI, is the 'classic'. However with a 8MHz oscillator, this will probably be drawing more power than the processor, so why go to sleep at all...
Timer2, and your PWM, will still stop, when you are asleep.
You program T1, to _asynchronous_ mode (which means it no longer uses the master clock, and can keep running while the chip is asleep). Then using it's /8 prescaller, it'll time out every 1/15th of a second. You sleep, and when you wake, increment a counter. When this gets to 915, a minute has passed.
Yes, delay_us(5). Look at section 12.2, in the chip data sheet for how to calculate the needed time.
Best Wishes |
|
|
Gast Guest
|
|
Posted: Wed Aug 23, 2006 10:49 am |
|
|
Quote: | You need to feed the oscillator to something that can wake the chip. T1OSI, is the 'classic' | ** I understand what you meen but i dont know with what...
Quote: | However with a 8MHz oscillator, this will probably be drawing more power than the processor, so why go to sleep at all.
| ** I think so to, but there is no other way to reduce the batery consumption, or ?
Quote: | Timer2, and your PWM, will still stop, when you are asleep.
| ** OK for me. All i wan to is to count the seconds till new cycle.
Quote: | You program T1, to _asynchronous_ mode
| ** This is the part i dont understand how to make.
Quote: | Then using it's /8 prescaller, it'll time out every 1/15th of a second. You sleep, and when you wake, increment a counter. When this gets to 915, a minute has passed. | *** I get the teoretic part, but is there some simple example how to make this ? |
|
|
Guest Guest
|
|
Posted: Fri Aug 25, 2006 4:16 am |
|
|
OK. I solve all of the questions, reported in my last post, accept this one:
Quote: | You sleep, and when you wake, increment a counter
| **
Code: | If (counter == 915 )
break the sleep, wakeup
else
sleep |
Quote: | Datasheet
The timer will continue to run during Sleep and can generate an interrupt-on-overflow, which will wake-up the processor. |
1.) how to define this counter so he can read this timeouts from timer1 ?
2.) When i reach 915 ( one minute ) can i just set T1SYNC = 0 to make the wakeup ? |
|
|
Ttelmah Guest
|
|
Posted: Fri Aug 25, 2006 4:28 am |
|
|
Code: |
int16 tick;
//Then to sleep:
tick=915;
disable_interrupts(INT_TIMER1)
do {
sleep();
delay_cycles(1);
clear_interrupts(INT_TIMER1);
} while (tick--);
//Code will carry on running here
|
Multiple 'parts' to what happens. Provided timer1, is set to run asynchronously, it'll carry on running, and it's interrupt flag will become set when it wraps. When it does, the chip will wake. The instruction after the sleep, is 'prefetched', so to avoid this causing poblems, a 'nop' is inserted here (delay_cycles(1)). Then the interrupt flag is cleared, the counter decremented, and if it is not zero, the sleep executed again. Note that the interrupt is disabled. This removes the need to have an interrupt 'handler', but the chip will still wake up, when the interrupt occurs.
Best Wishes |
|
|
Guest Guest
|
|
Posted: Tue Sep 05, 2006 10:42 am |
|
|
Hi !
Code: | #include <16F917.h>
#fuses HS,NOWDT,NOPUT,NOPROTECT,NODEBUG,BROWNOUT
#use delay(clock=8000000)
#include "picdem2LCD.c"
//********************* INIT *********************************
#byte T1CON = 0x10 // timer 1
#byte INTCON = 0x0B // Intcon
#byte ANSEL = 0x91 // Analog select register
#byte ADCON0 = 0x1F //
#byte ADCON1 = 0x9F //
#byte ADRESH = 0x1E //
#byte ADRESL = 0x9E //
//----------------------------------------------
#bit GIE = INTCON.0 // 0 Bit --> GlobalInterruptEnable
#bit TMR1ON = T1CON.0 // 0 Bit --> Timer1 - 1/8
#bit T1SYNC = T1CON.2 // 2 Bit
#bit T1CKPS1 = T1CON.5 // 5 Bit
#bit GO = ADCON0.1 // 1 bit
//************************************************************
void main()
{
int16 tick; long freqValue,count; short mode;
mode,count=0;
SET_TRIS_A(0x01);
ANSEL = 1;
ADCON0 = 3; // channel select bits
setup_adc_ports(sAN0);
setup_adc(ADC_CLOCK_DIV_16);
lcd_init();
while( TRUE ) {
GO = 1; // go bit
ADCON0 = 0; //
ADCON1 = 80; // speed
ADCON0 = 1; // start AD converter
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 132, 1); // 15,03 khZ --> 15
setup_timer_2(T2_DIV_BY_1, 99, 1); // 20 khZ -->
setup_timer_2(T2_DIV_BY_1, 79, 1); // 25 khZ
setup_timer_2(T2_DIV_BY_1, 65, 1); // 30,03 khz --> 30
setup_timer_2(T2_DIV_BY_1, 56, 1); // 35,08 kHz --> 35
setup_timer_2(T2_DIV_BY_1, 49, 1); // 40 kHz
setup_timer_2(T2_DIV_BY_1, 43, 1); // 45,4 kHz --> 45
set_adc_channel(0);
delay_ms(5);
freqValue = make16(ADRESL,ADRESH);
//freqValue=read_adc();
//set_pwm1_duty(freqValue);
printf(lcd_putc,"\n\rFreq:%LX",freqValue);
}
} |
I did some changes, add few things but i still can get it to run...
1.) With code above you get freq:0000
2.) I have removed the Timer 1 and sleep part until i solve this.
3.) All registers are set and running ( as far as i know :-)) but without result...
4.) I added the conversion ( make 16 ) to get the freqValue, but nothing.
Where is the problem in this part ? |
|
|
Guest Guest
|
|
Posted: Wed Sep 06, 2006 4:41 am |
|
|
After some changes this is now a bit more advanced look into the problem:
Code: | //********************* INIT *************************
#byte T1CON = 0x10 // timer 1
#byte INTCON = 0x0B // Intcon
#byte ANSEL = 0x91 // Analog select register
#byte ADCON0 = 0x1F //
#byte ADCON1 = 0x9F //
#byte ADRESH = 0x1E //
#byte ADRESL = 0x9E //
//------------------------------------------------------------
#bit GIE = INTCON.0 // 0 Bit --> GlobalInterruptEnable
#bit TMR1ON = T1CON.0 // 0 Bit --> Timer1 - 1/8
#bit T1SYNC = T1CON.2 // 2 Bit
#bit T1CKPS1 = T1CON.5 // 5 Bit
#bit GO = ADCON0.1 // 1 bit
//************************************************************
void main()
{
int16 adValue;
SET_TRIS_A(0x01);
setup_adc_ports(sAN0);
setup_adc(ADC_CLOCK_DIV_16);
ANSEL = 1;
ADCON0 = 3; // channel select bits
lcd_init();
while( TRUE ) {
ANSEL = 1;
ADCON0 = 0;
ADCON1 = 80;
ADCON0 = 1;
//----------------------------------------------------------
delay_ms(50);
GO = 1;
delay_ms(50);
lcd_putc("\fTesting:");
//----------------------------------------------------------
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 132, 1); // 15,03 khZ --> 15
setup_timer_2(T2_DIV_BY_1, 99, 1); // 20 khZ -->
setup_timer_2(T2_DIV_BY_1, 79, 1); // 25 khZ
setup_timer_2(T2_DIV_BY_1, 65, 1); // 30,03 khz --> 30
setup_timer_2(T2_DIV_BY_1, 56, 1); // 35,08 kHz --> 35
setup_timer_2(T2_DIV_BY_1, 49, 1); // 40 kHz
setup_timer_2(T2_DIV_BY_1, 43, 1); // 45,4 kHz --> 45
//----SLEEP---------------------------------------------
//------------------------------------------------------
/* read value */
adValue = ADRESL+(ADRESH<<8);
printf(lcd_putc,"\n\rFreq:%LX",adValue);
}
} |
Problems:
I get click sound (constant clicks each few seconds) on the buzzer and on the display i get displayed just 0040 and then again 0000 ?
If this is the wright way i will try to insert the sleep part... |
|
|
Guest Guest
|
|
Posted: Wed Sep 06, 2006 6:03 am |
|
|
and the part with sleep:
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1 | T1_CLK_OUT);
enable_interrupts(INT_TIMER1);
Code: |
void main()
...
//----SLEEP---------------------------------------------
tick=915;
do {
sleep();
delay_cycles(1);
clear_interrupt(INT_TIMER1);
} while (tick--); //---------------------------------------------------------- |
He enters sleep but there is no wakeup after some time and i can not continue to run my code ?
Is there some problem with switching form internal to external osc ? |
|
|
|
|
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
|