S3C2440之UART(一)

S3C2440的串口比较简单,基本上就是波特率、数据位、校验位、通道号、停止位配置OK即可

//===================================================================
// File Name : 2440lib.c
// Function  : S3C2410 PLL,Uart, LED, Port Init
// Date      : March 20, 2002
// Version   : 0.0
// History
// 0.0 : Programming start (February 20,2002) -> SOP
//===================================================================
//#define	GLOBAL_CLK		1//hzh
#include "UART.h"

//***************************[ UART ]******************************
static int whichUart=0;
static char str[30];
void __irq UART_INT (void);
/*************************************************************************************
***函数名:Uart_Init()
***功能:串口初始化,波特率 115200 8位数据位,无校验位,1位停止位
***参数:ch	串口通道号
***返回:无
*************************************************************************************/
void Uart_Init(int pclk,int baud)
{
    int i;

    if(pclk == 0)
        pclk    = PCLK;

    //*** PORT H GROUP
    //Ports  :  GPH10    GPH9  GPH8 GPH7  GPH6  GPH5 GPH4 GPH3 GPH2 GPH1  GPH0 
    //Signal : CLKOUT1 CLKOUT0 UCLK nCTS1 nRTS1 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
    //Binary :   10   ,  10     10 , 11    11  , 10   10 , 10   10 , 10    10
    rGPHCON = 0x00aaaa;
    rGPHUP  = 0x7ff;    // The pull up function is disabled GPH[10:0]

    rUFCON0 = 0x0;   //UART channel 0 FIFO control register,  FIFO disable
    rUFCON1 = 0x0;   //UART channel 1 FIFO control register,  FIFO disable
    rUFCON2 = 0x0;   //UART channel 2 FIFO control register,  FIFO disable
    rUMCON0 = 0x0;   //UART chaneel 0 MODEM control register, AFC  disable
    rUMCON1 = 0x0;   //UART chaneel 1 MODEM control register, AFC  disable

    //UART0
    rULCON0 = 0x3;   //Line control register : Normal,,No parity1 stop,8 bits
    //    [10]       [9]     [8]        [7]        [6]      [5]         [4]           [3:2]        [1:0]
    // Clock Sel,  Tx Int,  Rx Int, Rx Time Out, Rx err, Loop-back, Send break,  Transmit Mode, Receive Mode
    //     0          1       0    ,     0          1        0           0     ,       01          01
    //   PCLK       Level    Pulse    Disable    Generate  Normal      Normal        Interrupt or Polling
    rUCON0  = 0x245;                            // Control register
    rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 );   // Baud rate divisior register 0

    //UART1
    rULCON1 = 0x3;				//不采用红外线传输模式,无奇偶校验位,1个停止位,8个数据位
    rUCON1  = 0x245;			//发送中断为电平方式,接收中断为边沿方式,禁止超时中断,允许产生错误状态中断,禁止回送模式,禁止中止   //信号,传输模式为中断请求模式,接收模式也为中断请求模式。
    rUBRDIV1=( (int)(pclk/16./baud+0.5) -1 );

    //UART2
    rULCON2 = 0x3;			   	//不采用红外线传输模式,无奇偶校验位,1个停止位,8个数据位
    rUCON2  = 0x245;	       //发送中断为电平方式,接收中断为边沿方式,禁止超时中断,允许产生错误状态中断,禁止回送模式,禁止中止   //信号,传输模式为中断请求模式,接收模式也为中断请求模式。
    rUBRDIV2=( (int)(pclk/16./baud+0.5) -1 );    

    for(i=0;i<100;i++);
}


/*************************************************************************************
***函数名:Uart_Select()
***功能:串口选择。函数里面的whichUart在后面的函数中有引用,决定用哪个UART。
***参数:ch	串口通道号
***返回:无
*************************************************************************************/
void Uart_Select(int ch)
{
    whichUart = ch;
}


/*************************************************************************************
***函数名:Uart_TxEmpty()
***功能:等待。如果UART0、1、2的transmit shifter register和 buffer register,
          一直是空的,就一直等待,直到不为空,就跳出循环
***参数:ch	串口通道号
***返回:无
*************************************************************************************/
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.
}


