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

Timer Interrupt - not working
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

Timer Interrupt - not working
PostPosted: Sat Jul 28, 2012 7:21 am     Reply with quote

Hi All,

Apologies but I just Cannot figure out why this interrupt timer routine is not working:
Code:
/////// MASTER PROGRAM ////////

#include <18F4550.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=48000000)


#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)

#include "flex_lcd_16x1.c"
#define SPI_SS   PIN_E2

#define LSB_LATCH_LE_CL3  PIN_B7
#define LSB_LATCH_OE_CL8  PIN_B2
#define SB_LATCH_LE_CL4   PIN_B6
#define SB_LATCH_OE_CL7   PIN_B3
#define MSB_LATCH_LE_CL5  PIN_B5
#define MSB_LATCH_OE_CL6  PIN_B4


//============================

int tic = 0;
long int count_to_use=300;
static long int count=1;


#int_TIMER2
void TIMER2_isr()
{
 
     if (--count==0) {
        count=count_to_use;                                                                                                       
        tic = 1;
    }
    else  {                       
        tic = 2;                                                                                           
 }
}

void main()
{
setup_timer_2(T2_DIV_BY_16,256,8);
enable_interrupts(INT_TIMER2);
enable_interrupts(global);
output_high(SPI_SS);  // Initial Slave Select to a high level
setup_spi(SPI_MASTER | SPI_MODE_1 | SPI_CLK_DIV_4);
SETUP_ADC_PORTS(NO_ANALOGS);

while(1)
  {
if (tic == 1){
   tic=0;
   output_low(SPI_SS);
   spi_write(255);
   delay_us(10);
   spi_write(255);
   delay_us(10);
   spi_write(255);
   delay_us(10);
   output_high(SPI_SS);
   delay_ms(1000);
  }
else if (tic == 2){
   output_low(SPI_SS);
   spi_write(10);
   delay_us(10);
   spi_write(0);
   delay_us(10);
   spi_write(0);
   delay_us(10);
   output_high(SPI_SS);
   delay_ms(1000);
}
}
}


The plan is that it should just keep sending the value '10' until the interrupt occurs and then it should send the value 255.

It just keeps sending the value 10??
And altering the 'count_to_use' value up/down makes no difference.
I thought that by just setting a flag in the interrupt rather than doing any work is the correct plan (keep it very small) and then do everything in main.

But I just can't seem to get anything else apart from '10'. 'tic' never seems to be stored as '1'.

Any thoughts, its annoying me now!!!!!!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19491

View user's profile Send private message

PostPosted: Sat Jul 28, 2012 7:29 am     Reply with quote

Step back and prove your chip is running at the speed you expect. Your clock fuses are _impossible_.
You have HS selected, without the PLL enabled. This HS oscillator supports 25MHz max.
You can be working at 48MHz, if you have a crystal that is a multiple of 4Mhz, but then you need the PLLx fuse, where 'x' specifies the division to use to reduce the clock to 4Mhz. Also, HS_PLL, instead of HS, and CPUDIV1.
Always check the PIC is actually running, and running at the speed expected, _before_ looking for anything else.....

Best Wishes
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Jul 28, 2012 8:00 am     Reply with quote

Hi Ttelmah,

On no, I hope not. I looked over lots of datasheets for the fastest PIC available compared to the compiler version I had.

And I thought I had looked into in depth...
Just had another look at the datasheet, and it is not clear...

I am using a 'can oscillator' - IXQO-350 (48MHz). This has its own +5V supply.

Now in the datasheet, it seems that it can be used in the HS mode, as well as the ECIO. the difference is how OSC2 is configured - general I/O or just O. I have used HS mode. But I cannot find anywhere that states the limit for this configuration?? Where does it state 25MHz??

Regarding the PLL - this would jump it up to 96MHz not 48MHz.

Do you agree?

I changed the code and seriously slowed it down, so that count_to_use is now only 5. and it displayed on the screen - so it is working. I got the maths wrong, and need to work out how long the delay is.

Carl



Quote:
An external clock may also be used when the microcontroller
is in HS Oscillator mode. In this case, the
OSC2/CLKO pin is left open (Figure 2-3).
FIGURE 2-3: EXTERNAL CLOCK INPUT
OPERATION (HS OSC
CONFIGURATION)
2.2.3 EXTERNAL CLOCK INPUT
Ttelmah



