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

18F2550 interrupt problem

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



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

18F2550 interrupt problem
PostPosted: Wed Aug 11, 2010 12:43 pm     Reply with quote

The problem is with the rb interrupt. Without rb interrupt enabled, the ext int on B0 works fine.
If rb interrupts enabled, program hangs at "enable_interrupts(INT_RB);" and ext int stops working.
I have searched and searched the forum and tried any suggestions, but nothing works!
The push buttons are on RB5, RB6 & RB7 - pullup resistor to +5V, button from pin to ground.
B4 tied high (unused). rb_isr() not called at all.
Code:

//Compiler v3.29 - (HATE v4 interface!!)

#include "K:\Picc\Meter Extension\MExt.h"
#include "K:\Picc\Meter Extension\DS1302.C"
#include "K:\Picc\Meter Extension\FLEX_LCD420.C"

#ZERO_RAM

#define CB PIN_B6 //centre button
#define LB PIN_B5 //left button
#define RB PIN_B7 //right button

write_float_eeprom(int16 n, float data);
float read_float_eeprom(int16 n);

float units;
int setting;
byte last_b, port_b, c;
//---------------------------------------------------------------------------
#int_EXT
EXT_isr()
{
units = read_float_eeprom(0);
units += 0.01;
write_float_eeprom(0, units);
}
//---------------------------------------------------------------------------
#int_rb
rb_isr()
{
byte changes;
changes = last_b ^ port_b;
last_b = port_b;

if(bit_test(changes, 5) && !bit_test(last_b, 5))
 {
   lcd_putc("\fLeft Button");
   delay_ms(1000);
 }//Left Button
 
if(bit_test(changes, 6) && !bit_test(last_b, 6))
 {
  lcd_putc("\fCentre Button");
   delay_ms(1000);
 }//Middle Button

if(bit_test(changes, 7) && !bit_test(last_b, 7))
 {
  lcd_putc("\fRight Button");
   delay_ms(1000);
 }//Right Button
 delay_ms(100); //debounce
}
//---------------------------------------------------------------------------
void main()
{
setting = false;
SETUP_ADC_PORTS(NO_ANALOGS);
SETUP_ADC(ADC_OFF);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED, 0, 1);
setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
ext_int_Edge(H_TO_L); //trigger on hi to lo on RB0

lcd_init();
rtc_init();
setup_oscillator(False);

printf(lcd_putc, "Today:%2.2f Avg:%2.1f", units, units);

//if 1st use after compile, loc will be 0xFF
if(read_eeprom(0) == 0xFF)
 write_float_eeprom(0, 0);
 
c = port_b;    // Clear mismatch condition
clear_interrupt(INT_RB); 
enable_interrupts(INT_RB); //prog stops here
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);

while(true)
 {
  lcd_gotoxy(1, 2);
 
  output_high(PIN_A3); //flash LED
  delay_ms(500);
  output_low(PIN_A3);
  delay_ms(500);
  printf(lcd_putc, "Today:%2.2f Avg:%2.1f", read_float_eeprom(0), units);
 }//endwhile
}
//---------------------------------------------------------------------------
write_float_eeprom(int16 n, float data)
{
int8 i;
for(i = 0; i < 4; i++)
 write_eeprom(i + n, *(&data + i));
}
//---------------------------------------------------------------------------
float read_float_eeprom(int16 n)
{
int i;
float data;
for(i = 0; i < 4; i++)
 *(&data + i) = read_eeprom(i + n);
return(data);
}
//---------------------------------------------------------------------------

include file:
#include <18F2550.h>
#device *=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOPUT
#FUSES HSPLL                    //Crystal osc <= 4mhz
#FUSES PLL1
#FUSES CPUDIV2
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOPBADEN
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOLPT1OSC                //Timer1 not configured for low-power operation
#FUSES NOMCLR                  //Master Clear pin disabled
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES USBDIV
#FUSES VREGEN

#use delay(clock=48000000)
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 11, 2010 1:41 pm     Reply with quote

Do some testing. Comment out the bulk of the code in #int_rb, as shown
below in bold. Add a brief debounce delay. See if it still locks up.
Quote:

#int_rb
rb_isr()
{
byte changes;
changes = last_b ^ port_b;
last_b = port_b;

delay_ms(10); // Add brief delay

/* Comment out this block:
if(bit_test(changes, 5) && !bit_test(last_b, 5))
{
lcd_putc("\fLeft Button");
delay_ms(1000);
}//Left Button

if(bit_test(changes, 6) && !bit_test(last_b, 6))
{
lcd_putc("\fCentre Button");
delay_ms(1000);
}//Middle Button

if(bit_test(changes, 7) && !bit_test(last_b, 7))
{
lcd_putc("\fRight Button");
delay_ms(1000);
}//Right Button
delay_ms(100); //debounce

*/

}



Quote:

#include <18F2550.h>
#FUSES HSPLL //Crystal osc <= 4mhz
#FUSES PLL1
#FUSES CPUDIV2

#use delay(clock=48000000)

Also, this is not correct. These fuse settings, with a 4 MHz crystal, will
give a 32 MHz oscillator. So your #use delay is wrong.
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

18F2550 interrupt problem
PostPosted: Wed Aug 11, 2010 2:40 pm     Reply with quote

