2016-10-18 3 views
1

Я пытаюсь создать простую процедуру обслуживания прерываний Arduino, которая использует в ней указатель функции, чтобы он мог эффективно быть изменен с помощью функции main(). Ниже приведен мой код.Как использовать указатель функции внутри процедуры обработки прерываний 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); 
} 

Светодиоды подключены к контактам 3 и 4. Они должны поочередно загораться в течение 10 миллисекунд каждый. Однако при мигании этой программы на Arduino я вижу, что каждый светодиод загорается примерно на 2 секунды. Может ли кто-нибудь сказать мне, почему?

ответ

0

Как обычно, вы должны использовать модификатор volatile для переменной, используемой как в ISR, так и в остальном коде.

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 Как вы компилируете и загружаете? –

Смежные вопросы