ZYNQ学习笔记2-ZYNQ的UART控制器2

UART编程指南

示例:配置控制器功能

本示例配置字符帧、波特率、FIFO 触发水平、接收器超时机制,并使能控制器。所有这些步骤在复位后都是必需的,但在控制器使能与禁用之间则不必重复执行。

配置 UART 字符帧。uart.mode_reg0 写入 0x0000_0020

a. 禁止时钟预分频器(UART_REF_CLK/8):CLKS = 0

b. 选择 8 位字符长度:CHRL = 00

c. 选择无奇偶校验:PAR = 100

d. 选择 1 个停止位:NBSTOP = 00

e. 选择正常通道模式(模式开关):CHMODE = 00

配置波特率。写入三个寄存器:uart.Control_reg0、uart.Baud_rate_gen_reg0 和 uart.Baud_rate_divider_reg0。

a. 禁止接收通路:设置 uart.Control_reg0 RXEN = 0 和 RXDIS = 1。

b. 禁止发送通路:设置 uart.Control_reg0 TXEN = 0 和 TXDIS = 1。

c. 将计算得到的 CD 值写入 uart.Baud_rate_gen_reg0 CD 位字段。

d. 将计算得到的 BDIV 值写入 uart.Baud_rate_divider_reg0 BDIV 位字段。

e. 复位发送和接收通路:uart.Control_reg0 TXRSTRXRST = 1。这些位自清零。

f. 使能接收通路:设置 RXEN = 1 和 RXDIS = 0。

g. 使能发送通路:设置 TXEN = 1 和 TXDIS = 0。

设置 RxFIFO 触发水平。将触发水平写入 uart.Rcvr_FIFO_trigger_level0 寄存器。

选项 a:使能 Rx 触发水平。向 RTRIG 位字段写入 1 到 63 之间的值。

选项 b:禁用 Rx 触发水平。向 RTRIG 位字段写入 0。

使能控制器。向 uart.Control_reg0 寄存器写入 0x0000_0117。

a. 复位发送和接收通路:uart.Control_reg0 TXRSTRXRST = 1。这些位自清零。

b. 使能接收通路:RXEN = 1 和 RXDIS = 0。

c. 使能发送通路:TXEN = 1 和 TXDIS = 0。

d. 重启接收器超时计数器:RSTTO = 1。

e. 不开始发送 break 信号:STTBRK = 0。

f. 停止 break 发送:STPBRK = 1。

编程接收器超时机制。将超时值写入 uart.Rcvr_timeout_reg0 寄存器。

