找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1798|回复: 0
收起左侧

ARM9(S3C2440)的UART

[复制链接]
ID:105323 发表于 2016-3-4 16:34 | 显示全部楼层 |阅读模式
通用异步收发器简称UART,即“UniversalAsynchronous Receiver Transmitter”

     s3c2440提供了三个UART端口,它们都可以通过查询、中断和DMA方式传输数据,而且每个UART都分别有一个64个字节的接收FIFO和一个64个字节的发送FIFO。UART由波特率发生器、发送器、接收器和控制逻辑组成,使用系统时钟可以达到115.2Kbit/s,如果使用UEXTCLK引脚提供的外部时钟,则可以达到更高的波特率,波特率可以通过编程进行控制。UART的结构示意图如下所示:


     UART的工作原理是:当发送数据时,CPU先将数据写入发送FIFO中,然后UART会自动将FIFO中的数据复制到“发送移位器”中,发送移位器将数据一位一位(先发最低位)地发送到TXDn数据线上(根据设定的格式、插入开始位。校验位和停止位)。接收数据时,“接收移位器”将RXDn数据线上的数据一位一位(同样是先发最低位)接收进来,然后复制到接收FIFO中,CPU即可从中读取数据。
    S3C2440UART有3个独立通道,每个通道支持的停止位有1位、2位,数据位有5、6、7、8位,支持校验功能,另外还有红外发送/接收功能。
     在使用UART之前,需要设置波特率、传输格式(有多少个数据位、是否使用校验位、是奇校验还是偶校验、有多少个停止位、是否使用流量控制),选择UART通道的工作模式为中断模式或DMA模式。
    下面我们来介绍一下UART比较重要的寄存器。
1、UBRDIVn  寄存器(UART BAUD RATE DIVISOR):设置比特率
     根据给定的波特率、所选择的时钟源的频率,可以通过以下公式计算UBRDIVn寄存器的值(n为0~2,对应3个UART通道)


2.ULCONn寄存器(UART LINE CONTROL):设置传输格式

ULCONn寄存器(n为0~2),假如我们要设置UART0的传输格式为:8位数据位,每帧1个停止位,无奇偶校验位,普通模式。就要设置ULCON0的[7:0]为00000011 如下图红色标记所示

3、UCONx寄存器  (UART CONTROL)
     UCONn寄存器用于选择UART时钟源,设置UART中断方式等。S3C244UART有三个时钟源PCLK、UEXTCLK、FCLK/n,这里我们只列出[11:0]位,因为[15:12]是保留,使用默认值0000 ,这里我们不理它。
  
4、UFCONn寄存器(UART FIFOCONTROL)、UFSTATn寄存器(UART FIFO STATUS)
      UFCONn寄存器用于设置是否使用FIFO,设置各个FIFO的触发阈值,即发送FIFO中有多少个数据时产生中断,接收FIFO中有多少个数据时产生中断。
     读取UFSTATn寄存器可以知道各个FIFO是否已经满、其中有多少个数据。当不使用FIFO时候,可认为FIFO的深度为1,使用FIFO时候S3C2440的FIFO的深度是64比S3C2440多了4倍。
5、UMCONn寄存器(UART MODEMCONTROL)UMSTATn寄存器(UART MODEM STATUS)
    这两类寄存器用于流量控制,我们一般不会用到。
6、UTRSTATn寄存器(UART TX/RXSTATUS)
UTRSTATn寄存器用来表明数据是否已经发送完毕、是否已经接收到数据。
接受缓冲区数据就绪[0]位:表示当接收到数据时,此位被自动设为1
发送缓冲区空[1]位:表示当发送缓冲区中没有数据时,此位被自动设为1
发送器空[2]位:表示当发送缓冲区中没有数据,并且最后一个数据也已经发送出去时,此位被自动设为1

7、UERSTATn寄存器(UART ERRORSTATUS)
    这个寄存器用来表示各种错误是否发送。
8、UTXHn寄存器(UART TRANSMIT BUFFERREGISTER)
CPU将数据写入这个寄存器,UART即会将它保存到缓冲区中,并自动发送出去。

9、URXHn寄存器(UART RECEIVE BUFFERREGISTER)
当UART接收到数据时,CPU读取这个寄存器,即可获得数据。

