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

no timer1 interrupt on pic16f628

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



Joined: 07 Jan 2008
Posts: 10

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

no timer1 interrupt on pic16f628
PostPosted: Wed Jan 09, 2008 6:56 am     Reply with quote

Hello,

I'm using an external crystal oscillator to create a real time counter, i've used a 2,457600 MHz crystal.

I've allready checked the oscillation frequency, test was ok

But i ve noticed in the list file, that probably a bit is set on a wrong adress

on line 026B bit0 of 0C (= PIR1) is set, this a flag register

The interrupt enable of timer1 is on address 8C,0

Had someone the same problems?

How can I check in the hex file to be sure this the problem?

Thanks Wink

.................... ENABLE_INTERRUPTS (INT_TIMER1) ;
026A: BSF 03.5
026B: BSF 0C.0
.................... ENABLE_INTERRUPTS (GLOBAL) ;
026C: MOVLW C0
026D: BCF 03.5
026E: IORWF 0B,F
....................
.................... set_timer1(0x0000) ;
026F: CLRF 0F
0270: CLRF 0E
Ttelmah
Guest







PostPosted: Wed Jan 09, 2008 7:22 am     Reply with quote

You need to read up on how the PIC memory space is addressed.
The value '0C', addresses either address '0C', or address '8C', according to the value stored in the bank select bit. Guess what bit the line '026A' is setting?....
This is not your problem.

Best Wishes
karlo



Joined: 07 Jan 2008
Posts: 10

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

PostPosted: Wed Jan 09, 2008 7:48 am     Reply with quote

I did a test and it don't make a difference

What i did

#byte PIE1 = 0x8C

bit_set(PIE1,0) ;


But i've seen that i don't have a proper interrupt service routine.

The first few lines ,also the last ones are made for a proper jump into the progam where the interrupt had occur,

but if goto 05F is used i don't think the interrupt routine will finish his routine properly.

How can i changes the goto 0057 into a call 0057 instruction in the C language

0000: MOVLW 00
0001: MOVWF 0A
0002: GOTO 211
0003: NOP
0004: MOVWF 7F
0005: SWAPF 03,W
0006: CLRF 03
0007: MOVWF 21
0008: MOVF 7F,W
0009: MOVWF 20
000A: MOVF 0A,W
000B: MOVWF 28
000C: CLRF 0A
000D: SWAPF 20,F
000E: MOVF 04,W
000F: MOVWF 22
0010: MOVF 77,W
0011: MOVWF 23
0012: MOVF 78,W
0013: MOVWF 24
0014: MOVF 79,W
0015: MOVWF 25
0016: MOVF 7A,W
0017: MOVWF 26
0018: MOVF 7B,W
0019: MOVWF 27
001A: BCF 03.7
001B: BCF 03.5
001C: MOVLW 8C
001D: MOVWF 04
001E: BTFSS 00.0
001F: GOTO 022
0020: BTFSC 0C.0
0021: GOTO 05F
0022: MOVF 22,W
0023: MOVWF 04
0024: MOVF 23,W
0025: MOVWF 77
0026: MOVF 24,W
0027: MOVWF 78
0028: MOVF 25,W
0029: MOVWF 79
002A: MOVF 26,W
002B: MOVWF 7A
002C: MOVF 27,W
002D: MOVWF 7B
002E: MOVF 28,W
002F: MOVWF 0A
0030: SWAPF 21,W
0031: MOVWF 03
0032: SWAPF 7F,F
0033: SWAPF 7F,W
0034: RETFIE

#INT_TIMER1
.................... void isr()
.................... {
.................... count_13ms ++ ;
*
005F: INCF 2B,F
0060: BTFSC 03.2
0061: INCF 2C,F
.................... bit_clear(PIR1,0) ;
0062: BCF 0C.0
.................... }
Ttelmah
Guest







PostPosted: Wed Jan 09, 2008 11:01 am     Reply with quote

