S3C2440A的有3个UART,都可以基于中断和DMA进行数据传输,可以支持最高115.2Kbps的比特率。每个UART通道包含两个64字节的FIFO。
UART的七种状态信号:溢出错误,奇偶校验错误,帧错误,断点,接收缓冲器数据就绪,发送缓冲空以及发送移位空,全部由状态寄存器(UTRSTATn/UERSTATn)标示。
波特率的产生:可以选择内部时钟和UEXTCLK,由UCONn设置并由16位分频系数决定
寄存器配置:
ULCONn:行控制寄存器,主要控制数据帧格式
UCONn:时钟选择及其他控制
UFCONn:FIFO控制寄存器
UMCONn:模式控制位
UBRDIVn:16位波特率分频值
UTRSTATn:TX/RX状态寄存器 只读
UERSTATn:RX错误状态寄存器只读
UTXHn:发送缓冲寄存器 只写,以字节为单位
URXH0接收缓冲状态寄存器 只读,以字节为单位
UFSTATn:FIFO状态寄存器只读
UMSTAT0:
UART操作:
1.串口初始化
引脚的初始化,第二功能,电阻上拉
设置ULCONn寄存器:一般设为0x03,设置含义,八个数据位,一个停止位,无校验,正常操作模式
设置UCONn寄存器:一般设为0x0245,除了位[3:0],其他为都可以是默认设置,表示:发送和接收都是用“中断或查询方式”
设置UFCONn:设置为00,一般不使用FIFO
设置UMCONn:设置00,不使用流控
设置UBRDIV0具体设置,常用波特率115200
2.发送数据和接收数据
发送时,首先查询UTRSTATn[2]是否为1,若为1则表示f发送移位寄存器,发送缓冲器空闲,可以发送,UTXHn = C;
位[1]==1,在不使用FIFO的情况下,表示发送缓冲寄存器空(移位寄存器不一定空),此时也可以将数据写入缓冲器,前提是UCONn[9]设为1,中断响应才能使UTRSTATn[2]==1
接收时,若位[0]==1,则表示有缓冲区接收到数据
源码如下:
uart.c
#include"def.h"
#include"2440addr.h"
#include "option.h"
#include "uart.h"
#include<stdarg.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<ctype.h>
static unsigned char CHANG_UART = 0;
void Uart_Init( U8 uart_number,int baud)
{
int pclk,i;
rGPHCON = 0x2afaaa;
rGPHUP = 0x7ff;
pclk = PCLK;
switch(uart_number)
{
case 0:
{
rULCON0 = 0x03;
rUCON0 = 0x245;
rUBRDIV0 = ( (int)(pclk/16./baud+0.5) -1 ); //Baud rate divisior register 0
rUFCON0 = 0x0; //UART channel 0 FIFO control register, FIFO disable
rUMCON0 = 0x0; //UART chaneel 0 MODEM control register, AFC disable
CHANG_UART = 0;
break;
}
case 1:
{
rULCON1 = 0x03;
rUCON1 = 0x245;
rUBRDIV1 = ( (int)(pclk/16./baud+0.5) -1 ); //Baud rate divisior register 0
rUFCON1 = 0x0; //UART channel 1FIFO control register, FIFO disable
rUMCON1 = 0x0; //UART chaneel 1 MODEM control register, AFC disable
CHANG_UART = 1;
break;
}
case 2:
{
rULCON2 = 0x03;
rUCON2 = 0x245;
rUBRDIV2 = ( (int)(pclk/16./baud+0.5) -1 ); //Baud rate divisior register 0
rUFCON2 = 0x0; //UART channel 2 FIFO control register, FIFO disable
CHANG_UART = 2;
break;
}
default: break;
}
for(i = 0; i < 100; i++);
}
//等待发送移位寄存器空
void Uart_TxEmpty(int ch)
{
if(ch==0)
while(!(rUTRSTAT0 & 0x4)); //Wait until tx shifter is empty.
else if(ch==1)
while(!(rUTRSTAT1 & 0x4)); //Wait until tx shifter is empty.
else if(ch==2)
while(!(rUTRSTAT2 & 0x4)); //Wait until tx shifter is empty.
// rUTRSTAT0[2]==1,发射缓冲器空
}
//接收串口一个字节数据,此时会先等待串口接收
char Uart_Getch(void)
{
if (CHANG_UART == 0)
{
while(!(rUTRSTAT0 & 0x1)); //Receive data ready
return RdURXH0();
}
else if(CHANG_UART == 1)
{
while(!(rUTRSTAT1 & 0x1)); //Receive data ready
return RdURXH1();
}
else if(CHANG_UART == 2)
{
while(!(rUTRSTAT2 & 0x1)); //Receive data ready
return RdURXH2();
}
return 0 ;
}
//直接得到串口键值,前提默认是串口已接收到数据
char Uart_GetKey(void)
{
if(CHANG_UART==0)
{
if(rUTRSTAT0 & 0x1) //Receive data ready
return RdURXH0();
else
return 0;
}
else if(CHANG_UART==1)
{
if(rUTRSTAT1 & 0x1) //Receive data ready
return RdURXH1();
else
return 0;
}
else if(CHANG_UART==2)
{
if(rUTRSTAT2 & 0x1) //Receive data ready
return RdURXH2();
else
return 0;
}
return 0 ;
}
//串口得到字符串
void Uart_GetString(char *string)
{
char *string2 = string;
char c;
while((c = Uart_Getch())!='\r') //读取的是否为回车 ,若是回车,则读取结束
{
if(c=='\b') //如果读取的是退格
{
if( (int)string2 < (int)string ) //且第一个字符不是退格
{
Uart_Printf("\b \b");
string--;
}
}
else
{
*string++ = c; //将数据保存到string地址处
Uart_SendByte(c); //并将此字符送PC显示
}
}
*string='\0'; //字符串结束
Uart_SendByte('\n'); //发送回车
}
//得到串口初始号
int Uart_GetIntNum(void)
{
char str[30];
char *string = str;
int base = 10;
int minus = 0;
int result = 0;
int lastIndex;
int i;
Uart_GetString(string);
if(string[0]=='-')
{
minus = 1;
string++;
}
if(string[0]=='0' && (string[1]=='x' || string[1]=='X'))
{
base = 16;
string += 2;
}
lastIndex = strlen(string) - 1;
if(lastIndex<0)
return -1;
if(string[lastIndex]=='h' || string[lastIndex]=='H' )
{
base = 16;
string[lastIndex] = 0;
lastIndex--;
}
if(base==10)
{
result = atoi(string);
result = minus ? (-1*result):result;
}
else
{
for(i=0;i<=lastIndex;i++)
{
if(isalpha(string[i]))
{
if(isupper(string[i]))
result = (result<<4) + string[i] - 'A' + 10;
else
result = (result<<4) + string[i] - 'a' + 10;
}
else
result = (result<<4) + string[i] - '0';
}
result = minus ? (-1*result):result;
}
return result;
}
//串口发送字节
void Uart_SendByte(char data)
{
if(CHANG_UART == 0)
{
if(data=='\n')
{
while(!(rUTRSTAT0 & 0x2));
// Delay(1); //because the slow response of hyper_terminal
WrUTXH0('\r');
}
while(!(rUTRSTAT0 & 0x2)); //Wait until THR is empty.
// Delay(1);
WrUTXH0(data);
}
else if(CHANG_UART == 1)
{
if(data=='\n')
{
while(!(rUTRSTAT1 & 0x2));
//Delay(1); //because the slow response of hyper_terminal
rUTXH1 = '\r';
}
while(!(rUTRSTAT1 & 0x2)); //Wait until THR is empty.
//Delay(1);
rUTXH1 = data;
}
else if(CHANG_UART == 2)
{
if(data=='\n')
{
while(!(rUTRSTAT2 & 0x2));
//Delay(1); //because the slow response of hyper_terminal
rUTXH2 = '\r';
}
while(!(rUTRSTAT2 & 0x2)); //Wait until THR is empty.
//Delay(1);
rUTXH2 = data;
}
}
//串口发送数据串
void Uart_SendString(char *pt)
{
while(*pt)
Uart_SendByte(*pt++);
}
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.h
#ifndef __uart_h__
#define __uart_h__
#include "def.h"
void Port_Init(void);
void Uart_TxEmpty(int ch);
void Uart_Init(U8 uart_number,int baud);
char Uart_Getch(void);
char Uart_GetKey(void);
void Uart_GetString(char *string);
int Uart_GetIntNum(void);
int Uart_GetIntNum_GJ(void) ;
void Uart_SendByte(char data);
void Uart_Printf(char *fmt,...);
void Uart_SendString(char *pt);
#endif