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 CCS Technical Support

timer1 external

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



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

timer1 external
PostPosted: Wed Jun 13, 2012 6:13 pm     Reply with quote

I use one of pic16f684 in difficult condition (-15*C) and i chose to put crystal
resonator as 4MHz because is tested in low temperature.
I try to make interrupt of every 1 second with timer1 external but without any success.
If i chose T1_INTERNAL it's works but without good precision , i think T1_INTERNAL is copy of internal RC oscillator/4 - is correct?
And if i chose T1_EXTERNAL or T1_EXTERNAL_SYNC the timer don't work.
I am very confused and i spend a lot of time of this simple problem.
I posted a simple try of code.
Code:
#include <16F684.h>
#device *=16
//#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                      //High speed Osc (> 4mhz)
#FUSES PROTECT                //Code not protected from reading
//#FUSES NOBROWNOUT               //No brownout reset
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled

#use delay(clock=4000000)

#Byte TMR1H = 0x0F   // TIMER1 HIGH BYTE LOOK DATASHEET
#Byte T1CON = 0x10  //TIMER1 CONFIG REGISTER LOOK DATASHEET

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


void main()
   {

   setup_oscillator(OSC_4MHZ);
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);

   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);

       while(true)
              {

              }

   }

//=======================****************************************
#int_TIMER1
void TIMER1_isr()                       
{

   Bit_clear(T1CON,7);  //Enable access to the individual bytes of the timer register
   Bit_Set(TMR1H,854);   //Add 4000000 to timer1 by setting high bit or timer register       
   Bit_Set(T1CON,7);   //Disable access to the individual bytes of the timer register

   if(input_state(pin_c1) == false)
            output_high(pin_c1);   // !comanda
      else
            output_low(pin_c1);   // !comanda
}

I give many beer for any help. Cool
THX. Bogdan
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 13, 2012 7:53 pm     Reply with quote

Quote:
Bit_Set(TMR1H,854);

What is the 854 ? TMR1H is an 8-bit register. It only has bits from 0 to 7.
The CCS manual lists the possible parameters for bit_set():
Quote:

bit_set( )

Syntax: bit_set(var, bit)

Parameters: var may be a 8, 16 or 32 bit variable (any lvalue).
bit is a number 0-31 representing a bit number, 0 is the least significant bit.


Do you have a 32.768 KHz crystal (and capacitors) on the Timer1
oscillator pins ? You need them. These are different pins than the
main oscillator pins.

Also, to enable the Timer1 external crystal circuit, you need to do this:
Quote:

setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1 | T1_CLK_OUT);
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Thu Jun 14, 2012 1:48 am     Reply with quote

T1_INTERNAL, has nothing to do with an RC oscillator. It is the master clock/4. Whatever source this is from.

Best Wishes
wangine



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Thu Jun 14, 2012 6:05 am     Reply with quote

I have external crystal 4MHz and capacitors. I can't put 32768 kHz, my applications don't permit that, only 4MHz crystal.
Entire program's include communication rs232 and I2C works fine.
The single problem is the precise timer.
My application write with rs232 or I2C a data in internal eeprom of 16f684 and with condition of 1 pin decrement time of eeprom in seconds and ms.
Ex: my time is 123.4 = my 16f684 wait when powered this time in second and switch the state of 1 pin.
I try with T1_INTERNAL but the error of timer is random not in line.
I posted entire code.
Main file:
Code:
#include "16f684.h"
#device *=16

#FUSES NOWDT                    //No Watch Dog Timer
//#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES XT                       //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled

#use delay(clock=4000000)

#use rs232(baud=2400,xmit=PIN_c0,rcv=PIN_A2,bits=8) //   ,TIMEOUT=8000

#Byte TMR1H = 0x0F   // TIMER1 HIGH BYTE LOOK DATASHEET
#Byte T1CON = 0x10  //TIMER1 CONFIG REGISTER LOOK DATASHEET

#include </src/operatii.c>
#include </src/serial_1.c>
//====================================================================================================

