Created Mon, 19 Mar 2012 14:02:21 +0000 by carlosfandango
Mon, 19 Mar 2012 14:02:21 +0000
I'm trying to utilise the timer 2 (or other timer) interrupts on the Uno32 or Max32 so that I can manage background tasks. I've seen the code on the chipkit wiki and a number of other sites, similar to the following:
/* For AVR */ #if defined(AVR) #include <avr/io.h> #endif
/* For PIC32 / #if defined(PIC32MX) #include <p32xxxx.h> / this gives all the CPU/hardware definitions / #include <plib.h> / this gives the i/o definitions */ #endif
#define LED 6
boolean led_state; unsigned long currentMillis; unsigned long printt; int int_calls;
void setup() {
pinMode(LED,OUTPUT);
OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0xFFFF); ConfigIntTimer2((T2_INT_ON | T2_INT_PRIOR_3));
Serial.begin(38400); }
void loop() {
currentMillis = millis();
if (currentMillis >= printt) { Serial.print("Interrupts : "); Serial.println(int_calls); printt = currentMillis + 1000; }
}
#ifdef __cplusplus extern "C" { #endif
void __ISR(_TIMER_2_VECTOR,IPL3AUTO) int_handler(void) { mT2ClearIntFlag(); // Clear timer 2 interrupt flag if (led_state) { digitalWrite(LED, LOW); led_state = false; } else { digitalWrite(LED, HIGH); led_state = true; } int_calls++; }
#ifdef __cplusplus } #endif
This code compiles fine but does not work as expected. int_calls gets incremented to 1 and does not advance, meaning that the interrupt gets called once only. The led output pin does not change state.
I've tried various hacks to get this working, but no joy so far.
Since other users seem to be implementing similar code and finding that it executes correctly, I'm wondering what it is that I have not understood. Can someone tell me what I'm doing wrong?
Thanks
CF
Mon, 19 Mar 2012 19:50:36 +0000
The following works for me....
volatile int value;
setup and loop as you have given ... only interrupt code modified. It looks to me that the rload value might not be calcuated properly, so probably the led is blinking too fast ?
#ifdef __cplusplus extern "C" { #endif
void __ISR(_TIMER_2_VECTOR,IPL3AUTO) comms_handler(void) { static int count; mT2ClearIntFlag(); // Clear interrupt flag count++; if(count > 1000 ) } #ifdef __cplusplus } #endif
Mon, 19 Mar 2012 21:03:35 +0000
OK, thanks very much for the reply - I'll try this when I'm next to the board (at work!). Sure hope it does the trick...
I would have thought that the pin would toggle, however - and I have a 'scope on that, so I should see it, even if it's not possible to see the LED (which isn't connected to the pin anyway :-)
CF
Tue, 20 Mar 2012 14:07:36 +0000
The following works for me.... volatile int value; setup and loop as you have given ... only interrupt code modified. It looks to me that the rload value might not be calcuated properly, so probably the led is blinking too fast ? #ifdef __cplusplus extern "C" } #ifdef __cplusplus } #endif
I discovered what the problem is. If I execute a digitalWrite() inside my interrupt routine, it kills it, and no further interrupts are executed. I tried this same code on two Uno32's and two Max32's and the same problem is exhibited on all. So I don't really know what's going on... any answers, I'd be glad to hear them!
CF
Tue, 20 Mar 2012 15:50:09 +0000
The code which I have given, has worked on my MX32 UNO board !!!. Did you try my code ditto? I am toggling the IO in the ISR only.
Is the variable led_state toggles and still the pin does not toggle?
you may try make the pin toggle slowly as I have tried ,
make the varibale led_state volatile..
make int_calls as volatile and print in loop(), avoid using millis() and see if the results are good .. you may use delay(1000) if you do not want too much output from print.
as far as I know, the digitalWrite is made atomic and safe to use in ISR as per the posting at [url]http://www.chipkit.org/forum/viewtopic.php?f=6&t=654&hilit=digitalWrite+in+ISR[/url]
I am eager to know your results. In case if you need I can give you the full working sketch.
Regards, KN
Tue, 20 Mar 2012 16:18:22 +0000
Hmm, well it is odd I agree and I certainly appreciate your help. I've tried everything that I can, as soon as I uncomment the digitalWrite line in the code, the interrupt stops working (specifically it's called once only, and then stops). I thought maybe I had missed out a #include or something like that but it seems not.
It wouldn't matter how fast the pin toggled, as I am observing it with a scope - I would still be able to confirm whether it was operational or not.
I have confirmed that the Uno32 and Max32 exhibit the same behaviour. The only thing I can say about the Uno32 is that the boards that I have were part of a batch that was shipped with an incorrect bootloader, so I had to reflash this with the correct one from the Digilent site. But that shouldn't have any bearing on this issue....!
The only reason I am timing my print statements is to ensure that all parts of the code are looping continuously, at this stage I don't have any need to do this, but I will later. To be honest I find the loop() function a bit weird after programming in C and C++ for so long!
Indeed I would be interested in trying your complete sketch to see what's different, if anything.
CF
Tue, 20 Mar 2012 17:23:33 +0000
#if defined(__PIC32MX__)
#include <p32xxxx.h> /* this gives all the CPU/hardware definitions */
#include <plib.h> /* this gives the i/o definitions */
#endif
#define LED 13
volatile int value = 0;
int prev_val, curr_val;
void setup() {
Serial.begin(9600);
OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0xFFFFFF);
ConfigIntTimer2((T2_INT_ON | T2_INT_PRIOR_3));
}
void loop()
{
curr_val = value;
if(prev_val != curr_val)
{
Serial.println(prev_val);
Serial.println( curr_val);
prev_val = curr_val;
// Serial.println("value togled");
//digitalWrite(LED, value);
}
}
#ifdef __cplusplus
extern "C" {
#endif
void __ISR(_TIMER_2_VECTOR,IPL3AUTO) comms_handler(void)
{
static int count;
mT2ClearIntFlag(); // Clear interrupt flag
count++;
if(count > 1000 )
{
value = value ^ 1 ;
digitalWrite(LED, value);
Serial.println("value togled");
count = 0;
}
}
#ifdef __cplusplus
}
#endif
Wed, 21 Mar 2012 13:37:03 +0000
Hmm.. well, you sketch worked fine so I put a bit more effort in and discovered what the problem is. digitalWrite() does not function in the interrupt service routine on pins that support pwm (analog out). This may be correct and already known, or possibly it's to do with a jumper on the board - I haven't checked, I just assumed all digital pins would behave similarly. I've been trying adjacent pins especially 5 and 6 and these are pwm's.
So thanks for the help, your sketch made it quite clear that the ISR was functional.
CF
Wed, 21 Mar 2012 14:14:56 +0000
Hi, Glad to know that it works.. Regards, KN