我正在尝试设计一个简单的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);
}
LED连接到引脚3和4.这些应交替亮起,每个10毫秒。但是,在将此程序闪存到Arduino上时,我发现每个LED亮起大约2秒钟。谁能告诉我为什么?
答案 0 :(得分:1)
像往常一样,您必须对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)
{
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
答案 1 :(得分:0)
我无法在代码中看到您的计时器值,它将默认为0,并在256个计数(8位)后溢出,然后将服务您的计时器ISR,具体取决于您的函数指针Interrupt的值跳转到相应的功能(INT0或INT1),可能每次都会跳转到相同的功能,您将无法获得预期的结果。