a. 要使能超时机制,向 RTO 位字段写入 1 到 255 之间的值。(注意:原文写的是 RSTTO,但根据前面章节 Rcvr_timeout_reg0 的位字段应为 RTO,此处按合理逻辑修正为 RTO

b. 要禁用超时机制,向 RTO 位字段写入 0。

发送数据

软件可以使用轮询或中断方式控制数据流向 TxFIFO 和 RxFIFO。

++注意:++ ++当++ ++TxFIFO++ ++空状态为真时,软件可以一次性写入++ ++64++ ++字节(++ ++TxFIFO++ ++的大小)而无需检查++ ++TxFIFO++ ++状态。实际上,当发送器处于活动状态时,软件可以写入超过++ ++64++ ++字节的数据,因为在软件向++ ++TxFIFO++ ++写入数据的同时,控制器正在取出数据并将其串行化到++ ++TxD++ ++信号上。++

示例:使用轮询方法发送数据

在本示例中,软件可以选择持续填充 TxFIFO 直到满状态位置位,或者等待 TxFIFO 变空(然后写入最多 64 字节)。当 TxFIFO 几乎满时,软件始终可以写入一个字节。

  1. 检查 TxFIFO 是否为空。等待直到 uart.Channel_sts_reg0TEMPTY = 1。
  2. 向 TxFIFO 填充数据。向 uart.TX_RX_FIFO0 寄存器写入64字节数据。
  3. 向 TxFIFO 写入更多数据。有两种方法:
    • 选项 A 检查 TxFIFO 是否有空间再写入一个字节的数据(即 TxFIFO 未满):读取 uart.Channel_sts_reg0TFUL 直到其等于 0。当 TFUL = 0 时,向 TxFIFO 写入一个字节的数据,然后再次读取 TFUL
    • 选项 B 等待 TxFIFO 变空。读取 uart.Channel_sts_reg0TEMPTY 直到其等于 1,然后转到步骤 2,再次向 TxFIFO 填充 64 字节数据。

示例:使用中断方法发送数据

本示例首先以与轮询方法类似的方式填充 TxFIFO。然后,软件使能 TxFIFO 空中断,以提醒软件再次填充 TxFIFO。

  1. 禁用 TxFIFO 空中断。向 uart.Intrpt_dis_reg0TEMPTY 写入 1。
  2. 向 TxFIFO 填充数据。向 uart.TX_RX_FIFO0 寄存器写入 64 字节数据。
  3. 检查 TxFIFO 是否有空间再写入一个字节的数据(即 TxFIFO 未满):读取 uart.Channel_sts_reg0TFUL 直到其等于 0。当 TFUL = 0 时,向 TxFIFO 写入一个字节的数据,然后再次读取 TFUL
  4. 重复步骤 2 和 3。重复直到 uart.Channel_sts_reg0TFUL 未被置位。
  5. 使能中断。向 uart.Intrpt_en_reg0TEMPTY 写入 1 以使能中断。
  6. 等待 TxFIFO 变空。当 uart.Channel_int_sts_reg0TEMPTY 被置为 1 时,从步骤 1 开始重复。

接收数据

示例:使用轮询方法接收数据

  1. 等待 RxFIFO 填充至触发水平。检查 uart.Channel_sts_reg0RTRIG = 1 或 uart.Chnl_int_sts_reg0TIMEOUT = 1。
  2. 从 RxFIFO 读取数据。从 uart.TX_RX_FIFO0 寄存器读取数据。
  3. 重复步骤 2,直到 FIFO 为空。检查 uart.Channel_sts_reg0REMPTY = 1。
  4. 若接收超时中断状态位置位,则清除。向 Chnl_int_sts_reg0TIMEOUT 写入 1。

示例:使用中断方法接收数据

  1. 使能中断。向 uart.Intrpt_en_reg0TIMEOUT 和 uart.Intrpt_en_reg0RTRIG 各写入 1。
  2. 等待 RxFIFO 填充至触发水平或发生接收超时。检查 uart.Chnl_int_sts_reg0RTRIG = 1 或 uart.Chnl_int_sts_reg0TIMEOUT = 1。
  3. 从 RxFIFO 读取数据。从 uart.TX_RX_FIFO0 寄存器读取数据。
  4. 重复步骤 2 和 3,直到 FIFO 为空。检查 uart.Channel_sts_reg0REMPTY = 1。
  5. 若中断状态位置位,则清除。向 Chnl_int_sts_reg0TIMEOUT 或 Chnl_int_sts_reg0RTRIG 写入 1。

RxFIFO 触发水平中断

示例:设置 RxFIFO 触发水平并使能中断

Intrpt_en_reg0 寄存器的各位用于使能中断掩码,Intrpt_dis_reg0 寄存器的各位用于强制禁用中断。每对位应互斥设置(即,一个寄存器的对应位为 1,另一个寄存器的对应位为 0):

  • Intrpt_en_reg0:只写。使能中断位。
  • Intrpt_dis_reg0:只写。强制禁用中断位。
  1. 编程触发水平。写入 6 位字段 uart.Rcvr_FIFO_trigger_level0RTRIG
  2. 使能 RTRIG 中断 。设置使能位,清除禁用位,并验证掩码值:
    a. 设置 uart.Intrpt_en_reg0RTRIG = 1。
    b. 清除 uart.Intrpt_dis_reg0RTRIG = 0。
    c. 回读 uart.intrpt_mask_reg0RTRIG = 1(中断已使能)。
  3. 禁用 RTRIG 中断 。设置禁用位,清除使能位,并验证掩码值:
    a. 设置 uart.Intrpt_dis_reg0RTRIG = 1。
    b. 清除 uart.Intrpt_en_reg0RTRIG = 0。
    c. 回读 uart.intrpt_mask_reg0RTRIG = 0(中断已禁用)。
  4. 清除 RTRIG 中断。向 uart.Intrpt_dis_reg0RTRIG 位字段写入 1。

当某个中断的使能位和禁用位同时被置位时,该中断被禁用。

中断使能/禁用机制的状态可通过读取 uart.Intrpt_mask_reg0 寄存器来确定。若掩码位 = 1,则表示中断已使能。

UART寄存器总览

|------------|--------------------------|-----------------------|
| 功能 | uart. 寄存器名称 | 说明 |
| 配置 | Control_reg0 | 配置模式和波特率 |
| 配置 | mode_reg0 | 配置模式和波特率 |
| 配置 | Baud_rate_gen_reg0 | 配置模式和波特率 |
| 配置 | Baud_rate_divider_reg0 | 配置模式和波特率 |
| 中断处理 | Intrpt_en_reg0 | 使能/禁用中断掩码、通道中断状态、通道状态 |
| 中断处理 | Intrpt_dis_reg0 | 使能/禁用中断掩码、通道中断状态、通道状态 |
| 中断处理 | Intrpt_mask_reg0 | 使能/禁用中断掩码、通道中断状态、通道状态 |
| 中断处理 | Chnl_int_sts_reg0 | 使能/禁用中断掩码、通道中断状态、通道状态 |
| 中断处理 | Channel_sts_reg0 | 使能/禁用中断掩码、通道中断状态、通道状态 |
| 接收和发送数据 | TX_RX_FIFO0 | 读取已接收的数据 |
| 接收和发送数据 | TX_RX_FIFO0 | 写入待发送的数据 |
| 接收器 | Rcvr_timeout_reg0 | 配置接收器超时和 RxFIFO 触发水平值 |
| 接收器 | Rcvr_FIFO_trigger_level0 | 配置接收器超时和 RxFIFO 触发水平值 |
| 发送器 | Tx_FIFO_trigger_level0 | 配置 TxFIFO 触发水平值 |
| 调制解调器 | Modem_ctrl_reg0 | 配置类似调制解调器的应用 |
| 调制解调器 | Modem_sts_reg0 | 配置类似调制解调器的应用 |
| 调制解调器 | Flow_delay_reg0 | 配置类似调制解调器的应用 |