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 and functions?

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



Joined: 15 Jun 2011
Posts: 16

View user's profile Send private message

timer1 and functions?
PostPosted: Wed Oct 05, 2011 5:54 pm     Reply with quote

Hello,
I am trying to use Timer1 as a one second counter interrupt. I have put the initialization in a function. When I call the function to start timer and enable interrupts, all code after the call does not work. Can you initialize a timer and interrupts from a function? Any ideas why it doesn't work. If I comment out call to this function all code after it works normally. This is a power sensitive application and I don't want any peripherals running during sleep. The PIC is a 16F886. compiler is 4.124

Code:


#include <16F886.h>
#device *=16
#device ICD=TRUE
#device adc=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES PUT                      //Power Up Timer
#FUSES PROTECT                  //Code protected from reads
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES BORV21                   //Brownout reset at 2.1V
#FUSES WRT_50%                  //Lower half of Program Memory is Write Protected

#use delay(int=1000000,RESTART_WDT)

#use STANDARD_IO( A )
#use FIXED_IO( A_outputs=PIN_A5 )
#use FIXED_IO( B_outputs=PIN_B4,PIN_B2 )
#use FIXED_IO( C_outputs=PIN_C7,PIN_C5,PIN_C3,PIN_C1,PIN_C0 )


#include <hope_rx_new.h>

// DEFINES
#Define light_in sAN1
#Define VDI sAN2                    // ad inputs
#Define Pyro_in sAN2
#define Rad_enbl Pin_A5
#define led_1 Pin_a6
#define led_2 Pin_c0
#define sw_enbl pin_c1
#define rad_clk pin_c3
#define rad_sdi pin_c4
#define rad_sdo pin_c5
#define sw_in pin_c6
#define sw_clk pin_c7
#define rad_INT pin_b0
#define led_cntl pin_b2
#define pie2 0x8d
#define pcon 0x8e
#define intcon 0x0b
#define led_enbl pin_b4

//END DEFINES
//
int8 radio_freq=0;
int8 SWITCH_data=0;                                   //              variables
int16 seconds=0;
int16 ad_samples[32];
int8 samples=32;
int16 pyro_avg=0;
int16 pyro_avg_old=0;
int1 pyro_hit=false;
int16 pyro_avg_delta=0;
int1 pyro_hits=0;
int16 lite_in=0;
int16 light_threshold=100;
int1 lite_on=false;
int16 upper_level=0;
int16 lower_level=0;
int16 lower_limit=50;
int1 light_bright=false;
int16 light_reading=0;

//##############################################End Variables
//###############################################Radio
void init_radio()
{
}

void check_radio()
{
}

//#############################################End Radio
//############################################Light
VOID pyro_lite  ()//                            half power
 {
   byte y;
   output_high(led_enbl); //turn on light hard
   output_high(Led_cntl);
   
   // baseline = read_ad(1) + 5;
   FOR(y  = 0; y <= 15; y++)
   {
      output_high(led_cntl);
      delay_ms(1);
      //light_sensor = read_ad(1);
      output_low(led_cntl);
   }

   output_high(Led_enbl); //turn on light hard
   output_high(led_cntl);
 }

void light_on_full()
{
   output_high(Led_enbl); //turn on light hard
   output_high(led_cntl);
}

void light_off()
{
   output_low(Led_enbl); //turn on light hard
   output_low(led_cntl);
}

