历史上的今天
今天是: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 //==================================================== extern unsigned int PCLK; //==================================================== int Main(void) myUart_Select(1); //串口数量 void myUart_Select(int ch)//选择串口数量 //==================================================== void myUart_Init(int pclk, int baud) //UART0: RXD0<==>GPH3 TXD0<==>GPH2 这里串口1和串口2也进行了配置,但是没用到。 //==================================================== void myUart_SendByte(char ch) Delay(10); //超级中断的响应速度较慢 WrUTXH0('r'); //发送回车符 //发送
#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,...);//输出串口信息
static int UartNum=0;
char *string;
// 语法格式:int Main(void)
// 功能描述: 发送并接收字符串,测试UART通信
// 入口参数: 字符串指针
// 出口参数: 无
//======================================================================
{
//设置系统 总线时钟
SetSysFclk(FCLK_400M);
ChangeClockDivider(2, 1);
CalcBusClk();
myUart_Init(0,115200);//初始化串口
while(1)
{
myUart_Printf("Please Input a string:n");// 通过串口向上位机打印信息
myUart_receive(string);
Delay(50);
myUart_Send(string);
myUart_Send("n");
}
}
{
UartNum = ch;
}
// 语法格式:void myUart_Init(int whichuart, int baud)
// 功能描述: 对Uart进行初始化,以所需要的波特率为输入参数
// 入口参数: UART端口号 波特率
// 出口参数: 无
//======================================================================
{
if (pclk == 0)//这里用于计算下面串口波特率
pclk = PCLK;
if(UartNum == 0) //判断是否使用UART0,是的话需要设置相应的管脚位从原理图可以看到需要配GPHCON寄存器
{
rGPHCON = rGPHCON & (~(0xffff));
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)
// 功能描述: 发送字节数据
// 入口参数: 发送的字节数据
// 出口参数: 无
//====================================================================
{
if (UartNum ==0)
{
if(ch=='n')
{
//非FIFO模式时,等待,直到发送缓冲区为空,0010为空的时候退出,如果是FIFO模式那么检测UFTRSTAT寄存器,MODEM模式下,检测UMTRSTAT寄存器
while(!(rUTRSTAT0 & 0x2));
//这个在addr.h的宏定义,向发送缓冲区写入一个数#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
}
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);
}
}
史海拾趣
|
前段时间买了2440开发板也没怎么搞,惭愧:$ 最近没啥其它事情就好好啃啃吧,哎……没什么基础啊,先欣赏下别人的东西吧 【mini2440开发板实现国际象棋人机对弈 】 我在机子上跑了一下,好像不太能跟电脑对弈啊,不知道哪个地方还有问题 ...… 查看全部问答> |
|
上面这张令人震惊的照片展示了世界最高建筑哈利法塔遭闪电击中时的场面。 照片的拍摄者是一位23岁名叫穆罕默德·哈姆丹的学生,来自巴基斯坦,目前在阿联酋攻读建筑工程学。当时,迪拜正遭受暴风雨的袭击。雷电中,高达828米的哈利法塔在紫色的 ...… 查看全部问答> |
|
VC如何发彩信,已经实现ATDT*99***1#这一步了,下一步应该是什么,内容打包?如果打包? VC如何发彩信,已经实现ATDT*99***1#这一步了,下一步应该是什么,内容打包?如果打包? ATE AT+CMGF=0 AT+CIMI AT+CIMI获得IMSI IMSI 国际移动用户识别码(IMSI) international mobile subscriber identity 国际上为唯一识别 ...… 查看全部问答> |
|
/*进行SAA7121H的初始化*/ GPIO_RSET(GPVAL,0x0); addrI2C = 0xB8 >>1; /*选择第0路的I2C的地址*/ /*将第0路的视频输入口的数据口设为高阻状态, 使能SCLK,将第27脚设为输入*/ _IIC_write(hSeeddm642i2 ...… 查看全部问答> |
|
问题是这样的:我用flash烧写了一个控制电机的程序,不能运行,就把代码改了一下,再进行烧程序的时候就烧不进去啦,我也没有动“lock”和密码(在flash烧写的时候一直很小心的),怎么会锁住呢?很是不解。请EEWORLD老师和各位高手解答一下,谢谢 ...… 查看全部问答> |