Joined: 11 Mar 2010
Posts: 19491

View user's profile Send private message

PostPosted: Sat Jul 28, 2012 8:20 am     Reply with quote

EC is for using an external oscillator.
However you'd get less RF noise, and lower total power consumption, by using a slower oscillator and the PLL internally. It is probably never worth clocking the chip this fast externally....

Also add NOPBADEN to your fuses. PORT B defaults to analog operation.

Best Wishes
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Jul 28, 2012 8:31 am     Reply with quote

So is what I am doing wrong? or is it allowed?
Can I use a 48MHz canned oscillator in HS mode as shown and explained in figure 2-3 page 26.?

I understand your point about using a lower clock speed and using the PLL - and I am may have to depending on your answer above.

Thanks
Carl
temtronic



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

View user's profile Send private message

PostPosted: Sat Jul 28, 2012 9:39 am     Reply with quote

I use a 4MHz xtal and 2 caps in my 4550 boards. Having a huge stockpile of them from 16C84 days. Using the 4meg xtal allows running at 48MHz as well as using the internal USB peripheral.
Have to think it's cheaper than a 'canned' 48MHz, smaller footprint as well.

hth
jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19491

View user's profile Send private message

PostPosted: Sat Jul 28, 2012 11:36 am     Reply with quote

Use EC mode.
You can clock the input from an external source, in HS mode as well, but look at table 28-8. Param1.
In HS mode with an external input, you can only go to 40MHz.
In HS oscillator mode, 25MHz.
EC mode 48MHz.

I'm a bit puzzled on why you want to choose the 4550. It is slower than quite a few other PIC's (64MHz is common now), but it is pointless to try to actually run the external oscillator at this rate.

Best Wishes
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Jul 28, 2012 5:35 pm     Reply with quote

Thank you both for your replies.

CCS 4.038 only allows up to 48MHz - this is the reason why I didn't go for a 68MHz version.

Thank you for the clarification regarding the speed - I can use a 48MHz canned Oscillator -but need to change the fuse to EC.

Price is not a concern, ease of implementation is more important - and also an extra I/O is available in comparison to the standard Xtal and cap plan.

'Pointless point' - do you mean I can achieve the same thing by using a 4MHz canned oscillator in HSPLL mode and achieve the same speed? you are correct, and I am probably going to utilise this - but at the moment I will continue with the 48MHz canned oscillator in EC mode - it achieves the same thing (appreciating the possible problems that could occur).

Thanks Again
Carl
Ttelmah



Joined: 11 Mar 2010
Posts: 19491

View user's profile Send private message

PostPosted: Sun Jul 29, 2012 1:11 am     Reply with quote

Seriously, if you are using 4.038, then it is very likely this is the main problem. This was a 'beta' release at best. When this was available, there were two compilers for download, 4.xxx, and 3.249, with the latter shown as the 'known working' version. You'd need to dismantle the assembler produced 'line by line', and verify fuse settings etc., to have any hope of finding the problems...

The earliest V4 compilers that gave 99% working code are around the late 4.07x versions. Before this the compiler was full of bugs.

Yes, to run the input with a 48MHz clock coming in, requires the EC fuse.

Yes. You can use a 4MHz oscillator, with 'HS_PLL', 'PLL1' & 'CPUDIV1' to run the chip at 48MHz.

There are plenty of chips 'supported' by this compiler that work at 64MHz. 18F66K80, for example.

If you are working through MPLAB, make _sure_ you set this to compile to 'run' mode, not 'debug' mode. Depending on the version, it may well default to the latter, and when this happens, fuses can be set that prevent the chip from running normally.....

Best Wishes
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 3:59 am     Reply with quote

Hi Ttelmah. Temtronic

OK I decided to take a step back as you pointed out and see if I can get the timer to work - and I did and it worked. The reason why it didn't work was I didn't understand how timer2 worked (the PR2 issue). So I used timer0 and the code below works - it gives the interrpupt I expected, and I tried it with different value and it always worked:
Code:
/////// timer test program ////////

