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

Problems with timer 1 interrupt

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



Joined: 17 Jun 2010
Posts: 5
Location: Stockholm - Sweden

View user's profile Send private message

Problems with timer 1 interrupt
PostPosted: Thu Jun 17, 2010 2:47 am     Reply with quote

Hi!

My trouble is getting the timer1 to trigger. I presume its something in the initialization code. My chip is 16F887 and the code is temporary downsized to the following test code:

Code:

#include <16F887.h>
//#INT_TIMER1
void Timer_isr(void);

unsigned int8 flag;
void main(){
//   delay_ms(500); //wait 500ms for system to stabilize
   setup_oscillator(OSC_8MHZ, 0);
   setup_timer_0(RTCC_INTERNAL);
   shiftreg = 0;   
   out_shiftreg();

   //Set port direction
   set_tris_a(PORT_A); //See io_cfg.h for I/O-configurations
   set_tris_b(PORT_B);
   set_tris_c(PORT_C);
   set_bit(shiftreg, BAT_SENS);
   BATTERY_FET_ON();
   DCDC2_OFF();

   setup_comparator(NC_NC_NC_NC);
/*   setup_adc_ports( FUEL_CELL_1_CHANNEL |
                FUEL_CELL_2_CHANNEL |
                FUEL_CELL_3_CHANNEL |
                FUEL_CELL_4_CHANNEL |
                FUEL_CELL_SENSE_CHANNEL |
                IN_CURRENT_FUEL_CELL_CHANNEL |
                FUEL_CELL_TEMP_CHANNEL |
                IN_CURRENT_LITHIUM_CELL_CHANNEL |
                LITHIUM_CELL_TEMP_CHANNEL |
                IN_VOLT_LITHIUM_CHANNEL );

*/
   setup_adc( ADC_CLOCK_INTERNAL | VSS_VDD  );
   set_timer1(TIMER1_0_3125MS);                  //Set timer1 to interrupt every 312.5us
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);            //internal clock source and prescale as 1
   enable_interrupts(INT_TIMER1);                   //Enable overflow interrupt Timer1,
                                          //interrupt-routine Timer1_isr() see process.h
   enable_interrupts(global);                      //Enable global interrupt
   flag = 7;
   for(;;)
   {
      //All updates in main-loop are dependent on software-timers found in process.h
      //and timers are updated in interrupt-routine void Timer1_isr() also found in process.h
//      tt++;
   //   if(tt>18000){
      //   tt=0;
         toggle_shiftreg(LED_3);
         out_shiftreg();
         //printf("DUMP ADC:\n");
         //dump_adc();
         printf("\nTimer: %Ld", get_timer1());
         printf("\nFlag: %u", flag);
      }
}

#INT_TIMER1
void Timer_isr(void){
   flag = 121;
   set_shiftreg(LED_1_GREEN);
   clear_interrupt(int_timer1);   //Clear interrupt flag
   set_timer1(TIMER1_0_3125MS);                   //Load timer1-register to interrupt every 312,5us
}


The timer interrupt set the int8 flag to 11 as a "witness" and the main loop is constantly printing the timer and this flag to the UART. That way, I can see that the timer is running, but the interrupt is never trigging. What am I doing wrong?

I'm using MPLAB with CCS plugin.

Edit: More info from .LST file: CCS PCM C Compiler, Version 4.085, 47134
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Jun 17, 2010 7:52 am     Reply with quote

You code is incomplete; several variables and defines are missing.
So for sure we know this is not the code you have been testing with.

Please post a complete program including #fuses, etc, so we can copy/paste it into our IDE.
Make the program as small as possible (remove all the code in comments and non-related function calls).
Jonatan



Joined: 17 Jun 2010
Posts: 5
Location: Stockholm - Sweden

View user's profile Send private message

PostPosted: Thu Jun 17, 2010 8:28 am     Reply with quote

Ok, I didn't realize something except defines were missing, but here goes (I have streamlined it a bit more):

Main.c:
Code:
#include <16F887.h>
#include <project.h>

#define TIMER1_0_3125MS               0xFD8F            //Timer1 interrupts 3200/sec
//** PORT DIRECTIONS ***********************************************************************/
//#define PORT_A     0b00001111   //Port A directions
#define PORT_A      0b00111111
//#define PORT_B      0b00111111    //Port B directions
#define PORT_B      0b11111111
//#define PORT_C     0b00000000   //Port C directions
#define PORT_C      0b10000000
#define PORT_D      0b00001000
#define PORT_E      0b00000000
#define LED_1_RED      0
#define LED_1_GREEN      1
#define LED_2         2
#define LED_3         3
#define LED_4         4
#define LED_5         5
#define LED_6         6
#define LED_7         7
#define LED_8         8
#define LED_9         9
#define DCDC1_ENABLE   10
#define   DCDC2PWR      11
#define BAT_SENS      12
#define FC1_LOAD      13
#define FC2_LOAD      14
#define FC3_LOAD      15
#define FC4_LOAD      16

