I would like to "perform a given operation only while there is an interrupt, and not when there is no interrupt".
(1) Each time there is an interrupt, pulse++ is executed and stored in now1.
(2) Compare the value of now1 with the last time, judge that there is an interrupt if there is a change, and perform the prescribed operation in a loop. (In this case, the LED is blinked.)
#define LED1 (13)
/*pulsecounter*/
volatile unsigned int pulse1 = 0;
volatile unsigned int now ;
volatile unsigned int now0 ;
volatile unsigned int now1 ;
volatile unsigned int old ;
void setup(){
DDRB &= ~_BV(0); //interrupt_port
}
void loop(){
now0 = now1;
if(old ! = pulse1){
PORTB ^= _BV(5);
}
old = pulse1;
if (old == now0){
PORTB &= ~_BV(5) ;
}
}
ISR (PCINT0_vect){
old = now0;
pulse1++;
now1 = pulse1;
}
Q1) The prescribed operation is successful when there is an interrupt. However, the operation cannot be stopped when there is no interrupt. (will not the LED is turned off.)
Q2) I tried to get the value of pulse at regular intervals by millis or Timer2 and compare them, but the acquired value is kept and the comparison does not work.
Q3) I would like to know how to determine in real time whether there is or is not an interruption.
'state' is an int, which is two bytes. That makes it a critical section which you have provided no protection for. You have to disable interrupts, make a copy, and enable interrupts again. It's also an obscure name, doesn't tell you what it is, like for example 'pulseReceived'.
noInterrupts();
int state = pulseReceived;
interrupts();
if (state == 1) {
Otherwise, you should use a bool type which uses only one byte. It's what you should use for a flag anyway.
On a more obscure point, it's not a good idea to use /* */ for one line comments because those kind of comments don't nest. If you have to comment out multiple lines and one includes this, you have a problem.
If you want to toggle the LED, use '^' not '|'. It's probably dim because the ISR is being called rapidly by the unknown device you have connected to it.
Only by telling us what your "high speed pulse" is, can we help you with that aspect of your problem.
It is detecting a high speed pulse, so it had to be an interrupt to detect it.
Probably not. On an AVR based processor, this polling loop has a much faster response than an interrupt, but the processor can't do anything else while waiting:
while ( (PIND&(1<<2)) == 0); //wait for high on PortD, pin 2
Feel free to do so, but the response lag of that wait loop is 1 to 3 machine cycles (62.5 ns on a 16 MHz Arduino).
Machine code (from Compiler Explorer AVR-gcc):
.L2:
sbis 0x9,2
rjmp .L2
The interrupt has an unpredictable latency, depending on what instruction is currently being executed, then calls the ISR, which must save all registers potentially affected by the ISR, before anything else can be accomplished. Many machine cycles.
Look up "interrupt response latency" to learn more.
Yes, it's better to protect all ISR variables regardless of type. Then nothing will break if you change them, and it won't be vulnerable to compiler implementation details.
→The high speed pulse is 1~2us per pulse and is received every 25us.
→I found out that I should do an interrupt disable in the loop and hold the value once.
By holding, state=1 was achieved when the interrupt occurred.
However, it did not return to state=0 when there was no interrupt and I am trying to figure out how to do that again.
→The interrupt operation did not work.
But very interesting about PinChangeInterrupt.h. Thank you very much.
It's not only what @jremington describes in post #15.
When the interrupt occurs, registers are saved; from memory, there are around 60 to 80 machine cycles (I might be totally wrong though with that number) to achieve that. And at the end of the ISR, they need to be restored as well.
In assembly you are free to do what you want, in C/C++ the compiler decides.