jip*_*pie 3 c++ embedded arduino
以下程序的目的是定期输出串行数据帧.周期由定时中断定义,每秒一次.
该代码适用于Arduino IDE版本0022,但在1.0上我无法使其正常工作.使用定时器例程并maxFrameLength设置为0x40或更高时,控制器会锁定.使用0x39或更低时,程序继续运行(由闪烁的LED指示).
这里出了什么问题,为什么?这是一个错误吗?难道我做错了什么?
我正在使用http://code.google.com/p/arduino-timerone/downloads/detail?name=TimerOne-v9.zip作为Mega1280上的计时器例程.
#include "TimerOne.h"
#define LED 13
#define maxFrameLength 0x40
boolean stateLED = true;
byte frame[ maxFrameLength ];
void sendFrame() {
digitalWrite( LED , stateLED );
stateLED = !stateLED;
Serial.write( frame, maxFrameLength ); // ptr + bytes to send
}
void setup() {
pinMode( LED , OUTPUT );
Timer1.initialize( 1000000 ); // initialize timer1 with 1 second period
Timer1.attachInterrupt( sendFrame );
Serial.begin( 9600 );
};
void loop() {
};
Run Code Online (Sandbox Code Playgroud)
有许多问题可能会或可能不会导致问题,但在任何情况下都应该修复.这些评论是一般性的; 我并不熟悉Arduino或其库.
Serial.write()在中断处理程序(ISR)中发出调用几乎肯定是不合适的.如果Serial对象是中断驱动的,它将具有相关的缓冲区.如果该缓冲区不足以获取所有数据,则该函数可能会阻塞,这在中断处理程序中是否定的.而且,如果定时器中断的优先级高于串行中断,则会导致Serial.write()块死锁.0x40(64字节)似乎是串行输出的可能缓冲区大小,因此这可能是主要原因.如果您可以增加可能使其工作的缓冲区大小,但在ISR中执行可能的阻塞操作仍然是一个坏主意.
即使串行输出被轮询而不是中断驱动,你的中断处理程序将花费相当长的时间,这也是一个坏主意,但在这种情况下可能不是问题,但在9600,n,8,1,64个字符将需要67清除发送寄存器的毫秒数.
stateLED并且frame是共享变量(在中断和主要上下文之间),因此应该声明为volatile.
在您的片段中未显示frame更新的方式和位置,但由于中断将异步发生,因此任何更新frame都应位于关键部分 - 至少禁用timer1中断.
更新
根据AH的回复,我下载了源代码并看了一下.Serial是HardwareSerial\ arduino-1.0\hardware\arduino\cores\arduino\hardwareSerial.cpp/.h中定义的类的静态对象.发送缓冲区长度确实是64字节,HardwareSerial::write()如果缓冲区已满,则该函数会"忙等待".您需要修改并重新构建源以扩展缓冲区或添加非阻塞版本write().
然而,这肯定是锁定的原因 - 缓冲区永远不会为空,因为在timer1中断运行时无法处理发送中断.