SPI、IIC和UART是最常用的三种串行总线,这三种总线在s3c2440中都被集成了。在这里我们主要介绍UART,另两个总线在后面的文章中给出。
UART(Universal Asynchronous Receiver/Transmitter,通用异步接收/发送装置)用于异步通信,可以实现全双工发送和接收。它不仅可以实现不同嵌入式系统之间的通信,还可以实现与PC之间的通信。
s3c2440提供了三个UART端口,它们都可以通过查询、中断和DMA方式传输数据,而且每个UART都分别有一个64个字节的接收FIFO和一个64个字节的发送FIFO。在这里,我们只给出非FIFO模式,即传输数据不利用FIFO缓存,一个字节一个字节地传输。
下面我们就给出如何用s3c2440来实现非FIFO的UART通信。
第一步:串口编写流程
1、初始化引脚: 把使用到的引脚GPH2、GPH3定义为TXD0、RXD0
GPHCON |= 0xa0
GPHUP |= 0x0c
2、设置串口数据格式寄存器ULCON0:8个数据位,1个停止位,无校验,正常操作模式(与之相对的是Infra-Red Mode,此模式表示0、1的方式比较特殊)
ULCON0 :串口线性控制寄存器,
ULCON0 [1,0]——数据位数(5,6,7,8)位
ULCON0 [2]——停止位数(1,2)位
ULCON0 [5:3]——奇偶校验(奇校验,偶校验,不校验,强制校验)
ULCON0 [6]——普通模式还是红外模式
ULCON0 = 0x03
3、设置串口控制寄存器UCON0:设置发送、接收都使用“中断或查询方式”
UCON0 = 0x05
4、设置串口FIFO寄存器UFCON0:本次不使用FIFO,设为默认值0
UFCON0 = 0x00
5、UMCON0 :本次不使用流控,设为默认值0
UMCON0 = 0x00
6、设置波特率寄存器UBRDIV0:波特率计算公式UBRDIVn = (int)(PCLK / (bps x 16) ) –1 ,要看说明书验算一下此波特率是否在可容忍的误差范围之内;如果不在,则需要更换另一个波特率。这个计算结果很可能是小数,把该小数取最接近的整数,放入寄存器UBRDIVn中就完成了波特率的设置。如我们选择波特率的时钟源为PCLK,它为50MHz,我们设置的波特率为115.2kHz,通过上式计算的结果为26.13,取整后得到26,那么我们把26放入UBRDIVn中即可。
UBRDIV0 = 0x12
至此,串口初始化完毕,下面进行数据的收发:
由于UART是通过字节方式传输数据的,因此要区分是大端模式还是小端模式,也就是说这两个寄存器在这两种模式下,所在的地址是不同。为了了解当前数据传输的各种状态,还需要一些状态寄存器。
串口状态寄存器:UTRSTAT0 其位功能如下
位[2]:无数据发送时,自动设为1。当我们要使用串口发送数据时,先读此位以判断是否有数据正在占用发送口。
位[1]:发送FIFO是否为空,本次未用此位
位[0]:接收缓冲区是否有数据,若有,此位设为1。需要用到这位,需要不断查询此位一判断是否有数据已经被接收。
串口发送寄存器UTXH0 :把要发送的数据写入此寄存器。
3、接收数据:
UTRSTAT0:如同上述“发送数据”所列,我们用到位[0]
接收缓存寄存器URXH0 : 当查询到UTRSTAT0 位[0]=1时,读此寄存器获得串口接收到的数据。
我们给出UART通信的两种方法:查询和中断。为了验证程序,使用任一款的串行通信软件来实现PC和s3c2440之间的通信即可。
首先给出的是查询程序。它是在主程序的循环体内不断查询UART端口,当有数据来时,就接收数据,并再通过UART发送该数据。然后根据所接收数据的不同,分别执行不同的内容,如点亮、熄灭LED,蜂鸣器响、或不响。在这里,我们每次只完成一个字节的传输。
#define rGPBCON (*(volatile unsigned *)0x56000010) //Port B control
#define rGPBDAT (*(volatile unsigned *)0x56000014) //Port B data
#define rGPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
#define rGPHCON (*(volatile unsigned *)0x56000070) //Port H control
#define rGPHUP (*(volatile unsigned *)0x56000078) //Pull-up control H
#define rULCON0 (*(volatile unsigned *)0x50000000) //UART 0 Line control
#define rUCON0 (*(volatile unsigned *)0x50000004) //UART 0 Control
#define rUFCON0 (*(volatile unsigned *)0x50000008) //UART 0 FIFO control
#define rUMCON0 (*(volatile unsigned *)0x5000000c) //UART 0 Modem control
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) //UART 0 Tx/Rx status
#define rUERSTAT0 (*(volatile unsigned *)0x50000014) //UART 0 Rx error status
#define rUFSTAT0 (*(volatile unsigned *)0x50000018) //UART 0 FIFO status
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) //UART 0 Modem status
#define rUBRDIV0 (*(volatile unsigned *)0x50000028) //UART 0 Baud rate divisor
//little endian
#define rUTXH0 (*(volatile unsigned char *)0x50000020) //UART 0 Transmission Hold
#define rURXH0 (*(volatile unsigned char *)0x50000024) //UART 0 Receive buffer
void Main(void)
{
char ch;
rGPBCON = 0x015551;
rGPBUP = 0x7ff;
rGPBDAT = 0x1e0;
rGPHCON = 0x00faaa; //使用UART0功能
rGPHUP = 0x7ff;
rULCON0 = 0x3; //设置UART0无奇偶校验,一位停止位,8位数据
rUCON0 = 0x245; //PCLK为时钟源,接收和发送数据为查询或中断方式
//10 0100 0101
rUFCON0 = 0; //
rUMCON0 = 0; //
rUBRDIV0 = 26; //设置波特率,PCLK为50MHz,波特率为115.2kHz
while(!(rUTRSTAT0 & 0x2)); //等待并判断发送缓存是否为空
rUTXH0 = 0xaa; //是空,则发送0xAA字节
while(1)
{
while(!(rUTRSTAT0 & 0x1)); //等待并判断接收缓存是否准备好
ch = rURXH0; //接收一个字节数据
while(!(rUTRSTAT0 & 0x2)); //等待并判断发送缓存是否为空
rUTXH0 = ch; //发送一个字节数据
switch(ch) //根据所接收数据的不同,执行不同的程序
{
case 0x11: //灭LED
rGPBDAT |= 0x1e0;
break;
case 0x22: //亮LED
rGPBDAT &= 0x1f;
break;
case 0x33: //蜂鸣器不响
rGPBDAT &= 0x1e0;
break;
case 0x44: //蜂鸣器响
rGPBDAT |= 0x1;
break;
default: //LED灭,蜂鸣器不响
rGPBDAT = 0x1e0;
break;
}
}
}
下面是UART中断程序,它要比查询复杂一些,因为涉及到了中断处理,并且UART发送数据和接收数据是一个中断源。主程序循环体内不执行任何程序,都在UART中断程序内执行。当接收到0x55字节数据时,亮两个LED,当接收到其他数据时,发送该字节,并在发送部分执行亮4个LED程序。
#define _ISR_STARTADDRESS 0x33ffff00
#define pISR_UART0 (*(unsigned *)(_ISR_STARTADDRESS+0x90))
#define U32 unsigned int
#define rGPBCON (*(volatile unsigned *)0x56000010) //Port B control
#define rGPBDAT (*(volatile unsigned *)0x56000014) //Port B data
#define rGPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
#define rGPHCON (*(volatile unsigned *)0x56000070) //Port H control
//#define rGPHDAT (*(volatile unsigned *)0x56000074) //Port H data
#define rGPHUP (*(volatile unsigned *)0x56000078) //Pull-up control H
#define rULCON0 (*(volatile unsigned *)0x50000000) //UART 0 Line control
#define rUCON0 (*(volatile unsigned *)0x50000004) //UART 0 Control
#define rUFCON0 (*(volatile unsigned *)0x50000008) //UART 0 FIFO control
#define rUMCON0 (*(volatile unsigned *)0x5000000c) //UART 0 Modem control
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) //UART 0 Tx/Rx status
#define rUERSTAT0 (*(volatile unsigned *)0x50000014) //UART 0 Rx error status
#define rUFSTAT0 (*(volatile unsigned *)0x50000018) //UART 0 FIFO status
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) //UART 0 Modem status
#define rUBRDIV0 (*(volatile unsigned *)0x50000028) //UART 0 Baud rate divisor
//little endian
#define rUTXH0 (*(volatile unsigned char *)0x50000020) //UART 0 Transmission Hold
#define rURXH0 (*(volatile unsigned char *)0x50000024) //UART 0 Receive buffer
#define rSRCPND (*(volatile unsigned *)0x4a000000) //Interrupt request status
#define rINTMSK (*(volatile unsigned *)0x4a000008) //Interrupt mask control
#define rINTPND (*(volatile unsigned *)0x4a000010) //Interrupt request status
#define rSUBSRCPND (*(volatile unsigned *)0x4a000018) //Sub source pending
#define rINTSUBMSK (*(volatile unsigned *)0x4a00001c) //Interrupt sub mask
void __irq uartISP(void)
{
char ch;
rSUBSRCPND |= 0x3;
rSRCPND = 0x1<<28;
rINTPND = 0x1<<28;
if(rUTRSTAT0 & 1) //接收数据处理部分
{
ch = rURXH0; //接收字节数据
if(ch==0x55)
rGPBDAT = ~0x61; //亮两个LED
else
rUTXH0 = ch; //发送字节数据
}
else //发送数据处理部分
{
rGPBDAT = ~0x1e1; //亮4个LED
}
}
void Main(void)
{
rGPBCON = 0x015551;
rGPBUP = 0x7ff;
rGPBDAT = 0x1e0;
rGPHCON = 0x00faaa;
rGPHUP = 0x7ff;
rULCON0 = 0x3;
rUCON0 = 0x5;
rUFCON0 = 0;
rUMCON0 = 0;
rUBRDIV0 = 26;
rSRCPND = 0x1<<28;
rSUBSRCPND = 0x3;
rINTPND = 0x1<<28;
rINTSUBMSK = ~(0x3); //打开UART0发送和接收中断屏蔽
rINTMSK = ~(0x1<<28); //打开UART0中断屏蔽
pISR_UART0 = (U32)uartISP;
while(1);
}
最后还要强调几点关于非FIFO模式下UART中断的一些注意事项:
1. 对于s3c2440来说,接收数据是被动的,发送数据是主动的,因此一般来说,接收数据用中断方式,发送数据用查询方式较好;
2. 在中断方式下,当接收到数据时,尽管可能该数据无用,但也一定要读取它,否则下次再接收数据时,不会再引起中断,因为接收数据缓存器被上次接收到的数据所霸占,只要没有读取它,它就永远在那里;
3. 由于UART中断涉及到SUBSRCPND寄存器,因此在中断处理程序中不仅要清SRCPND寄存器,还要清SUBSRCPND寄存器,它们的顺序一定是先清SUBSRCPND寄存器,再清SRCPND寄存器,否则就会引起一个中断两次响应的问题。因为是否中断由SRCPND寄存器决定,而SRCPND寄存器的相关状态位由SUBSRCPND寄存器决定,如果先清SRCPND寄存器,而还没有清SUBSRCPND寄存器的话,SRCPND寄存器的相关位还是会被置1,而一旦被置1,则一定还会引起中断。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhaocj/archive/2010/03/10/5364412.aspx
s3c2440串口文档
s3c2440的UART提供了三个同步串行IO口,第一个串口都可以使用中断模式和DMA模式,换句话说就是UART可以产生一个中断或者是DMA请求使数据在CPU和UART之间进行传递。UART在系统时钟下可以支持最高位传送为115.2K BPS.如果一个外部设备能过UEXTCLK为UART提供时钟,UART可以达到更高的速度。每个UART通道包括两个64字节的FIFO作为接收数据和发送数据使用。
s3c2440的UART包括可编程的波特率,红外收发,一个或者两个停止位。5位,6位,7位,8位的数据位和校验检测。
每一个UART包括一个波特率产生器,发送器,接收器和一个控制单元。波特率产生器可以使用PCLK,FCLK/n或者UEXTCLK之一控制。发送器和接收器包含64字节的FIFO和一个数据移位器。数据先写到FIFO中然后再拷贝到发送移位器中,然后再移位发送通过数据针TxDn。在些期间远端发送过来的数据通过针RxDn进入到移位器中再拷贝到接收器的FIFO中去。
属性
--RxD0,TxD0,RxD1,TxD1,RxD2,和TxD2都可使用基于DMA的和中断的操作
--UART通道0,1,和2都拥有IrDA和64字节的FIFO
--UART通道0和1:nRTS0,nCTS0,nRTS1,nCTS1
--收发数据时支持握手
UART的操作
UART的操作,包括数据传输,数据接收,产生中断,波特率的产生回环模式,红外模式和自动流控制。
数据传输
发送的数据帧是可以改变的,它由起始位5~8个数据位一个可选的校验位和1~2个停止位构成。这些都可以通过策略控制器ULCONn设置。数据发送器也可以产生一个停止标志,它可以强迫串口输出逻辑0达一帧的时间,它在一个字传输完成以后阻塞了停止信号的传送。然后继续传输数据到Tx FIFO中。
数据接收
与数据的发送相似,接收到的数据帧也是可以修改的。它包括一个起始位,五到八个数据位,一个可选的校验位和一到两个停止位。接收器可检测到覆盖错误,校验错误,帧错误和终止的情况。每一种情况都会设置一个错误标志位。
--覆盖错误产生的情况是这样的,新数据覆盖掉了还没有来的及取出的旧数据,也就是说接收数据速度快于取出的速度导致一部分数据还没有取出就被新的数据盖掉了。
--校验错误是指接收到的数据经过计算与校验位不符。
--帧错误是指收到的数据不含有停止位。
--终止的情况是指RxDn端保持在逻辑零的状态时间长于一帧数据传送的时间。
--接收超时的情况是指在可以接收3个字的时间里没有收到任何的数据,并且在FIFO模式时Rx的FIFO非空。
自动流量控制(AFC)
S3C2440的UART 0和UART 1通过信号nRTS和nCTS支持自动流量控制。在这种情况下,它可以连接到外部的UARTs中去。如果用户想把串口连接到Modem上,需要关闭寄存器UMCONn的自动流控制位,并通过软件控制nRTS信号线。
在AFC模式下,nRTS依赖于接收器,nCTS信号控制着发送器的操作。UART的数据发送器只在nCTS信号使能的时候才把数据传送到FIFO中(在AFC模式下nCTS的意思是其它UART的FIFO已经准备好接收数据了)。
在UART开始接收数据之前,需要先根据数据接收器的FIFO剩余空间设置nRTS的值,如果剩余空间大于32字节则nRTS使能,否则如果剩余空间小于32字节则nRTS关闭(在AFC模式下,nRTS的作用就是表示它所控制的接收器的FIFO准备好接收数据了)。
UART 2不支持AFC功能,因为S3C2440没有nRTS2和nCTS2
非自动流量控制的例子(通过软件控制信号nRTS和nCTS)
接收器对FIFO的操作
1.选择接收模式(中断模式或者DMA模式)
2.检查寄存器UFSTATn中Rx FIFO的值,如果这个值小于32,用户必须设置UMCONn[0]为“1”(使能nRTS),如果值大于32,用户必须设置UMCONn[0]的值为“0”(关闭nRTS)
3.重复第2步。
发送器对FIFO的操作
1.选择一个发送模式(中断或者DMA)
2.检查UMSTATn[0]的值,如果为“1”(使能nCTS),用户写数据到Tx FIFO寄存器
S3C2440的每个UART都有七个状态:覆盖错误,校验错误,帧错误,终止,接收缓冲区已准备好,发送缓冲区空,和发送移位器空。所有这些都对应到UART的状态寄存器中(UTRSTATn/UERSTATn).
覆盖错误,校验错误,帧错误和终止属于接收错误,它们中的任何一个都可以引起一个叫“receive error status”的中断请求。如果这个中断请求在寄存器UCONn中的使能位被置为“1”,并且当这个请求被处理时通过读取UERSTSATn的值可知引起这个中断的信号,也就是找到是哪种错误引起的中断。
FIFO模式与非FIFO模式
在FIFO模式下,接收器从接收移位器中收数据然后写入到FIFO中,如果收到数据的个数达到Rx FIFO的触发点,且在寄存器UCONn中的接收模式被设置成“1”(中断或者轮询模式),将会产生一个Rx中断。在非FIFO模式下,不论是中断模式还是轮询模式,只要有数据从接收移位寄存器中传送到数据接收保持寄存器中都会产生一个Rx中断。
在FIFO模式下,如果发送模式在控制寄存器UCONn中被设置成中断模式或者轮询模式,发送数据要从发送FIFO中传送到发送移位器中,如果在FIFO中剩余的数据个数达到了Tx FIFO的触发点,就是产生一个Tx中断。在非FIFO模式下,发送的数据从发送保持寄存器传送到发送移位器中后会产生一个Tx中断,这个也是要求数据发送方送方式为中断模式或者是轮询模式。
如果在控制寄存器中数据发送方式和接收方式被设置成DMA模式,那么和上面的情况一样,只是产生的Rx和Tx中断被换成了DMA请求。
UART的错误FIFO
UART有一个“错误状态”FIFO组,它对应着接收器的FIFO,它指示在接收器的FIFO中哪个数据错误了。只有在接收器中错误数据被读取的时候才会产生错误中断。在从URXHn读取数据的时候同时读取UERSTATn寄存器的值就知道这个数据哪里错了,什么错误。
例子
假设UART顺序接收了A B C D E这五个数据,其中接收B的时候发生了帧错误,接收D的时候发生了校验错误。
在接收B的时候不会产生“错误中断”,在接收“D”的时候也不会产生“错误中断”。当读取B数据和D数据的时候“错误中断”才会产生。
波特率的产生
ART的波特率发生器为串行数据的发送与接收提供时钟,波特率发生器的“源时钟”可以是S3C2440的内部系统时钟也可以是外部时钟(UEXTCLK),换句话说就是通过设置UCONn的“时钟”选项可以改变除数因子。波特率是由“源时钟”(PCLK,FCLK/n UEXTCLK)除以16和一个除数因子。公式是这样的:
除数因子=(整型)(“源时钟”除以波特率乘以16)减1
除数因子UBRDIVn的取值范围是1~2^16-1,但当使用外部时钟UEXTCLK时它却可以等于0.(这个外部时钟要低于PCLK)
例如:如果波特率是115200bps,UART的时钟是40MHz,除数因子UBRDIVn是
UBRDIVn = (int)(40000000 / (115200 x 16) ) -1
= (int)(21.7) -1 [round to the nearest whole number]
= 22 -1 = 21
波特率的错误容忍度
UART的帧错误必须低于1.87%
ADS下的串口配置
def.h 中的UART寄存器定义:
#define rULCON0 (*(volatile unsigned *)0x50000000) //UART 0 Line control
#define rUCON0 (*(volatile unsigned *)0x50000004) //UART 0 Control
#define rUFCON0 (*(volatile unsigned *)0x50000008) //UART 0 FIFO control
#define rUMCON0 (*(volatile unsigned *)0x5000000c) //UART 0 Modem control
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) //UART 0 Tx/Rx status
#define rUERSTAT0 (*(volatile unsigned *)0x50000014) //UART 0 Rx error status
#define rUFSTAT0 (*(volatile unsigned *)0x50000018) //UART 0 FIFO status
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) //UART 0 Modem status
#define rUBRDIV0 (*(volatile unsigned *)0x50000028) //UART 0 Baud rate divisor
#define rULCON1 (*(volatile unsigned *)0x50004000) //UART 1 Line control
#define rUCON1 (*(volatile unsigned *)0x50004004) //UART 1 Control
#define rUFCON1 (*(volatile unsigned *)0x50004008) //UART 1 FIFO control
#define rUMCON1 (*(volatile unsigned *)0x5000400c) //UART 1 Modem control
#define rUTRSTAT1 (*(volatile unsigned *)0x50004010) //UART 1 Tx/Rx status
#define rUERSTAT1 (*(volatile unsigned *)0x50004014) //UART 1 Rx error status
#define rUFSTAT1 (*(volatile unsigned *)0x50004018) //UART 1 FIFO status
#define rUMSTAT1 (*(volatile unsigned *)0x5000401c) //UART 1 Modem status
#define rUBRDIV1 (*(volatile unsigned *)0x50004028) //UART 1 Baud rate divisor
#define rULCON2 (*(volatile unsigned *)0x50008000) //UART 2 Line control
#define rUCON2 (*(volatile unsigned *)0x50008004) //UART 2 Control
#define rUFCON2 (*(volatile unsigned *)0x50008008) //UART 2 FIFO control
#define rUMCON2 (*(volatile unsigned *)0x5000800c) //UART 2 Modem control
#define rUTRSTAT2 (*(volatile unsigned *)0x50008010) //UART 2 Tx/Rx status
#define rUERSTAT2 (*(volatile unsigned *)0x50008014) //UART 2 Rx error status
#define rUFSTAT2 (*(volatile unsigned *)0x50008018) //UART 2 FIFO status
#define rUMSTAT2 (*(volatile unsigned *)0x5000801c) //UART 2 Modem status
#define rUBRDIV2 (*(volatile unsigned *)0x50008028) //UART 2 Baud rate divisor
#ifdef __BIG_ENDIAN
#define rUTXH0 (*(volatile unsigned char *)0x50000023) //UART 0 Transmission Hold
#define rURXH0 (*(volatile unsigned char *)0x50000027) //UART 0 Receive buffer
#define rUTXH1 (*(volatile unsigned char *)0x50004023) //UART 1 Transmission Hold
#define rURXH1 (*(volatile unsigned char *)0x50004027) //UART 1 Receive buffer
#define rUTXH2 (*(volatile unsigned char *)0x50008023) //UART 2 Transmission Hold
#define rURXH2 (*(volatile unsigned char *)0x50008027) //UART 2 Receive buffer
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000023)=(unsigned char)(ch)
#define RdURXH0() (*(volatile unsigned char *)0x50000027)
#define WrUTXH1(ch) (*(volatile unsigned char *)0x50004023)=(unsigned char)(ch)
#define RdURXH1() (*(volatile unsigned char *)0x50004027)
#define WrUTXH2(ch) (*(volatile unsigned char *)0x50008023)=(unsigned char)(ch)
#define RdURXH2() (*(volatile unsigned char *)0x50008027)
#define UTXH0 (0x50000020+3) //Byte_access address by DMA
#define URXH0 (0x50000024+3)
#define UTXH1 (0x50004020+3)
#define URXH1 (0x50004024+3)
#define UTXH2 (0x50008020+3)
#define URXH2 (0x50008024+3)
#else //Little Endian
#define rUTXH0 (*(volatile unsigned char *)0x50000020) //UART 0 Transmission Hold
#define rURXH0 (*(volatile unsigned char *)0x50000024) //UART 0 Receive buffer
#define rUTXH1 (*(volatile unsigned char *)0x50004020) //UART 1 Transmission Hold
#define rURXH1 (*(volatile unsigned char *)0x50004024) //UART 1 Receive buffer
#define rUTXH2 (*(volatile unsigned char *)0x50008020) //UART 2 Transmission Hold
#define rURXH2 (*(volatile unsigned char *)0x50008024) //UART 2 Receive buffer
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
#define RdURXH0() (*(volatile unsigned char *)0x50000024)
#define WrUTXH1(ch) (*(volatile unsigned char *)0x50004020)=(unsigned char)(ch)
#define RdURXH1() (*(volatile unsigned char *)0x50004024)
#define WrUTXH2(ch) (*(volatile unsigned char *)0x50008020)=(unsigned char)(ch)
#define RdURXH2() (*(volatile unsigned char *)0x50008024)
#define UTXH0 (0x50000020) //Byte_access address by DMA
#define URXH0 (0x50000024)
#define UTXH1 (0x50004020)
#define URXH1 (0x50004024)
#define UTXH2 (0x50008020)
#define URXH2 (0x50008024)
#endif
Uart.c 文件中定义串口配置函数:
//====================================================
// 语法格式: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
{
/ /设置GPH端口为UART口
rGPHCON = rGPHCON & (~(0xffff)); //UART0: RXD0<==>GPH3 TXD0<==>GPH2
rGPHCON = rGPHCON | (0xaaa0) ;
rGPHUP = 0x0; //使能上拉功能
rUFCON0=0x00; // 不使用FIFO
rUMCON0=0x00; //不使用自动流控制
rULCON0=0x03; //不采用红外线传输模式,无奇偶校验位,1个停止位,8个数据位
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')
{
while(!(rUTRSTAT0 & 0x2)); //等待,直到发送缓冲区为空
// Delay(10); //超级中断的响应速度较慢
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);
}
}
//====================================================
// 语法格式:void myUart_Send (char *str)
// 功能描述: 发送字符串
// 入口参数: 字符串指针
// 出口参数: 无
//====================================================================
void myUart_Send (char *str)
{
myUart_Init(0,115200);
while (*str)
myUart_SendByte(*str++);
}
char myUart_ReceiveByte(void)
{
if(UartNum==0)
{
while(!(rUTRSTAT0 & 0x1)); //等待接收数据
return RdURXH0();
}
else if(UartNum==1)
{
while(!(rUTRSTAT1 & 0x1)); //等待接收数据
return RdURXH1();
}
return 0;
}
void myUart_receive(char *string)
{
char *string2 ;
char c;
string2 = string;
myUart_Init(0,115200);
while((c = myUart_ReceiveByte())!='\r')
{
if(c=='\b')
{
if( (int)string2 < (int)string )
{
printf("\b \b");
string--;
}
}
else
{
*string++ = c;
myUart_SendByte(c);
}
}
*string='\0';
myUart_SendByte('\n');
}
void myUart_Printf(char *fmt,...)
{
va_list ap;
char string[256];
va_start(ap,fmt);
vsprintf(string,fmt,ap);
myUart_Send(string);
va_end(ap);
}
U-boot中配置串口:
board/TX2440/TX2440.c中的board_init函数
int board_init (void)
{
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
gpio->GPGUP = 0x0000FFFF;()
gpio->GPHCON = 0x002AFAAA;(串口0和串口1的nCTS, nRTS, TXD,RXD,还有时钟)
gpio->GPHUP = 0x000007FF;
……
}