Locking up solved by changing NOEXTINST to EXTINST. int_rb never called. Have removed bulk of code in int_rb, as suggested - no change
About oscillator - I give up! With 4MHz xtal, how do I get cpu clocking at 48MHz? (and with USB at 96MHz)
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 11, 2010 3:05 pm     Reply with quote

Quote:

Locking up solved by changing NOEXTINST to EXTINST.

Just because something appears to be solved doesn't make it really
be solved. The real solution might actually require more trouble-shooting.
You must use the NOXINST fuse. The CCS compiler doesn't support
the XINST mode. If you use XINST, your program will start to fail in
weird ways.

Quote:
About oscillator - I give up! With 4MHz xtal, how do I get cpu clocking at 48MHz?

Read the PIC data sheet and do some experiments. Make a little test
program that blinks an LED at a nominal rate of once per second.
Time it with a stopwatch. That's what I do.

Look at the program shown below. What fuse might you change to
make it run at 48 MHz ? What's the most logical thing ? (This is like
part of an SAT test).
Code:

#include <18F4550.h>
#FUSES HSPLL                   
#FUSES PLL1
#FUSES CPUDIV2

#use delay(clock=48000000)
 

//======================================
void main(void)
{
 
while(1)
  {
   output_high(PIN_B0);
   delay_ms(100);
   output_low(PIN_B0);
   delay_ms(900);
  }

}
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Wed Aug 11, 2010 4:01 pm     Reply with quote

Hi PCM programmer.
Thank you for your info about XINST. I must say that I find your following comments somewhat condescending. Yes, I have looked at the data sheet. Obviously, we are not all as fortunate as you appear to be in the intelligence department, or, perhaps as skilled as you with these devices!!! I thought that the purpose of these forums was to offer help, not condescention! I do this as a hobby, not as a profession.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 11, 2010 4:21 pm     Reply with quote

I agree, but so many people appear to me that they "don't want to work".
If you notice the posts on here, someone will take a piece of code, modify
it, discover that it doesn't work, and then dump the code on the forum.
Then I imagine they go take a pizza break, and hope that I (or others)
will fix it all for them. If we don't do it immediately, they come back and
post "Please help !!!". Lately, the amount of this is "getting to me".
But you are right, I should tone down my frustration.

Anyway, to answer your #fuses question, change it to CPUDIV1 to get
48 MHz operation.
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Wed Aug 11, 2010 4:28 pm     Reply with quote

Hi PCM programmer. I am NOT in the category you describe! I am new to the 18 series, but I have spent MANY hours trying to solve my own problems and it is only out of desperation that I have posted at all! I agree that some of the posts one sees shouldn't have been made, but please don't tar us all with the same brush! Having restored NOIEXT and changed the delay line to 32MHz, the int_rb function is now called continuously, as well as the ext int. The buttons make no change at all. If I disable the int_rb in the handler, then it duly stops. I simply don't know where to go next. Two days, I have been on this problem!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 11, 2010 5:48 pm     Reply with quote

Code:

#int_rb
rb_isr()
{
byte changes;
changes = last_b ^ port_b;
last_b = port_b;

I just started looking at your code, and in the code above, you're not
reading the physical Port B. You're just talking to a variable. You need
to read the port and load it into the 'port_b' variable, as shown below
in bold:
Quote:

#int_rb
rb_isr()
{
byte changes;
port_b = input_b();
changes = last_b ^ port_b;
last_b = port_b;


Also in main(), you have the following line. It has the same problem.
Code:

c = port_b;    // Clear mismatch condition

You need to change it to this:
Quote:

c = input_b();


All of this is probably the reason for the lock-ups in #int_rb.
The mismatch condition was never being cleared, so the interrupt just
occurs over and over again.
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

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

while loop
PostPosted: Wed Aug 11, 2010 5:59 pm     Reply with quote

I would put your enable interrupts inside your WHILE loop...

this works for me... if you disable your interrupts you need to re-enable them on each loop.

i.e. use a disable command inside of your ISR and re-enable on each loop in your MAIN...
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Thu Aug 12, 2010 1:15 am     Reply with quote

Hi both
I will make those changes. It is interesting that the rb_isr() code is straight out of the CCS manual!! One would expect that to be kosher! I will let you know the results. One question however: The int is supposed to be called ONLY when there is a change in bits 4 - 7, so why is it being called anyway. I could understand problems as you point out once a change had taken place on B4 - B7. Does enabling an interrupt automatically call it, regardless?
Ttelmah



Joined: 11 Mar 2010
Posts: 19448

View user's profile Send private message

PostPosted: Thu Aug 12, 2010 1:59 am     Reply with quote

Key difference, is how 'port_b' is defined.
In the CCS example, it is assumed you have a #byte definition 'mapping' the variable called 'port_b' to the physical port register. Hence when you read 'port_b', you are reading the register, and the interrupt clears. You have the variable just defined as an ordinary byte variable, without this extra mapping, hence the code will always fail.....

Best Wishes
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

18F2550 interrupt problem
PostPosted: Thu Aug 12, 2010 2:44 am     Reply with quote

Hi Ttelmah
That's cured it and all is working, thank you. I had used the self-same code on a 16F648 last year and it worked fine, so I presume that the mapping must exist for that PIC, but not for the 18F2550. Thanks again. Razz
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