【问题标题】:UARTs & RegistersUART 和寄存器
【发布时间】:2018-12-10 22:22:25
【问题描述】:

所以我对此很陌生,并试图了解寄存器和 UART,并获得了以下代码来学习。

#include <stdint.h>

typedef volatile struct {
    uint32_t DR;
    uint32_t RSR_ECR;
    uint8_t reserved1[0x10];
    const uint32_t FR;
    uint8_t reserved2[0x4];
    uint32_t LPR;
    uint32_t IBRD;
    uint32_t FBRD;
    uint32_t LCR_H;
    uint32_t CR;
    uint32_t IFLS;
    uint32_t IMSC;
    const uint32_t RIS;
    const uint32_t MIS;
    uint32_t ICR;
    uint32_t DMACR;
} pl011_T;

enum {
    RXFE = 0x10,
    TXFF = 0x20,
};

pl011_T * const UART0 = (pl011_T *)0x101f1000;
pl011_T * const UART1 = (pl011_T *)0x101f2000;
pl011_T * const UART2 = (pl011_T *)0x101f3000;

static inline char upperchar(char c) {
    if((c >= 'a') && (c <= 'z')) {
        return c - 'a' + 'A';
    } else {
        return c;
    }
}

static void uart_echo(pl011_T *uart) {
    if ((uart->FR & RXFE) == 0) {
        while(uart->FR & TXFF);
        uart->DR = upperchar(uart->DR);
    }
}

void c_entry() {
    for(;;) {
        uart_echo(UART0);
        uart_echo(UART1);
        uart_echo(UART2);
    }
}

我只是想知道是否有人可以解释 pl011 DRFR 寄存器如何通过相关的 UART 外设发送和接收数据。 任何帮助都将不胜感激。

【问题讨论】:

  • 如果没有 UART 的数据表,该代码很难理解。看看那个文档,应该可以解释很多。
  • 如果您能告诉我们您使用的是哪种处理器,这也将非常有帮助。我只看到,这个嵌入式 MCU 有 3 个 UART。 pl011_T 就是这个结构,它由这三个地址上的硬件寄存器组成,从 0x101F1000、0x101F2000 和 0x10F3000 开始。 FR 似乎是一个标志寄存器,其中设置了 TX 和 RX 标志 RXFE 和 TXFF。 DR是接收和发送的数据寄存器,不是吗?请告诉我们您使用哪种硬件,有 MCU 的数据表和手册......
  • 您到底有什么不明白的地方?你知道 DR 和 FR 寄存器实际上是硬件的一部分吗?这些寄存器的行为由硬件中的晶体管定义。当硬件检测到您正在写入或读取与这些寄存器关联的地址时,它可以做一些特殊的事情。代码中的 typedef 只是帮助您使用程序员友好的名称写入正确的 UART 寄存器地址;它并没有真正定义寄存器。

标签: c embedded uart


【解决方案1】:

这里有一些关于这个 UART 的不错的文档 - http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183g/DDI0183G_uart_pl011_r1p5_trm.pdf

此程序的工作方式受 UART 是否处于FIFO 模式的影响。我还没有阅读足够多的文档来知道哪个是默认状态。 Tx 和 Rx 的操作根据该模式略有不同。看起来代码只对单个单词起作用,所以可能它不在 FIFO 模式下(或者对这段代码无关紧要)。

  • FR 是 UART 标志寄存器 (AKA UARTFR)。这包含一堆可以查询的位,以查看 UART 的状态。这个问题的两个重要问题是:

    • TXFFFR 中的一个位,当传输缓冲区已满时变为1
    • RXFEFR中的一个位,当接收缓冲区为空时变为1
  • DR 是 UART 数据寄存器 (AKA UARTDR)。这包含要传输的数据和已接收的数据。

所以看看代码的主要工作部分~

static void uart_echo( pl011_T *uart ) 
{
    if ( ( uart->FR & RXFE ) == 0 )      // While the receive buffer is NOT empty
    {
        while( uart->FR & TXFF );        // Do <nothing> while the Tx buffer is full

        // Read the content of the Data Register, converting it to uppercase(),
        // then make a write to the DR, which initiates a transmit
        uart->DR = upperchar(uart->DR);  
    }
}  

所以这个函数正在回显它读取的任何内容,但是是大写的。程序依次为三个 UART 中的每一个调用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-02
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 2012-03-23
    相关资源
    最近更新 更多