在TQ2440上的UART程序:
void main(void)
{
//.........//时钟初始化省略
charstring[256];//用于存放接收到的字符
Uart_Init(0,115200);        // UART初始化,0代表使用当前的PCLK ,115200是波特率

rGPHCON&=~((3<<4)|(3<<6));
rGPHCON|=(2<<4)|(2<<6);     //把GPH3、GPH2设置为RXD[0] 、TXD[0] 功能

Uart_Printf("\n uart test  madeby huang ge\n"); //串口上打印

while(1)
{
   Uart_Printf("please,inputstring\n") ;   //这些函数都是在2440lib.c 中定义的
  Uart_GetString(string);      //获取输入的字符
   Uart_Printf("you inputstring:\n%s\r\n",string);  //打印出输入的字符
}           

}


//以下是函数的定义:

//***************************[ UART]******************************
static int whichUart=0;//选择串口:0 1 2
void Uart_Init(int pclk,intbaud)
{
    int i;
    if(pclk ==0)
   pclk = PCLK;

    rUFCON0 =0x0;//FIFO disable
    rULCON0 =0x3;//Line control register:Normal,No parity,1 stop,8bits
    rUCON0 =0x5;//P11-22 control register
    rUBRDIV0 =(int)(plck/16./baud+0.5)-1 //Baud rate divisior register
    for(i=0;i<100;i++);
}

//***************************Uart_Printf******************************

//If you don't use vsprintf(), thecode size is reduced very much.
void Uart_Printf(char *fmt,...)
{
va_list ap;
char string[256];
va_start(ap,fmt);
vsprintf(string,fmt,ap);
Uart_SendString(string);
va_end(ap);
}


//***************************Uart_SendString ******************************


void Uart_SendString(char *pt)
{
   while(*pt)
       Uart_SendByte(*pt++);
}

//***************************Uart_SendByte ******************************

void Uart_SendByte(int data)
{
if(whichUart==0)
{
  if(data=='\n')
  {
   while(!(rUTRSTAT0& 0x2));
   //Delay(1);                //because the slow response of hyper_terminal
   WrUTXH0('\r');//rUTXH0= ('\r')
  }
  while(!(rUTRSTAT0& 0x2));   //Waituntil THR is empty.
  // Delay(1);
  WrUTXH0(data);//rUTXH0 =(unsigned char)data;
}
else if(whichUart==1)
{
  if(data=='\n')
  {
   while(!(rUTRSTAT1& 0x2));
   //Delay(1);                //because the slow response of hyper_terminal
   rUTXH1 ='\r';
  }
  while(!(rUTRSTAT1& 0x2));   //Waituntil THR is empty.
  //Delay(1);
  rUTXH1 = data;
}  
else if(whichUart==2)
{
  if(data=='\n')
  {
   while(!(rUTRSTAT2& 0x2));
   //Delay(1);                //because the slow response of hyper_terminal
   rUTXH2 ='\r';
  }
  while(!(rUTRSTAT2& 0x2));   //Waituntil THR is empty.
  //Delay(1);
  rUTXH2 = data;
}      
}      
//***************************Uart_GetString ******************************
void Uart_GetString(char*string)
{
    char*string2 = string;
    charc;
    while((c =Uart_Getch())!='\r')
    {
       if(c=='\b')
       {
           if( (int)string2 < (int)string )
           {
               Uart_Printf("\b \b");
               string--;
           }
       }
       else
       {
           *string++ = c;
           Uart_SendByte(c);
       }
    }
   *string='\0';
   Uart_SendByte('\n');
}


//***************************Uart_Getch ******************************
char Uart_Getch(void)
{
   if(whichUart==0)
   {      
       while(!(rUTRSTAT0 & 0x1)); //Receive dataready
       return RdURXH0();
    }
    elseif(whichUart==1)
   {      
       while(!(rUTRSTAT1 & 0x1)); //Receive dataready
       return RdURXH1();
    }
    elseif(whichUart==2)
    {
       while(!(rUTRSTAT2 & 0x1)); //Receive dataready
       return RdURXH2();
    }
   
    return 0;
}      









回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表