View previous topic :: View next topic |
Author |
Message |
kjankows
Joined: 03 Aug 2010 Posts: 9
|
port B interrupt on changes int not clearing |
Posted: Tue Aug 03, 2010 2:58 pm |
|
|
I have a 16f1937 which will wait for the first transition on port b2. The interrupt routine is processed (turns led on then off). The interrupt will be called continually from this point on. It doesn't matter if the input is back to the original state or not.
The ISR is as follows:
Code: |
#int_rb noclear
void RB_ISR(void)
{
output_low (LED);
position++;
int current;
static int last=0;
current=input_b();
clear_interrupt(INT_RB);
#if LOWTOHIGH
if ((!bit_test(last,1))&&(bit_test(current,1))) {dbutton1=1;}
#elif HIGHTOLOW
if ((!bit_test(current,1))&&(bit_test(last,1))) {dbutton1=1;}
#endif
last=current;
output_high (LED);
}
|
I am using version 4.3.0.285
I appreciate any help/clues of where to look for this.
Thanks |
|
|
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
Posted: Tue Aug 03, 2010 3:26 pm |
|
|
#int_rb only detects change on RB4 to RB7. You are trying to detect a change on RB2 so it doesn't seem like that is the right interrupt. Your PIC does have separate IOC (interrupt-on-change) for all the PORTB pins. I don't know which #int_xxx function supplied by CCS is the right one for an IOC on RB2. Looking through the list in the manual it doesn't seem like any of it matches. You might have to manually write to the appropriate SFRs.
Does anyone else know? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Aug 03, 2010 3:33 pm |
|
|
Post a complete test program, with the #define statement for 'LED'.
Post the #include for the PIC, #fuses, #use delay, and main(). In
main() you should have the interrupt enable statements and any other
setup required for PortB, and a continuous loop at the end of main().
The program should compile without errors.
Post the real compiler version number from the top of the .LST file.
The .LST file will be in your project directory. The version number
is in this format: x.xxx (Example: 4.109). |
|
|
kjankows
Joined: 03 Aug 2010 Posts: 9
|
|
Posted: Tue Aug 03, 2010 3:53 pm |
|
|
Sorry for not posting enough information.
Here is the entire program:
Code: |
#include <16F1937.h>
#include <STDIO.h>
#fuses BROWNOUT
#fuses NOWDT //WDT
#fuses PUT
#fuses INTRC_IO
#fuses NOVCAP
#fuses BORV27
#fuses MCLR
#fuses NOCLKOUT
#define LOWTOHIGH TRUE
#define HIGHTOLOW FALSE
#define LED PIN_D2
#define SER_SDNF PIN_D0
#use delay(clock=16000000) //16MHz Clock
#use fast_io(ALL)
#use rs232(BAUD=9600, xmit=PIN_C6, rcv=PIN_C7, enable=SER_SDNF)
volatile unsigned int8 current=0;
short int dbutton1;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
#int_rb noclear
void RB_ISR(void)
{
output_low (LED);
int current;
static int last=0;
current=input_b();
clear_interrupt(INT_RB);
#if LOWTOHIGH
if ((!bit_test(last,1))&&(bit_test(current,1))) {dbutton1=1;}
#elif HIGHTOLOW
if ((!bit_test(current,1))&&(bit_test(last,1))) {dbutton1=1;}
#endif
last=current;
output_high (LED);
}
void main(void)
{
setup_oscillator(OSC_16MHZ | OSC_INTRC | OSC_PLL_ON);
setup_timer_6(T6_DIV_BY_16, 250, 1);
set_tris_d(0x00);
output_low (PIN_A7);
output_low (PIN_E2);
output_low (PIN_A6);
set_tris_a(0x0F);
set_tris_b(0xFF); //all inputs
set_tris_c(0x00);
set_tris_d(0x00);
set_tris_e(0xFA);
port_b_pullups(true);
enable_interrupts(INT_RB1);
enable_interrupts(global);
output_high (LED); //turn off led by default
while (1)
{
output_c(current);
}
}
|
The lst file reports the version as: CCS PCM C Compiler, Version 4.106, 52170 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Aug 03, 2010 4:40 pm |
|
|
Describe the external circuit on pin B2, including component values.
What are the voltage levels provided by that circuit to pin B2 ?
Is the circuit a push-button switch, or something else ? |
|
|
kjankows
Joined: 03 Aug 2010 Posts: 9
|
|
Posted: Tue Aug 03, 2010 5:17 pm |
|
|
It is a switch to ground. There is a 100ohm series resistor. When the switch is closed the input sees less then 0.2V and when it is open it sees 5V.
It doesn't matter whether the input is High or Low when the cycle starts. After the first transistion the interrupt continues to be called.
Thanks for the help.
Kevin |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Aug 03, 2010 10:39 pm |
|
|
Quote: |
port_b_pullups(true);
|
The 16F1937 has individual enables for the pullups on Port B (on each pin).
You need to use a bitmask as the parameter instead of True/False.
The line above only enables a pullup on Pin B0 (because 'true' is 0x01).
You need to change the parameter to 0x02, to enable a pullup on Pin B1.
Also, the pullups don't pull up instantly when enabled. It's safer to do a
short delay (such as 10 us) after enabling them, before you do anything else.
This may not fix everything because I think there are some compiler
bugs for the 16F1937 in vs. 4.106, but at least it's a start. |
|
|
kjankows
Joined: 03 Aug 2010 Posts: 9
|
|
Posted: Wed Aug 04, 2010 5:33 am |
|
|
Thank you. I will make that change. I have ordered the upgrade to 4.109 and should be able to download it today. Hopefully that will help. I will post if that works.
Thanks
Kevin |
|
|
kjankows
Joined: 03 Aug 2010 Posts: 9
|
|
Posted: Wed Aug 04, 2010 9:39 am |
|
|
PCM programmer.
I have made the change you suggested and also upgraded to 4.109 The ISR still continues to be called repeatedly once it gets called the first time. Any ideas where I should look next?
Thanks again.
Kevin |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Aug 04, 2010 9:45 am |
|
|
Code: |
volatile unsigned int8 current=0;
short int dbutton1;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
#int_rb noclear
void RB_ISR(void)
{
output_low (LED);
int current;
static int last=0;
current=input_b();
clear_interrupt(INT_RB);
#if LOWTOHIGH
if ((!bit_test(last,1))&&(bit_test(current,1))) {dbutton1=1;}
#elif HIGHTOLOW
if ((!bit_test(current,1))&&(bit_test(last,1))) {dbutton1=1;}
#endif
last=current;
output_high (LED);
}
|
You have a global called current and you are using it as a local for your interrupt.
I have run into problems myself with doing this (accidentally), admittedly mine were different sizes (int16 and int8) and a different version of the compiler, but the compiler was getting confused between them.
And I didn't know that CCS had started allowing var definitions after a function or instruction had been used |
|
|
kjankows
Joined: 03 Aug 2010 Posts: 9
|
|
Posted: Wed Aug 04, 2010 10:16 am |
|
|
I have looked at the disassembly listing for the ISR. The register/bit that is being cleared by the clear_interrupt seems to be the incorrect register. The datasheet shows the intcon register is at location 0x0B.
Or am I reading this wrong.
Code: |
33: #int_rb noclear
34: //#int_rb
35: void RB_ISR(void)
36: {
37:
38: // int current;
39: static int last=0;
40:
41: output_low (LED);
001E 0022 MOVLB 0x2
001F 110F BCF 0xf, 0x2
42: current=input_b();
0020 0020 MOVLB 0
0021 080D MOVF 0xd, W
0022 00A6 MOVWF 0x26
43: clear_interrupt(INT_RB);
0023 1012 BCF 0x12, 0
44:
45: #if LOWTOHIGH
46: if ((!bit_test(last,5))&&(bit_test(current,5))) {dbutton1=1;}
0024 1AA8 BTFSC 0x28, 0x5
0025 2828 GOTO 0x28
0026 1AA6 BTFSC 0x26, 0x5
0027 1427 BSF 0x27, 0
47: #elif HIGHTOLOW
48: if ((!bit_test(current,5))&&(bit_test(last,5))) {dbutton1=1;}
49: #endif
50:
51: last=current;
0028 0826 MOVF 0x26, W
0029 00A8 MOVWF 0x28
52:
53: output_high (LED);
002A 0022 MOVLB 0x2
002B 150F BSF 0xf, 0x2
54: }
|
Thanks
Kevin |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 04, 2010 11:07 am |
|
|
That is one of the bugs that I spotted in vs. 4.106. But what version
are you using for this latest test ? |
|
|
kjankows
Joined: 03 Aug 2010 Posts: 9
|
|
Posted: Wed Aug 04, 2010 11:48 am |
|
|
From the lst file:
CCS PCM C Compiler, Version 4.109, 53512
Thanks
Kevin |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 04, 2010 12:32 pm |
|
|
As a work-around, add this code above main():
Code: |
#byte INTCON = 0x0B
#bit IOCIF = INTCON.0
#define clear_int_rb() IOCIF = 0
|
Then in every place where you call clear_interrupt(INT_RB),
change it to clear_int_rb().
CCS should be emailed about this bug. Maybe you should wait until
you get the whole program working, because there may be more bugs. |
|
|
kjankows
Joined: 03 Aug 2010 Posts: 9
|
|
Posted: Wed Aug 04, 2010 12:52 pm |
|
|
PCM programmer
Thanks for the information. The disassembly now looks correct for the clear interrupt. But the app still behaves the same way. Once the first interrupt triggers the LED continues to toggle for ever. Any ideas how best to figure out where the next problem may be?
Thanks again for all the help.
Kevin |
|
|
|