//float triger = 0;
int1 flag_data = false;
//int16 start_err = 1810;
//===============================//=======================//==========================================
#int_RTCC
void RTCC_isr(void)
   {
      counter++;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#int_EXT
void  EXT_isr(void)
{
    cifre.id = fgetc();
    cifre.m = fgetc();
    cifre.s = fgetc();
    cifre.z = fgetc();
    cifre.u = fgetc();
      
   flag_data = true;
//disable_interrupts(INT_TIMER1);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//=========//===========//===========//=========//========//=========//========//=========//========//========
 void main()
  {
   output_low(pin_c1);
   output_high(pin_c2);
   output_high(pin_c3);
   output_high(pin_c5);
//   output_float(pin_a2);
//   output_low(pin_c0);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   setup_ccp1(CCP_PWM);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   setup_oscillator(OSC_4MHZ);
//   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);      //524 ms overflow
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
//    setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1); 
    setup_timer_1(T1_EXTERNAL|T1_CLK_OUT);       //    external TIMER1 with
   setup_timer_2(T2_DIV_BY_1, 180, 1);  // 100 kHz  // only from PWM
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//   set_pwm1_duty(0);                    // 25% duty cycle on pin C2 // 160L pt 96kHz
      read_eeprom_data();
   triger = 0;
      suma_t();
   set_RTCC(0);
//   set_timer0(0);
   enable_interrupts(INT_RTCC);
//   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);

//   printf("%Lu\n\r", triger);

         if(input(PIN_C4)==0)  //if button pressed
        {    
      disable_interrupts(INT_EXT);
      }
      else
      {
         enable_interrupts(INT_EXT);
         enable_interrupts(GLOBAL);
         disable_interrupts(int_RTCC);
      }

while (true)
      {

   bum();
      
//******************************************************
   if(flag_data == true)
      {
disable_interrupts(INT_EXT);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
      if(cifre.id == 0xA0)
         {
      test_min_max_data();
      re_send_eeprom_data();

      flag_data = false;
       enable_interrupts(INT_EXT);   
        enable_interrupts(GLOBAL);
//      disable_interrupts(INT_TIMER1);   
         }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if(cifre.id == 0xD0)
         {
      re_send_eeprom_data();

      flag_data = false;
       enable_interrupts(INT_EXT);   
        enable_interrupts(GLOBAL);
//      disable_interrupts(INT_TIMER1);   
         }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if(cifre.id != (0xD0 && 0xA0))   
         {
         delay_ms(3000);
         putc(0xB2);// limit min config
         putc(0xB2);
      clear_variable();
         reset_cpu();
         }   
      }
   }
}
//   if (INPUT_STATE(PIN_B0) == 0)
//   {   output_low(pin_d7);
//=======================****************************************
#int_TIMER1
void TIMER1_isr()    // 2^16=  65536/2 = 32768 * 1/32.768Hz <--- (1sec)                     
{
//      counter++

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   Bit_clear(T1CON,7);  //Enable access to the individual bytes of the timer register
   Bit_Set(TMR1H,7);   //Add 32768 to timer1 by setting high bit or timer register       
   Bit_Set(T1CON,7);   //Disable access to the individual bytes of the timer register

   if(input_state(pin_c1) == false)
            output_high(pin_c1);   // !comanda
      else
            output_low(pin_c1);   // !comanda
}


Operatii file.

Code:
unsigned int16 counter = 0;
unsigned int16 counter_s = 0;

struct{
   unsigned int8 id; // ident
    unsigned int8 m; // mii
    unsigned int8 s; // sute
    unsigned int8 z; // zeci
    unsigned int8 u; // unit

}cifre;

struct{
    unsigned int8 m_1; // mii
    unsigned int8 s_1; // sute
    unsigned int8 z_1; // zeci
    unsigned int8 u_1; // unit      
}suma_1;

float temporizare = 0;
unsigned int16 triger = 0;
unsigned int16 err_min_max = 0;


//==============================================================================
void init_cifre()
   {
    cifre.m = 0;
    cifre.s = 0;
    cifre.z = 0;
    cifre.u = 0;
   }
//==============================================================================
void suma_t()
{
        temporizare = ((int16)suma_1.m_1*1000)+((int16)suma_1.s_1*100)+((int16)suma_1.z_1*10)+suma_1.u_1 ;
//      triger *= 24;
//      triger/= 10;
      temporizare = temporizare*0.976464f;   //0.9785f
      triger = temporizare ;
//      triger = triger * 24;   // normalize in concordance of timer
//      triger = triger / 10;   // normalize in concordance of timer
//      triger = triger - 30;
//   printf("%Lu\n\r", triger);
}
//==============================================================================
void suma_err()
   {
      err_min_max = ((int16)cifre.m*1000) + ((int16)cifre.s * 100) + ((int16)cifre.z * 10) + cifre.u ;
   }
//===============================================================================

void read_eeprom_data()
   {
    suma_1.m_1 = read_eeprom(0x00);
    suma_1.s_1 = read_eeprom(0x01);
    suma_1.z_1 = read_eeprom(0x02);
    suma_1.u_1 = read_eeprom(0x03);
   }

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void bum()
   {
   if(counter >= 100)
   {
      counter_s ++;
      counter = 0;

      set_RTCC(0);
   }

//   triger --;
//   delay_us(1990);

   if(counter_s >= triger)
      {
      delay_ms(0);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~           
        set_pwm1_duty(360L);    // 40L
        delay_ms(825);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      output_low(pin_c3); 
      delay_ms(2000);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      output_high(pin_c1);   // !comanda
      output_low(pin_c2);      // comanda
      }

   }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void test_bum()
   {
   if(counter >= 3000)
   {
      counter_s ++;
      counter = 0;
   }

   if(counter_s >= 6)
      {
      output_high(pin_c1);   // !comanda
      output_low(pin_c2);      // comanda
      }
   }


and serial file.

Code:

int1 flag_err_min = false;
int1 flag_err_max = false;

   extern int1 flag_data;
//   extern unsigned int16 triger;
   extern unsigned int16 err_min_max;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//===========================================
//===============================================
void clear_variable()
   {
    cifre.id = 0;
    cifre.m = 0;
    cifre.s = 0;
    cifre.z = 0;
    cifre.u = 0;
   }
//=============================================
void re_send_eeprom_data()
   {
   unsigned int8 temp_m = 0;
   unsigned int8 temp_s = 0;
   unsigned int8 temp_z = 0;
   unsigned int8 temp_u = 0;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   temp_m = read_eeprom(0x00);
   temp_s = read_eeprom(0x01);
   temp_z = read_eeprom(0x02);
   temp_u = read_eeprom(0x03);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      delay_ms(3000);

   putc(0xC0);
   putc(temp_m);
      delay_ms(20);     
   putc(0xC1);
   putc(temp_s);
      delay_ms(20);
   putc(0xC2);
   putc(temp_z);
      delay_ms(20);
   putc(0xC3);
   putc(temp_u);
      delay_ms(20);
   }
//=============================================

//================================================
void write_eep_data()
   {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if(cifre.id == 0xA0)
      {
    write_eeprom(0x00, cifre.m);
   write_eeprom(0x01, cifre.s);
   write_eeprom(0x02, cifre.z);
   write_eeprom(0x03, cifre.u);
      }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//   test_min_max_data();
   }
//================================================
void test_min_max_data()
   {
   unsigned int16 temp_min = 0;
   unsigned int16 temp_max = 0;
//   unsigned int16 temp_s = 0;

   suma_err();

//~~~~~~~~~~~~~~~~~ pt minim ~~~~~~~~~~~~~~~~~~~~~
   temp_min = read_eeprom(0xF1);
   temp_min += (int16)read_eeprom(0xF0) * 100;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~ pt maxim ~~~~~~~~~~~~~~~~~~~~~
   temp_max = read_eeprom(0xFF);
   temp_max += (int16)read_eeprom(0xFE) * 100;
//~~~~~~~~~~~~~~ verif min max ~~~~~~~~~~
   if(err_min_max < temp_min)
   {   flag_err_min = true;
delay_ms(3000);
   putc(0xB0);// limit min config
   putc(0xB0);
   clear_variable();
//      reset_cpu();
   }
   if(err_min_max > temp_max)
   {   flag_err_max = true;
delay_ms(3000);
   putc(0xB1);// limit max config
   putc(0xB1);
   clear_variable();
//      reset_cpu();
   }
//   if(temp_s == 9999)
//      reset_cpu();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   if((flag_err_min && flag_err_max) == false)
      {
      write_eep_data();
      }

   }
//===============================================


I try to normalize the error of timer. Normally I think the right value is 1024 ms and not 1000 ms because is impossible to divide exactly 4MHz to 1000.
Code:

temporizare = temporizare*0.976464f;   //0.9785f

I have 1 solution but I don't know how to do that.
To divide the timer with 8 and with 125
Code:

setup_timer_0(RTCC_INTERNAL | RTCC_DIV_8);

and = 4000000/4 = 1000000 / 8 = 125000 / 125 = 1000ms.
But again the questions RTCC_INTERNAL copy master clock (XT 4MHz) or internal RC oscillator ?
Is not important what timer I use 0 or 1.
THX again for fast reply.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Thu Jun 14, 2012 8:16 am     Reply with quote

One key thing leaps out, before going very far. You _cannot_ expect an interrupt based timer to keep reasonable time, if you sit for a minimum of 0.02 seconds inside an other interrupt. Seriously, if you are using 'int_ext', to give serial reception, the interrupt means you have the falling edge on a start bit, and _one_ character may be coming. Using software serial this way is 'bad enough', but to then sit and wait for six characetrs, could have you locked in this interrupt 'for ever', if the bits don't arrive....
Rethink this code as the first _vital_ thing.
Realistically far better to switch to a chip with a USART, and give yourself a chance.
Repeat the old mantra, that an interrupt _should only do the thing that the interrupt signal implies, and exit ASAP. Anything else is asking for trouble.
The rest is I'm afraid a mess as well.
For getting an accurate time, do a search on the forum. There was a tidy routine for generating accurate times from a 'tick' running at an odd interval using integer maths, and letting a counter wrap, to give exact timings, posted a long time ago.

Best Wishes
wangine



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Thu Jun 14, 2012 8:24 am     Reply with quote

Is impossible to switch to other chip and I don't have any solution for serial.
If serial running, timer is disabled and if timer is active serial is disabled.
Serial working with small problem,
Maximum count of timer is 900 sec and precision must be less than 10 ms.
Thx for reply and if you want to send a link with timer trick, I search 2 h and can't find any solution.
Thx again
Bogdan
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jun 15, 2012 5:28 pm     Reply with quote

Quote:
I you want to send a link with timer trick, I search 2 h and can't find any solution.

It's in the CCS forum. You don't need a 2 hr search. Go to the CCS
Code Library forum. http://www.ccsinfo.com/forum/viewforum.php?f=2
It's on the first page. Look for:
Quote:
Timer based Real Time Clock (RTC)
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jun 15, 2012 7:31 pm     Reply with quote

PCM p is right again ! I've used that code on a number of projects over the past couple of years so I know it does work.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Sat Jun 16, 2012 1:40 am     Reply with quote

Important also to say, that you can improve the serial handling by a huge factor, by just receiving one character at a time.
Basically the same as the 'standard' approach if you had a hardware USART. Just have your interrupt trigger reception of one character and exit. Use a state machine so you know 'where' you are in the string of characters. Difference is that at the end of every character you have at least half a character time, when other jobs (like servicing the timer interrupt) can be done. This gives everything else a 'chance'.... Smile

Best Wishes
wangine



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Sun Jun 17, 2012 9:31 am     Reply with quote

I understand now. but other solution to detect serial transmission without ext interrupt?
This solution has simple for me but now i see the error of this.
True i have something problems but with 2400 and 19600 works.
I say again is impossible to switch to other chip . This is condition :d.
I resolve with timer i read in library code a tutorial and i use timer0.
THX again.
Maybe now other solution with serial interrupt.
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