|
|
View previous topic :: View next topic |
Author |
Message |
neilelph
Joined: 01 Apr 2012 Posts: 5 Location: Edinburgh
|
External Interrupt Problem |
Posted: Sun Apr 01, 2012 8:19 am |
|
|
I am trying to get the External Interrupt (on RB0) to work on a PIC16LF877.
Unfortunately my code will not work or simulate as I would like it to - in fact the interrupt just doesn't work!
I am using MPLAB V8.84 and the PCW C Compiler.
My interrupt code is written as below:
Code: |
#INT_EXT
void ext_isr(void)
{
if (psuState == DELAY_WAIT)
{
disable_interrupts(INT_EXT); // Disable future interrupts on RB0
PROCESSOR_ON; // Enable logic supplies
psuState = DELAY_BOOT; // Move to next stage
}
return;
|
I am enabling the interrupt using the code below:
Code: |
/* Switch off all supplies except PIC supply, enable
interrupt at PIC RB0 pin and enter wait state */
PROCESSOR_OFF;
enable_interrupts(INT_EXT);
psuState = DELAY_WAIT;
|
When the low to high transition occurs on RB0, nothing happens. I have ensured that the interrupt enabling code is being executed during simulation.
The enable_interrupts (GLOBAL) function is executed at the beginning of the code which is why it is not listed above. I also have the INT_TIMER1 interrupt working away quite happily.
Can anyone see what I am missing here?
Thank you. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Sun Apr 01, 2012 8:49 am |
|
|
Without seeing the whole, real program ,it's hard to tell....
Since you disable the interrupt within itself, it could have executed before you think it should and is now disabled...
What triggers the ISR? Are you sure that it can or is being triggered?
hmm..simulation....if Proteus...throw it away, it doesn't work ! See ANY previous 'simulation' posts. |
|
|
neilelph
Joined: 01 Apr 2012 Posts: 5 Location: Edinburgh
|
|
Posted: Sun Apr 01, 2012 9:10 am |
|
|
The interrupt is to allow a delayed start feature to my tool. It is only ever required once.
My tool is controlled by an ARM Processor and the PIC Monitors vital functions. If a delayed start has been configured by the user, the ARM Processor programs an alarm into an RTC and then tells the PIC to shut everything down apart from its own power supply. At this point the PIC arms the External Interrupt which is connected to the RTC and then waits. When the RTC alarms, the PIC turns on all other power supplies and the ARM Processor resumes overall control. The PIC External Interrupt is never required again.
Full code below.
Code: |
/*
*******************************************************************************
**
** Project: ATEX SAAM (D741)
** Filename: atex_saam.c
** Author:
** Created:
** Description:
**
** Firmware for ATEX SAAM logger control
**
** Revision History
** ----------------
**
** Version Date Author Comments
** ------- ---- ------ --------
** 0.1 26/09/11 ajs Release to debug
** 0.2 21/11/11 nae MEM_FULL polarity inverted and sounder timer
** counter ammended
** 0.3 12/03/12 nae User Delay code added. Sets up External
** interrupt
** 0.4 xx/xx/12 ajs Interrupt edge on pin interrupt now setup
** before global interrupts enabled
**
**
** COPYRIGHT 2011 WEATHERFORD. All Rights Reserved.
**
*******************************************************************************
*/
#include "atex_saam.h"
/*
* Function Name: ext_isr() - interrupt handler to enable logic supplies
* following user delay
* Parameters: None
* Returns: None
*/
#INT_EXT
void ext_isr(void)
{
if (psuState == DELAY_WAIT)
{
disable_interrupts(INT_EXT); // Disable future interrupts on RB0
PROCESSOR_ON; // Enable logic supplies
psuState = DELAY_BOOT; // Move to next stage
}
return;
}
//----------------------------End of isr----------------------------------------
/*
* Interrupt Routine: sounder_mode() - interrupt routine to manage the
* sounder output
* Parameters: none
* Returns: none
*
*/
#INT_TIMER1
void sounder_mode(void)
{
/* Overflow approx. once every second
(ie. period(sec)=(65535-64503)/(32.768(OSC freq in kHz)/32)) */
set_timer1(64503);
// Update timer counter
if (sounderCount==1)
sounderCount = 6;
else
--sounderCount;
// Control ON/OFF status of sounder
switch(psuState)
{
case DELAY_QUERY: // Drop thru'
case DELAY_WAIT: // Drop thru'
case DELAY_BOOT: // Drop thru'
case LOG:
if (loopCount < 20)
{
if (sounderCount < 4)
SOUNDER_ON;
else
SOUNDER_OFF;
}
else
SOUNDER_OFF;
break;
case USB_FAULT: SOUNDER_ON;
break;
case LOG_FAULT: // Drop thru'
case USB_COMMS: // Drop thru'
case READ_ADC: // Drop thru'
case START: // Drop thru'
case SHUTDOWN: SOUNDER_OFF;
break;
default: break;
}
if (loopCount < 25)
loopCount++;
return;
}
//-------------------------------End of isr-------------------------------------
/*
* Function Name: proc_config() - function initiates PSU microcontroller
* ports and features following power on reset
* Parameters: none
* Returns: none
*/
void proc_config(void)
{
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
/* Port A
RA0: Not used INPUT
RA1: SOUNDER OUTPUT
RA2: Not used INPUT
RA3: Not used INPUT
RA4: Not used INPUT
RA5: Not used INPUT */
SOUNDER_OFF;
TRISA=0x3d;
/* Port B
RB0: /RTC_INT INPUT
RB1: PS_CNTRL OUTPUT
RB2: PS_IF INPUT
RB3: Not used INPUT
RB4: /P3V3_EN OUTPUT
RB5: SENSORS_EN OUTPUT
RB6: PGC INPUT/OUTPUT
RB7: PGD INPUT/OUTPUT */
TRISB = 0xcd;
PSW_OFF;
SUPPLY_OFF;
PROCESSOR_ON;
/* Port C
RC0: BATTERY_GOOD INPUT
RC1: P3V3_GOOD INPUT
RC2: P1V8_GOOD INPUT
RC3: /USB_DET INPUT
RC4: DP_GOOD INPUT
RC5: /MEM_FULL INPUT
RC6: LOG_EN OUTPUT
RC7: PSU_STATUS OUTPUT */
TRISC = 0x3f;
LOGGING_OFF;
PSU_OFF;
/* Port D
RD0: AP_GOOD INPUT
RD1: DP_EN OUTPUT
RD2: AP_EN OUTPUT
RD3: Not used INPUT
RD4: USB_HIPWR OUTPUT
RD5: Not used INPUT
RD6: Not used INPUT
RD7: Not used INPUT */
TRISD = 0xe9;
DP_OFF;
AP_OFF;
USB_OFF;
/* Port E
RE0: Not used INPUT
RE1: Not used INPUT
RE2: Not used INPUT */
TRISE = 0x07;
return;
}
//----------------------------End of HW_Init------------------------------------
void main()
{
proc_config(); // Initialise PIC
while(1)
{
switch(psuState)
{
case START: // Select startup state
delay_ms(50);
// Setup pin interrupt edge and timer, and enable interrupts
set_timer1(64503);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER1);
/* Select operating state upon powerup or restart: USB_COMMS,
DELAY_QUERY or USB_FAULT */
if ((PORTC & 0x0f) == 0x07)
psuState = USB_COMMS;
else if ((PORTC & 0x0f) == 0x0f)
{
delay_ms(100);
psuState = DELAY_QUERY;
}
else
{
PROCESSOR_OFF;
psuState = USB_FAULT;
}
break;
case DELAY_QUERY: // Query if user delay is requested
// Check for Pressure Switch Latch first
if ((PORTB & 0x04) != 0x04)
PSW_ON;
else
PSW_OFF;
/* Check battery and logic supply levels */
if ((PORTC & 0x07) == 0x07)
{
/* Has ATMEL uC flagged memory as not full? If so, enable
sensor supply and logging */
if ((PORTC & 0x20) != 0x20)
{
delay_ms(10);
SUPPLY_ON; // Enable instrument supply switch
delay_ms(300);
DP_ON; // Power DP sensor
delay_ms(50);
AP_ON; // Power AP sensor
delay_ms(100);
LOGGING_ON;
psuState = LOG;
}
else
{
delay_ms(250);
if (loopCount2 > 3)
{
/* Switch off all supplies except PIC supply, enable
interrupt at PIC RB0 pin and enter wait state */
PROCESSOR_OFF;
ext_int_edge(H_to_L);
enable_interrupts(INT_EXT);
psuState = DELAY_WAIT;
}
}
loopCount2++;
}
else
{
PROCESSOR_OFF;
psuState = LOG_FAULT;
}
break;
case DELAY_WAIT: // Holding state while waiting for RTC alarm
break;
case DELAY_BOOT: // Boot power supplies following user delay
delay_ms(500); // Delay to allow logic supplies to settle
if ((PORTC & 0x07) == 0x07)
{
SUPPLY_ON; // Enable instrument supply switch
delay_ms(300);
DP_ON; // Power DP sensor
delay_ms(50);
AP_ON; // Power AP sensor
delay_ms(100);
LOGGING_ON;
psuState = LOG;
}
else
{
PROCESSOR_OFF;
psuState = LOG_FAULT;
}
break;
case LOG: // Logging mode
/* Check for system faults:
1. If processor logic supply faulty, battery low or memory full,
shutdown logging and supplies
2. If overcurrent detected at DP sensor, remove power from DP sensor
3. If overcurrent detected at AP sensor, remove power from AP sensor
*/
if (((PORTC & 0x37) != 0x17) || ((PORTD & 0x01) != 0x01))
{
if ((PORTC & 0x27) != 0x07)
{
LOGGING_OFF;
SUPPLY_OFF;
DP_OFF;
AP_OFF;
PROCESSOR_OFF;
disable_interrupts(GLOBAL);
disable_interrupts(INT_TIMER1);
setup_timer_1(T1_DISABLED);
psuState = LOG_FAULT;
}
if ((PORTC & 0x10) != 0x10)
DP_OFF;
if ((PORTD & 0x01) != 0x01)
AP_OFF;
}
break;
case USB_COMMS: // USB (100mA)
/* If USB cable connected, check USB regulated and processor
supplies shutting down all supplies if fault(s) detected. If
READ_ADC is selected by user, enable power to sensors */
if ((PORTC & 0x08) != 0x08)
{
if ((PORTC & 0x07) != 0x07)
{
PROCESSOR_OFF;
psuState = USB_FAULT;
}
else if ((PORTB & 0x04) != 0x04)
{
USB_ON; // Enable 500mA USB mode at DC-DC switcher
delay_ms(200);
SUPPLY_ON; // Enable instrument supply switch
delay_ms(300);
DP_ON; // Power DP sensor
delay_ms(50);
AP_ON; // Power AP sensor
delay_ms(50);
psuState = READ_ADC;
}
}
else
psuState=SHUTDOWN;
break;
case READ_ADC: // USB (500mA)
/* Check for system faults:
1. If overcurrent detected at DP sensor, remove power from sensor
2. If overcurrent detected at AP sensor, remove power from sensor
*/
if ((PORTC & 0x10) != 0x10)
DP_OFF;
if ((PORTD & 0x01) != 0x01)
AP_OFF;
/* If USB cable connected, check USB regulated and processor
supplies shutting down all supplies if fault(s) detected. If
READ_ADC is deselected by user, remove power from sensors */
if ((PORTC & 0x08) != 0x08)
{
if ((PORTC & 0x07) != 0x07)
{
SUPPLY_OFF;
DP_OFF;
AP_OFF;
USB_OFF;
PROCESSOR_OFF;
psuState = USB_FAULT;
}
else if ((PORTB & 0x04) == 0x04)
{
SUPPLY_OFF;
DP_OFF;
AP_OFF;
delay_ms(50);
USB_OFF;
psuState = USB_COMMS;
}
}
else
psuState = SHUTDOWN;
break;
case LOG_FAULT: // Fault trap - escape only by removing user cover
break;
case USB_FAULT: // Fault trap - escape only by removing USB cable
break;
case SHUTDOWN:
// Switch off 1s timer and sounder
disable_interrupts(GLOBAL);
disable_interrupts(INT_TIMER1);
setup_timer_1(T1_DISABLED);
SOUNDER_OFF;
delay_ms(3500); // Delay > power down time of processor
psuState = START; // Wait 3.5s and restart process loop
break;
} // End switch
}
}
/*-------------------------End of main()--------------------------------------*/
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sun Apr 01, 2012 9:51 am |
|
|
Seriously, you need to learn how to debug problems. You trim away code, till you only have the parts causing the problem. You then have a minimum program showing he problem that can be posted if you still can't see it for yourself.
As it is, I doubt if anyone will even bother to look at a program this large, especially given that it is still incomplete. Things like the state values are not defined, etc. etc...
Separately, forget simulators. The only one that is reasonably 'worthwhile', is MPLAB, and this is slow, and still doen't handle quite a few peripherals. Get an ICE, or ICD.
Most likely thing is that the interrupt is being immediately called, and then cleared. _Read the data sheet_. What can happen when you change the interrupt edge?.
Best Wishes
Last edited by Ttelmah on Sun Apr 01, 2012 9:58 am; edited 1 time in total |
|
|
neilelph
Joined: 01 Apr 2012 Posts: 5 Location: Edinburgh
|
|
Posted: Sun Apr 01, 2012 9:58 am |
|
|
Seriously, if you've nothing helpful to post, then don't bother.
I only posted the whole code, because it was requested. I have been through various debug procedures and not found the problem. I have limited tools as I work for a tight fisted company.
I didn't just post on here as soon as I had a problem, I only post so I can get a second pair of eyes looking at the problem that may be staring me in the face.
But thanks for your comments. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Sun Apr 01, 2012 11:25 am |
|
|
The MPLAB simulator he is speaking of is absolutely FREE. I would suggest the one with MPLAB 8.whatever IDE versus MPLAB X IDE, since MPLAB X is very new and still buggy.
Try the following program:
Code: |
volatile unsigned int8 ext_isr_triggered = 0;
#INT_EXT
void ext_isr(void)
{
ext_isr_triggered = 1;
}
void main(){
unsigned int8 status = 0;
//if you need to drive any lines to turn on hardware, do it here
//but don't use TRIS junk. Stick to output_high(PIN_B8) and
//output_low(PIN_B8) or similar.
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(TRUE){
if(ext_isr_triggered){
status = 1;
//you can do output stuff here if you need to see output
}
}
}
|
If you need to do any output driving to turn on other hardware, do it where I specified to start with. See if the interrupt triggers. If it doesn't, try moving your hardware initialization to just below the enable_interrupt() calls and try again. Again, please don't use TRIS settings and such. Stick to CCS routines for this test.
Let us know what happens |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sun Apr 01, 2012 12:23 pm |
|
|
It was 'requested', because what you posted originally was not enough to give even the faintest hint of what your problem might be. However Temtronic, like me, assumed you would have at least started to try to actually debug the problem yourself, and would therefore have a trimmed set of code.
Your postings are a bit like a person having trouble getting a car to track straight, who posts a picture of the steering wheel, and says "I can't get this to work", and then when asked to show some more information, instead of showing perhaps some details of the steering arms and geometry, instead shows a photo of the car....
My comment about looking in the data sheet, at what happens when you change the interrupt edge, still applies.
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Help |
Posted: Sun Apr 01, 2012 2:45 pm |
|
|
I fully endorse what the other guys are saying.
Read the CCS forum guide.
Amongst other things, it advises you to post MINIMUM compilable code which allows us to diagnose your problem.
I, for one, will not touch simulator issues, nor plough my way through mountains of irrelevant code.
The advice you get here is freely given by experts who normally charge $$$$/££££ for their services.
You need to make it easy for them to help you.
Mike |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Apr 02, 2012 1:13 am |
|
|
I agree with Ttelmah that the problem might be in how you enable the interrupt, an essential instruction is missing here. Check the datasheet.
A similar problem lures with the Timer1 interrupt enabling.
I normally don't like long code postings but nonetheless had a quick look at it:
1) I don't see code for initializing the variables. Perhaps this is done in the missing declaration code? At least loopCount2 has a problem as it is never reset again.
2) Code: | setup_spi(SPI_SS_DISABLED); | Disable SPI by giving the setup_spi call the parameter FALSE. Your code is invalid and might cause problems (an error in the CCS setup wizard created this line).
3) Code: | RC5: /MEM_FULL INPUT
...
/* Has ATMEL uC flagged memory as not full? If so, enable
sensor supply and logging */
if ((PORTC & 0x20) != 0x20)
{
...
LOGGING_ON;
| According to your comments the RC5 input being 0 indicates the memory to be full, but your implementation is inverted. Which is correct?
4) Code: | /* Check battery and logic supply levels */
if ((PORTC & 0x07) == 0x07)
{
/* Has ATMEL uC flagged memory as not full? If so, enable
sensor supply and logging */
if ((PORTC & 0x20) != 0x20)
{
....
LOGGING_ON;
psuState = LOG;
}
else
{
...
psuState = DELAY_WAIT;
}
loopCount2++;
}
else
{
PROCESSOR_OFF;
psuState = LOG_FAULT;
}
break; | This doesn't look right to me. When power is incorrect you now set LOG_FAULT. But when logging memory is full you don't set an error code? Seems mixed up.
Even worse mixed up as you now only start the delay_wait code in case there is a logging memory problem. Feels like a rewrite is required here.
As a generic remark: I'm missing a lot of debugging code. How did you do your debugging? You say the int_ext doesn't work but when I look at your code I have a strong feeling the int_ext is never enabled. This is so easy to check, even when you don't have an ICD tool. Just add little extra debugging code that activates an output in several parts of your code and connect an LED to these outputs.
I strongly recommend to you and your employer to buy an In Circuit Debugging tool. Even a cheap PicKit3 would suffice for a mere €35. As you are living in the UK that equals to less than 1 hour development time. |
|
|
neilelph
Joined: 01 Apr 2012 Posts: 5 Location: Edinburgh
|
|
Posted: Mon Apr 02, 2012 2:03 am |
|
|
Apologies if I seemed over-sensitive to criticism, but I was only responding to a request that I perhaps took too literally! I also clearly state the tools I have used in my first post (free or otherwise).
I accept constructive criticism openly, but there are ways of doing it without jumping down someones throat. I am also a professional who designs digital and analogue electronics along with developing firmware and software, but I can't apologise for not being an expert in all!
I thank you all for your feedback and input - it is very much appreciated. I also provide help to others on forums occasionally, so it's not a one way street with me.
Thanks again. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Mon Apr 02, 2012 3:03 am |
|
|
Many of those who provide most of the help here are also professionals, myself included. I can only speak for myself: I post in my tea and lunch breaks. I do it because I want to help.
I have limited time. I cannot read through and understand more than a few tens of lines of code in an example. I can't wade through lines and lines of application specific code that's (probably) irrelevant to the problem.
What we want, and can deal with, is a complete but very short code example that will compile and show the problem. That means we expect the poster to have isolated the problem to a significant extent. It also gets round the problem of IP issues by not requiring the posting of proprietary code. It also means the "helped" needs to do some of the work. In return we give freely of our own time to help as much as we can. Sometimes though that's not good enough, as we can't know everything.
Only if that fails is it useful to cast the net wider.
That though is what we'd like to happen. What actually usually happens is that someone posts a very vague "my stuff doesn't work", then when requested for more information, gives a nearly complete info dump of their code, often missing out vital information such as fuse set-up, PIC type, compiler version and so on and expects us to work out what their problem is without even telling us the symptoms. Oh yes, and they've generally not bothered to read the CCS manual, which to be fair is not always correct or updated to reflect the current state of the tool set.
Do you still wonder why some of us are a more than a little twitchy and touchy about what goes on here?
RF Developer.
PS: My tea is now cold and I've been moaned at to get my timesheets for March done.... |
|
|
neilelph
Joined: 01 Apr 2012 Posts: 5 Location: Edinburgh
|
|
Posted: Mon Apr 02, 2012 3:22 am |
|
|
Again, I apologise for any offence caused.
However, as mentioned already I have done all the work in debugging to the point where I needed help and my first post shows this. I only posted the whole code in response to a request. I don't expect anyone else to do my work for me.
I fully understand where you are coming from with regards to time etc., but I also work under pressured conditions and tight timelines but I don't shoot people down in flames for doing what was requested of them (albeit I accept I misinterpreted what was being asked).
Again, I thank and respect all comments and help provided, and have no bones to grind with anyone.
Thanks again. |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Mon Jul 02, 2012 9:47 am |
|
|
From your post...
Code: |
#INT_EXT
void ext_isr(void)
{
if (psuState == DELAY_WAIT)
{
disable_interrupts(INT_EXT); // Disable future interrupts on RB0
PROCESSOR_ON; // Enable logic supplies
psuState = DELAY_BOOT; // Move to next stage
}
return;
|
Maybe its a copy/paste issue... but your missing a bracket ..."}"
Also, what are you returning? its void...
and is the right syntax not:
Just my two cents...
EDIT... i just realized this is an old thread... i side tracked... sorry...
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
|
|
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
|