Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
UART传输完成后,如何使Arduino切换变量?_Arduino_Arduino Uno_Uart_Usart_Isr - Fatal编程技术网

UART传输完成后,如何使Arduino切换变量?

UART传输完成后,如何使Arduino切换变量?,arduino,arduino-uno,uart,usart,isr,Arduino,Arduino Uno,Uart,Usart,Isr,我想执行一些代码(比如切换标志变量), 完成串口发送的UART传输后。写入(buf,len) 我做了几件事都没有成功。有人能提出最好的办法吗 谢谢。 m根据Arduino存储库上的代码(您可以看到它,特别是硬件序列、流和打印类),串行类函数没有阻塞:它们使用内部缓冲区,由ISR清空 看看代码,有两种可能 第一个也是最简单的方法是使用内置函数。此函数等待uC完成发送,并仅在发送完所有内容后返回 第二种方法是模仿刷新行为;如果您不希望程序停止(即执行其他任务),只需检查电路板是否正在发送数据,这就是

我想执行一些代码(比如切换标志变量), 完成串口发送的UART传输后。写入(buf,len)

我做了几件事都没有成功。有人能提出最好的办法吗

谢谢。
m

根据Arduino存储库上的代码(您可以看到它,特别是
硬件序列
打印
类),
串行
类函数没有阻塞:它们使用内部缓冲区,由ISR清空

看看代码,有两种可能

第一个也是最简单的方法是使用内置函数。此函数等待uC完成发送,并仅在发送完所有内容后返回

第二种方法是模仿刷新行为;如果您不希望程序停止(即执行其他任务),只需检查电路板是否正在发送数据,这就是您需要的。如果设置了位UDRIE0(寄存器UCSR0B),则库的队列中有一些数据。但是,在最后,您必须等待发送最后一个字节,因此您还必须检查位TXC0(寄存器UCSR0A)是否已清除

为了实现和测试这一点,我编写了以下简单程序:

unsigned long thisMillis = -1;
unsigned long lastMillis = -1;
char mybuffer[256];

void setup() {
  Serial.begin(9600);
}
bool isSending()
{
  return bit_is_set(UCSR0B, UDRIE0) || bit_is_clear(UCSR0A, TXC0);
}
void loop() {
  int printed = snprintf(mybuffer, 256, "time: %lu\r\n", millis());
  Serial.write(mybuffer, printed);
  // Just enable ONE of the following methods
  //Serial.flush();
  //while(isSending());
  lastMillis = millis();
}
然后我模拟了一下

当flush和while都未启用时,电路板将缓冲字符串,直到它可以。然后,当缓冲区变满时,开始等待一些字符消失,然后再填充它。因此,我们将在最初的几毫秒内看到大量字符串,然后是几乎等距的字符串(当缓冲区已满时)。实际上,程序的输出是这样的:

time: 0
time: 0
time: 1
time: 1
time: 1
time: 1
time: 2
time: 2
time: 7
time: 17
time: 27
但是,当我们取消对Serial.flush函数的注释时,循环将等待所有数据从uC中取出,然后再次循环。这会导致从一开始就有相等间隔的时间戳,事实上这就是输出

time: 0
time: 9
time: 19
time: 29
time: 39
time: 51
启用while循环时,行为完全相同:

time: 0
time: 9
time: 19
time: 29
time: 39
time: 51
因此,总结一下:如果您想等待主板发送,只需使用
Serial.flush()
;如果您只想测试它(然后执行其他操作),请测试上面报告的两个位。

尝试以下操作:

void setup() {

Serial.begin(9600);

 _SFR_BYTE(UCSR0B) |= _BV(TXCIE0);        //Enable TXCIE0 interrupts

Serial.print("When UART finishes to send this text, it will call the routine ISR(USART0_TX_vect) ");

}


void loop() {


}

  ISR(USART1_TX_vect)
{
//do whatever you want, but as quick as you can.

}

非常感谢frarugi!我使用了您描述的技术(检查UDRIE0),但没有TXC0部分-感谢您指出这一点。尽管如此,我还是想知道我是否可以让ISR将字节推送到USART,以触发一个计时器,例如,当它没有更多的数据要处理时。。。这样,主代码和“多任务处理”将变得更加优雅和高效(如果我没有弄错的话)。好吧,如果你不检查TXC0位,你就不会等待所有数据发送,因为最后一个字节仍在传输中。至于你所要求的,它可能有一些优势,但我认为它们非常有限。如果您真的需要它在传输结束的那一刻触发某些东西,您可以获取硬件序列的源代码(请参阅检索它的链接,或在arduino文件夹中)并对其进行修改(您只需重命名它,然后只修改ISR,其余代码保持不变)。这就是开源的力量!:)