1/2MHz signal Pin Change interrupt

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello!

I am having some troubles with reading a 500,000Hz signal (a complete cycle is 2us) in the atmega328 (same with the atmega168). I am having a variable increment by one every time there is a change in the pin, but the timing is not precise... Well, here is the code:

volatile int32_t timer;
void setup() {
   EICRA |= (1<<ISC10);
   EIMSK |= (1<<INT1);
   EIFR |= (1<<INTF1);
sei();
}

ISR(INT1_vect)
{
timer++;
}

When the variable timer reaches a number higher than 100,000 I have a LED that should be turned on.. It should take 1 second, but it is taking forever to turn on the LED (more than 1 min).

Is the signal too fast for the MCU?

Thanks in advance

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Is the signal too fast for the MCU?

LOL--it takes a minimum of 12 AVR clocks to service an ISR. GCC ain't known for skinny ISRs either; let's be conservative and add another dozen clocks. Now you have a 32-bit increment of an SRAM variable--at least another dozen.

You are trying to process a complete interrupt every 1us. Your AVR would need to run at a minimum of 40MHz. You do the rest.

You say "pin change" but the setup code appears to be for "external interrupt".

Yes, AVRs running at a few MHz can handle your need. You use timer1 and the T1 pin. Look in the datasheet to see whether the timer prescaler applies--if so it is easy. If not, you have to count some number like 50000 or 65536 and then count the rest after the compare match/overflow.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, the signal is too fast, not for the MCU but for your approach. You are trying to respond to an interrupt and do 32-bit math every 2us. Have you done a cycle count for that?

To count a 500 kHz signal use a 16-bit timer configured to count pulses on an external pin. You can then create larger counts (larger than 16-bits) by using the counter overflow to generate an interrupt, and use that interrupt to count 65k chunks of count in software.

If you wanted to count exactly 100,000 counts, you could set a compare register to generate an interrupt at 50,000 counts, and on every 2nd interrupt you've got 100,000.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

(Why would one bother with both edges counting many repetitions of a fast signal?)

There still could be latency getting to the ISR, but that could be addressed by using the OC pin for the indicator.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmmm--can you use the asynchronous mode of timer2, and then the prescaler can be used? At /1024 it would give a lot of range.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just for the record, here is that ISR - a nasty little beast!

ISR(INT1_vect) 
{ 
  b8:	1f 92       	push	r1
  ba:	0f 92       	push	r0
  bc:	0f b6       	in	r0, 0x3f	; 63
  be:	0f 92       	push	r0
  c0:	11 24       	eor	r1, r1
  c2:	8f 93       	push	r24
  c4:	9f 93       	push	r25
  c6:	af 93       	push	r26
  c8:	bf 93       	push	r27
timer++; 
  ca:	80 91 06 01 	lds	r24, 0x0106
  ce:	90 91 07 01 	lds	r25, 0x0107
  d2:	a0 91 08 01 	lds	r26, 0x0108
  d6:	b0 91 09 01 	lds	r27, 0x0109
  da:	01 96       	adiw	r24, 0x01	; 1
  dc:	a1 1d       	adc	r26, r1
  de:	b1 1d       	adc	r27, r1
  e0:	80 93 06 01 	sts	0x0106, r24
  e4:	90 93 07 01 	sts	0x0107, r25
  e8:	a0 93 08 01 	sts	0x0108, r26
  ec:	b0 93 09 01 	sts	0x0109, r27
}
  f0:	bf 91       	pop	r27
  f2:	af 91       	pop	r26
  f4:	9f 91       	pop	r25
  f6:	8f 91       	pop	r24
  f8:	0f 90       	pop	r0
  fa:	0f be       	out	0x3f, r0	; 63
  fc:	0f 90       	pop	r0
  fe:	1f 90       	pop	r1
 100:	18 95       	reti

If I set PC to the start of that and break on the RETI then the simulator counts 51 cyles.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yep, very instructive. And all the while those hardware counters are sitting there, feeling unloved, wanting to help. :)