Interrupt quesion

Hi Guys,

I am trying to trigger an interrupt on an ATMega328P chip which is running on a breadboard on an external clock. I can oscillate a pin via code and play around with it, so I know that my circuit is running ok.

I am trying to get an interrupt going, but it is not responding to the input transition (low to high, high to low, etc...).

volatile int sync = 0;    // Global

void interruptSync()      // The ISR
{
  sync = 1;
}

attachInterrupt(digitalPinToInterrupt(1),interruptSync,FALLING);   // Attaching the interrupt via setup

while(sync == 0)    // Endless loop inside the main loop until the interrupt is triggered
{
}

Ideally I want to be triggering the interrupt from pin 15 on the IC (PB1), but I am possibly querying the wrong pin (as far as the Arduino SDK goes) due to the confusion on the Arduino diagrams, in the link below (I'm not sure how to insert the picture itself on these forums yet).

8e3a980f0f964cc539b4cbbba2654bb660db6f52_arduino-uno-pinout-diagram.png (1089×779) (prismic.io)

Any advice on how to setup an interrupt on PB1 (or any pin really) would be greatly appreciated. I have tried a bunch of different pin values attempting to decipher the layout, but so far no luck.

Many thanks in advance.

1 Like

Post all your code.

Thanks for using code tags.

If I remember well only pin 2 and 3 have individual interrupts ISR's all other pins are grouped per port meaning the ISR is activated if one of the pins on a port is triggered. In the ISR your need to look for which pin it was that activated the ISR.
look for PCINT0, PCINT1, PCINT2 they describe the interrupt per port mechanism

I hope this helps you in the right direction.

1 Like
// The C file

extern "C"
{
  void init();
  void loop();
}

volatile int sync = 0;    // Global

void interruptSync()      // The ISR
{
  sync = 1;

}

void setup()
{
  init();

  //attachInterrupt(digitalPinToInterrupt(1),interruptSync,FALLING);   // Attaching the interrupt via setup

  while(sync == 0)    // Endless loop inside the main loop until the interrupt is triggered
  {
  }

  detachInterrupt(digitalPinToInterrupt(1));

  noInterrupts();
}


// The ASM file
#define OUTPUT	0
#define INPUT	1


.global init
.global loop


init:

				SBI		DDRB, OUTPUT	; PB0 is an output
				CBI		DDRB, INPUT		; PB1 is an input
				SBI		PORTB, OUTPUT   ; Set OUTPUT pin to high
				RET



loop:

here:
				SBIS	PINB, 1			; Skip next instruction if Port B pin 1 is high
				RJMP  here;

				SBI		PORTB, OUTPUT   ; Clear output pin
				
				CBI		PORTB, OUTPUT   ; Set OUTPUT pin
				RJMP	loop

So, essentially I have an 1 MHz waveform going in to PB1 and am just toggling PB0 high and low in response to that.

  • Clock 8 MHz crystal
  • 1 MHz to PB1 (1 MHz is divided from the 8 MHz ATMega clock - so is 100% in sync)
  • PB0 driving high or low depending on what it sees on PB1

^^ This part is ok (if you remove the interrupt code), but the wave position varies on power up depending on that startup conditions. When it is running it is stable but the initial offset varies when power is applied.

Blue is the 1 MHz input on PB1 and Yellow is the output on PB0.

The reason for the interrupt was to hopefully set the initial starting position of the yellow waveform in stone rather than the three or so clock cycle drift in initial starting point.

Thanks for the tip. Pins 2 & 3 with reference to the ATMega chip or the Arduino board though?

I think I may even need to dig a little deeper. The IC I am using is a completely new chip. I had to set the fuse bits a few days back to get it to recognise the external clock. It seems that I might need to do additional work to it to recognise interrupts perhaps.

The reason behind my thinking is that I am getting no jitter when firing the output at maximum speed. Normally I have to add NoInterrupts() to my C code to get rid of the jitter. But it is completely stable without that function.

Your ISR won't be able to keep up if you interrupt the Atmega328p at 1 MHz

Even if it's only four clock cycles?

Edit - Actually, I only want to interrupt if for the first clock cycle to get it in sync. At the moment my brute force method of testing a pin, gives an error of a few clock cycles either side.

The 'theory' is for the ATMega to sample the 1MHz input at start up (via interrupt) by the clock edge. Once it goes to the ISR and returns immediately back and then disable interrupts, I should be at a known point on the clock cycle. From there I can add a couple of NOP's to get me exactly where I want to be.

From there I'll have 8 clock cycles to do the main loop (which includes the relative jump back I know).

That's the theory anyway...

Pretty much what I am after is to ensure that my main loop (of only a few clock cycles) starts here-

Untitled-1

Or on the tailing edge - doesn't really matter.

At this point at initial power on, the loop may execute at slightly different points. The point is rock solid when running, but just varies slightly on every power up, because of this;

here:
	SBIS	PINB, 1
	RJMP  here

Because that's three clock cycles, the variance can be up to three clock cycles on power up and anywhere on the high edge of the input clock.

You need to study the data sheet, the ATmega328 chip pinout and the Arduino pin mapping.

This line will not work, as it attempts to assign Arduino digital pin 1 (TX, PD1) to the interrupt routine.

attachInterrupt(digitalPinToInterrupt(1),interruptSync,FALLING);   // Attaching the interrupt via setup

External interrupts 0 and 1 are the most flexible, and they are assigned to Arduino Uno digital pins 2 and 3, which correspond to ATmega328 port pins PD2 and PD3.

1 Like

Thanks, I have been trying to make sense of the datasheet, it's quite overwhelming. Every snippet of information is highly appreciated. :grinning:

I keep this handy on my Desktop. It works for ATmega328 too.

Ard_PinMap

1 Like

I did have the input hooked to pin 4 (INT0) earlier today in my testing, but it became confusing as to what to reference that pin as via code as the pins in the Arduino SDK are labeled differently.

I'm guessing Pin 2 in this case for INT0?

attachInterrupt(digitalPinToInterrupt(2),interruptSync,FALLING); 

I'll go back and try now. :grinning:

Don't waste your time guessing, look it up in the reference guide on line.

https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

LOL, doing my best not to guess. I've only been using Arduino's for a week or two now. :rofl:

Completely new territory for me.

For problems with the Arduino IDE (integrated development environment). NOT for problems with your project.

So, what's your Arduino IDE question?

How to make a simple interrupt work, using the Arduino IDE. :wink:

So, no question about the IDE.

This would be a good place to start.

Well, as I said. I am new to this forum. So please take that kindly in to consideration. :slightly_smiling_face:

Feel free to point me in the right direction so next time I do not re-commit my heinous crime.

Or as a Moderator you could move the topic in to the correct sub forum. :wink:

Done.