UART :Universal Asynchronous Receiver and Transmitter 通用异步收/发器,是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。一般由波特率产生器(产生的波特率等于传输波特率的 16 倍)、UART 接收器、UART 发送器组成,硬件上有两根线,一根用于发送,一根用于接收。 显然,如果用通用 IO 口模拟 UART 总线,则需一个输入口,一个输出口。
但对于 USART ,是什么,与 UART 有什么区别.....
这时候,小编其实想说:咦!!!不好意思,好像我走错地方了......
一、USART 模块介绍
1.1、USART 特性介绍:
- LPC824 中有 3 个 USART 接口可以使用:USART 0/1/2。串口可以支持 异步模式 以及 同步模式。其中异步模式下最高速率可达 875Mbits/s;同步模式下最高速率可达 10Mbits/s.
- USART 数据格式可以设置为 7、8、9 个数据位,1、2 个停止位。其中校验可以设置为:无校验/奇校验/偶校验。
- USART 的中断源为:接收就绪、发送就绪、发送器空闲、校验错误,数据帧错误。
- USART 的波特率可以支持常用的波特率,最高为 921600,最低为 300,并且可以通过设置让其自动监测波特率。
- USART 具有低功耗模式唤醒的功能,其中在异步通信模式下,能够在睡眠模式下唤醒;在同步通信模式下,能够在全部低功耗模式下唤醒。
2.1、USART 的功能框图
如 图 2-1-1 所示:
其中串口的时钟是由两个时钟源提供的,主时钟经过 FRGCLKDIV 分频之后的 U_PCLK 时钟源用于波特率的产生,其他均由系统时钟提供。以下 图 2-1-2 即为异步模式下的波特率产生过程,在 USART 模块得到有主时钟分频之后的 U_PCLK 之后,内部还会经过波特率分频器以及过采样分频器两个分频器进行分频,最后得到的才是波特率。
2.2、设置 USART 模块配置流程
2.3、USART 的详细配置步骤:
以下我们就以“波特率为 115200、无校验位、数据位为 8 位、停止位为 1 位”的参数进行串口配置。
1. 基本配置:
通过 USART 的 CFG 寄存器配置关键参数:
a. 使能 USART:CFG[0:0] = 1
b. 配置数据位为 8 位:CFG[3:2]=1
c. 配置校验为无校验:CFG[5:4]=0
e. 配置为无流控:CFG[9:9]=0
f. 不使用同步收发模式:CFG[12:11,14]=0
g. 不使用环回(自发自收):CFG[15:15]=0
h. 不使用 RS-485:CFG[21:18]=0
i. 不反向识别波形极性:CFG[23:22]=0
综上所述,寄存器的配置为:
CFG = 1 << 0 | 1 << 2 | 0 << 4 | 0 << 6 | 0 << 9 | 0 << 11 | 0 << 14 | 0 << 15 | 0xF << 18 | 3 << 22;
其中寄存器里面没有定义的位必须为 0。设置后如下图 2-3-1 所示。
以上关于 CFG 寄存器的配置在代码中可以通过 Chip_UART_ConfigData() 函数进行配置。
2. 设置波特率:
在设置波特率时可以有多种解法,现在假设主时钟为 12MHz 时:
a. 保守解法:先配置整数分频器,有误差时用分数分频器弥补
SYSCON.UARTCLKDIV = 1
USART.OSR = 16 - 1 = 15
USART.BRG = 6 – 1 = 5 (12000000/115200/16 = 6.51)
SYSCON.UARTFRAGMULT = 22((6.51/6 - 1)*255 = 22)
波特率 = 12000000/1/(1+22/255)/6/16 = 115072,误差为 0.12%
b.“投机”解法:在线路较好时不使用分数分频器,而是减少过采样倍率(该方法对于通讯的信号波形要求较高)
ON.UARTCLKDIV = 1
SYSCON.UARTFRAGMULT = 0
USART.OSR = 13 – 1 = 12 (减少过采样倍率,12000000/115200/13=8.013,除不尽的部分最小)
USART.BRG = 8 – 1 = 7(最后再确定 BRG 的值)
波特率 = 12000000/1/(1+0/255)/8/13 = 115384,误差率为 0.3%
其中减少过采样倍率会提高对信号波形的质量要求。
以上相关的 API 函数为 Chip_Clock_SetUSARTNBaseClockRate()与Chip_UART_SetBaud()(其中仅支持 16 倍过采样)。
3. 杂项配置:
通过 USART 的 CTL 寄存器使能发送器,
- 解除对发送器的禁用:CTL[6:6] = 0;
- 不发送断路信号:CTL[1:1] = 0;
- 不使用 RS-485 的地址检测功能:CTL[2:2] = 0;
- 不使用同步模式(连续时钟发送):CTL[9:8] = 0
- 不做自动波特率的检测:CTL[16:16] = 0
综上所述,CTL 寄存器的配置具体为:
UART.CTL = 0<
在代码中,关于 CTL 寄存器的相关配置函数为 Chip_UART_TXEnable();
4. 中断配置:
在关于中断的设置中,需要通过两个寄存器 INTENSET 与 INTENCLR 来使能需要的中断,禁止不需要的中断,其中这两个寄存器均为写 1 有效。除此之外,INTENSET 可以通过读取其值来判断当前使能的中断有哪些。在之前的特性的介绍中,我们知道串口的中断源有:接收就绪中断,闲置中断等,现在我们来配置哪一些需要使能,哪一些需要禁用:
a. 使能接收就绪中断:INTENSET[0:0] = 1
b. 使能发送器闲置中断:INTENSET[3:3] = 1
使能:发送器一空闲就会发中断,所以要在发送一个数据后再使能
禁用:在发送全部数据后,要禁用这个中断。
c. 使能接收数据溢出中断:INTENSET[8:8] = 1
d. 禁用发送器就绪中断:INTENSET[2:2] = 1
发送器就绪中断会有助于提高发送效率,但是中断产生时最后一个数据很可能尚在发送中,容易出错。
e. 禁用其他中断
由于这两个寄存器为写 1 有效,我们可以先除能全部的中断,然后再使能我们需要的中断,设置后如下图 2-3-3 所示:
UART.INTENSET = 1<
UART.INTENCLR = 0X0001F96D(空白位不能写 1)
5. 标志位:
在设置完上述的中断设置之后,我们可以通过 STAT 寄存器来查看当前的事件标志,如右图 2-3-4 所示,在 STAT 中,有一些标志需要我们写1来清除标志,有些则由硬件自动设置与清除,我们现在就了解与 USART 相关的几个标志位:
a. 接收到数据标志:STAT[0:0],这个为只读,当读取串口数据时会自动清除
b. 发送器闲置标志:STAT[3:3],这个为只读,当写入新数据时会自动清除
c. 接收数据溢出标志:STAT[8:8],这个需要手动写 1 清除。
由于我们使用的是中断,所可以在中断处理函数中判断是进入了哪一种的中断,而当我们使用轮询的话,则可以在我们的循环中轮询寄存器中上述的标志位。
6. 数据处理:
在处理数据中,我们可以分为两部分:发送数据与接收数据。
a. 发送数据
在 1.1.5 中介绍到 STAT 寄存器,如果 STAT 中 bit2 (发送器就绪)或者 bit3 (发送器空闲)有被设置的话,这时候说明 USART 能够发送数据,我们可以往 USART 的 TXDAT 寄存器中发送数据。所以在发送数据之前我们需要先判断 STAT 的 bit2 & bit3,确定是空闲之后再发送数据。
b. 接收数据
当我们在触发了接收中断,或者是在轮询的过程中检测到 STAT 寄存器的 bit0 被设置之后,这是说明 USART 中接收到了数据。我们有两个寄存器可以读取到 USART 的数据,如右图 2-3-5 所示:
RXDAT 寄存器:可以读取接收到的纯数据,但是不知道是否有错。
RXDATSTAT 寄存器:可以读取接收到的数据,并且 RXDATSTAT[15:13] 会表示当前数据的错误状态。其中:
[13:13]: 存在帧错误(停止位错误)
[14:14]: 存在奇/偶校验错误
[15:15]: 在接收该数据时线路中噪声过大(线路质量不好,有可能出现个别数据接收错误)
2.4、USART 的 DMA 数据收发
当我们在使用过程中需要通过串口收发大量数据,如果我们还是使用轮询或者中断的方式来进行处理的话,会占用程序的大部分时间。我们可以通过使能 USART 上的 DMA 进行数据收发。如下图 2-1-9 所示,USART 有 6 个 DMA 通道,分别对应三个 USART 的接收与发送。
在使用 DMA 功能时,不需要在 USART 中进行任何的配置,只需要在 DMA 控制器中进行初始化即可:
- 填写相应通道的描述符。
- 配置对应的 DMA 通道(CFG 寄存器)
- 开启传输完成中断。
- 使能外设请求。
2.5、USART 对 RS-485 的支持
RS-485 通讯采用的是主从通讯方式,即为一个主机带多个从机,其中从机不主动发命令与数据,一切由主机控制。在通讯过程中,主设备会通过总线广播发送一个从机地址,与地址相符的从设备会相应请求,然后在进行串口通信。因此对寄存器进行修改:
作为从设备:
- 在 CFG[3:2] 位段中,设置数据位为 9 个。
- 设置 CFG[19:19](AUTOADDR) 为 1
- 当需要接收地址时,设置 CTL.bit2(ADDRDET)为 1,此时仅当收到的数据第 9 位为 1,且 8 位地址与 ADDR 的设置相匹配时才会接受(产生中断或 DMA)
- 当需要接受数据时,设置 CTL.bit2(ADDRDET)为 0,此时接收全部数据。
作为主设备:
- 在 CFG[3:2] 位段中,设置数据位为 9 个
- 由于主设备负责广播从机地址数据,所以不需要做识别设置。
除此之外,RS-485 通讯是一种半双工通讯,与 RS-232,RS-422 这些全双工的通讯不一样,需要控制传输方向的流向。因此需要对 USART 进行一些设置修改:
- 设置 CFG.bit20(OESEL)为 1,把原本 RTS 信号改用为 RS-485 的 OE 信号
- 根据 RS-485 收发器对 OE 极性的要求设置:0=OE 低电平有效,1=OE 高电平有效。
- 根据软件反应的延迟设置 CFG.bit18(OETA):当使用 DMA 进行数据发送时,可以 OETA 设置为 0,即发完数据后立即解除 OE 有效;当使用中断发送,最好将 OETA 设置为 1,即发完数据再等一个帧的时间给 ISR 作处理后才解除 OE 有效。
2.6、USART 低功耗模式唤醒
LPC82x 的休眠模式有三种,分别是睡眠模式,深度睡眠和掉电模式。其中 USART 异步模式与同步模式能够唤醒低功耗模式如下表 2-6-1 所示:
USART 工作模式 |
能唤醒的低功耗模式 |
异步模式 |
睡眠模式 |
同步模式 |
睡眠模式、深度睡眠、掉电模式 |
睡眠模式唤醒的相关配置流程如下图 2-6-1:
在深度睡眠/掉电模式下唤醒的相关配置流程如下图 2-6-2:
三、USART 应用实例
3.1、实验目的
通过本次实验,了解和掌握 LPC82X USART 的以下几点:
- 如何配置 USART 的引脚 IO;
- 如何配置 USART 的参数,如波特率,数据位等;
- 如何使用板级 API 来发送串口数据;
3.2、实验软/硬件环境搭建
硬件:LPC82x Xpresso v2/mbed
软件:SDK 从 NXP 官网下载(https://mcuxpresso.nxp.com/en/select)
工程位置:..\..\boards\lpcxpresso824max\driver_examples \usart\polling\mdk\
usart_polling_example.uvprojx
3.3、实验描述
本实验使能 UART0 进行数据收发,使用方式为 polling 的方式。在轮询的过程中会不断的检测 UART0 的 RXDAT 是否有数据,然后将其数据通过 UART0 给上位机。
3.4、实验结果
通过串口助手往 LPC82x 板子上发送串口数据后,串口助手会打印出我们发送给设备数据。
3.5、实验代码
#include "board.h"
#include "fsl_usart.h"
#include "pin_mux.h"
#include
/*****************************************************************
* Definitions
*****************************************************************/
#define EXAMPLE_USART USART0
#define EXAMPLE_USART_CLK_SRC kCLOCK_MainClk
#define EXAMPLE_USART_CLK_FREQ CLOCK_GetFreq(EXAMPLE_USART_CLK_SRC)
/*****************************************************************
* Prototypes
*****************************************************************/
/*****************************************************************
* Variables
*****************************************************************/
uint8_t txbuff[] =
"Usart polling example.\r\nBoard will send back received characters.\r\nNow, please input any character:\r\n";
/*******************************************************************************
* Code
******************************************************************************/
/*!
* @brief Main function
*/
int main(void)
{
uint8_t ch;
usart_config_t config;
//使能 UART0 的时钟
/* Enable clock of uart0. */
CLOCK_EnableClock(kCLOCK_Uart0);
// 对 UART0 的输入时钟进行分频
CLOCK_SetClkDivider(kCLOCK_DivUsartClk, 1U);
//在该函数里面定义了 UART0 中关于 RX、TX 的引脚
BOARD_InitPins();
BOARD_BootClockIRC12M();
BOARD_InitDebugConsole();
/* Default config by using USART_GetDefaultConfig():
* config->baudRate_Bps = 9600U;
* config->parityMode = kUSART_ParityDisabled;
* config->stopBitCount = kUSART_OneStopBit;
* config->bitCountPerChar = kUSART_8BitsPerChar;
* config->loopback = false;
* config->enableRx = false;
* config->enableTx = false;
* config->syncMode = kUSART_SyncModeDisabled;
*/
/*获取串口参数的默认设置
串口波特率为 9600
禁用校验位;
停止位为 1 个;
数据位为 8 个;
禁用环回;
禁用接收;
禁用发送;
设置为异步模式;
*/
USART_GetDefaultConfig(&config);
/*
将得到的默认参数按照我们想要的进行设置:
使能接收;
使能发送;
修改波特率为 115200(通过宏定义)
*/
config.enableRx = true;
config.enableTx = true;
config.baudRate_Bps = BOARD_DEBUG_USART_BAUDRATE;
/* Initialize the USART with configuration. */
// 使能串口。
USART_Init(EXAMPLE_USART, &config, EXAMPLE_USART_CLK_FREQ);
/* Send data in polling way. */
// 发送串口数据
USART_WriteBlocking(EXAMPLE_USART, txbuff, sizeof(txbuff) - 1);
while (1)
{
/* Receive a character from USART, this API will wait until one character has been received. */
/*在轮询中查看 RXDAT 的 buff 是否有数据*/
USART_ReadBlocking(EXAMPLE_USART, &ch, 1);
/* Send the received character to the terminal. */
/*将读取的串口数据数据发送出去*/
USART_WriteBlocking(EXAMPLE_USART, &ch, 1);
}
}
评论