/*************************************************************************************
***函数名:Uart_Getch()
***功能:从终端上获取敲入的字符。 返回值为char类型。RdURXH有数据时,返回URXH的
         数据。当URXH没有数据时,总是等待,直到有数据。这个函数,非要从终端那
		 获得字符,否则一直等待。
***参数:无
***返回:终端上敲入的字符
*************************************************************************************/
char Uart_Getch(void)
{
    if(whichUart==0)
    {       
        while(!(rUTRSTAT0 & 0x1)); //Receive data ready
        return RdURXH0();
    }
    else if(whichUart==1)
    {       
        while(!(rUTRSTAT1 & 0x1)); //Receive data ready
        return RdURXH1();
    }
    else if(whichUart==2)
    {
        while(!(rUTRSTAT2 & 0x1)); //Receive data ready
        return RdURXH2();
    }
    
    return 0 ;
}


/*************************************************************************************
***函数名:Uart_GetKey()
***功能:这个与Uart_Getch 不同的是,当URXH没有数据时返回0。有数据时,返回数据,
         这个函数用来查看URXH中的值。
***参数:无
***返回:获取PC机按键
*************************************************************************************/
char Uart_GetKey(void)
{
    if(whichUart==0)
    {       
        if(rUTRSTAT0 & 0x1)    //Receive data ready
            return RdURXH0();
        else
            return 0;
    }
    else if(whichUart==1)
    {
        if(rUTRSTAT1 & 0x1)    //Receive data ready
            return RdURXH1();
        else
            return 0;
    }
    else if(whichUart==2)
    {       
        if(rUTRSTAT2 & 0x1)    //Receive data ready
            return RdURXH2();
        else
            return 0;
    }    

	return 0 ;
}

 /*************************************************************************************
***函数名:Uart_GetString()
***功能:从终端那得到一个字符串,并存储到 字符型指针string 中
***参数:string 存放接收到的字符串
***返回:
*************************************************************************************/
void Uart_GetString(char *string)
{
    char *string2 = string;		 //指针string2用来做比较
    char c;
    while((c = Uart_Getch())!='\r')		 //输入的字符不是 回车,就存储到string中
    {
        if(c=='\b')					   //输入的是 退格(删除) ,
        {
            if( (int)string2 < (int)string )	//sring如果还没有输入数据(此时string2==string),就删除,不做任何操作。
            {
                Uart_Printf("\b \b"); //实际中,我在调试的时候发现Uart_Printf("\b");并不能删除显示字符。Uart_Printf(" \b");也不能。Uart_Printf("\b \b\b \b");可以删除2个字符
                string--;		//有数据才删除

            }
        }
        else 
        {
            *string++ = c;	  //输入的 不是 回车和退格 ,将数据存储到string中
            Uart_SendByte(c);	//回写,没输入一个数据,在 超级终端上显示
        }
    }
    *string='\0';			 // 在C语言中没有字符串变量,字符串不能存放在一个变量中,只能存放在字符型数组中。以'\0'作为字符串结束的标志。'\0'不计入串的长度。

    Uart_SendByte('\n');	   //在超级终端上显示换行
}