#include <18F4550.H>
#fuses EC_IO, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP,NOUSBDIV, NOVREGEN
#use delay(clock=48000000)
#use standard_io(a)     
#use standard_io(b)
#use standard_io(c)     
#use standard_io(d)
#use standard_io(e)
#define tohex(x) (x & 0xF) < 10 ? x + '0' : x + '7'

#byte UCFG = getenv("SFR:UCFG") //USB Registors
#bit UTRDIS = UCFG.3         //USB Registors

int tic, input_lsb, input_sb, input_msb = 0;
long int count_to_use=300;
static long int count=1;
#include "flex_lcd_16x1.c"

#int_RTCC
void RTCC_isr(void)

     if (--count==0) {
        count=count_to_use;                                                                                                       
        tic = 1;
    }
    else  {                       
        tic = 2;                                                                                         
 }
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_256);
enable_interrupts(INT_TIMER0);
enable_interrupts(global);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
lcd_init();   

while(1)
  {
if (tic == 1){   ////////////////////INTERRUPT HAS OCCURRED///////////////////////////
    tic=0;                     //RESET TIMER
printf(lcd_putc,"\f\interrupt");
delay_ms(500);
}                                         
else if (tic == 2){      ////////////////////INTERRUPT HAS NOT OCCURRED///////////////////////////
 tic=0;
printf(lcd_putc,"\fNo");
}
}
}



So going back to my current project with a new timer set up and I really need your help to see if I am doing anything wrong or the possible cause of the error. The project has been discussed previously in the thread belowhttp://www.ccsinfo.com/forum/viewtopic.php?t=47489&highlight=

It is an absolute test box that takes a snap-shot of the code every 50uS (ideal target), detects if it OK, then send it via SPI to the 2nd PIC. all this occurs in real time. The LCD displays the value now and again on a seperate PIC.

I am utilising three external latches (74HCT573N) to take the snap shot, and if the encoder is turned very slowly (0.5rps), then the code works - No error is detected as the encoder turns (or is stationary) in either CW/CCW direction.

But when the encoder is turned faster, then an error is generated. And the error occurs in different locations - not just one part of the count.
The code is below:
Code:
/////// MASTER PROGRAM ////////
///*
#include <18F4550.H>
#fuses EC, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP, NOPBADEN, NOVREGEN
#use delay(clock=48000000)
#use standard_io(a)     
#use standard_io(b)
#use standard_io(c)     
#use standard_io(d)
#use standard_io(e)

#byte UCFG = getenv("SFR:UCFG") //USB Registors
#bit UTRDIS = UCFG.3         //USB Registors

#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)

#include "flex_lcd_16x1.c"
#define SPI_SS   PIN_E2

#define LSB_LATCH_LE_CL3  PIN_B7
#define LSB_LATCH_OE_CL8  PIN_B2
#define SB_LATCH_LE_CL4   PIN_B6
#define SB_LATCH_OE_CL7   PIN_B3
#define MSB_LATCH_LE_CL5  PIN_B5
#define MSB_LATCH_OE_CL6  PIN_B4


//============================

signed int tic, input_lsb, input_sb, input_msb = 0;
signed long int ans;
int count_to_use=8;                          // NOT USED FOR NOW
static long int count=1;
signed long int fullbyte_read_current, fullbyte_read_old;

#int_RTCC
void RTCC_isr(void)
{
//    if (--count==0) {
//        count=count_to_use;                                                                                                       
        tic = 1;                           // SET INTERRUPT HAS OCCURRED FLAG                           
//    }
//    else  {                       
//        tic = 2;                                                                                         
// }
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_8);  // this should generate a 170.6uS interrupt.
enable_interrupts(INT_TIMER0);
enable_interrupts(global);
output_high(SPI_SS);  // Initial Slave Select to a high level
setup_spi(SPI_MASTER | SPI_MODE_1 | SPI_CLK_DIV_4);
SETUP_ADC_PORTS(NO_ANALOGS);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
output_low(LSB_LATCH_LE_CL3);      //Disable all latch's
output_high(LSB_LATCH_OE_CL8);
output_low(SB_LATCH_LE_CL4);
output_high(SB_LATCH_OE_CL7);
output_low(MSB_LATCH_LE_CL5);
output_high(MSB_LATCH_OE_CL6);

