Mini2440裸机开发之串口UART
一、S3C2440上的UART
1.1 串口概述
串口的使用位于S3C2440芯片手册的第11章。S3C2440A 的通用异步收发器(UART)配有3 个独立异步串行I/O端口,每个都可以是基于中断或基于DMA 模式的操作。换句话说,UART 可以通过产生中断或DMA 请求来进行CPU和UART之间的数据传输。 UART 通过使用系统时钟可以支持最高115.2Kbps 的比特率。如果是外部器件提供UEXTCLK 的UART,则UART 可以运行在更高的速度。每个UART 通道包含两个的64 字节的FIFO 给发送和接收。
S3C2440A 的UART 包括了可编程波特率,红外(IR)发送/接收,插入1 个或2 个停止位,5 位、6 位、7 位 或8 位的数据宽度以及奇偶校验。
1.2 特性
- 基于DMA 或基于中断操作的RxD0,TxD0,RxD1,TxD1,RxD2 和TxD2;
- UART 通道0,1 和2 带IrDA 1.0 和64 字节FIFO;
- UART 通道0 和1 带nRTS0,nCTS0,nRTS1 和nCTS1;
- 支持握手发送/接收;
1.3 串口结构
每个UART 包含一个波特率发生器、发送器、接收器和一个控制单元。波特率发生器可以由 PCLK、FCLK/n 或UEXTCLK(外部输入时钟)时钟驱动。发送器和接收器包含了64 字节FIFO 和数据移位器。 将数据写入到FIFO 接着在发送前复制到发送移位器中。随后将在发送数据引脚(TxDn)移出数据。与此同时从接收数据引脚(RxDn)移入收到的数据,接着从移位器复制到FIFO。
1.4 串口数据发送
可编程发送数据帧。由1 个起始位、5 至8 位数据位、1 个可选奇偶校验位以及1 至2 个停止位组成,是由行控制寄存器(ULCONn)指定。
发送器也可以产生单帧发送期间强制串行输出为逻辑0状态的断点状态。此模块在完成发送当前发送字后发送断点信号。在发出断点信号后,其不断发送数据到Tx FIFO(非FIFO 模式情况下Tx 保持寄存器)中。
1.5 串口数据接收
与发送类似,接收数据帧也是可编程的。由1个起始位、5至8位数据位、1 个可选奇偶校验位以及1至2个停止位组成,是由行控制寄存器(ULCONn)指定。
接收器能够检测出溢出(overrun)错误、奇偶校验错误、帧错误和断点状态,每个都可以设置一个错误标志。
- 溢出错误表明新数据在读出旧数据前覆盖了旧数据;
- 奇偶校验错误表明接收器检测出一个非预期奇偶校验字段;
- 帧错误表明接收到的数据没有有效的结束位;
- 断点状态表明RxDn 的输入保持为逻辑0 状态的时间长于单帧传输时间。 当其在3 字时间期间(此间隔在字宽位的设置随后)并且在FIFO 模式中Rx FIFO 为非空时不接收任何数据时 发生接收超时状态。
1.6 串口波特率
每个UART 的波特率发生器为发送器和接受器提供串行时钟。波特率发生器的源时钟可以选择S3C2440A 的 内部系统时钟或UEXTCLK。换句话说,分频由设置UCONn 的时钟选项选择。
波特率时钟是通过16 和由UART波特率分频寄存器(UBRDIVn)指定的16 位分频系数来分频源时钟(PCLK,FCLK/n 或UEXTCLK)产生的。 UBRDIVn 由下列表达式决定:
$$UBRDIVn=(int)\frac{UART时钟}{波特率 \times 16} - 1$$
其中UART时钟:PCLK、FCLK/n或UEXTCLK.
例如:如果波特率位115200bps,并且UART时钟位40MHz,则UBRDIVn为:
$$UBRDIVn=(int)\frac{40000000}{115200 \times 16} - 1 = 21$$
二、UART相关寄存器
2.1 UART线路控制寄存器ULCONx
在UART 模块中包含了ULCON0、ULCON1 和ULCON2,设置数据长度,开始位,停止位,奇偶校验相关。
寄存器 | 地址 | R/W | 描述 | 复位值 |
ULCON0 | 0x50000000 | R/W | UART0线路控制寄存器 | 0x00 |
ULCON1 | 0x50004000 | R/W | UART1线路控制寄存器 | 0x00 |
ULCON2 | 0x50008000 | R/W | UART2线路控制寄存器 | 0x00 |
寄存器位信息:
ULCONn | 位 | 描述 | 初始状态 |
保留 | [7] | - | 0 |
红外模式 | [6] |
决定是否使用红外模式 0:普通模式 1:红外Tx/Rx模式 |
0 |
奇偶校验模式 | [5:3] |
指定在UART 发送和接收操作期间奇偶校验产生和检查的类型 0xx:无奇偶校验位 100:奇校验 101:偶校验 110:固定/检查奇偶校验为1 111:固定/检查奇偶校验为0 |
000 |
停止位数 | [2] |
指定用于结束帧信号的停止位的个数 0:每帧1个停止位 1:每帧2个停止位 |
0 |
字长度 | [1:0] |
指出每帧用于发送或接收的数据位的个数 00:5位 01:6位 10:7位 11:8位 |
00 |
2.2 UART控制寄存器UCONx
在UART 模块中包含了UCON0、UCON1 和UCON2,选择设置UART时钟,中断类型,FIFO状态等。
寄存器 | 地址 | R/W | 描述 | 复位值 |
UCON0 | 0x50000004 | R/W | UART0控制寄存器 | 0x00 |
UCON1 | 0x50004004 | R/W | UART1控制寄存器 | 0x00 |
UCON2 | 0x50008004 | R/W | UART2控制寄存器 | 0x00 |
寄存器位信息:
UCONn | 位 | 描述 | 初始状态 |
FCLK分频器 | [15:12] |
当UART 时钟源选择了FCLK/n 时的分频器值。n由UCON0[15:12]、UCON1[15:12]、UCON2[14:12]所决定。 UCON0 的情况:UART 时钟 = FCLK / (分频器+6);分频器>0。 UCON1 的情况:UART 时钟 = FCLK / (分频器+21);分频器>0。 UCON2 的情况:UART 时钟 = FCLK / (分频器+36);分频器>0。 如果UCON0/1[15:12]和UCON2[14:12]都全为0,则分频器将为44, |
0000 |
时钟选择 | [11:10] |
选择PCLK,UEXTCLK 或FCLK/n 给UART 波特率。 00:PCLK 10:PCLK 01:UEXTCLK 11:FCLK/n |
00 |
Tx中断类型 | [9] |
中断请求类型 0:脉冲(非FIFO模式中Tx缓冲器一变为空或FIFO 模式中达到Tx FIFO 触发深度就请求中断) 1:电平(当非FIFO模式中Tx缓冲为空或FIFO模式中达到Tx FIFO触发深度时请求中断) |
0 |
Rx中断类型 | [9] |
中断请求类型 |
0 |
Rx超时使能 | [7] |
当使能了UART FIFO 使能/禁止Rx 超时中断。该中断是一个接收中断 0: 禁止 1:使能 |
0 |
Rx错误状态中断使能 | [6] |
异常时允许UART 产生中断,如接收操作期间的断点、帧错误、奇偶错误或溢出错误。 0:不产生接收错误状态中断 1:产生接收错误状态中断 |
0 |
环回模式 | [5] |
设置环回模式为1 使得UART 进入环回模式。此模式只用于测试。 0: 正常操作 1:环回模式 |
0 |
发出断点信号 | [4] |
设置此位使得UART 在单帧期间发出一个断点信号。此位在发出断点信号后将自动清零。 0:正常传输 1:发出断点信号 |
0 |
发送模式 | [3:2] |
确定哪个功能能够将Tx数据写入UART 发送缓冲寄存器。 (UART Tx 启用/禁用) 00:禁止 01:中断请求或轮询模式 10:DMA0 请求(仅适用于 UART0) DMA3 请求(仅适用于 UART2) 11:DMA1 请求(仅适用于 UART1) |
|
接收模式 | [1:0] |
确定哪个功能能够将Rx数据读取到UART 接收缓冲寄存器。 (UART Tx 启用/禁用) 00:禁止 01:中断请求或轮询模式 10:DMA0 请求(仅适用于 UART0) DMA3 请求(仅适用于 UART2) 11:DMA1 请求(仅适用于 UART1) |
注意:应该在选择或者取消FCLK/n后加上一下代码:
GPHCON =rGPHCON & ~(3<<16); //GPH8(UEXTCLK)输入
Delay(1); //大约100μs
GPHCON =rGPHCON & ~(3<<16) | (1<<17); //GPH8(UEXTCLK)UEXTCLK
2.3 FIFO控制寄存器
UART 模块中包含了UFCON0、UFCON1 和UFCON2。
寄存器 | 地址 | R/W | 描述 | 复位值 |
UFCON0 | 0x50000008 | R/W | UART0 FIFO控制寄存器 | 0x00 |
UFCON1 | 0x50004008 | R/W | UART1 FIFO控制寄存器 | 0x00 |
UFCON2 | 0x50008008 | R/W | UART2 FIFO控制寄存器 | 0x00 |
寄存器位信息:
UFCONx | 位 | 描述 | 初始状态 |
Tx FIFO触发深度 | [7:6] |
决定发送FIFO 的触发深度 00:空 01:16字节 10:32字节 11:48字节 |
00 |
Rx FIFO触发深度 | [5:4] |
决定接收FIFO 的触发深度 00:空 01:16字节 10:32字节 11:48字节 |
00 |
保留 | [3] | - | 0 |
Tx FIFO复位 | [2] |
复位FIFO后自动清零 0:正常 1:Tx FIFO复位 |
0 |
Rx FIFO复位 | [1] |
复位FIFO后自动清零 0:正常 1:Rx FIFO复位 |
0 |
FIFO使能 | [0] | 0:禁止 1:使能 | 0 |
2.4 UART MODEM控制寄存器
UART 模块中包含了UMCON0 和UMCON1。
寄存器 | 地址 | R/W | 描述 | 复位值 |
UMCON0 | 0x5000000C | R/W | UART0 Modem控制寄存器 | 0x00 |
UMCON1 | 0x5000400C | R/W | UART1 Modem控制寄存器 | 0x00 |
保留 | 0x5000800C | - | 保留 | 未定义 |
寄存器位信息:
UMCONn | 位 | 描述 | 初始状态 |
保留 | [7:5] | 这些位必须位0 | 000 |
自动流控制(AFC) | [4] | 0:禁止 1:使能 | 0 |
保留 | [3:1] | 这些位必须为0 | 000 |
请求传送 | [0] |
如果AFC 位为使能,将忽律此值。这种情况下S3C2440A 将自动控制 请求传送 [0] nRTS。如果 AFC 位为禁止,nRTS必须由软件控制。 0:高电平(撤消nRTS) 1:低电平(激活nRTS) |
0 |
2.5 UART TX/RX状态寄存器
在UART 模块中包含了UTRSTAT0,UTRSTAT1 和UTRSTAT2。
寄存器 | 地址 | R/W | 描述 | 复位值 |
UTRSTAT0 | 0x50000010 | R | UART0 Tx/Rx状态寄存器 | 0x06 |
UTRSTAT1 | 0x50004014 | R | UART1 Tx/Rx状态寄存器 | 0x06 |
UTRSTAT2 | 0x50008018 | R | UART2 Tx/Rx状态寄存器 | 0x06 |
寄存器位信息:
UTRSTATn | 位 | 描述 | 初始状态 |
发送器空 | [2] |
当发送缓冲寄存器无有效数据要发送并且发送移位寄存器为空时将自动设置为1 0:非空 1:发送器(发送缓冲和移位寄存器)空 |
1 |
发送缓冲器空 | [1] |
当发送缓冲寄存器为空时自动设置为1 0 : 缓冲寄存器非空 如果UART 使用FIFO,用户应该用UFSTAT 寄存器中的Rx FIFO 计数位和Rx FIFO 满位取对代此位的检查。 |
1 |
接收缓冲器 |
[0] |
每当通过RXDn 端口接收数据,接收缓冲寄存器包含了有效数据时自动设置为1 0:空 1:缓冲寄存器接收到有效数据(非FIFO 模式中,请求中断或DMA) 如果UART 使用FIFO,用户应该用UFSTAT 寄存器中的Rx FIFO 计数位和Rx FIFO 满位取对代此位的检查。 |
0 |
2.6 UART发送缓冲寄存器(保持寄存器和FIFO寄存器)
在UART 模块中包含了UTXH0,UTXH1 和UTXH2。UTXHn 发送数据为8 位数据。
寄存器 | 地址 | R/W | 描述 | 复位值 |
UTXH0 |
0x50000020(L) 0x50000023(B) |
W | UART0 发送缓冲寄存器 | - |
UTXH1 |
0x50004020(L) 0x50004023(B) |
W | UART1 发送缓冲寄存器 | - |
UTXH2 |
0x50008020(L) 0x50008023(B) |
W | UART2 发送缓冲寄存器 | - |
寄存器位信息:
UTXHn | 位 | 描述 | 初始状态 |
TXDATAn | [7:0] | UARTn要发送的数据 | - |
注意:L小端模式,B大端模式。
2.7 UART接收缓冲寄存器(保持寄存器和FIFO寄存器)
在UART 模块中包含了URXH0,URXH1 和URXH2。URXHn 发送数据为8 位数据。
寄存器 | 地址 | R/W | 描述 | 复位值 |
URXH0 |
0x50000024(L) 0x50000027(B) |
W | UART0 接收缓冲寄存器 | - |
URXH1 |
0x50004024(L) 0x50004027(B) |
W | UART1 接收缓冲寄存器 | - |
URXH2 |
0x50008024(L) 0x50008027(B) |
W | UART2 接收缓冲寄存器 | - |
寄存器位信息:
URXHn | 位 | 描述 | 初始状态 |
RXDATAn | [7:0] | UARTn接收到的数据 | - |
注意:L小端模式,B大端模式。
注意: 当发生溢出错误时,必须读出URXHn。如果未读出,即使清除了UERSTATn 的溢出位下次接收数据将同样发出溢出错误。
2.8 UART波特率分频寄存器
在UART 模块中包含了UBRDIV0,UBRDIV1 和UBRDIV2。
存储在波特率分频寄存器中的值(UBRDIVn)是用于决定如下的串行Tx/Rx 时钟率(波特率):
$$UBRDIVn=(int)\frac{UART时钟}{波特率 \times 16} - 1$$
其中UART时钟:PCLK、FCLK/n或UEXTCLK.
例如:如果波特率位115200bps,并且UART时钟位40MHz,则UBRDIVn为:
$$UBRDIVn=(int)\frac{40000000}{115200 \times 16} - 1 = 21$$
寄存器 | 地址 | R/W | 描述 | 复位值 |
UBRDIV0 |
0x50000028 |
R/W | UART0 波特率分频寄存器 | - |
UBRDIV1 |
0x50004028 |
R/W | UART1 波特率分频寄存器 | - |
UBRDIV2 |
0x50008028 |
R/W | UART2 波特率分频寄存器 | - |
寄存器位信息:
UBRDIVn | 位 | 描述 | 初始状态 |
UBRDIV | [15:0] |
波特率分频值UBRDIVn > 0。 使用UEXTCLK 作为输入时钟时,可以设置UBRDIVn 为0。 |
- |
三、串口初始化步骤
以UART0为例,其引脚如下:
- RX:GPH3
- TX:GPH2
输出波特率位115200,数据位8位,停止位1位,奇偶校验位None。时钟源选择PCLK=50HMz。
3.1 计算波特率
PLCK为50MHz,波特率位:
$$(int)\frac{50000000}{115200 \times 16} - 1 = 26$$
3.2 I/O状态设置
设置GPH控制寄存器,同时设置GPH2、GPH3为上拉使能。
GPHCON &= ~((3<<4) | (3 <<6));
GPHCON |= ((2<<4) | (2<<6));
GPHUP &= ~((1<<2) | (1<<3));
3.3 设置数据长度,开始位,停止位,奇偶校验相关
ULCON0 = 0x03;
3.4 禁止FIFO、禁止自动流控制
默认就是禁止的,可以不用设置。
UFCON0 = 0x00; /* 关闭FIFO */ UMCON0 = 0x00; /* 关闭自动流控制 (AFC) */
3.5 设置UART时钟、接收中断使能
设置时钟源为PCLK,中断/查询模式。
UCON0 = 0x05;
3.6 设置波特率
/* 设置波特率 */ /* UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1 * UART clock = 50M * UBRDIVn = (int)( 50000000 / ( 115200 x 16) ) –1 = 26 */ UBRDIV0 = 26;
四、代码
4.1 串口初始化
/************************************************************************** * * Function : 配置GPH2,GPH3复用为UART功能,串口初始化 * Author : zy * *************************************************************************/ void uart_init() { UART0_RX_STA = 0; /* 清零 */ GPHCON &= ~((3<<4) | (3<<6)); /* GPH[3:2]清零 */ GPHCON |= ((2<<4) | (2<<6)); /* GPH2配置为UART TX[0],GPH3配置为UART RX[0] */ GPHUP &= ~((1<<2) | (1<<3)); /* 使能内部上拉 */ /* Parity Mode [5:3] Specify the type of parity generation and checking during UART transmit and receive operation. 0xx = No parity 100 = Odd parity 101 = Even parity 110 = Parity forced/checked as 1 111 = Parity forced/checked as 0 */ //ULCON0 &= ~(0x07<<3); /* 设置为无校验位 */ /* Number of Stop Bit [2] Specify how many stop bits are to be used for end-of-frame signal. 0 = One stop bit per frame 1 = Two stop bit per frame */ //ULCON0 &= ~(0x01<<2); /* 1位停止位 */ /* Word Length [1:0] Indicate the number of data bits to be transmitted or received per frame. 00 = 5-bit 01 = 6-bit 10 = 7-bit 11 = 8-bit */ ULCON0 = 0x03; /* 设置为无校验位,1位停止位,字长为8位 */ /* Clock Selection [11:10] Select PCLK or UEXTCLK or FCLK/n clock for the UART baud rate. x0 = PCLK : DIV_VAL1 = (PCLK / (bps x 16) ) -1 01 = UEXTCLK: 11 = FCLK/n: */ //UCON0 &= ~(0x03<<10); /* 设置时钟源为PCLK = 50MHZ */ /* Tx Interrupt Type [9] Interrupt request type. 0 = Pulse (Interrupt is requested as soon as the Tx buffer becomes empty in Non-FIFO mode or reaches Tx FIFO Trigger Level in FIFO mode.) 1 = Level (Interrupt is requested while Tx buffer is empty in NonFIFO mode or reaches Tx FIFO Trigger Level in FIFO mode.) */ //UCON0 |= 0x01<<9; /* Tx Interrupt Type设置为level*/ //UCON0 &= ~(0x01<<8); /* Rx Interrupt Type设置为Pulse*/ /* Transmit Mode [3:2] Determine which function is currently able to write Tx data to the UART transmit buffer register. 00 = Disable 01 = Interrupt request or polling mode 10 = DMA0 request (UART0) DMA3 request (UART2) 11 = DMA request (DMA_UART1) */ //UCON0 &= ~(0x03<<2); //UCON0 |= 0x01<<2; /* 发送为中断触发方式 */ /* Receive Mode [1:0] Determine which function is currently able to read data from UART receive buffer register. 00 = Disable 01 = Interrupt request or polling mode 10 = DMA request (DMA_UART0) 11 = DMA request (DMA_UART1) */ //UCON0 &= ~0x03; //UCON0 |= 0x01; /* 接收为中断触发方式 */ UCON0 = 0x05; UFCON0 = 0x00; /* 关闭FIFO */ UMCON0 = 0x00; /* 关闭自动流控制 (AFC) */ /* 波特率设置位115200 DIV_VAL1) = (PCLK / (bps x 16) ) -1 = 50000000/(115200*16) - 1 = 26 */ UBRDIV0 = 26; }
4.2 串口发送
/************************************************************************** * * Function : UART0发送数据 * Input : ch : 待发送的字符 * Author : zy * *************************************************************************/ void uart_putchar(u8 ch) { /* Transmitter empty [2] Set to 1 automatically when the transmit buffer register has no valid data to transmit and the transmit shift register is empty. 0 = Not empty 1 = Transmitter (transmit buffer & shifter register) empty */ while(!(UTRSTAT0 & (0x01<<2))); /* 等待发送缓冲区和移位寄存器为空 /判断前一个数据是否发送完成 */ UTXH0 = ch; /* 发送数据 */ } /************************************************************************** * * Function : UART0发送字符串 * Input : str : 待发送的字符串 * Author : zy * *************************************************************************/ void uart_send_str (const char *str) { while(*str) { uart_putchar(*str++); } } /************************************************************************** * * Function : UART0发送数字 * Input : num : 待发送的数字 * Author : zy * *************************************************************************/ void uart_send_num(u32 num) { char ch[32]; u8 i = 0; int_to_str(num, ch); uart_send_str(ch); }
4.3 int_to_str
/************************************************************************** * * Function : 把无符号数字转换成字符串 * Input : num : 无符号数字 str : 字符串 * Author : zy * *************************************************************************/ void int_to_str( u32 num, char *str ) { u8 i,j,k; char ch; i = 0; do { str[i++] = num%10 + '0'; } while( (num/=10)>0 ); str[i] = '\0'; for( k=0, j=i-1; k<j; k++,j--) /* 倒序排列 */ { ch = str[k]; str[k] = str[j]; str[j] = ch; } }
4.4 串口接收
/************************************************************************** * * Function : 等待接受1个字节 * Input : ch : 读取的字符 * Author : zy * *************************************************************************/ void uart_getchar(char *ch) { while(!(UTRSTAT0 & (0x01))); /* 等待接收到数据 */ *ch=URXH0; /* 获取接收到的8为数据 */ }
五、代码下载
Young / s3c2440_project【4.uart】
这个代码引入了c的一些标准库,同时重定向了prinf函数,输出到串口。这个代码已经远超过4kb,并且没有将代码从NAND拷贝到SDRAM运行,只可以下载到SDRAM 0x30000000处运行。