//##########################################End Light
void read_SWITCH()         //read switch
{
   byte SWITCH_count = 0;
   byte a = 0;
   output_high(sw_enbl);
   delay_us(1000);
   output_low(SW_clk);
   output_high(sw_enbl);

   //load SWITCH
   delay_us(1000);
   //output_low(enable_SWITCH);
   for(SWITCH_count  = 0; switch_count <= 7; ++switch_count)
   {
      output_high(SW_clk);
      delay_us(1);
      output_low(SW_clk);
      output_low(sw_enbl);
      a = input(SW_in);
      shift_left(&SWITCH_data, 1, a);
   }

   //output_low(enable_SWITCH); // turn off resistors
   output_low(SW_enbl);
   radio_freq = SWITCH_data&0x0f;
   radio_freq *= 2;

   IF(radio_freq  < 2)//this will change to radio freq
      radio_freq = 2;

   //options = ( SWITCH_data&128);
   //options = & SWITCH_data;

   /* control light
   output_high(pin_b2);
   delay_us(50);
   output_low(pin_b2);
   delay_us(50);
   output_high(pin_b2); */
}

VOID my_sleep_ulpwu (INT16 y)
 {
   output_high(PIN_A0);
   delay_ms(y); // was ms
   clear_interrupt(INT_ULPWU);
   * pie2 = 4;
   output_FLOAT(PIN_A0);
   * intcon = 64;
   enable_interrupts(INT_ULPWU);
   * pcon = 32;
 }

//    #########################################timer functions
void start_sec_timer()
{
   clear_interrupt(INT_timer1);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);//             one second timer
   set_timer1(0);
   enable_interrupts(INT_timer1);
   enable_interrupts(global);
   seconds = 0;
}

void stop_sec_timer()
{
   clear_interrupt(INT_timer1);
   setup_timer_1(T1_disabled);
   set_timer1(0);
   disable_interrupts(INT_timer1);
   disable_interrupts(global);
   seconds = 0;
}

void start_quarter_sec_timer()
{
   clear_interrupt(INT_timer0);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_bit); //262 ms overflow
   set_timer0(0);
   enable_interrupts(INT_timer0);
   enable_interrupts(global);
}

void stop_quarter_sec_timer()
{
   clear_interrupt(INT_timer0);
   setup_timer_0(T0_EXT_L_TO_H); //262 ms overflow
   set_timer0(0);
   disable_interrupts(INT_timer0);
   disable_interrupts(global);
}

void start_100ms_timer()
{
   clear_interrupt(INT_timer2);
   setup_timer_2(T2_DIV_BY_16, 97, 16); //6.2 ms overflow, 100 ms interrupt
   set_timer2(0);
   enable_interrupts(INT_timer2);
   enable_interrupts(global);
}

void stop_100ms_timer()
{
   clear_interrupt(INT_timer2);
   setup_timer_2(T2_disabled, 1, 1); //6.2 ms overflow, 100 ms interrupt
   set_timer2(0);
   disable_interrupts(INT_timer2);
   disable_interrupts(global);
}

// ########################################  end time functions
//######################################### Start AD Functions
int16 Sampling_ad(INT8 samples, INT8 channel)//      sampling ad
{
   setup_adc(ADC_CLOCK_INTERNAL);
   
   // must be integer of 8
   INT8 shift;
   INT32 accum = 0;
   INT16 x = 0;
   INT16 ad_in = 0;
   //INT16 ad_samples[samples];
   set_adc_channel(channel);
   delay_us(500);
   FOR(x  = 0; x <= samples; x++)
   {
      ad_in = read_adc();
     
      ad_samples[x] = ad_in;
      accum += ad_in;
   }

   shift = (samples / 8) + 1;
   
   setup_adc(ADC_off);
   RETURN(accum>>shift);
}

int16 one_shot_ad( INT8 channel)//         one shot reading
{
   INT16 x = 0;
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(channel);
   delay_us(500);
   x = read_adc();
   setup_adc(ADC_off);
   RETURN(x);
}