////////////////////////////////////////INITIAL 24-BIT CATCH (OLD VALUE)//////////////////////////

   output_high(LSB_LATCH_LE_CL3);   //LSB Latch Enable
   output_high(SB_LATCH_LE_CL4);    //SB Latch Enable
   output_high(MSB_LATCH_LE_CL5);   //MSB Latch Enable
   delay_us(1); 
 
   output_low(LSB_LATCH_OE_CL8);   //LSB Latch Output Enable
   delay_us(1);
   input_lsb = input_d();         //Read LSB Byte
   delay_us(1);
   output_low(LSB_LATCH_LE_CL3);
   output_high(LSB_LATCH_OE_CL8);
   delay_us(1);

   output_low(SB_LATCH_OE_CL7);      //SB Latch Output Enable
   delay_us(1);
   input_sb = input_d();         //Read SB Byte
   delay_us(1);
   output_low(SB_LATCH_LE_CL4);
   output_high(SB_LATCH_OE_CL7);
   delay_us(1);

   output_low(MSB_LATCH_OE_CL6);    //MSB Latch Output Enable
   delay_us(1);
   input_msb = input_d();         //Read MSB Byte
   delay_us(1);
   output_low(MSB_LATCH_LE_CL5);
   output_high(MSB_LATCH_OE_CL6);
   delay_us(1);

   fullbyte_read_old = make32(0, input_msb, input_sb, input_lsb); //Take initial 24-bit Snap-Shot

//////////////////////////////////////////////////////////////////////////////////////////////////
 
while(1)
  {
if (tic == 1){   ////////////////////INTERRUPT HAS OCCURRED - WE NOW HAVE 170.4uS TO DO EVERYTHING BEFORE THE NEXT INTERRUPT///////////////////////////
   tic=0;                     //RESET INTERRUPT FLAG
 
   output_high(LSB_LATCH_LE_CL3);   //LSB Latch Enable
   output_high(SB_LATCH_LE_CL4);    //SB Latch Enable
   output_high(MSB_LATCH_LE_CL5);   //MSB Latch Enable
   delay_us(1);                //More than required
 
   output_low(LSB_LATCH_OE_CL8);   //LSB Latch Output Enable
   delay_us(1);                //More than required
   input_lsb = input_d();         //Read LSB Byte
   delay_us(1);                  //More than required???
   output_low(LSB_LATCH_LE_CL3);   //Disable Latch
   output_high(LSB_LATCH_OE_CL8);
   delay_us(1);                  //More than required

   output_low(SB_LATCH_OE_CL7);      //SB Latch Output Enable
   delay_us(1);                  //More than required
   input_sb = input_d();         //Read SB Byte
   delay_us(1);                  //More than required???
   output_low(SB_LATCH_LE_CL4);      //Disable Latch
   output_high(SB_LATCH_OE_CL7);
   delay_us(1);                //More than required

   output_low(MSB_LATCH_OE_CL6);    //MSB Latch Output Enable
   delay_us(1);                  //More than required
   input_msb = input_d();         //Read SB Byte
   delay_us(1);                  //More than required???
   output_low(MSB_LATCH_LE_CL5);   //Disable Latch
   output_high(MSB_LATCH_OE_CL6);
   delay_us(1);                  //More than required


/////////////////////////////////////ERROR DETECTION CODE///////////////////////////////
   fullbyte_read_current = make32(0, input_msb, input_sb, input_lsb);    //TAKE CURRENT READ
   ans = (fullbyte_read_current - fullbyte_read_old);               //TAKE ANWAY FORM PREVIOUS READ            
   fullbyte_read_old = fullbyte_read_current;                      //OLD = NEW READ
//////////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////CHECK IF AN ERROR HAS OCCURRED AND SEND VALUE//////////
         if ((( ans >=-1) && (ans <=1)) || (ans == 0)) {
//         if (true){
          output_low(SPI_SS);           // NO ERRORS DETECTED - SEND 24 BIT VALUE TO SLAVE
          delay_cycles(7);
          spi_write(ans); 
         delay_cycles(7);
       // spi_write(input_sb);   
         // delay_us(10);
         // spi_write(input_msb); 
         // delay_us(10);
            output_high(SPI_SS);
         //input_lsb = 0;                   //RESET
         //input_sb = 0;
         //input_msb = 0;
           delay_cycles(7);
            ans = 0;
}
   
     else if (( ans <-1) || (ans >1)){
           output_low(SPI_SS);           //  ERROR DETECTED - SEND ERROR MESSAGE
          delay_cycles(7);
          spi_write(ans); 
         delay_cycles(7);
       // spi_write(input_sb);   
         // delay_us(10);
         // spi_write(input_msb); 
         // delay_us(10);
            output_high(SPI_SS);
         //input_lsb = 0;                   //RESET
         //input_sb = 0;
         //input_msb = 0;
           delay_ms(1000);}
}
   
////////////////////////////////////////////////////////////////////////////////////////////////////

                                   
//else if (tic == 2){      ////////////////////INTERRUPT HAS NOT OCCURRED - DO SOMETHING ELSE///////////////////////////
//   tic=0;
//   output_low(SPI_SS);
//   spi_write(10);
//   delay_cycles(7);
//   spi_write(0);
//   delay_us(10);
//   spi_write(0);
//   delay_us(10);
//   output_high(SPI_SS);
//   delay_cycles(7);
//   delay_ms(1000);
//}

}
}