You don't want to, or need to.
If code is 'called' from only one location, it is faster, to jump to it, and then jump back at the end. The compiler does this automatically for you, which is why it is using 'goto', not a call. The only 'fault' in the code shown, is you clearing the PIR bit. You should not do this. The compiler will automatically do this, unless you add the keyword 'noclear' to the interrupt declaration.
If you remove the '#nolist' line from the processor include file, the extra code, will become visible in the listing (otherwise a lot of this gets excluded, making the listing hard to understand...).
I'm afraid you are chasing 'hairs'. Describe your hardware better. What prescaler are you using on timer1?. Are you running with synchronisation enabled or disabled?. What processor clock?. What is actually happening?. You are looking for faults in the compiled code, when something else is wrong...

Best Wishes
karlo



Joined: 07 Jan 2008
Posts: 10

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

PostPosted: Fri Jan 11, 2008 5:24 am     Reply with quote

I've installed the MPLAB simulator to see what's happening.

The timer1 interrupt occurs and i made it visible by toggling the LCD backlight.

But when the interrupt service routine is finished, the next step is to jump into main program at the program address + 1

In my program it jump to the next address under my interrupt routine (no instruction there) and than back to line where the interrupt is detected.(= endless loop)

My program

while (TRUE) // endless loop
{
/*----------sec. counter--------*/


if(count_13ms == ms_to_1s)
{
count_sec ++ ;
count_13ms = 0 ;
}

LcdPutC (0x0C) ;
LCD_dec_byte (count_sec) ;
Lcd_dec_byte (count_13ms) ;

loop: // wait for timer1 interrupt

goto loop ;
}

Interrupt routine

#INT_TIMER1
void Timer1_isr()
{
output_toggle(LCD_backlight) ; // for test purpose normally
//count_13ms++; filled in here
}
Ttelmah
Guest







PostPosted: Fri Jan 11, 2008 7:06 am     Reply with quote

Start by posting the actual program, including the headers, and setup. Use the 'code'buttons, so it is legible...
What you post, can't work, since it does not setup the timer, enable the interrupts, etc. etc.
Make the program simple, but showing the fault. For example:
Code:

#include "C:\Program Files\PICC\USBtest\628test.h"
int16 count_26mSsec=0;
#define count_per_sec (37)

#int_TIMER1
void  TIMER1_isr(void)
{
   count_26mSec++;
}

void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT|T1_EXTERNAL_SYNC);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);

   while (true) {
      if (count_26mSec==count_per_sec) {
          count_sec++;
          count_26mSec=0;
      }
   }
}

Your test, should be a complete program, that can be compiled, and works/fails, to show the problem.
As you see, I have changed the counter to be 26mSec, since if your clock is 2.3576MHz, then the counter will wrap at 23457600/65536 = 37.5 times per second, which is 26.6666mSec.

Best Wishes
karlo



Joined: 07 Jan 2008
Posts: 10

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

PostPosted: Fri Jan 11, 2008 9:53 am     Reply with quote

Code:

#if         defined(__PCM__)
#include    <16F628.H>
#fuses      INTRC_IO,NOWDT,NOPROTECT,NOLVP
#ID         CHECKSUM


typedef unsigned int8   uc;
                 int8   current, last ;
               int32  count_13ms;
                 int8   count_sec, prev_count_sec, count_minutes, count_hours ;
                 int8   workreg, status, ms_to_1s ;


            /*----- Constant Definitions -----*/

#define LCD_TYPE        2       // 0=5x7, 1=5x10, 2=2 lines
#define LCD_LINE_TWO    0x40    // LCD RAM address for the second line
#define LCD_WRITE       0xF0    // ddr port-b lcd write  b'11110000'
#define LCD_READ        0xFF    // ddr port-b lcd read   b'11111111'
#define offset          60    // minimum temperature
#define ms_to_1s        74    // divide by 75

                                // ports bit definitions

#define magneetdetector (input(PIN_B4))
#define LCD_RS          PIN_A7
#define LCD_RW          PIN_A3
#define LCD_EN          PIN_A4
#define PUSHBUTTON      PIN_A0
#define LCD_backlight   PIN_A6

