Confusion about none working Interrupt 2 on a ATMega644P/1284P

Bit of advice from the wise please,

I want to be able to use the external interrupt pins on a 40 pin PDIP ATMega such as the 1284p / 644p/pa uController in a standalone project.

What I have is three inputs wired individuality to digital 10, 11 and 2 (INT0(16), INT1(17) and INT2(3)). For the sake of simplicity we'll call them simple tactile buttons (GND when pushed) with pullup resistors (10k) going to VCC.

I should point out at before going further that this works on a Arduino Mega 2560 board ok in both the hardware set up and software - hence my confusion.

For some reason the ISR are being called for INT0 and INT1 but not on INT2. I have wired the test circuit that goes into INT2 into INT0 and the hardware circuit is working as in it triggers on INT0 as expected but the same circuit going to INT2 does not even trigger ( i put a temporary digitalWrite(27,HIGH) to a C.Ltd LED at the beginning of the ISR as a visual que)

I have the attachInterupt(ISR,FALLING) for all int calls .

I also tested that I can use the PIN D2 as a output and input in the usual manner and it works ok. I even tried a different ATMega Chip just in case.

Is there a fuse setting that needs to set so that INT2 works? Mine are currently set to Low=FF, HIGH=DA Ext=FF (note: I need JTAG OFF as I am using PORTC pins Digital 18,19,20 and 21). I see in the data sheet there is a Clock output on PORTB1 but surely that is not what I need turned on is it?

Many thanks in advance.

Steve
PS I am uploading via an ISP if that is relevant

Well normally you'd probably get asked to post your code, but if it were me, I'd write a minimal sketch to exercise a single interrupt, prove to myself that it works on INT0 and INT1 and then try it on INT2.

Yep Jack, That's what I did - it's a bit room 101 but here is the code

const int MotorLED1 = A5;
const int MotorLED2 = A7;
const int MotorLED3 = 13;

void setup()
{
pinMode(MotorLED1,OUTPUT);
pinMode(MotorLED2,OUTPUT);
pinMode(MotorLED3,OUTPUT);

attachInterrupt(0, Motor1, FALLING);
attachInterrupt(1, Motor2, FALLING);
attachInterrupt(2, Motor3, FALLING);
}

void loop()
{
delay (300);
digitalWrite(MotorLED1, LOW);
digitalWrite(MotorLED2, LOW);
digitalWrite(MotorLED3, LOW);
}

void Motor1()
{
    digitalWrite(MotorLED1, HIGH);
}
void Motor2()
{
    digitalWrite(MotorLED2, HIGH);
}
void Motor3()
{
    digitalWrite(MotorLED3, HIGH);
}

I'm just getting started with the 1284P myself but I do happen to have one right here, let me play a bit with it.

Which core are you using?

Sorry Jack, do you mean what chip core? - it's a ATMega644p and a ATMega644PA have 3 of the later direct from Atmel and 1 of the former from a h/ware supplier which was meant to be pre bootloaded but wasn't as confirmed by AVRdude - not that that matters now I have a h/ware ISP and to be honest it runs better without the bootloader haha!

Thanks for having a look / play really appreciate it. boards.txt is attached

Regards

Steve

boards.txt (1.24 KB)

Hi Steve,

By core I meant the Arduino "core" code ... I'm using maniacbug's mighty-1284p core.

Anyway the following sketch works fine for INT0, 1 or 2. I'm just using a 1Hz square wave from an RTC as the signal to the interrupt pin, and toggling an LED.

const uint8_t ledPin = 7;

void setup(void)
{
    pinMode(ledPin, OUTPUT);
    attachInterrupt(2, intHandler, FALLING);
}

void intHandler(void)
{
    static bool ledState;
    
    digitalWrite(ledPin, ledState = !ledState);
}

void loop(void)
{
}

Hi Jack,

umm Yes your (neater) code does a similar thing to the rubbish one I wrote :), I can't use that core as I have a USBtinyISP and I am not sure it will work with the 644 and can't get my Atmel Dragon working as Studio won't run at present (Atmel technical are working out why for me at the moment).

