UART中断禁用Sam3X8E / Arduino的I / O.

时间:2015-02-09 16:05:06

标签: io arduino interrupt uart atsam3x

我开始使用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查看范围输出(此处没有足够的信誉发布图片!)。

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

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

任何人都有任何想法我可能做错了什么?提前谢谢。

2 个答案:

答案 0 :(得分:0)

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

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

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

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

希望这会有所帮助。

答案 1 :(得分:0)

我刚刚意识到可能是我问题根源的真正错误。 UART中断寄存器描述在发送缓冲区空的上下文中讨论TXBUFE位,因此我的假设是这个位告诉我何时可以将另一个字节放入发送保持寄存器。然而,UART状态寄存器描述表明TXBUFE位是"来自发送器PDC通道的缓冲器满信号"。后者对这一点的作用完全不同。根据UART状态寄存器的描述,我需要看的是TXRDY位!