|
|
View previous topic :: View next topic |
Author |
Message |
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
18F2550 interrupt problem |
Posted: Wed Aug 11, 2010 12:43 pm |
|
|
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
|
|
Posted: Wed Aug 11, 2010 1:41 pm |
|
|
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
|
18F2550 interrupt problem |
Posted: Wed Aug 11, 2010 2:40 pm |
|
|
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
|
|
Posted: Wed Aug 11, 2010 3:05 pm |
|
|
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
|
|
Posted: Wed Aug 11, 2010 4:01 pm |
|
|
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
|
|
Posted: Wed Aug 11, 2010 4:21 pm |
|
|
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
|
|
Posted: Wed Aug 11, 2010 4:28 pm |
|
|
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
|
|
Posted: Wed Aug 11, 2010 5:48 pm |
|
|
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:
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
|
while loop |
Posted: Wed Aug 11, 2010 5:59 pm |
|
|
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
|
|
Posted: Thu Aug 12, 2010 1:15 am |
|
|
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: 19569
|
|
Posted: Thu Aug 12, 2010 1:59 am |
|
|
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
|
18F2550 interrupt problem |
Posted: Thu Aug 12, 2010 2:44 am |
|
|
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. |
|
|
|
|
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
|