#define LATCH_OUT   PIN_D2
#define SHIFT_CLK   PIN_D1
#define DATA_IN      PIN_D0


#define _BV(abit) (1 << (abit))

#define clear_bit(port, abit)        {port = port & ~_BV(abit);}
#define set_bit(port, abit)       {port = port | _BV(abit);}
#define toggle_bit(port, abit)       {port = port ^ _BV(abit);}
#define set_bitmask(port, mask)      {port = port | mask;}
#define clear_bitmask(port, mask)   {port = port & ~ mask;}
unsigned int16 shiftreg = 0x00;

#define set_shiftreg(abit)      {set_bit(shiftreg, (unsigned int16)abit);}
#define clear_shiftreg(abit)   {clear_bit(shiftreg, (unsigned int16)abit);}
#define toggle_shiftreg(abit)   {toggle_bit(shiftreg, (unsigned int16)abit);}



unsigned int8 flag;

void out_shiftreg(void);


#int_timer1
void TIMER1_ISR(){
   flag = 121;
   clear_interrupt(int_timer1);   //Clear interrupt flag
   set_timer1(TIMER1_0_3125MS);                   //Load timer1-register to interrupt every 312,5us
}

#INT_DEFAULT
void glob_isr(){
   flag=144;
}


void main(){
//   delay_ms(500); //wait 500ms for system to stabilize
   setup_oscillator(OSC_8MHZ, 0);
   setup_timer_0(RTCC_INTERNAL);
   setup_wdt(WDT_OFF);

   set_tris_a(PORT_A); //See io_cfg.h for I/O-configurations
   set_tris_b(PORT_B);
   set_tris_c(PORT_C);
   
   set_timer1(TIMER1_0_3125MS);                  //Set timer1 to interrupt every 312.5us
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);            //internal clock source and prescale as 1
   enable_interrupts(INT_TIMER1);                   //Enable overflow interrupt Timer1,
   enable_interrupts(GLOBAL);                      //Enable global interrupt
   flag = 7;

   bit_set(BAUDCTL,4);      //Invert the data using UART, if no invert of data bit clear this bit


   for(;;)
   {
         toggle_shiftreg(LED_1_GREEN);
         printf("\nTimer: %Ld", get_timer1());
         printf("\nFlag: %u", flag);
         out_shiftreg();
      }
}

void out_shiftreg(void){
   unsigned int8 i;
   unsigned int16 reg;
   reg = shiftreg;
   output_bit(LATCH_OUT, 0);
   for(i = 0; i < 16; i ++){
      if(reg & 0x8000){
         output_bit(DATA_IN, 1);
      }else{
         output_bit(DATA_IN, 0);
      }
      reg = reg << 1;
      output_bit(SHIFT_CLK, 1);
      output_bit(SHIFT_CLK, 0);
   }
   output_bit(LATCH_OUT, 1);
}


Project.h:
Code:
/********************************************************************************************
* FileName:        project.h                                                     *
* Processor:       PIC16F886                                                     *
   *
* Company:         NNNNNNN AB                                                     *
* Project:       NNN                                      *
* Date:            080122                                                        *
*          *
********************************************************************************************/
#ifndef PROJECT_H_
#define PROJECT_H_


//#include <16F886.h>
//#include <16F887.h>




/** C O N F I G U R A T I O N **************************************************************/
// ,BORV21,BROWNOUT_NOSL
#pragma device ADC=10
#fuses NOWDT,NOPROTECT,NOCPD,PUT,NOBROWNOUT,MCLR,INTRC_IO   
#use delay(clock=8000000, restart_wdt)         // timer0 is the watchdog. restart wdt during delays
                                     // previous clock = 8000000,7500000




//#use rs232(UART1,baud=19200,parity=N,bits=8,restart_wdt)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)



/** RS232 **********************************************************************************/

#define PRINT_STATUS

#ifdef PRINT_STATUS
#define BUFFER_SIZE 10
#use rs232(UART1,force_sw,invert,baud=9600,parity=N,bits=8,restart_wdt,XMIT=PIN_C6)//UART1
#endif

#if __DEVICE__ == 916 || __DEVICE__ == 886 || __DEVICE__ == 887
#   pragma byte BAUDCTL = 0x0187
#    pragma byte RCSTA = 0x0018
#   pragma byte TRISC = 0x0087
#endif

#endif // PROJECT_H_

/** EOF project.h **************************************************************************/


The code constantly puts the timer1 value and the "flag" on UART. The flag is updated in the ISRs.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Jun 17, 2010 10:18 am     Reply with quote

I forgot to mention I like the example program to be small .

