历史上的今天
返回首页

历史上的今天

今天是:2025年03月03日(星期一)

正在发生

2020年03月03日 | s3c2440A开发板UART总结以及UART代码详解

2020-03-03 来源:eefocus

一.概述:

s3c2440A 提供三个独立异步串口端,每个端口可以在中断模式和DMA模式下操作,也就是讲UART可以产生一个中断或DMA请求用于CPU和UART之间的数据传输。


每一个串口UART都有一个64字节的发送FIFO,一个64字节的接收FIFO。


要实现UART与上位机之间的通信,必须遵循木一个协议,通过ULCON可以定义传输数据的位数,停止的位数,红外模式等。


波特率的时钟源有:PCLK,FCLK/n,UEXTCLK,通过UCON寄存器的10,11位进行选择。大小可以这样计算:时钟源频率/(波特率*16)-1;如果计算的结果是个小数,那么把这个最接近的整数放到UBRDIVn中,即如果算的结果是16.25,那么可以把这个数取16放到UBRDIVn中。


对于FIFO和MODEM的设定是否决定相应寄存器的设定。如果没有使用FIFO和MODEM那么可以不设定这两个相应寄存器。


二.UART发送与接收:

数据发送:先由ULCON寄存器设置停止位,数据位,奇偶校验位等,因为他是可编程的,发送完数据后可以发送一个终止信号。之后串口发送数据到TxFIFO。


数据接收:先由ULCON寄存器设置停溢出,停止条件,奇偶校验错等,因为他是可编程的,接收到的数据存放在RxFIFO中。当接收器三个字长的时间內没有接收到数据并且RxFIFO在FIFO模式下不为空那么接收超时。


三.相关寄存器

S3C2440A的UART单元对每个串口使用10多个寄存器,3个串口共使用了30多个寄存器。我稍微总结了下(下面的n表示串口编号,取值为0,1,2;寄存器名称中第一个字母U应该是表示UART):

ULCONn:线路控制寄存器,用于设定线路的字长度、停止位个数、奇偶校验方式、是否使用红外模式。(看的书中翻译成“线性控制寄存器”,我感觉是不正确的)

UCONn: 控制寄存器,用于设定操作模式(中断或轮询/DMA)、环回模式、中断方式、时钟选择。

UFCONn:FIFO控制寄存器,用于控制FIFO操作方式,如是否使用FIFO以及触发级别。

UMCONn:Modem控制寄存器,用于设置是否使用AFC(自动流控制)和RTS。TTL2是不支持流控制的,所以没有UMCON2寄存器。

UTRSTATn:收发状态寄存器,可从中读取收发保持寄存器的状态,即是否有数据,仅在非FIFO模式下使用。

UFSTATn:FIFO状态寄存器,可从中读取FIFO状态信息,用于FIFO模式。

UMSTATn:Modem状态寄存器,可从中读取Modem状态,即CTS信号状态。TTL2不支持流控制,所以没有UMSTAT2寄存器。

UERSTATn:错误状态寄存器,可从中读取接收错误状态。

UTXHn和URXHn:收发保持(对非FIFO模式)和缓冲(对FIFO模式)寄存器,用于收发数据。

UBRDIV:波特率除数寄存器,用于设定串口通信波特率。


四.看到有关于中断的介绍不错 贴进来分享下:

边沿(脉冲?)触发:一旦(as soon as)Tx缓冲区变为(becomes)空(非FIFO模式)或者达到(reaches)Tx FIFO触发级别(FIFO模式),则请求中断。注意,这里的“一旦”不仅限定前半句(非FIFO模式),也限定后半句(FIFO模式)。“一旦”与“变为”和“达到”连接起来,表示的是一个时间点,一个变化过程,是变为空或者达到触发级别的时间点或者说变化过程中请求中断。这个时间点过后,或者变化完成后,就不再请求中断了。只要处理中断后,清除源未决寄存器(SRCPND)和中断寄存器(INTPND)的相关位,就不会再有中断发生了。


电平触发:当(while)Tx缓冲区为空(非FIFO模式)或者达到Tx FIFO触发级别,则请求中断。这里的“当”限定前半句和后半句。“当”表示的是一种状态,是处于缓冲区空或者达到Tx FIFO触发级别的状态的时候,就请求中断。处理中断后,即使清除了源未决寄存器(SRCPND)和中断寄存器(INTPND)的相关位,只要这种状态存在,就一直请求中断,即会再次发起中断请求。只有不存在这种状态了,才不会再发起中断请求。

 

五.FIFO与非FIFO的区别:

