CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Timer_2 + calculation problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Guest








Timer_2 + calculation problem
PostPosted: Tue Aug 22, 2006 6:30 am     Reply with quote

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







PostPosted: Tue Aug 22, 2006 8:45 am     Reply with quote

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







PostPosted: Wed Aug 23, 2006 3:04 am     Reply with quote

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







PostPosted: Wed Aug 23, 2006 10:02 am     Reply with quote

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







PostPosted: Wed Aug 23, 2006 10:49 am     Reply with quote

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







PostPosted: Fri Aug 25, 2006 4:16 am     Reply with quote

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







PostPosted: Fri Aug 25, 2006 4:28 am     Reply with quote

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







PostPosted: Tue Sep 05, 2006 10:42 am     Reply with quote

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







PostPosted: Wed Sep 06, 2006 4:41 am     Reply with quote

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







PostPosted: Wed Sep 06, 2006 6:03 am     Reply with quote

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 ?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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