Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Timer 如何在arduino中断服务例程中使用函数指针修改ISR?_Timer_Arduino_Interrupt_Interrupt Handling - Fatal编程技术网

Timer 如何在arduino中断服务例程中使用函数指针修改ISR?

Timer 如何在arduino中断服务例程中使用函数指针修改ISR?,timer,arduino,interrupt,interrupt-handling,Timer,Arduino,Interrupt,Interrupt Handling,我正试图设计一个简单的Arduino中断服务例程,在其中使用函数指针,以便可以有效地从main()函数修改它。下面是我的代码 #include <stdio.h> #include <util/delay.h> #include "gpio.h" // "gpio.h" is my own library that contains the // definitions of digital_write, d

我正试图设计一个简单的Arduino中断服务例程,在其中使用函数指针,以便可以有效地从
main()
函数修改它。下面是我的代码

#include <stdio.h>
#include <util/delay.h>
#include "gpio.h"        // "gpio.h" is my own library that contains the
                         // definitions of digital_write, digital_read,
                         // pin_mode, analog_write, etc.
                         // It also configures all the timer/counter
                         // circuits to operate in fast-PWM mode
                         // with an undivided input clock signal.
                         // This library has been tested.

/* Two interrupt service routines */

void INT_1(void);
void INT_2(void);

/* Function pointer to choose any one of the above defined ISRs */

void (* interrupt)(void) = NULL;

/* main */

int main(void) {

    pin_mode(3, OUTPUT);
    pin_mode(4, OUTPUT);

    cli();
    TIMSK0 |= _BV(TOIE0);     // Enable Timer0 overflow interrupt
    sei();

    while(1)
    {
        interrupt = INT_1;    // For 10 ms, INT_1 executes on interrupt
        _delay_ms(10);

        interrupt = INT_2;    // For next 10 ms, INT_2 executes on interrupt
        _delay_ms(10);
    }

    return 0;
}

ISR(TIMER0_OVF_vect) {        // Execute the function pointed to by
                              // "interrupt" on every overflow on timer 0
    if(interrupt != NULL)
    {
        interrupt();
    }
}

void INT_1(void) {

    digital_write(3, LOW);
    digital_write(4, HIGH);
}

void INT_2(void) {

    digital_write(3, HIGH);
    digital_write(4, LOW);
}
#包括
#包括
#include“gpio.h”/“gpio.h”是我自己的库,其中包含
//数字写入、数字读取、,
//引脚模式、模拟写入等。
//它还配置所有计时器/计数器
//在快速PWM模式下工作的电路
//具有不可分割的输入时钟信号。
//这个库已经过测试。
/*两个中断服务程序*/
void INT_1(void);
void INT_2(void);
/*函数指针,用于选择上述任何一个定义的ISR*/
无效(*中断)(无效)=无效;
/*主要*/
内部主(空){
引脚_模式(3,输出);
引脚_模式(4,输出);
cli();
TIMSK0 |=_BV(TOIE0);//启用定时器0溢出中断
sei();
而(1)
{
中断=INT_1;//在10毫秒内,INT_1在中断时执行
_延迟时间(10);
interrupt=INT_2;//对于接下来的10毫秒,INT_2在中断时执行
_延迟时间(10);
}
返回0;
}
ISR(TIMER0_OVF_vect){//执行
//计时器0上的每个溢出都有“中断”
如果(中断!=NULL)
{
中断();
}
}
void INT_1(void){
数字写入(3,低);
数字写入(4,高);
}
void INT_2(void){
数字写入(3,高);
数字写入(4,低);
}

LED连接到引脚3和引脚4。这些灯应交替点亮10毫秒。然而,在Arduino上闪烁该程序时,我看到每个LED亮起约2秒钟。谁能告诉我为什么

通常,您必须对
ISR
和代码其余部分中使用的变量使用
volatile
修饰符

void(*易失性中断)(void)=NULL应该可以做到这一点

我的代码(在PlatformIO中编译)


我无法在代码中看到您的计时器值。默认值为0,在256次计数(8位)后将溢出,然后您的计时器ISR将得到服务,并且根据您的函数指针中断值,它将跳转到相应的函数(INT0或INT1)也许每次它都会跳转到同一个函数,而你不会按照你的期望得到结果

@KennethGoveas它对我有效:没有volatile它不起作用,有volatile它起作用。已测试。8您是如何编译和上载的?在clasic Arduino IDE中。然而,在纯C(PlatformIO CLI)中,它也可以工作。我将在答案中更新代码。请注意,您必须将赋值设置为
中断
全局变量原子(例如,通过
cli();…sei();
)!否则,您会遇到竞争条件,ISR可能会尝试跳转到损坏/无效的函数指针。
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>

/* Two interrupt service routines */

void INT_1(void);
void INT_2(void);

/* Function pointer to choose any one of the above defined ISRs */

void (* volatile interrupt)(void) = NULL;

/* main */

int main(void) {
    DDRB = _BV(PB5);

    TCCR0B = _BV(CS00);      // enable timer, overflow every 256 clock cycles
    TIMSK0 = _BV(TOIE0);     // Enable Timer0 overflow interrupt
    sei();

    while(1)
    {
        cli();
        interrupt = INT_1;    // For 10 ms, INT_1 executes on interrupt
        sei();
        _delay_ms(10);

        cli();
        interrupt = INT_2;    // For next 10 ms, INT_2 executes on interrupt
        sei();
        _delay_ms(10);
    }
    return 0;
}

ISR(TIMER0_OVF_vect) {        // Execute the function pointed to by
                              // "interrupt" on every overflow on timer 0
    if(interrupt != NULL)
    {
        interrupt();
    }
}

void INT_1(void) {
    PORTB |= _BV(PB5);
}

void INT_2(void) {
    PORTB &= ~_BV(PB5);
}
[Fri Oct 21 19:29:40 2016] Processing uno (platform: atmelavr, board: uno)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Collected 0 compatible libraries
Looking for dependencies...
Project does not have dependencies
avr-gcc -o .pioenvs/uno/src/main.o -c -std=gnu11 -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DPLATFORMIO=030100 -DARDUINO_ARCH_AVR -DARDUINO_AVR_UNO -Isrc src/main.c
avr-gcc -o .pioenvs/uno/firmware.elf -Os -mmcu=atmega328p -Wl,--gc-sections,--relax .pioenvs/uno/src/main.o -L.pioenvs/uno -Wl,--start-group -lm -Wl,--end-group
Checking program size .pioenvs/uno/firmware.elf
text       data     bss     dec     hex filename
296           0       2     298     12a .pioenvs/uno/firmware.elf
avr-objcopy -O ihex -R .eeprom .pioenvs/uno/firmware.elf .pioenvs/uno/firmware.hex