S3C2440A的UART内部对于接收和发送各有64字节的缓冲区,当使用FIFO模式时,UART将使用这个缓冲区进行数据暂存操作,这样可以增加数据吞吐量,提高传输速率。其实,非FIFO模式也可以看作是特殊的FIFO模式,即只有一个字节缓冲区的FIFO模式。二者的主要不同在于读取缓冲区状态的方式:非FIFO模式下,通过UTRSTAT寄存器得知收发缓冲区状态;FIFO模式下,则从UFSTAT寄存器获得缓冲区状态。要注意的是,在FIFO模式下,只有达到触发级别后才会发起Rx或Tx中断。比如说,如果设置接收触发级别为16字节,则只有在接收缓冲区中有16个字节以上数据时,才会发起Rx中断请求。如果需要进行输入回显,则可能导致不能立即回显用户在串口工具中输入的字符。


六。自动流控制(AFC)

AFC(Auto Flow Control):自动流控制。S3C44BoX中的UART用nRTS(发送请求信号)和nCTS(清除发送信号)来支持自动流控制,以此实现UART之间的互联。

自动流控制涉及到RTS和CTS,我查了下相关缩写的含义:

DTE:Data Terminal Equipment,数据终端设备,一般指计算机。

DCE:Data Communication Equipment,数据通信设备,一般是调制解调器(Modem)。

DTR:Data Terminal Ready,数据终端就绪,DTE向DCE发送这个信号表示已经准备就绪。

DSR:Data Set Ready,数据设备就绪,DCE向DTE发送这个信号表示已经准备就绪。

RTS:Request To Send,请求发送,DTE向DCE请求发送数据。

CTS:Clear To Send,清除发送,DCE向DTE表示准备就绪,可以接收数据了。


摘自百度文库:

 The S3C2440A's UART 0 and UART 1 support auto flow control with nRTS and nCTS signals. In case, it can be

  connected to external UARTs. If users want to connect a UART to a Modem, disable auto flow control bit in

  UMCONn register and control the signal of nRTS by software.

  In AFC, nRTS depends on the condition of the receiver and nCTS signals control the operation of the transmitter.

  The UART's transmitter transfers the data in FIFO only when nCTS signals are activated (in AFC, nCTS means

  that other UART's FIFO is ready to receive data). Before the UART receives data, nRTS has to be activated when

  its receive FIFO has a spare more than 32-byte and has to be inactivated when its receive FIFO has a spare under

  32-byte (in AFC, nRTS means that its own receive FIFO is ready to receive data).


下面是代码UART详细注释:

//=========================================================================
//  工程名称: UART.mcp
//  文件名称:  main.c
//  功能描述:  通过超级终端完成PC和S3C2440的数据传输,利用超级终端输入需要发送的字符,回车后,字符会再发送回来显示。
//  组成文件: main.c 2440lib.c 2440init.s 2440slib.s
//    头文件:  2440addr.h def.h option.h 2440lib.h 2440slib.h
//  程序分析: 采用宏定义的方法实现LED循环点亮
//  硬件连接: 用串口线将开发板和PC机串口相连  
//  维护记录: 2009-8-14 v1.0  
//=========================================================================

#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "option.h"

#include


#include
#include
#include
#include

//====================================================
// 函数定义区
//====================================================
extern void Delay(int time);//延时函数在lib.h中定义
void myUart_Select(int ch);//串口选择
void myUart_Init(int whichuart, int baud);//初始化串口
void myUart_SendByte(char ch);//串口发送一个字节
char myUart_ReceiveByte(void);//接收一个字节
void myUart_Send (char *str);//发送一个字符串
void myUart_receive(char *string);//接收一个字符串
void myUart_Printf(char *fmt,...);//输出串口信息

extern unsigned int PCLK;
static int UartNum=0;
char *string;

//====================================================
// 语法格式:int Main(void)
// 功能描述: 发送并接收字符串,测试UART通信
// 入口参数: 字符串指针
// 出口参数: 无
//======================================================================

int Main(void)
{   
     //设置系统 总线时钟
    SetSysFclk(FCLK_400M);
    ChangeClockDivider(2, 1);
    CalcBusClk();

   

    myUart_Select(1);   //串口数量 
    myUart_Init(0,115200);//初始化串口
 while(1)
 { 
     myUart_Printf("Please Input a string:n");// 通过串口向上位机打印信息
     myUart_receive(string);  
     Delay(50);
     myUart_Send(string);
     myUart_Send("n");
    } 
}

void myUart_Select(int ch)//选择串口数量
{
    UartNum = ch;
}

//====================================================
// 语法格式:void myUart_Init(int whichuart, int baud)
// 功能描述: 对Uart进行初始化,以所需要的波特率为输入参数
// 入口参数: UART端口号  波特率
// 出口参数: 无
//======================================================================