//######################################## End AD Functions
//########################################Pyro Functions
INT1 read_pyro  ()
 {
   
   INT16 pyro_min = 1024;
   INT16 Pyro_max = 0;
   INT16 ad_in = 0;
   pyro_hit = false;
   INT16 x;
   //ad_old = 512;
   
   pyro_avg = Sampling_ad(32, pyro_in); // sampling ad
   
   FOR(x  = 0; x <= 31; x++) //was 64
   {
     
     
      ad_in = ad_samples[x];
     
      IF(ad_in  > pyro_max)
      {
         pyro_max = ad_in;
      }

      IF(ad_in  < pyro_min)
      {
         pyro_min = ad_in;
      }
   }

   
   
   pyro_avg_delta = abs(pyro_avg - pyro_avg_old);
   
   pyro_avg_old = pyro_avg;

   /*
   IF(wake_ups  >= 10)
   {
      count_up = 0;
      count_dn = 0;
      pyro_hits = false;
      wake_ups = 0;
   }

   */
   
   
   
   IF((pyro_max  - pyro_min) > 10)//radio_freq)//&&(abs(pyro_avg_delta  > 10)))
   pyro_hits = true;
   
   
   
   IF((pyro_max  - pyro_avg > 20)&&pyro_avg - pyro_min > 20)
   pyro_hits = true;
   
   RETURN(pyro_hits);
 }

//######################################## End Pyro
//######################################## Read light
 VOID read_light()
 {
    //setup_adc_ports(sAN1|sAN2|sAN3);
   
    light_reading = 0;
   
   
    light_reading = one_shot_ad(1); // one shot reading
    IF(light_reading  < light_threshold)
    {
       light_bright = false;
       
       BREAK;
    }

    else IF((light_reading  > 6)&&(light_reading  < 50))
    {
       light_bright = false; //this will be limbo
       //light_threshold = 15;
    }

    ELSE
    {
       light_bright = true;
    }

    // fprintf(debugger, " lite in % Lu Sec % lu \n\r", lite_in, sec);
 }

 VOID check_light()
 {
    read_light();

    IF(light_reading  > light_threshold)//300)/// was 600
    {
       shift_left(&upper_level, 2, 1);
       SHIFT_left(&lower_level, 2, 0);
    }

    IF((light_reading  < light_threshold)&&(light_reading  > lower_limit))// was 300
    {
       upper_level = 0;
       lower_level = 0;
    }

    IF(light_reading  < lower_limit)
    {
       shift_left(&lower_level, 2, 1);
       //SHIFT_left(&upper_level, 2, 0);
    }

    IF(bit_test(upper_level, 0)&&(bit_test(lower_level,  0)))
    {
       lite_on = true;
       upper_level = 0;
    }
 }

 //########################################End Read Light
 #USE SPI(MASTER, MODE = 0, BITS = 8, STREAM = SPI_1, MSB_FIRST)
 #INT_EXT
 VOID EXT_isr(VOID)
 {
 }

 #INT_TIMER1
 VOID TIMER1_isr(VOID)
 {
    seconds++;                   //count seconds
 }

 #INT_TIMER2
 VOID TIMER2_isr(VOID)
 {
 }

 #INT_TIMER0
 VOID TIMER0_isr(VOID)
 {
 }

 VOID main()
 {
    port_B_pullups(0x01);
    setup_adc_ports(sAN0|sAN1|sAN2);
    setup_adc(ADC_CLOCK_INTERNAL);
    setup_timer_0(T0_EXT_L_TO_H); //262 ms overflow
    setup_timer_1(T1_disabled); //1.0 s overflow
    setup_timer_2(T2_disabled, 97, 16); //6.2 ms overflow, 100 ms interrupt
    setup_comparator(NC_NC_NC_NC); // This device COMP currently not supported by the PICWizard
    disable_interrupts(INT_EXT);
    disable_interrupts(INT_TIMER1);
    disable_interrupts(INT_TIMER2);
    disable_interrupts(INT_TIMER0);
    disable_interrupts(GLOBAL);
    setup_oscillator(OSC_1MHZ);
    delay_ms(50);
    Read_SWITCH(); // get switch data
    init_radio();
    light_off(); // turn light off
   
   
   
    // ada in here radio init
   
   
   
   
   
   
    WHILE(1)
    {
       
       my_sleep_ulpwu(100);
       Sleep(); // Sleep
       delay_us(0); // NOP
       
       // returns light_Bright and Lite on
       check_light(); // this routine checks light and determines then snap
       // and wheter to check pyro or not
       IF( ! light_bright&&Lite_on)
       {
         
         
         
         start_sec_timer();
       
        //code fails after this line when timer is started
       
       
        light_on_full();

          DO
          {
             delay_ms(1);
             read_light();
          }WHILE((light_bright  == 0)&&(seconds  < 30));

          light_off();
          stop_sec_timer();
       }

       // this will call light snap routine
       
       
       IF( ! light_bright)// if light is low check pyro and radio
       {
          read_pyro();

          // IF pyro hit do pyro light
          check_radio();

          // radio hit DO radio light
       } //end of light bightr
    }//##################################################end of WHILE
 }// ###############################################end of main