Funny how you are mixing the compiler's internal function bit_set() and your home brew set_bit(). Why not use the compiler's optimized version everywhere?
Same applies to the bit_clear v.s. clear_bit

Several code simplifications are possible:
- There is no need to clear the timer interrupt flag inside the interrupt handler. The compiler does this for you.
- Setting the RS232 invert option by addressing the BAUDCTL option is not in the CCS way. Use the INVERT option in the #use RS232 line instead (surprise, you already have it there !).
- You have defined #use RS232 with 'force_sw' option. This conflicts with the UART1 option. And you know the interrupts will distort communication timings unless you specify DISABLE_INTS?
- For demonstrating the problem you can remove the FAST_IO, led toggling, watchdog, shiftreg stuff.

Removing all the non-important stuff I reduced the program to:
Code:
#include <16F887.h>
#fuses NOWDT,NOPROTECT,NOCPD,PUT,NOBROWNOUT,MCLR,INTRC_IO   
#use delay(clock=8000000)
#use rs232(UART1,force_sw,invert,baud=9600,parity=N,bits=8,restart_wdt,XMIT=PIN_C6)//UART1

#define TIMER1_0_3125MS 0xFD8F    //Timer1 interrupts 3200/sec

unsigned int8 flag;

#int_timer1
void TIMER1_ISR(){
   flag = 121;
   set_timer1(TIMER1_0_3125MS);   //Load timer1-register to interrupt every 312,5us
}

#INT_DEFAULT
void glob_isr(){
   flag=144;
}


void main(){
   setup_oscillator(OSC_8MHZ, 0);

   set_timer1(TIMER1_0_3125MS);             //Set timer1 to interrupt every 312.5us
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);  //internal clock source and prescale as 1
   enable_interrupts(INT_TIMER1);           //Enable overflow interrupt Timer1,
   enable_interrupts(GLOBAL);               //Enable global interrupt
   flag = 7;

   for(;;)
   {
      printf("\nTimer: %Ld", get_timer1());
      printf("\nFlag: %u", flag);
   }
}


I tested it in the simulator and v4.077 and it works like a charm.

With a software UART and this many interrupts I doubt you were able to get a readable text over the RS232. Is this really the code you used?
Jonatan



Joined: 17 Jun 2010
Posts: 5
Location: Stockholm - Sweden

View user's profile Send private message

PostPosted: Fri Jun 18, 2010 1:49 am     Reply with quote

The UART code is working without problems. Set_bit() and clear_bit(), etc, are not in use. It's legacy code. The set_shiftreg() etc is necessary for my particular hardware.

My program works in the simulator yes, but not on the HW (I discovered this last night). The UART code somehow works, but the interrupt is never trigged. I myself find the UART code somewhat inconsistent, but that is legacy too (I'm, to my despair, forced to use a big chunk of legacy code as I'm only supposed to do some patchwork to fit in new HW), and it seems to work. Sorry for failing to exclude anything not necessary but that has to do with the way I'm debugging on this particular HW. The strange thing is that all this is supposed to work on older HW built around 16F886. My job is to port it to 16F887 and add some functions.

I will play a little with your a bit more downsized version, thanks! Smile
Jonatan



Joined: 17 Jun 2010
Posts: 5
Location: Stockholm - Sweden

View user's profile Send private message

PostPosted: Fri Jun 18, 2010 2:00 am     Reply with quote

I tried your version in a new project and found the same behavior. It works perfectly in the simulator but not on the controller. Unfortunately I use Pickit 2. Probably I have to HW debug it with ICD3 or something?

Edit: But thanks for the more sane UART code!

On AVR system using GCC you should have any variables that gets updated in ISRs declared volatile. Is there some similar pitfalls on PIC/CCS? (I already tried volatile at no success).
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Jun 18, 2010 3:35 am     Reply with quote

I never understood the differences between the PicKit2 and ICD2, but for most chips they suffice both.

Quote:
On AVR system using GCC you should have any variables that gets updated in ISRs declared volatile. Is there some similar pitfalls on PIC/CCS? (I already tried volatile at no success).
Using volatile is good programming practice when sharing variables between main() and ISRs but hardly ever used on the PIC. Because of the simplified architecture design in the PIC16/18 you will be save without using 'volatile' as long as the shared variables are 8 bit only. For larger variables & structs you'll have to temporarily disable interrupts on reading/writing.
Jonatan



Joined: 17 Jun 2010
Posts: 5
Location: Stockholm - Sweden

View user's profile Send private message

PostPosted: Fri Jun 18, 2010 8:05 am     Reply with quote

I was wrong. The new UART code fail to invert the signal rendering all output to gibberish (after a build all). Now back to the old UART code...

Edit: However, it's the timer 1 interrupt that is bugging me, not the UART. Maybe they depend on each other?
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