我正在编写一个小型测试程序,尝试在ISR中执行serial.write()
后跟serial.read()。该代码最终将用于提示外部GSM屏蔽定期发送短信。
ISR(TIMER2_OVF_vect) {
Serial.println("AT+CMGS=\"0123456789\""); // Tell Sim900 To prepare sms to number 01...
while(Serial.read()!='>'); // Wait for Sim900 to respond
Serial.print("A text message"); // the SMS body
Serial.write(0x1A); //Confirm send instruction
Serial.write(0x0D);
Serial.write(0x0A);
}
}
经过大量测试后我发现,ISR中的Serial.read()
无法读取实时串行提示,而只会读取在ISR被触发之前缓冲的任何输入。
有什么方法吗?
我找到的唯一解决方案是将此代码放在主loop()
中。但我想使用定时器中断发送短信。
谢谢
答案 0 :(得分:1)
您需要将代码放在loop()
中,但使用IF:
float toBeSent = interval;
loop() {
if (millis() > toBeSent) {
Send();
toBeSent = milli() + interval;
}
}
间隔是您的发送间隔(以毫秒为单位)。
答案 1 :(得分:0)
前一段时间我遇到了类似的问题,我通过使用Arduino SoftwareSerial库而不是基于硬件的Serial.read
来解决这个问题。
使用SoftwareSerial有一些开销,你一次只能读一个端口,所以我把它留给那些更了解Arduino平台的人,告诉你这是不是一个好主意,但是这个库的好处是你可以在ISR中使用它。
要使用SoftwareSerial库,请在草图顶部添加以下两行代码,记住要将rx_pin和tx_pin与要使用的相应引脚值重新对齐:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(rx_pin, tx_pin);
然后用Serial
(或您为SoftwareSerial实例选择的任何名称)替换整个草图中的关键字mySerial
。
使用SoftwareSerial时要记住的一件重要事情是,您只能使用Arduino上的某些引脚,因此请先阅读documentation。
答案 2 :(得分:0)
如果您想要危险地生活,您可以在ISR中启用中断并使用标志来防止重新进入。
int flag=0;
ISR(TIMER2_OVF_vect) {
flag = 1
if (flag){return;}
sei();
Serial.println("AT+CMGS=\"0123456789\""); // Tell Sim900 To prepare sms to number 01...
while(Serial.read()!='>'); // Wait for Sim900 to respond
Serial.print("A text message"); // the SMS body
Serial.write(0x1A); //Confirm send instruction
Serial.write(0x0D);
Serial.write(0x0A);
}
flag = 0;
}