2016-10-18 10 views
1

私は、効果的にmain()関数から変更できるように、関数ポインタを使用する単純なArduino割り込みサービスルーチンを設計しようとしています。以下は私のコードです。arduino割り込みサービスルーチン内で関数ポインタを使用してISRを変更する方法は?

#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); 
} 

LEDは、ピン3,4に交互に接続されます。これらは、それぞれ10ミリ秒間交互に点灯します。しかし、このプログラムをArduinoに点滅させると、各LEDが約2秒間点灯することがわかります。なぜ誰かが私に言うことができますか?

答えて

0

いつものようにISRと残りのコードで使用される変数にはvolatile修飾語を使用する必要があります。

void (* volatile interrupt)(void) = NULL;はすべきことです。

私のコード(PlatformIOでコンパイル)

#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) 
    { 
     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) { 
    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 
+1

は動作しませんでした。すべてはまったく同じです –

+0

@KennethGoveasそれは私のために働く:揮発性がなければ、それは動作していない、揮発性と動作している。テスト済み。 – KIIV

+0

8どのようにコンパイルしてアップロードしていますか? –

関連する問題