void myUart_Init(int pclk, int baud)
{
    if (pclk == 0)//这里用于计算下面串口波特率
     pclk = PCLK;
    if(UartNum == 0)  //判断是否使用UART0,是的话需要设置相应的管脚位从原理图可以看到需要配GPHCON寄存器  
    {        
      rGPHCON = rGPHCON & (~(0xffff));  

//UART0: RXD0<==>GPH3  TXD0<==>GPH2 这里串口1和串口2也进行了配置,但是没用到。
      rGPHCON = rGPHCON | (0xaaa0) ;     //设置GPH端口为UART口1010101010100000
      rGPHUP  = 0x0;                     //使能上拉功能

 
        rUFCON0=0x00;   // 不使用FIFO 
        rUMCON0=0x00;   //不使用自动流控制
        rULCON0=0x03;   //不采用红外线传输模式,无奇偶校验位,1个停止位,8个数据位
        //发送中断为电平方式,接收中断为边沿方式,禁止超时中断,允许产生错误状态中断,禁止回送模式,禁止中止信号,传输模式为中断请求模式,接收模式也为中断请求模式。 001001000101
        rUCON0=0x245;  

         


        rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 );  //根据波特率计算UBRDIV0的值
        Delay(10);
     }
     else if(UartNum == 1)
     {
       rGPHCON = rGPHCON & (~(0xffff)) ; //UART1: RXD1<==>GPH5  TXD1<==>GPH4
       rGPHCON = rGPHCON | (0xaaa0) ;    //设置GPH端口为UART口
       rGPHUP  = 0x0;                    // 使能上拉功能
 
        rUFCON1=0x0;   
        rUMCON1=0x0;  
        rULCON1=0x3;
        rUCON1=0x245;
        rUBRDIV1=( (int)(pclk/16./baud+0.5) -1 );
        Delay(10);
     }
}

//====================================================
// 语法格式:void myUart_SendByte(char ch)
// 功能描述: 发送字节数据
// 入口参数: 发送的字节数据      
// 出口参数: 无
//====================================================================

void myUart_SendByte(char ch)
{
 if (UartNum ==0)
    {
  if(ch=='n')
  {



 //非FIFO模式时,等待,直到发送缓冲区为空,0010为空的时候退出,如果是FIFO模式那么检测UFTRSTAT寄存器,MODEM模式下,检测UMTRSTAT寄存器

      while(!(rUTRSTAT0 & 0x2)); 

       Delay(10);             //超级中断的响应速度较慢 
     //这个在addr.h的宏定义,向发送缓冲区写入一个数#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)

      WrUTXH0('r');              //发送回车符
  }
    while(!(rUTRSTAT0 & 0x2));      //等待,直到发送缓冲区为空
//  Delay(10);
    WrUTXH0(ch);                    //发送字符

//发送
    }
 else
    {
  if(ch=='n')
     {
      while(!(rUTRSTAT1 & 0x2));   //等待,直到发送缓冲区为空
//      Delay(10);                  //等待
      rUTXH1='r';
     }
     while(!(rUTRSTAT1 & 0x2));  //Wait until THR is empty.
//     Delay(10);
     WrUTXH1(ch);
    } 
}

推荐阅读

史海拾趣

CommScope Inc公司的发展小趣事

CommScope Inc公司的前身可以追溯到1953年,在北卡罗莱纳州的山核桃成立的高级电缆公司。这个公司以其卓越的电话线产品赢得了市场的认可。到了1964年,康普的产品线开始使用高级电缆和同轴电缆,标志着公司在电缆技术领域的突破。随着技术的不断革新,1966年,康普在卡托巴县的福特社区开始数控制造,进一步提升了生产效率。1976年,大陆高级康普部门被Frank Drendel领导的投资者集团收购,这为公司日后的发展奠定了坚实的基础。

Hitachi Chemical Co America Ltd公司的发展小趣事

尽管康普在通信行业取得了显著的成就,但它也面临着诸多挑战。其中最大的挑战之一来自网络安全和数据保护。近年来,随着网络安全事件的频发,康普也遭受了数据泄露等网络安全事件的冲击。然而,康普积极应对挑战,加强了网络安全和数据保护的投入,提升了公司的网络安全防护能力。同时,康普也积极寻找新的增长点,拓展5G、物联网等新兴市场及成长型市场的渠道,为公司的未来发展奠定了坚实的基础。

以上五个故事仅是CommScope Inc公司电子行业发展的部分缩影,实际上,公司的发展历程远比这些故事更为丰富和复杂。但通过这些故事,我们可以看到CommScope Inc公司在技术创新、市场开拓、产品升级以及应对挑战等方面所做出的努力和取得的成就。

