S3C2440A 的通用异步收发器 (UART )配有 3 个独立异步串行 I/O (SIO )端口 ,每个都可以是基于中断或基
于 DMA 模式的操作。换句话说 ,UART 可以通过产生中断或 DMA 请求来进行 CPU 和 UART 之间的数据传输。
UART 通过使用系统时钟可以支持最高 115.2Kbps 的比特率。如果是外部器件提供 UEXTCLK 的 UART ,则 UART
可以运行在更高的速度。每个 UART 通道包含两个的 64 字节的 FIFO 给发送和接收。
S3C2440A 的 UART 包括了可编程波特率 ,红外 (IR )发送/接收 ,插入 1 个或 2 个停止位 ,5 位、6 位、7 位
或 8 位的数据宽度以及奇偶校验。 每个 UART 包含一个波特率发生器、发送器、接收器和一个控制单元 .
波特率发生
每个 UART 的波特率发生器为发送器和接受器提供串行时钟。波特率发生器的源时钟可以选择 S3C2440A 的
内部系统时钟或 UEXTCLK。换句话说 ,分频由设置 UCONn 的时钟选项选择。波特率时钟是通过 16 和由 UART
波特率分频寄存器 (UBRDIVn )指定的 16 位分频系数来分频源时钟 (PCLK ,FCLK/n 或 UEXTCLK )产生的。
UBRDIVn 由下列表达式决定 :
UBRDIVn = (int)( UART 时钟 / ( 波特率 × 16) ) - 1
(UART 时钟 :PCLK ,FCLK/n 或 UEXTCLK )
当然 ,UBRDIVn 应该是从 1 至 (216-1 ),只有在使用小于 PCLK 的 UEXTCLK 时设置为 0 (旁路模式 )。
例如 ,如果波特率为 115200 bps 并且 UART 时钟为 40 MHz ,则 UBRDIVn 为 :
UBRDIVn = (int)(40000000 / (115200 x 16) ) - 1
= (int)(21.7) - 1 [取最接近的整数]
= 22 - 1 = 21
UART特殊寄存器:
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/APtHtQue71b2hQG8faF_mw==/2700752401555624467.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](https://i-blog.csdnimg.cn/blog_migrate/9ed7f16e89b8a17215ebead05767ad95.gif)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/9lJu1Jyv1Mc6mZlrt9Kg8w==/1584422643921164204.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/IH9HjdUtMexlmjjajwzv9A==/1584422643921164210.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/bJgzkpDuXgGjDRaZ-N2cCA==/1273674269632599999.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/VkVi4Pa-dUPEdTUrUw-7OA==/1019220890686166345.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/csCZISXzjRCZjQmZpF5KaA==/587156801435309778.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](https://i-blog.csdnimg.cn/blog_migrate/50fd9ff955ecb2b89db7859cc16fb6ef.gif)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/0vpHdNMkPqKwR-WxxyZgKA==/2565081462781089316.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/SbOc3tAdZ8DmF0XKgzoZCg==/1050183138124340296.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/tLCHmy_Zyh8KI7uNYhHOew==/1318991740883016321.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/Ufky-UZE4PZWYq4CjFX46g==/2767180496059340081.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/iQ29vm8llp3CjnuaIwp7Rg==/2809120267589228488.jpg)
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/QrKcx52X4He-Io4E7FUDSA==/573083052599775768.jpg)
************************************************************************************************************************************************************************
![第三节 UART的编程 - 盼盼 - 盼盼的博客](http://img.ph.126.net/ChEMIlFLnx3J8u--9ZW5qA==/1581607894154056040.jpg)
**************************************************************************************************************************************************************************
C示例程序: (实现串口的收发数据)
//***************************************************
//功能:实现查询发式串口的收发功能,接收来自串口的字符,
// 并将接收到的字符发送到超级终端
//接口:串口0
//***************************************************
/*
UART可以进行以下参数设置:
可编程的波特率,红外收/发模式,1或2个停止位,
5,6,7,8位数据宽度和奇偶位校验。
UART包括的寄存器:串口线性控制寄存器(ULCONn),
串口控制寄存器(UCONn),串口收/发状态寄存器(UTRSTATn),
串口波特率分频寄存器(UBRDIVn),串口发送缓存寄存器(UTXHn),
串口接收缓存寄存器(URXHn)。
UBRDIn的置可以按照下式确定:
UBRDIn=(int)(PCLK/(bps*16))-1
除数的范围为1到(16**2-1)。
例如,如果波特率为115200bps且PCLK或UCLK为50MHz,则UBRDIn为:
UBRDIn =(int)(50000000/(115200×16))-1
=(int)(27.1)-1
=26
*/
/*
编程步骤:
1,UART的初始化:包括串口的选择,IO口的初始化,UART的UFCONn,
UMCONn,ULCONn,UCONn及波特率的初始化
2,UART的发送数据:要发送的数据,首先被写入FIFO,然后拷贝到发送
移位寄存器,接着它从数据输出端(TxDn)依次被移位输出。
3UART的接收数据:被接收的数据也同样从数据接口RxDn移位
输入到移位寄存器,然后拷贝到FIFO中
4,UART的发送数据。
*/
#include "2440lib.h"
#include "2440addr.h"
static int UartNum=0; //串口选择的标志位,可以省略,只是方便多个串口选择
//===============================================================
//对Uart进行初始化,以所需要的波特率为输入参数
void myUart_Init(int whichuart, int baud)
{
if(whichuart==0) //判断是否选择串口0,假如选择串口1,则应该初始化串口1的寄存器
{
UartNum=0; //串口选择的标志位
rGPHCON = rGPHCON & (~(0xffff)) ;
rGPHCON = rGPHCON | (0xaaa0) ;
rGPHUP = 0x0; // 使用内部上拉电阻。
rUFCON0=0x00; //不使用FIFO
rUMCON0=0x00; //不使用自动流控制
rULCON0=0x03; //不采用红外线传输模式,无奇偶校验位,1个停止位,8个数据位
rUCON0=0x245; //发送中断为电平方式,接收中断为边沿方式,禁止超时中断,允许产生错误状态中断,禁止回送模式,禁止中止
//信号,传输模式为中断请求模式,接收模式也为中断请求模式。
rUBRDIV0=( (int)(PCLK/16./baud+0.5) -1 );
Delay(10);
}
}
/*******************************************************************/
void myUart_SendByte(char ch)
{
if (UartNum ==0) //判断是否选择串口0,在这里也可以不用这句,
//只是方便多个串口选择时用
{
if(ch=='\n') //判断是否是换行字符,如果是换行字符,发送一个回车符
{
while(!(rUTRSTAT0 & 0x2)); //等待,直到发送缓冲区为空
WrUTXH0('\r'); //发送回车符
}
while(!(rUTRSTAT0 & 0x2)); //等待,直到发送缓冲区为空
Delay(100);
WrUTXH0(ch); //串口0发送字符
}
}
/********************************************************************/
void Uart_Send (char *str)
{
myUart_Init(0,115200);
while (*str)
myUart_SendByte(*str++);
}
/********************************************************************/
char myUart_ReceiveByte(void) //接收字符函数
{
if(UartNum==0) //选择串口0
{
while(!(rUTRSTAT0 & 0x1)); //检查串口状态寄存器0,是否有数据到来,启动接收过程
return RdURXH0(); //URXH0串口接收缓存寄存器0
}
return 0;
}
/********************************************************************/
void Uart_receive(char *string) //接收函数
{
char *string2 = string;
char c;
myUart_Init(0,115200); //串口的选择与波特率的选择
while((c = myUart_ReceiveByte())!='\r') //循环判断接收字符函数返回的字符是不是换行字符
{
if(c=='\b')
{
if( (int)string2 < (int)string )
{
Uart_Printf("\b \b");
string--;
}
}
else
{
*string++ = c;
myUart_SendByte(c);
}
}
*string='\0'; //接收完毕后执行空格
myUart_SendByte('\n'); //如果接收完毕后,补充一个回车
}
/********************************************************************/
int Main(void)
{
char *str;
char *string;
ChangeClockDivider(3,1); //1:3:6
ChangeMPllValue(127,2,1); //405MHZ
Port_Init();
Isr_Init();
Uart_Send("Please Input a string:\n"); //超级终端提示输入一串字符
Uart_receive(string); //2440接收字符
*str=*string; //发送的跟接收的字符相等
Delay(500);
Uart_Send(str); //2440发送字符显示到超级终端上
while(1);
}
*************************************************************************************************************************************************************