View previous topic :: View next topic |
Author |
Message |
soonc
Joined: 03 Dec 2013 Posts: 215
|
IOC not working |
Posted: Wed Dec 26, 2018 3:35 pm |
|
|
Chip:18F46K42
Compiler: 5.082
IOC does not appear to work.
PIN_B5 has a 100K Pull up resistor to 3V3 and the signal is pulling the pin low about once every 1-2 seconds confirmed with scope.
I'm somewhat confused as the .h for the chip has
INT_IOC and INT_IOC_B5 Pin B5 is the pin I'm interested in checking.
I've tried several different combinations of
Code: |
enable_interrupts(INT_IOC);
enable_interrupts(INT_IOC_B5);
|
the IOC does not function.
For test I tried
Code: | n1B5 = input(PIN_B5); |
and sure enough B5 is changing, but of course I need the interrupt and can't reply on polling.
Has anyone been able to make the IOC work on this chip ?
Thanks
Code: |
#include <18F46K42.h>
#device ADC=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or
// B5(PIC18) used for I/O !
#use delay(crystal=12000000)
#define GREEN_LED_ON output_high(PIN_C5)
#define GREEN_LED_OFF output_low(PIN_C5)
int8 g_n8PortB;
#INT_IOC
void IOC_isr(void)
{
g_n8PortB = input_b(); // read the port clear the IF
}
void main()
{
int1 n1OldB5=0;
int1 n1B5=0;
enable_interrupts(INT_IOC);
enable_interrupts(INT_IOC_B5);
enable_interrupts(GLOBAL);
n1OldB5 = n1B5;
while(TRUE)
{
n1B5 = bit_test( g_n8PortB, 5 );
// for test n1B5 = input(PIN_B5); // works B5 is changing
if ( n1B5 != n1OldB5 )
{
n1OldB5 = n1B5;
if( n1B5 )
{
GREEN_LED_ON;
}
else
{
GREEN_LED_OFF;
}
}
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 27, 2018 12:04 am |
|
|
The 18F46K42.h file IOC definitions are incorrect in vs. 5.082.
To fix it, place this section of code just above main():
Code: |
#define INT_IOC_B5_L2H 0x11200080 // IOC on rising edge on B5
#define INT_IOC_B5_H2L 0x21200080 // IOC on falling edge on B5
#undef INT_IOC_B5
#define INT_IOC_B5 0x31200080 // IOC on either edge on B5
|
Choose one of those, only.
For example, if you want an IOC interrupt on either edge of B5, use this one:
Code: | enable_interrupts(INT_IOC_B5);
|
Don't use this:
Code: | enable_interrupts(INT_IOC); |
Note: This fixes pin B5 IOC only. The other pins are wrong too.
And it's missing the individual edge #defines for all the other pins.
CCS support should be informed of this. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Thu Dec 27, 2018 12:55 am |
|
|
Understand that the physical interrupt is INT_IOC.
So your handler should use this name.
The standard code is correctly setting up the interrupt, what they have omitted
is to setup the 'edge' register bits to set which edges the interrupt will
trigger on. These default to 'off' on boot, so the interrupt doesn't respond
to either edge... |
|
|
soonc
Joined: 03 Dec 2013 Posts: 215
|
Thanks I test it. |
Posted: Thu Dec 27, 2018 9:05 am |
|
|
PCM programmer wrote: | The 18F46K42.h file IOC definitions are incorrect in vs. 5.082.
To fix it, place this section of code just above main():
Code: |
#define INT_IOC_B5_L2H 0x11200080 // IOC on rising edge on B5
#define INT_IOC_B5_H2L 0x21200080 // IOC on falling edge on B5
#undef INT_IOC_B5
#define INT_IOC_B5 0x31200080 // IOC on either edge on B5
|
Choose one of those, only.
For example, if you want an IOC interrupt on either edge of B5, use this one:
Code: | enable_interrupts(INT_IOC_B5);
|
Don't use this:
Code: | enable_interrupts(INT_IOC); |
Note: This fixes pin B5 IOC only. The other pins are wrong too.
And it's missing the individual edge #defines for all the other pins.
CCS support should be informed of this. |
Will test in about an hour and report back.
Thanks for the help. |
|
|
soonc
Joined: 03 Dec 2013 Posts: 215
|
One more thing |
Posted: Thu Dec 27, 2018 8:47 pm |
|
|
Just reading port B in the ISR does not clear the interrupt.
clear_interrupt(INT_IOC_B5); // Required when the interrupt is first enabled, and in the ISR.
Thanks for the help.
Code: |
#include <18F46K42.h>
#device ADC=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or
// B5(PIC18) used for I/O !
#use delay(crystal=12000000)
#define GREEN_LED_ON output_high(PIN_C5)
#define GREEN_LED_OFF output_low(PIN_C5)
int8 g_n8PortB;
#INT_IOC
void IOC_isr(void)
{
g_n8PortB = input_b(); // read the port clear flag actually does not do that
// this code will work without reading port B
// Just clear the interrupt
clear_interrupt(INT_IOC_B5); // Required
}
// Thanks PCM_Programmer
#define INT_IOC_B5_L2H 0x11200080 // IOC on rising edge on B5
#define INT_IOC_B5_H2L 0x21200080 // IOC on falling edge on B5
#undef INT_IOC_B5
#define INT_IOC_B5 0x31200080 // IOC on either edge on B5
void main()
{
int1 n1OldB5=0;
int1 n1B5=0;
enable_interrupts(INT_IOC_B5);
clear_interrupt(INT_IOC_B5); // required or it hangs the entire chip
enable_interrupts(GLOBAL);
n1OldB5 = n1B5;
while(TRUE)
{
n1B5 = bit_test( g_n8PortB, 5 );
if ( n1B5 != n1OldB5 )
{
n1OldB5 = n1B5;
if( n1B5 )
{
GREEN_LED_ON;
}
else
{
GREEN_LED_OFF;
}
}
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Dec 28, 2018 3:09 am |
|
|
I sent a detailed bug report to CCS support, regarding the incorrect and
missing IOC constants for the K42-series PICs. |
|
|
|