#ROM     0x2100=    {0x00,0x40,0x01,0x06,0x01,0x09,0x01,0x09,0x01,0x06,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
                   0x00,0x48,0x01,0x0E,0x01,0x11,0x01,0x11,0x01,0x11,0x01,0x11,0x01,0x11,0x01,0x0E,0x01,0x00}

/*----- Global Variables -----*/

#byte   Port_A = 0x05
#byte   Port_B = 0x06
#byte   CMCON = 0x1F
#byte   VRCON = 0x9F
#byte   PIR1 = 0x0C
#USE    FAST_IO(A)
#USE    FAST_IO(B)
#USE    DELAY(CLOCK=4000000)
//#priority TIMER1, RB

/*----- interrupt routine -----*/

#INT_TIMER1
void Timer1_isr()
{
count_13ms ++ ;
}


/*----- Functions Prototypes -----*/


void        Initialize (void) ;
uc          LcdReadByte (void);
void        LcdSendNibble (uc n) ;
void        LcdSendByte (uc address, uc n) ;
void        LcdPutc (uc c) ;
void          Lcd_dec_byte(unsigned char val);    // display a value in decimal
char        num_to_char(unsigned char val);      // convert to ASCII





uc  const LCD_INIT_BYTES[4] = {0x20 | (LCD_TYPE << 2), 0x0C, 1, 6} ;


uc      Cursor ;

   signed int8     Dx, Dx_1, max_min ;
           int8     tx, tx_1, motor_temp,data_flag, ee_address, value, a ;




/*------------------------------*/

void    main (void)
{

                           // Presettings



Port_A = 0x04 ;           // b'00000100'
set_tris_a (0x27) ;       // set port-a bits direction b'00100111'


Port_B = 0x00 ;           // b'00000000'
set_tris_b (0x30) ;       // set port-b bits direction b'11110000'



CMCON = 0x25 ;
VRCON = 0xC0 ;


tx      = 0 ;
tx_1    = 0 ;
Dx      = 0 ;
Dx_1    = 0 ;
max_min = 0 ;
motor_temp = 0 ;
data_flag = 0 ;
bit_set (last,6) ;
current = 0 ;
last= 0xFB ;               // Input RB4 is H to L ; RB5 is L to H active
count_13ms = 0 ;
prev_count_sec = 0x3D ;     // Startvalue of 61 seconds
count_sec = 0 ;
count_minutes = 0 ;
count_hours = 0 ;
workreg = 0 ;
status = 0 ;
ee_address = 0 ;
value = 0 ;


Initialize() ;

LcdPutc (0x0C) ;

for (a=0; a<=18;a++)       // loading special characters from eeprom into LCD RAM memory
{
ee_address = read_eeprom(workreg) ;
workreg ++ ;
value = read_eeprom(workreg) ;
workreg ++ ;
LcdSendByte (ee_address,value) ;
}

setup_timer_1 ( T1_EXTERNAL | T1_DIV_BY_2 | T1_CLK_OUT) ;          // Timer1 overflow at 65536 / (2.457600 * 2) = 13333.3333333 µs
delay_ms (100) ;

ENABLE_INTERRUPTS (INT_TIMER1) ;
ENABLE_INTERRUPTS (GLOBAL) ;


set_timer1(0) ;


   while (TRUE)             // endless loop
   {

   if ( bit_test (CMCON,7) && VRCON <= 204)            // repeat temperature measurement every 13.3333 ms
         {
         tx = VRCON & 0x0F ;
         VRCON ++ ;
         Dx = tx - tx_1 ;
         }
         else
         {
              if (VRCON >= 193)
              {
             Dx = tx_1 - tx ;
              VRCON -- ;
              }
             else
             {
             LcdPutC (0x0C);
             LcdPutC ("motor cold") ;
             goto no_data ;
             }
         }

         max_min = Dx - Dx_1 ;

         tx_1 = tx ;
         Dx_1 = Dx ;

         if ( tx_1 >= 12)
         {
         LcdPutC (0x0C);
         LcdPutC ("motor too hot!") ;
         }
         else
         {

              if ( max_min == 0 )
              {
                 LcdPutc (0x0C) ;
               motor_temp = tx_1 * 5;
               motor_temp += offset ;
               Lcd_dec_byte ( motor_temp) ;
               LcdPutc ("°C ") ;
              }
       }
         /*----------sec. counter--------*/

no_data:
         if(count_13ms == ms_to_1s)
         {
         count_sec ++ ;
         count_13ms = 0 ;
         }

         LcdPutC (0x0C) ;
         LCD_dec_byte (count_sec) ;
         Lcd_dec_byte (count_13ms) ;

loop:                  // wait for timer1 interrupt

     goto loop ;


   }


}

