|
|
View previous topic :: View next topic |
Author |
Message |
armondo58
Joined: 15 Jun 2011 Posts: 16
|
timer1 and functions? |
Posted: Wed Oct 05, 2011 5:54 pm |
|
|
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
|
|
Posted: Thu Oct 06, 2011 9:47 pm |
|
|
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.
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
|
|
Posted: Fri Oct 07, 2011 2:10 am |
|
|
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
|
|
Posted: Sat Oct 08, 2011 6:25 am |
|
|
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. |
|
|
|
|
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
|