Io 由于以下原因,UART中断禁用Sam3X8E/Arduino上的I/O

Io 由于以下原因,UART中断禁用Sam3X8E/Arduino上的I/O,io,arduino,interrupt,uart,atsam3x,Io,Arduino,Interrupt,Uart,Atsam3x,我开始在一些需要UART的项目工作中使用Arduino Due,我对UART中断和I/O之间的交互感到困惑 我的第一段代码是一个设置UART的小程序,在接收到TXBE中断时通过加载传输缓冲区连续发送数据。我将UART输出连接到示波器上,并将另一个I/O引脚设置为通用输出,该输出将翻转状态,因此在传输缓冲区重新加载时用于触发示波器。问题是我看到了UART数据,看起来不错,但I/O并没有翻转。此时,我的loop()例程为空,因此我设置了另一个输出端口,并在loop()中切换其状态,作为一个健全性检查

我开始在一些需要UART的项目工作中使用Arduino Due,我对UART中断和I/O之间的交互感到困惑

我的第一段代码是一个设置UART的小程序,在接收到TXBE中断时通过加载传输缓冲区连续发送数据。我将UART输出连接到示波器上,并将另一个I/O引脚设置为通用输出,该输出将翻转状态,因此在传输缓冲区重新加载时用于触发示波器。问题是我看到了UART数据,看起来不错,但I/O并没有翻转。此时,我的
loop()
例程为空,因此我设置了另一个输出端口,并在
loop()
中切换其状态,作为一个健全性检查。除了UART,仍然没有输出

以下是我最终得到的代码:

uint32_t tempo; // 32-bit temporary variable
boolean flag = true;

void UART_Handler(void) {
  REG_UART_THR = 0x6DL; // load data into the transmit buffer
  if (flag) {
    REG_PIOD_SODR = 0x02L; // drive PD1 high
    flag = false;
  } else {
    REG_PIOD_CODR = 0x02L; // drive PD1 low
    flag = true;
  }
}

void setup() {
  // set up the UART I/O
  REG_PIOA_IDR = 0x0300L; // disable interrupts on PA8 and PA9
  tempo = REG_PIOA_ABSR; // get the current settings of the AB select register
  REG_PIOA_ABSR = tempo & 0xFFFFFCFF; // set PA8 and PA9 to peripheral A control
  REG_PIOA_PDR = 0x0300L; // disable parallel I/O for PA8 and PA9
  NVIC_EnableIRQ(UART_IRQn); // enable UART interrupts in NVIC
  // now set up the UART
  tempo = REG_PMC_PCSR0; // get the current settings of the peripheral clock register 0
  REG_PMC_PCER0 = tempo | 0x0100L; // enable the UART clocks
  REG_UART_CR = 0x0CL; // reset UART receiver and transmitter
  REG_UART_MR = 0x0800L; // set to normal outputs with no parity
  REG_UART_BRGR = 0x89L; // baud rate set to 38400
  REG_UART_IDR = 0x1FBL; // disable all UART interrupts
  REG_UART_IER = 0x0800L; // enable TXBUFE interrupt
  REG_UART_CR = 0x50L; // enable UART receiver and transmitter
  // set up the debug outputs
  REG_PIOD_IDR = 0x03L; // disable interrupts on PD0 and PD1
  REG_PIOD_PER = 0x03L; // enable parallel I/O for PD0 & PD1
  REG_PIOD_OER = 0x03L; // set PD0 & PD1 output enabled
  REG_PIOD_CODR = 0x03L; // drive PD0 & PD1 low
}

void loop() // run over and over
{
   REG_PIOD_SODR = 0x01L; // drive PD0 high
   delay(1);
   REG_PIOD_CODR = 0x01L; // drive PD0 low 
   delay(1);
}
可以在上查看范围输出(这里没有足够的声誉来发布图像!)

在盯着事情看了一段时间后,我没有得到任何洞察,我通过注释掉行
REG\u UART\u IER=0x0800L;/,禁用了TXBUFE中断启用TXBUFE中断
,然后可以看到端口D1的切换,但显然没有UART输出(请参阅)。这两者似乎是相互排斥的,如果这是真的,那就太傻了。我肯定我遗漏了什么,但我看不到或找不到它是什么

我已经阅读了SAM3X8E数据表,看看是否有明显的遗漏,如果有,我看不到。我也做过我认为相关的网络搜索,但没有找到解决方案。我还尝试在端口A和端口D的两个输出上使用通用输出,并在两个Arduino Due板上进行了尝试,结果相似


有人知道我做错了什么吗?提前谢谢。

好吧,我已经弄清了这个问题的真相。不确定这是不是最好的答案,但这是一个解决方案。它的长短是为了避免TXBE中断。如果我使用TXEMPTY中断,它就可以正常工作

Atmel数据表第168页上的一行(原文如此)“中断可以进入挂起状态,即使它被禁用”,因此我想知道TXBE的问题是否是因为我没有在ISR之前或甚至在ISR内部清除挂起的中断,所以我添加了
NVIC_ClearPendingIRQ(UART_IRQn)在ISR开始时,也是在我启用TXBE中断之前,但(错误)行为没有改变

TXEMPTY的操作(对我来说)仍然有点奇怪,因为似乎中断是由传输移位寄存器为空而不是变空时生成的。如果在未加载传输缓冲区的情况下启用中断,将立即得到中断。有些人可能喜欢这种“自启动”行为,但我不喜欢。我正在编写发送例程,以便在变送器加载第一个要发送的字节之前,TXEMPTY中断不会启用

基于Arduino论坛上的这篇帖子:我认为美国空军也有类似的问题


希望这能对其他人有所帮助。

我刚刚意识到问题根源的真正错误可能是什么。UART中断寄存器描述在传输缓冲区为空的情况下讨论TXBUFE位,因此我的假设是,这是告诉我何时可以将另一个字节放入传输保持寄存器的位。然而,UART状态寄存器描述表明TXBUFE位是“来自发射机PDC信道的缓冲区满信号”后者对这个钻头的作用有完全不同的看法。根据UART状态寄存器描述,我需要查看的位是TXRDY位

如何调用UART_处理程序?似乎一旦启用UART,就会调用中断处理程序,并将第一个值加载到传输缓冲区。然后,每次数据传输到传输移位寄存器时,TXBE中断调用处理程序。这是我的假设,因为我没有在初始化中明确加载变送器,尽管如此,它还是开始发送数据。