/*************************************************************************************
***函数名:Uart_GetIntNum()
***功能:此函数是将转换为10进制,因为从UART从 超级终端 得到的10进制、或16进制,
   都是当做字符在处理。这个函数,就是将输入的如:"0X12BD"或"-0x334ACC"或"-BBH"
   或"123"之类的字符串,转换成10进制。由此可知,不支持输入二进制和八进制表示的数。
***参数:无
***返回:接收到的-十进制整数数字
*************************************************************************************/
int Uart_GetIntNum(void)
{
	char str[30];	          //定义字符型数组。
	char *string = str;	      //将数组的首地址,赋值给指针string。数组名就是首地址
	int base     = 10;	      //是10进制
	int minus    = 0;         //判断是否为负,为负是minus=1
	int result   = 0;         //最后转换的结果,因为从 超级终端 那得到的都是字符
	int lastIndex;    	      //数组的最后一个字符是什么
	int i;			          //从超级终端那得到字符,并存储到string所指向的数组str[]中。

	Uart_GetString(string);	  //如果是负数

	if (string[0]=='-')		 //更新负数标志
	{
		minus = 1;			  //string指向str[1]
		string++;
	}

	/*除去那个负号外,或没有负号,如果是以0x或0X开头,即16进制*/
	if (string[0]=='0' && (string[1]=='x' || string[1]=='X'))
	{
		base    = 16;		  //指示为16进制
		string += 2;		  //指向str[2],因为str[0]存储了字符'0'、str[1]存储了字符'x'或'X'
	}

	/*strlen函数,求字符串的长度。减1是因为,数组下标从0开始。'\0'不计入串的长度。*/
	lastIndex = strlen(string) - 1;
	if (lastIndex<0)			 //说明0x或0X或- 后面没有任何内容
		return -1;

	if (string[lastIndex]=='h' || string[lastIndex]=='H' ) //如果16进制是用H或h表示的
	{
		base = 16;			   //指示是16进制的数
		string[lastIndex] = 0; //把H或h去掉
		lastIndex--;		   //数组最后一位不要,即存储H或h的那位
	}

	if (base==10)			   //如果是10进制
	{
		result = atoi(string);  //atoi函数,将字符串转换成整型,转换后赋值给result
		result = minus ? (-1*result):result; //是负数,就在 乘以 -1
	}

	/****************************如果是16进制******************************************/
	else
	{
		for (i=0;i<=lastIndex;i++)
		{
			if (isalpha(string[i]))	        //isalpha函数,判断是否是字母。
			{
				if (isupper(string[i]))	    //isupper函数,判断是否是大写字母
					result = (result<<4) + string[i] - 'A' + 10; //将大写字母转换为相应的10进制
				else
					result = (result<<4) + string[i] - 'a' + 10;  //将小写字母转换为相应的10进制
			}  //result<<4,左移4位相当于乘以16,举例说明更好理解。如果字符串为ABCH,
			//处理A:result=0X16+0+10,处理B:result=10(A)X16+11,处理C :result=10(A)X16X16+11(B)X16,
			//处理C:result=10(A)X16X16X16+11(B)X16X16+12 。这样才能将16进制转化为正确的10进制

			else //如果是数字字符,转换成十进制数,分析过程同上
				result = (result<<4) + string[i] - '0';
		}
		result = minus ? (-1*result):result;  //是负数,别忘了乘以负号
	}
	return result;					          //将正确的10进制返回
}

/*************************************************************************************
***函数名:Uart_GetIntNum_GJ()
***功能:接收10进制的数,将'0'至'9'的字符,转换成10进制数。
***参数:无
***返回:接收到的-十进制数字
*************************************************************************************/
int Uart_GetIntNum_GJ(void)
{
    char string[16] ;
    char *p_string = string ;
    char c;
    int i = 0 ;
    int data = 0 ;

    while(   ( c = Uart_Getch()) != '\r'  )
    {
		if(c=='\b')		p_string--;
		else		*p_string++=c;
		
		Uart_SendByte( c ) ;
    }

    *p_string = '\0';

	i = 0 ;
	while( string[i] != '\0' )
	{
		data = data * 10 ;
		if( string[i]<'0'||string[i]>'9' )
			return -1 ;
		data = data + ( string[i]-'0' ) ;
		i++ ;		
	}	
	
	return data ;
}

/*************************************************************************************
***函数名:Uart_SendByte()
***功能:发送一个字符
***参数:要发送字符数据
***返回:无
***备注	: 函数中的 WrUTXH0('\r')相当于 
          (*(volatile unsigned char *)0x50000020)=(unsigned char)('\r')。
       而0x50000020为UTXH0寄存器的地址。因为前面初始化串口的时候,FIFO disable 。 
       相当于将 '\r' 发送赋值给UTXH0,然后UART发送 。UTXH0为 UART channel 0 transmit
       buffer register 。 rUTRSTAT0 & 0x2   取出rUTRSTAT0 寄存器中的第2位,含义为
       Transmit buffer是否为空 。为1时表示空。while(!(rUTRSTAT0 & 0x2)); 注意这是一
      个空循环语句。后面有个分号,这代表空循环语句,直到THR为空时,就跳出循环,
       执行下一条。WrUTXH0(data);
*************************************************************************************/
void Uart_SendByte(int data)
{
    if(whichUart==0)
    {
        if(data=='\n')
        {
            while(!(rUTRSTAT0 & 0x2));	 //等待,直到发送缓冲区为空

            WrUTXH0('\r');	             //发送回车符
        }

        while(!(rUTRSTAT0 & 0x2));       //Wait until THR is empty.

        WrUTXH0(data);			         //发送字符
    }
    else if(whichUart==1)
    {
        if(data=='\n')
        {
            while(!(rUTRSTAT1 & 0x2));
            rUTXH1 = '\r';
        }
        while(!(rUTRSTAT1 & 0x2));       //Wait until THR is empty.
        rUTXH1 = data;
    }   
    else if(whichUart==2)
    {
        if(data=='\n')
        {
            while(!(rUTRSTAT2 & 0x2));
            rUTXH2 = '\r';
        }
        while(!(rUTRSTAT2 & 0x2));        //Wait until THR is empty.
        rUTXH2 = data;
    }       
}               