I have increased the timer time so thst the timer should produce an interrupt every 170us - which leads me onto my first question:

1) Is this enough time to do everything?? I presume its more than enough, when using a 48MHz Osciallator. this gives over 2000 instrcutions untill the interrupt occurs - surely this is enough??

2) Is the code above correct - especially the error detection (make 32 function). So new value - old value = ans. and 'ANS' should only ever be -1 (shown as 255 on the display), 0 or 1 - depending on which way the shaft is turning. And this is what I currently have the code set up to display - just the 'ANS' value. and when rotated very slow - it flickers between 0, 255 and 1 - which is good. But when run faster it errors.

3) The delays I have incorporated in the code - do they look ok? I have tried various values - but it doesn't make any difference really.

4) Is the problem possibly due to erronous reads when I carry out the snap-shot?? noise or a glitch?? I checked with a scope on some of the channels and the signal looks OK - but I would need a logic analyser to be sure - and I dont have that!

Also to note, that for now, assuming the maximum frequency out of the 2^0 on the encoder was 5KHz - this would equate to a change every 200uS - which is more than the interrupt - so no code could be missed.

I really need your help, as I am running out of ideas as too why it is failing.
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 5:11 am     Reply with quote

I find that setting an output high in the ISR and returning it to low when processing is done is a pretty fair way to see if there's enough headroom in my interrupt rate.
Ttelmah



Joined: 11 Mar 2010
Posts: 19491

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 5:15 am     Reply with quote

There are a few things leaping out.
You are making a 32bit value, and then writing this into a 16bit value. A 'signed long int', is a 16 bit value. You need a 'signed int32', or a 'signed long long'.

You can save yourself a few cycles straight away, by taking advantage of unions:
Code:

typedef struct {
    int8 LSB;
    int8 NMSB;
    int8 MSB;
    int8 TOP;
} my_bytes;
   
union to_int32 {
    my_bytes part;
    int32 whole;
} data_current, data_old;

//Then you can write to the bytes as:
data_current.part.LSB=input_d();

//and NMSB, then MSB. Clear data_current.part.TOP once at the start of
//the program.

//Then access the whole thing with:

ans=data_current.whole-data_old.whole;
data_old.whole=data_current.whole;


This way the bytes are written _directly_ into the bytes of the int32, as they are read. No need to move them later to the right place.

I suspect the big problem is the need to use int32's.....

Best Wishes
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 5:19 am     Reply with quote

Good point, This is what I have done with 'tic'.
Tic = 1 when Interruopt occurs.
And in main Tic is reset to 0.

But how to check the 'time' it takes to go from '1' to '0' sounds tricky to do. Obvioculy I cannot do it on the LCD. So how would I time this?

I have not used 'debug' before on MPLAB, although I presume you could 'clock it' somehow.

However I still think the concept of 2000 instructions should be sufficient.
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 5:23 am     Reply with quote

Thanks Ttelmah for replying,

I will look into it and get back.
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Fri Aug 03, 2012 5:25 am     Reply with quote

Oscilloscope. A key piece of bench gear that everyone beyond novice hobbyist should have.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
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