Last edited by armondo58 on Thu Oct 06, 2011 5:57 am; edited 2 times in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 06, 2011 9:47 pm     Reply with quote

First give a description of normal operation and of the failure mode.
When it fails, what is it that doesn't work ?

You said that it fails when you enable the Timer1 interrupt. The first
question would be, does it fail purely because of the interrupt, or because
the interrupt changes a variable ? To test this, keep the following line
in your main(). That should enable the failure.
Code:

start_sec_timer();


But then in your isr, comment out the incrementing of 'seconds'.
Quote:

#INT_TIMER1
VOID TIMER1_isr(VOID)
{
// seconds++; //count seconds
}

Compile, download and run it. See if you get the same failure mode.
If it still fails, then it's the interrupt itself that is the problem. If it doesn't
fail, then it's the incrementing of 'seconds' that causes the failure.

I'll wait to get the results of your tests before I comment more.
But, we still need to know what is the expected operation of the program
and a description of the failure.
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Fri Oct 07, 2011 2:10 am     Reply with quote

There is a radical problem here.

You must _never_ enable an interrupt, with the GIE enabled at the same time, without an interrupt handler being present. Otherwise when the interrupt triggers, the code will jump to the non-existent handler, which then won't have the code to clear the interrupt, and the code will crash.

Instead of using the CCS functions, you have a block of stuff for handling ulpw, which _will_ cause problems:
Code:

VOID my_sleep_ulpwu (INT16 y)
 {
   output_high(PIN_A0);
   delay_ms(y); // was ms
   clear_interrupt(INT_ULPWU);
   * pie2 = 4;
   output_FLOAT(PIN_A0);
   * intcon = 64;
   enable_interrupts(INT_ULPWU);
   * pcon = 32;
 }

In this, you have enabled the GIE, and the ULPW, but your code does not contain a handler for this interrupt. Some comments:

1) The easiest way to declare registers, is not to fiddle around with pointer addressing. Just use:
Code:

#byte INTCON = 0x0B

//Then write to it with:

INTCON=64;

This generates much faster code.
Same comment obviously applies to the other registers you change.

Then, to wake up from sleep, GIE does not need/want to be enabled. Disable GIE, disable all other interrupts, enable ULPW, and go to sleep. The code will then execute the next instruction, when ULPW fires. If GIE is enabled as well, then the code instead jumps to the handler, which is not there.....

I'd suggest that your routine, saves the contents of the interrupt control registers, then sets them as you require, and then when you wake up you write them back, before contining, which will turn off ULPW, and the pattern of interrupts set before the call, is not lost. Currently, it appears that after your sleep, the timer interrupt will be left off, ULPW enabled, and the GIE enabled.....

Best Wishes
armondo58



Joined: 15 Jun 2011
Posts: 16

View user's profile Send private message

PostPosted: Sat Oct 08, 2011 6:25 am     Reply with quote

Thanks Guys for info. I just updated the compiler to 4.125 and now the debugger stopped working. Dont know what the problem is yet.
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