/*************************************************************************************
***函数名:Uart_SendString()
***功能:发送字符串
***参数:字符串指针
***返回:无
*************************************************************************************/
void Uart_SendString(char *pt)
{
    while(*pt)
        Uart_SendByte(*pt++);
}

/*************************************************************************************
***函数名:Uart_Printf()
***功能:串口打印函数,相当于标准C中的printf()
***参数:可变参
***返回:无
***If you don't use vsprintf(), the code 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_INT_initialize
***功能:串口中断初始化
***参数:无
***返回:无
*****************************************************************************/
void UART_INT_initialize (void)
{
              
	//第三步 清子中断标志,开子屏蔽
	ClearSubPending (BIT_SUB_RXD0);
	EnableSubIrq(BIT_SUB_RXD0);

	//第四步 清总中断
	ClearPending(BIT_UART0);              //清除INTPND,SRCPND中断标示

	//第五步:设置中断服务函数入口
	pISR_UART0 = (unsigned)UART_INT ;

	//开总中断
	EnableIrq(BIT_UART0);
}

/*****************************************************************************
***函数名:UART_INT()
***功能:串口中断服务函数
***参数:无
***返回:无
*****************************************************************************/
void __irq UART_INT (void)
{
	static U8 i;
	static U8 time_flag = 0;
	static U8 password_flag = 0;
	U8 ch;
	if(rUTRSTAT0 & 0x1)   //判断接收缓存是否准备好
	{
		ch = rURXH0;
		if (ch != '#')
		{
			str[i++] = ch;
			while(!(rUTRSTAT0 & 0x2));
			rUTXH0 = ch; 
		}
		else if ((time_flag == 0)&(password_flag == 0))
		{
			str[i]='\0';
			i=0;
			if (!(strcmp(str,"time" )))                      //灭LED
			{
				time_flag = 1;
			}
			
			
			if (!(strcmp(str ,"password" )))                        //亮LED
			{
				password_flag = 1;
			}
			
			
			if (!(strcmp(str ,"bellon" )))                         //蜂鸣器响
			{  
			rGPBCON |=0x01;
			rGPBDAT |= 0x1;
			}
			
			if (!(strcmp(str ,"belloff" )))                         //蜂鸣器不响
			{rGPBDAT &= 0x1e0;}
		}
		else if(time_flag == 1)
		{
			check_ASCII_table((U8*)str,(U8*)str,14);
			combine((U8*)str,(U8*)str,14);
			RTC_time_set(str[0],str[1],str[2],str[3],str[4],str[5],str[6]);
			time_flag = 0;
			i = 0;
		}
		else if(password_flag == 1)
		{
			check_ASCII_table((U8*)str,(U8*)str,6);
			password_administrator = str[0]*100000+str[1]*10000+
			                         str[2]*1000+str[3]*100+str[4]*10+str[5];
//			Wr24C080(0xa0,(U8)DOOR_PASSWOR1_1,str[0]);
//			Wr24C080(0xa0,(U8)DOOR_PASSWOR1_1,str[1]);
//			Wr24C080(0xa0,(U8)DOOR_PASSWOR1_1,str[2]);
//			Wr24C080(0xa0,(U8)DOOR_PASSWOR1_1,str[3]);
//			Wr24C080(0xa0,(U8)DOOR_PASSWOR1_1,str[4]);
//			Wr24C080(0xa0,(U8)DOOR_PASSWOR1_1,str[5]);
			password_flag = 0;
			i = 0;
			store_password = 1;
		}
	}
	ClearSubPending (BIT_SUB_RXD0);
	ClearPending(BIT_UART0);              //清除INTPND,SRCPND中断标示
}

头文件如下

#ifndef UART_H
#define UART_H
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include <stdarg.h>		//主要是定义Uart_Print,实现字符串格式化输出。
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "RTC.h"
#include "common_functions.h"
#include "2440lib.h"
#include "global_value.h"
/*************************************************************************************
***函数名:Uart_Init()
***功能:串口初始化,波特率 115200 8位数据位,无校验位,1位停止位
***参数:ch	串口通道号
***返回:无
*************************************************************************************/
extern void Uart_Init(int pclk,int baud);
extern void Uart_SendByte(int data);
extern void Uart_Printf(char *fmt,...);
extern void UART_INT_initialize (void);
#endif

猜你喜欢

转载自blog.csdn.net/pxy198831/article/details/86346027