The core I do have is a modified sanduino, which seems old news from what I can see on the net. but at least it works ???? well maybe not as we might be finding out. Out of the box I had to edit it to use the 644P properly as it left the Jtag enabled and I need those pins.

Might it be a fuse setting?

Steve

I get mixed results using the USBtinyISP with the 1284P. Sometimes it seems to work, but I usually get an error message as well. Others here have reported better results.

BUT that's with a 1284P, if you have a 644P I would definitely give it a try.

I've used both the USBtiny and a cheap $5 Asian E-bay usbasp programmer to burn bootloaders and sketches to both 644P and 1284P chips. It always works but the USBtiny often reports a verify error upon completion but it appears to be a 'false positive' as the resulting bootloader and fuses always end up being fine. The USBasp has never reported an error. And I'm pretty sure I even used a arduino board running the arduinoISP sketch to burn a bootloader to a 1284P with no problems seen.

Lefty

And I'm pretty sure I even used a arduino board running the arduinoISP sketch to burn a bootloader to a 1284P with no problems seen.

I do this regularly with success.

Well ISP aside, I'm gonna try the USBtiny with Jacks suggestion. Might just see if the fuse settings change anything, but I have downloaded the files mentioned.

Those that have used ISP successfully.. have you run sketches that use all three INTs without problems like Jack did? if you have what (as I know it now - thanks Jack) Core do/did you use (link if pos.) I am not keen on the sandy thing as it seems a bit hackerish rather than proven main stream ( I am inventing new words as well now) :).

I have looked though the pins_xxx.h files and other trying to see if there is something obvious to change but to no avail.

I would like to try and keep this in the Arduino spirit as learning another language for this project would not be time constructive, but I fully intend to switch over on other projects (current firmware is some (streamlined) 46k so pretty large by most sketch standards.) but I do like the arduino IDE because of its basic and non-techy approach to C - its really good at making our hobby popular and the more peeps that use it the better as it seems to NOT carry a frightening inroad than other languages do., but it is fair to say once you get into this stuff you do get drawn in, so well done Arduino for bring a seemingly difficult subject to the masses. - oww sorry advert over. :slight_smile:

Thanks guys, Having not tried the suggestions yet I am no further forward as of tonight (UK time) but have some options to explore in the morning which is encouraging.

Steve

Well I have tried one or two things and put in an order for some ATMega1284P's (+ a couple of 2560s) the reason being there seems far more support for these MCUs than the 644PA.

Anyways. after much poking and prodding around I eventually gave up on INT2 and added in PinChangeInt and to my surprise this was really easy and gave me back the other interrupts I could have lived without but were useful (originally this project was written for a 2560 MEGA and I really need it to go stand alone). So in case others need it; the bits I added to make it work are:

#define NO_PORTC_PINCHANGES // to indicate that port c will not be used for pin change interrupts
#define NO_PORTD_PINCHANGES // to indicate that port d will not be used for pin change interrupts
#include <PinChangeInt.h> // you need to download the repository and install in libraries folder
..........
const int selectPin = 2;                      //Joystick and Rotary encoder press button
.........
void setup() 
{
.........
  pinMode(selectPin, INPUT); digitalWrite(selectPin, HIGH);
  PCintPort::attachInterrupt(selectPin, toggle, FALLING);
.........
}
void loop() { /*some code*/ }
void toggle() { /*ISR code*/ }

And that solved it.. Ok so maybe it's not the most elegant way but Jack sparked a thought in something he wrote and I had a light bulb moment as I sat with my first cup of coffee this morning.

I would still like to know how to get this working using attachInterrupt though - just for the sake of knowing :slight_smile:

Thanks guys. It's great to have so many great engineers around to bark ideas at.

Steve

