程序项目代做,有需求私信(vue、React、Java、爬虫、电路板设计、嵌入式linux等)

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]所决定。
UCON2[15]为FCLK/n 时钟使能/禁止位: 0 = 禁止;1 = 使能;
设置n为7 至21 时,则使用UCON0[15:12];
设置n为22 至36 时,则使用UCON0[15:12];
设置n为37 至43 时,则使用UCON0[14:12]。

UCON0 的情况:UART 时钟 = FCLK / (分频器+6);分频器>0。
UCON1,UCON2 必须为0。
例)
1:UART 时钟 = FCLK/7;
2:UART 时钟 = FCLK/8;
3:UART 时钟 = FCLK/9;
……
15:UART 时钟 = FCLK/21。

UCON1 的情况:UART 时钟 = FCLK / (分频器+21);分频器>0。
UCON0,UCON2 必须为0。
例)
1:UART 时钟 = FCLK/22;
2:UART 时钟 = FCLK/23;
3:UART 时钟 = FCLK/24;
……
15:UART 时钟 = FCLK/36

UCON2 的情况:UART 时钟 = FCLK / (分频器+36);分频器>0。
UCON0,UCON1 必须为0。
例)
1:UART 时钟 = FCLK/37;
2:UART 时钟 = FCLK/38;
3:UART 时钟 = FCLK/39;
……
15:UART 时钟 = FCLK/43

如果UCON0/1[15:12]和UCON2[14:12]都全为0,则分频器将为44,
即UART 时钟 = FCLK/44。总分频范围在7到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:脉冲(非FIFO 模式中Rx缓冲器接收到数据或FIFO模式中达到Rx FIFO 触发深度
则立刻请求中断)
1:电平(当非FIFO 模式中Rx缓冲器正在接收数据或FIFO模式中达到Rx FIFO 触发
深度请求中断)

 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:使能 
保留   [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 : 缓冲寄存器非空
1 : 空(非FIFO 模式中,请求中断或DMA。FIFO 模式中,当Tx FIFO 触发深度设置为00(空)时请求中断或DMA)

如果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处运行。

posted @ 2021-06-12 17:50  大奥特曼打小怪兽  阅读(632)  评论(0编辑  收藏  举报
如果有任何技术小问题,欢迎大家交流沟通,共同进步