/*------------------------------*/
void    Initialize()
{
uc     i ;
Cursor = 0 ;

delay_ms (30) ;

for (i=1 ; i <= 3 ; ++i)
    {
     LcdSendNibble (3) ;
     delay_ms (5) ;
    }

LcdSendNibble (2) ;

for (i=0 ; i <= 3 ; ++i)
    LcdSendByte (0, LCD_INIT_BYTES[i]) ;
}

/*------------------------------*/
uc      LcdReadByte (void)
{
uc     low, high ;

dataread:

set_tris_b (LCD_READ) ;
output_high (LCD_RW) ;
delay_cycles (2) ;

output_high (LCD_EN) ;
delay_cycles (2) ;
high = (Port_B & 0x0F) ;   // b'00001111'
high = high << 4 ;


output_low (LCD_EN) ;
delay_cycles (2) ;
output_high (LCD_EN) ;
delay_us (2) ;
low = (Port_B & 0x0F) ;          //  b'00001111'



output_low (LCD_EN) ;
set_tris_b (LCD_WRITE) ;



if (bit_test (high,7) )
goto dataread ;

else
 if (data_flag)
{
 output_high (LCD_RS) ;
 data_flag = FALSE ;
 goto dataread ;
}

return (high | low) ;
}

/*------------------------------*/
void    LcdSendNibble (uc n)
{

Port_B &= 0xF0 ;      // clear RB0 to RB3 b'11110000'
Port_B |= n ;         // OR the data with the lower nibble of Port_B
delay_cycles (4) ;

output_high (LCD_EN) ;
delay_us (4) ;
output_low (LCD_EN) ;
}

/*------------------------------*/
void    LCdSendByte (uc address, uc n)
{
output_low (LCD_RS) ;

LcdReadByte() ;

output_low (LCD_RS) ;
if (address)
   output_high (LCD_RS) ;

delay_cycles (3) ;

output_low (LCD_RW) ;
delay_cycles (3) ;

output_low (LCD_EN) ;

LcdSendNibble (n >> 4) ;

LcdSendNibble (n & 0x0F) ;



}


/*------------------------------*/
void    LcdPutc (uc c)
{
switch (c)
   {
    case 0x0C :
               LcdSendByte (0, 1) ;
               delay_ms (3) ;
               break ;

    case 0x0D :
               LcdSendByte (0,0x0D) ;
               delay_ms (3) ;
               break ;

    case 0x10 :
               LcdSendByte (0, 0x10) ;
               break ;

    case 0x14 :
               LcdSendByte (0, 0x14) ;
               break ;

    case '°'  :
               LcdSendByte (1, 0b00000);
               break;

    case '0'  :
               LcdSendByte (1, 0b00001);
               break;


    default   :
               LcdSendByte (1, c) ;
               break ;
   }
}
/*------------------------------*/
void Lcd_dec_byte(unsigned char val)
{
   unsigned char d,e;
   char c;

   d=val/1000;
   if (d < 1)
   LcdPutc(0x14);
   else
   {
      c=num_to_char(d);
      LcdPutc(c);
   }


   d=val/100;
   if (d < 1)
   LcdPutc(0x14);
   else
   {
      c=num_to_char(d);
      LcdPutc(c);
   }

   val=val%100;
   d=val/10;
   c=num_to_char(d);
   LcdPutc(c);

   d=val % 10;
   c=num_to_char(d);
   LcdPutc(c);
}

/*------------------------------*/
char num_to_char(unsigned char val)
{
   char c;

   c=val+'0';

   return(c);
}