Steve, glad to hear you made some progress. I'll add a couple things. First, the 644PA is basically the same chip as the 1284P, just with less memory. They share the same datasheet. I think the 644PA lacks the second 16-bit timer (Timer/Counter3) but I think that's the only difference. So given that, code that works on one should work on the other. (The price difference between the two is less than a dollar, so unless I was building dozens or hundreds of copies of something, I'd just stick with the 1284P.)

Second, I hardly ever use attachInterrupt(), reason being it is quite straightforward to set the registers directly. This code is equivalent to what I posted above. It just uses INT2 to toggle an LED. Maybe give that approach a try.

const uint8_t ledPin = 7;

void setup(void)
{
    pinMode(ledPin, OUTPUT);
    EICRA = _BV(ISC21);          //external interrupt on falling edge
    EIFR = _BV(INTF2);           //clear the interrupt flag (setting ISCnn can cause an interrupt)
    EIMSK = _BV(INT2);           //enable external interrupt
}

void loop(void)
{
}

ISR(INT2_vect)
{
    static bool ledState;
    digitalWrite(ledPin, ledState = !ledState);
}

Hi Jack,

Yes you are absolutely right. there seems more support for the 1284p than it's smaller brother. I just saw the 644p advertised on a suppliers site advertised as a go between the 328 and 2560 so thought I would give it a try. but in hindsight should have opted to get some 1284's which I have now done.

After reading the datasheets (most of which went over my head) I realised that INT2 is not enabled by default and you need to set the port up. even then it only responds to a changing edge not a rising or falling like INT0 and INT1 (Can't find the web pages where I read that :frowning: )

I'll certainly have a go with your code once I get Studio working lol - Atmel support sent me a patch today but that won't even install so the issue is on giong. I want to get more into this type of programming as I can see some advantages - like it doesn't limit you to using Arduino IDE (which is still a great tool.

Thanks for your help and it has been great chatting with you.

All the Best Steve

even then it only responds to a changing edge not a rising or falling like INT0 and INT1 (Can't find the web pages where I read that )

13.2.1 EICRA – External Interrupt Control Register A

The External Interrupts 2 - 0 are activated by the external pins INT2:0 if the SREG I-flag and the corresponding interrupt mask in the EIMSK is set. The level and edges on the external pins that activate the interrupts are defined in Table 13-1.
Table 13-1
ISCn1 ISCn0 Description
0 0 The low level of INTn generates an interrupt request
0 1 Any edge of INTn generates asynchronously an interrupt request
1 0 The falling edge of INTn generates asynchronously an interrupt request
1 1 The rising edge of INTn generates asynchronously an interrupt request

Note: 1. n = 2, 1 or 0.
When changing the ISCn1/ISCn0 bits, the interrupt must be disabled by clearing its Interrupt Enable bit in the EIMSK Register. Otherwise an interrupt can occur when the bits are changed.

There is nothing to indicate INT2 is any different than INT1 or INT0

Well that's what I was expecting with INT2 then I read a couple of reports on-line that said otherwise. which to be honest I thought was rather daft, why would a MCU man. bother doing that. Certainly I found nothing in the data sheet to allow me to confirm this and surely that should be the only source of accurate data.

Proper Port addressing seems to be the best and most robust way of doing this task. and with the knowledge gained from this exercise and help given here that is certainly the only way I will be handling them in future.

1studio1:
I'll certainly have a go with your code once I get Studio working lol - Atmel support sent me a patch today but that won't even install so the issue is on giong. I want to get more into this type of programming as I can see some advantages - like it doesn't limit you to using Arduino IDE (which is still a great tool.

What kind of limitations are you running up against with the IDE? I wrote that code in the Arduino IDE, and it runs just fine there. Both use the GCC compiler, so moving source code between the two rarely requires anything more than copy and paste.

Sorry Jack,

My mistake - I thought is was not an IDE sketch. Yes just tried it and it works flawlessly Thanks - I am going to have a play with tonight as it looks interesting (or am I just a bit of a sado :slight_smile: )

TY Steve

Hi Jack ,im using maniacbug's mighty-1284p core but none of my interrupts work if I use the attachInterrupt method however, configuring the interrupts directly from the registers and get rid of Winterrupts.c works them!(however creating unexpected uC behaviour!) , how to make interrupts work normlly?

EDIT
im compiling it as 'Original Mighty 1284p 8MHz' bcz I have a INTROSC based system!