Gould Fiber Optics公司的发展小趣事
可能是电源插头未插好、保险丝熔断、输入电压异常或电源内部元件损坏。
EOZ Secme公司的发展小趣事

随着环保意识的不断提高,EOZ Secme积极响应绿色环保的号召。公司在生产过程中采用了多项环保措施,减少了对环境的污染。同时,EOZ Secme还积极参与社会公益事业,通过捐款、赞助等方式回馈社会。这些举措不仅提升了公司的社会形象,也为其赢得了更多消费者的认可和支持。

Anaren公司的发展小趣事

EOZ Secme公司自创立之初,就致力于电子安全技术的研发。在2010年代初,随着物联网技术的兴起,EOZ Secme敏锐地捕捉到这一机遇,投入大量资源进行物联网安全技术的研发。经过数年的努力,公司成功开发出了一系列具有自主知识产权的物联网安全解决方案,并在市场上获得了广泛应用。这些技术的创新不仅提高了EOZ Secme的市场竞争力,也奠定了其在电子安全领域的领先地位。

中微股份(Cmsemicon)公司的发展小趣事

在刻蚀设备领域取得成功后,中微并没有满足于现状,而是积极拓展多领域,实现业务多元化。2012年,公司完成了首台MOCVD设备的研制,成功进入薄膜沉积领域。2016年,公司又完成了首台ICP刻蚀设备的研制,进一步巩固了在刻蚀设备领域的领先地位。此外,公司还在环保领域有所布局,成功研制出首台VOC设备。这些举措不仅丰富了公司的产品线,也为公司带来了更多的市场机遇。

问答坊 | AI 解惑

简易数控直流电源

简易数控直流电源  94年的题, 谁会做啊, 我想了解以下他的原理几过程. 我的邮箱,cf2928@163.com 要不谁告诉我那有我去下也行,谢了.…

查看全部问答>

【分享】mini2440开发板实现国际象棋人机对弈

前段时间买了2440开发板也没怎么搞,惭愧:$ 最近没啥其它事情就好好啃啃吧,哎……没什么基础啊,先欣赏下别人的东西吧 【mini2440开发板实现国际象棋人机对弈 】 我在机子上跑了一下,好像不太能跟电脑对弈啊,不知道哪个地方还有问题 ...…

查看全部问答>

闪电击中世界最高建筑哈利法塔

上面这张令人震惊的照片展示了世界最高建筑哈利法塔遭闪电击中时的场面。 照片的拍摄者是一位23岁名叫穆罕默德·哈姆丹的学生,来自巴基斯坦,目前在阿联酋攻读建筑工程学。当时,迪拜正遭受暴风雨的袭击。雷电中,高达828米的哈利法塔在紫色的 ...…

查看全部问答>

传输线和反射的经典文章

传输线和反射的经典文章…

查看全部问答>

U盘多盘符的问题

我在一个嵌入式系统中,主机在GET MAX LUN我已经返回01,但是主机并未显示2个盘符.仅仅出现了一个盘符 还需要做哪方面的工作…

查看全部问答>

VC如何发彩信,已经实现ATDT*99***1#这一步了,下一步应该是什么,内容打包?如果打包?

VC如何发彩信,已经实现ATDT*99***1#这一步了,下一步应该是什么,内容打包?如果打包? ATE AT+CMGF=0 AT+CIMI   AT+CIMI获得IMSI  IMSI 国际移动用户识别码(IMSI) international mobile subscriber identity 国际上为唯一识别 ...…

查看全部问答>

DM642 编码器初始化

 /*进行SAA7121H的初始化*/ GPIO_RSET(GPVAL,0x0); addrI2C = 0xB8 >>1; /*选择第0路的I2C的地址*/ /*将第0路的视频输入口的数据口设为高阻状态,   使能SCLK,将第27脚设为输入*/ _IIC_write(hSeeddm642i2 ...…

查看全部问答>

关于桥式整流

这是在空闲之际模拟的几张桥式整流和接电容的图片,希望能对大家有点用处。    大家注意看波形随着电容的变化而变化。…

查看全部问答>

2812 flash不能烧写

问题是这样的:我用flash烧写了一个控制电机的程序,不能运行,就把代码改了一下,再进行烧程序的时候就烧不进去啦,我也没有动“lock”和密码(在flash烧写的时候一直很小心的),怎么会锁住呢?很是不解。请EEWORLD老师和各位高手解答一下,谢谢 ...…

查看全部问答>

C题智能小车群

本帖最后由 paulhyde 于 2014-9-15 08:55 编辑 109197413  …

查看全部问答>