Hereby my program to check the temperature of an engine
But i also need a real time clock for speed counts.

I also prefer to wait until timer1 is overflowed and than go back to temperature analysis of the engine,speed counts (input change on RB5 = also interrupt for this)
I want no conflicts between both interrupts if they should both been set on the same time (priority timer1 instead of RB)

Thanks
 
Ttelmah
Guest







PostPosted: Fri Jan 11, 2008 10:37 am     Reply with quote

First,the prescaler, _divides_ the clock, it does not multiply it. Your interrupt will only be every 53.3mSec...
You seem to be trying to increment the Vref signal, and use this to change the comparator, to provide a crude ADC. Presumably with a signal conected to RA1?.
Read what I said, about making the program _simple_ to show the problem. What you have here, is a mess.

Best Wishes
SET



Joined: 15 Nov 2005
Posts: 161
Location: Glasgow, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Jan 11, 2008 12:54 pm     Reply with quote

Karlo, your code is:

Code:

while (TRUE) // endless loop
{
/*----------sec. counter--------*/

if(count_13ms == ms_to_1s)
{
count_sec ++ ;
count_13ms = 0 ;
}

LcdPutC (0x0C) ;
LCD_dec_byte (count_sec) ;
Lcd_dec_byte (count_13ms) ;

loop: // wait for timer1 interrupt

goto loop ;
}


This will write once to the LCD, then sit in an endless loop goto'ing loop.. I assume thats not what you intended?

Try:

Quote:
Code:

while (TRUE) // endless loop
{
     /*----------sec. counter--------*/

    while(count_13ms < ms_to_1s)
   {
    count_sec ++ ;
    count_13ms = 0 ;
   }

   LcdPutC (0x0C) ;
   LCD_dec_byte (count_sec) ;
   Lcd_dec_byte (count_13ms) ;

}


You dont need to 'wait' for the interrupt, it takes care of itself.

And if you want the LCD updated every interrupt:

Quote:
Code:

while (TRUE) // endless loop
{
     /*----------sec. counter--------*/
    while(!interrupted); // flag set in ISR
    interrupted=0;

    if(count_13ms == ms_to_1s)
   {
    count_sec ++ ;
    count_13ms = 0 ;
   }

   LcdPutC (0x0C) ;
   LCD_dec_byte (count_sec) ;
   Lcd_dec_byte (count_13ms) ;

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jan 11, 2008 6:13 pm     Reply with quote

See my post at the end of this thread. It has a small test program
that shows how to check if Timer1 interrupts are working, when
Timer1 is clocked by the Timer1 oscillator with an external crystal.
http://www.ccsinfo.com/forum/viewtopic.php?t=25824

You need to make a very simple program like this to test your problem.
karlo



Joined: 07 Jan 2008
Posts: 10

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

PostPosted: Wed Jan 16, 2008 5:36 am     Reply with quote

I found out what the problem was, it had nothing to do with the interupt(routine) Confused

I tested 2 variables with an if statement, if (var1 < var2)
If checked the assembly code and i saw that only the zero flag was tested.
Somehow var1 was bigger than var2 , and if (var1 < var2) condition was true. The carry flag was set (but not tested)

How can i check var1 < var2 without checking the assembly code?

THX
Ttelmah
Guest







PostPosted: Wed Jan 16, 2008 5:54 am     Reply with quote

'var1 < var2', should evaluate fine.
How are var1, and var2 declared (integers or what?).
What values do they contain?.
The behaviour you are seeing, will sometimes happen, if the values are impossible for the variables concerned.

Best Wishes
SET



Joined: 15 Nov 2005
Posts: 161
Location: Glasgow, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Jan 16, 2008 7:13 am     Reply with quote

Quote:
I tested 2 variables with an if statement, if (var1 < var2)
If checked the assembly code and i saw that only the zero flag was tested.
Somehow var1 was bigger than var2 , and if (var1 < var2) condition was true. The carry flag was set (but not tested)

How can i check var1 < var2 without checking the assembly code?


Post your code that shows this behaviour.
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