0

我开始使用 Arduino Due 进行一些需要 UART 的项目工作,并且对 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);
}

范围输出可以在http://www.iwanczuk.com/temp/scope1.png查看(这里没有足够的声誉来发布图像!)。

在盯着事情看了一会儿并且没有得到任何见解之后,我通过注释掉该行来禁用 TXBUFE 中断,REG_UART_IER = 0x0800L; // enable TXBUFE interrupt然后可以看到 PortD1 的切换,但显然没有 UART 输出(参见http://www.iwanczuk.com/temp/scope2.png)。似乎两者是相互排斥的,如果这是真的,那将是愚蠢的。我确定我错过了一些东西,但我看不到或找不到它是什么。

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

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

4

2 回答 2

0

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

于 2015-02-11T13:06:53.937 回答
0

好吧,我已经深入了解了这个问题。不确定这是最好的答案,但它是一个解决方案。它的长短是避免 TXBE 中断。如果我使用 TXEMPTY 中断代替它工作正常。

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

TXEMPTY 的操作仍然有点奇怪(对我来说),因为看起来中断是由发送移位寄存器为空产生的,而不是在它空时产生的。如果您在未加载发送缓冲区的情况下启用中断,您将立即获得中断。有些人可能喜欢这种“self=priming”的行为,但它不适合我。我正在编写我的发送例程,以便在发送器加载了要发送的第一个字节之前不启用 TXEMPTY 中断。

根据 Arduino 论坛上的这篇文章:http: //forum.arduino.cc/index.php? topic=186388.0我认为 USART 也有类似的问题。

希望这对其他人有帮助。

于 2015-02-11T12:31:48.847 回答