Hi, sorry if this has been covered elsewhere, my searches haven't come up with anything.
In my Ardiono Leonardo I want to set up to use the analog comparator interrupt and I can't see how to get the address of my service routine into the interrupt vector. The Arduino Reference only deals with external interrupts and so far I haven't been able to find any discussion of this anywhere. I thought I should be able to use a pointer to achieve it but if so I can't find the right syntax. Any help would be appreciated.
Yes, the ISR keyword declares an interrupt handler. The best place to learn IMO is the source code, WInterrupts.c IIRC has the source for the external into handlers.
Well, I've looked into WInterrupts.c and also avr/interrupt.h but I'm afraid I find the code almost completely impenetrable so I should be very grateful if either of you guys could elaborate a little. I regret that my brain is wired completely differently to the people who write this stuff.
If I declare a handler using the code posted by AWOL how come it doesn't require both the vector name and the handler name?
Do you mean that is the declaration of the interrupt service routine and should be followed by the code of the routine? I wrongly assumed it would be analogous to the attachInterrupt() function.
Anyway I used the ISR() keyword to create the routine after having initialised the DIDR1 and ACSR registers in the setup() function. Note that the body of the routine has previously worked using attachInterrupt() to link it to INT0 on port D pin 0:-
// Initialise interrupts on the analog comparator
DIDR1 = 0x01; // disable digital input buffer on AIN0 (PE6)
ACSR = 0x08; // enable interrupt on analog comparator output toggle
If I've got it right this should connect port E pin 6, AIN0, to the analog comparator AIN+ input and the internal bandgap to AIN- with interrupts enabled on the output toggling. However as soon as a signal comes into the AIN0 pin the sketch stops responding to all inputs and the board won't accept a new upload without a power cycle (or possibly a manual reset, I haven't tried that yet). I presume this is because the comparator interrupt disables global interrupts and for some reason they are not getting enabled on return from interrupt. The body of the routine is very simple at the moment:-
ISR(ANA_COMP_vect)
{
if (PORTB & MOTOR_POS) ++posn;
else if (PORTB & MOTOR_NEG) --posn;
}
Ok. I realised I hadn't #included avr/interrupt.h. However even after correcting that it still locks up as soon as the signal changes on the comparator input. I've even tried explicitly re-enabling global interrupts at the end of the service routine but have since discovered, by putting a Serial.print() into the routine, that it doesn't actually go there (or maybe that won't work with interrupts disabled?). In the absence of trace facilities in the Arduino IDE it's difficult to see where I go from here. Do I need to #include any other headers?
You should never use serial.print etc from with in an ISR. Serial requires the use of interrupts but an ISR on the Arduino IDE turns off all interrupts the net result is that serial will block untill data has been sent but it can;t send data because interrupts are turned off.
Hi Mark,
Yes I realised that as I was posting which is why I queried if it would work. I just need a way to check if the interrupt is being correctly vectored into my service routine. I wonder if I explicitly re-enable global interrupts with sei(); or interrupts(); before the serial print whether that would work, just to let me do that check. Otherwise I'm completely stuck.
I wonder if I explicitly re-enable global interrupts with sei(); or interrupts(); before the serial print whether that would work, just to let me do that check. Otherwise I'm completely stuck.
Sounds like a very bad idea. How about updating a global volatile variable inside the ISR and checking whether it has changed outside the ISR ? If it changed then the ISR was triggered and the correct routine was run.
Hi UKHeliBob,
Thanks for the reply but I'm afraid that won't work as the whole thing is locking up, apparently as soon as the comparator interrupts. In fact the main loop prints out the value of the volatile variable 'posn' at the rate of about once a second. This stops as soon as the interrupt occurs.
If you've read through the earlier posts you'll have seen that I was somewhat confused about how to implement a service routine for an internal interrupt. Since then I've re-read through interrupt.h and have started to make some sense of it. As far as I can see what I have done ought to work but it doesn't and I've pretty much run out of ideas to try.
The entire sketch worked (and still does) using the external interrupt INT0 with the signal applied to Port D pin 0 and enabled with attachInterrupt(); The only changes have been to take out attachInterrupt(), initialise the comparator control register as shown in the code I posted, replace the service routine declaration with ISR() as also shown in the code and move the signal onto Port E pin 6.
I'm beginning to suspect that the interrupt is vectoring into the middle of nowhere and placing a serial print in the routine is the only way I can think of to check this. Do you know if the vector I'm using is correct? It would be useful if you, or anyone else reading this, knows where to look for documentation on these topics as trying to make sense of headers and sources, especially with multiple embedded headers and all the conditional compilation statements, is something I find quite challenging.
Well it clearly doesn't work so it would be helpful to have a clue as to why not. I've established that it's not vectoring to the ISR but having used your suggestion and now having looked through iom8.h I'm completely baffled as to what I'm doing wrong.
Well it clearly doesn't work so it would be helpful to have a clue as to why not
No, as I've already said, the code you posted does not, and cannot, compile, so it cannot run, so it cannot possibly work.
If you don't want to post your code, that's fine, but I gave up guessing games when my kids were old enough to read on long car journeys, and I'm not about to start again.
Ok, I've found the problem. After trawling through the header files again it finally led me to iom32u4.h where the vector is shown as ANALOG_COMP_vect not ANA_COMP_vect as you originally suggested. So thanks for leading me up the garden path.
I was/am not asking you to indulge in guessing games. If I wasn't providing the info you needed you only had to tell me what you wanted. It's all very well saying "it cannot compile" but you must know that is of no use whatsoever if you do not give your reasons.
If you thought I was wasting your time it would have been preferable to ignore my posts rather than reply in the peremptory tone you have used.
Notice the question mark?
That's the pointer to the garden path.
When I posted, I was sitting on a train, posting from my phone.
My phone doesn't have the whole of the AVR includes on it.
In fact, it doesn't have any.
I was working from memory, and for that, I apologise, but I assumed you were sitting in front of a machine that was equipped with all the appropriate include files, and that I was at least pointing you in the right direction.
Now, had you posted your code (note, all of it, not a snippet), I might have been inclined to copy and paste it into an IDE when I got back, but you didn't, and I couldn't be bothered to write it for myself and try it.
It was a snippet, so it couldn't possibly compile - that is obvious to all.
I may have pointed this out.
I may have pointed this out twice.
That's one of the reasons we ask you to post all your code.
If you thought I was wasting your time it would have been preferable to ignore my posts rather than reply in the peremptory tone you have used.
Please be assured, your posts will be resolutely ignored in future.