TX2440裸机程序-uart

该文章部分参考http://blog.csdn.net/yx_l128125/article/details/7703653

一、uart原理简介

数据通信方式为:并行通信串行通信两种:

§并行通信:利用多条数据线将数据的各位同时传送

它的特点是:传输速度快,是用于短距离通信;

§串行通信:利用一条数据线将数据一位位地顺序传送。

特点是通信线路简单,利用简单的线缆就实现通信,低成本,是用于远距离通信。

 

异步通信:

ª异步通信:以一个字符为传输单位,通过两个字符间的时间间隔是不固定的,然而同一字符中的两个相邻位之间的时间间隔是固定的

ª通信协议:是指通信双方约定的一些规则。在异步通讯时,对数据格式有如下约定:规定有空闲位、起始位、资料位、奇偶校验位、停止位。

 

起始位:先发一个逻辑“0”信号,表示传输字符的开始;

数据位:紧接在起始位之后。数据位的个数可以是45678等,从最低位开始传送,靠时钟定位。

奇偶校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或(奇校验),以此校验数据传送的正确性。

停止位:它是一个字符数据的结束标志。

空闲位:处于逻辑“1”状态,表示当前线路没有数据传送。

     UART:Universal Asynchronous Receiver/Transmitter(通用异步收发送器),用来传输串行数据,发送数据时,CPU将并行数据写入UART,UART按照一定格式在TxD线上串行发出;接收数据时,UART检测到RxD线上的信号,将串行收集放到缓冲区中,CPU即可读取UART获得的这些数据。

     UART最精简的连线形式只有3根线,TXD用于发送,RXD用于接收,GND用于提供参考电平。UART之间以帧作为数据传输单位,帧由具有完整意义的若干位组成,它包含开始位、数据位、校验位和停止位。发送数据之前,互相通信的UART之间要约定好数据传输速率(波特率的倒数)、数据的传输格式(多少个数据位、是否使用校验位、奇校验还是偶校验、多少个停止位)。

二、s3c2440 uart特性

     S3C2440的通用异步收发器(UART)配有3个独立异步串行I/O(SIO)端口,每个都可以通过产生中断或DMA请求(及查询)来进行CPU和UART之间的数据传输。如下图所示:每个UART包含一个波特率发生器、发送器、接收器和一个控制单元。

     波特率发生器可以由PCLK、FCLK/n或UEXTCLK(外部输入时钟)时钟驱动。UART通过使用系统时钟可以支持最115.2Kbps的比特率。如果是使用外部器件提供UEXTCLK的UART,则UART可以运行在更高的速度。发送器和接收器各包含一个64字节的FIFO和数据移位器。

      发送数据:1、将外设总线的数据写入到发送缓冲区(缓冲区控制单元UFCONn控制寄存器设置:FIFO模式或非FIFO模式)

            2、将发送缓冲区数据复制到8bit的发送移位器中。若非FIFO模式,操作一次即可;而FIFO模式根据存储深度决定。

            3、波特率发生器提供将数据从发送数据引脚(TXDn)移出的移位时钟

  接收数据同发送数据相似。从接收数据引脚(RXDn)移入收到的数据,接着从移位器复制到FIFO

                        

   波特率发生器

    每个UART的波特率发生器为发送器和接收器提供串行时钟,波特率发生器的时钟源可以选择S3C2440A的内部时钟系统或者UEXTCLK。波特率时钟是通过16和由UART波特率分频寄存器(UBRDIVn)指定的16位分频系数来分频源时钟(PCLK,FCLK/n或者UEXTCLK)产生的,UBRDIVn由下列表达式确定:

UBRDIVn=(int)(UART时钟/(波特率*16))-1

UART时钟:PCLK,FCLK/n或者UEXTCLK,例如,如果波特率为115200bps并且UART时钟为25MHz,则UBRDIVn为:

UBRDIVn=(int)(25000000/(115200*16))-1=(int)(13.5)-1(取最接近的整数)=14-1=13

三、s3c2440 uart应用

   我用的开发板是天祥的TX2440,电路连接如图所示:

                                

   介绍发送和接收操作之前,先介绍几个重要的寄存器

UBRDIVn寄存器:设置波特率,UART的时钟源有两种选择:PCLK、UEXTCLK、FCLK/n,其中n的值通过UCON0-UCON2联合设置

ULCONn寄存器:设置传输格式

UCONn寄存器:它用于选择UART时钟源、设置UART中断方式

UFCONn寄存器:用于设置是否使用FIFO,设置各FIFO的触发阙值,即发送FIFO中有多少个数据时产生中断、接收FIFO中有多少个数据时产生中断。并可以通过设置UFCONn寄存器来复位各个FIFO。读取UFSTATn寄存器可以知道各个FIFO是否已经满,其中有多少个数据。

UMCONn寄存器:用于流量控制


UTRSTATn寄存器:表明数据是否已经发送完毕、是否已经接收到数据

UERSTATn寄存器,用来表示各种错误是否发生

UTXHn寄存器,CPU将数据写入这个寄存器,UART即会将它保存到缓冲区中,并自动发送出去

URXHn寄存器,当UART接收到数据时,CPU读取这个寄存器,即可获得数据。

 

  对于S3C2440,使用UART之前,首选需要对2440的UART模块进行初始化,

1、uart对应IO端口设置
2、传输帧格式设置(如数据位、停止位、基偶校验位等)
3、传输协议设置(是否FIFO,中断等)
4、波特率生成设置

		/*1、uart对应IO端口设置*/
		rGPHCON = rGPHCON & (~(0xffff));   //UART0: RXD0<==>GPH3  TXD0<==>GPH2
		rGPHCON = rGPHCON | (0xaaa0) ;     //设置GPH端口为UART口,详情见S3C2440手册输入输出端口  
    	rGPHUP  = 0x0;                     //使能上拉功能
    	
	    /*2、传输帧格式设置*/
	    rULCON0=0x03;   //不采用红外线传输模式,无奇偶校验位,1个停止位,8个数据位
	    
	    /*3、传输协议设置*/
		rUFCON0=0x00;   // 不使用FIFO  
        rUMCON0=0x00;   //不使用自动流控制
        rUCON0=0x245;   //发送中断为电平方式,接收中断为边沿方式,禁止超时中断,允许产生错误状态中断,禁止回送模式,禁止中止		
                        //信号,传输模式为中断请求模式,接收模式也为中断请求模式。
                        
        /*4、波特率生成设置*/
        rUBRDIV0=( (int)(pclk/16/baud+0.5) -1 );  //根据波特率计算UBRDIV0的值
        

 

四、uart程序

//=========================================================================
//  工程名称:	UART.mcp
//  文件名称:  main.c
//  功能描述: 	通过超级终端完成PC和S3C2440的数据传输,利用超级终端输入需要发送的字符,回车后,字符会再发送回来显示。
//              1、通过串口0、1发送和接收单个字节
//				2、通过串口0、1发送和接收字符串
//  组成文件:	main.c 2440lib.c 2440init.s 2440slib.s 
//    头文件:  2440addr.h def.h option.h 2440lib.h 2440slib.h
//  程序分析:	
//  硬件连接:	用串口线将开发板和PC机串口相连		
//  维护记录:	2011年4月7日	
//
//

//=========================================================================

#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "option.h"
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

//====================================================
// 函数定义区
//====================================================
extern void Delay(int time);
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);//FCLK_400M=((92<<12)|(1<<4)|1),MPLL=2*(92+8)*12M/((1+2)*2)=400M
    					  //电源工作模式默认NORMAL,FCLK=MPLL
    ChangeClockDivider(2, 1);//设置FCLK HCLK PCLK 分频比1:8:16
	CalcBusClk();//启动总线

	myUart_Select(0);//UART的端口选择,0--选择UART0,1--选择UART1  (只可以选择UART0和UART1)  
    myUart_Init(0,115200);
	while(1)
	{	
	    Delay(500);
	    //myUart_Printf("Please Input a string:\n");
	   	myUart_Send("Please Input a string:\n");//myUart_Printf与myUart_Send功能相同。
	    myUart_receive(string); 
	     //myUart_Printf("hailin\n");
	     //myUart_SendByte(0x35);
	     Delay(500);
	    myUart_Send(string);
	    myUart_Send("\n");
    }	
}

void myUart_Select(int ch)//UART的端口选择,UartNum定义成全局变量
{
    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     
    {         
		/*1、uart对应IO端口设置*/
		rGPHCON = rGPHCON & (~(0xffff));   //UART0: RXD0<==>GPH3  TXD0<==>GPH2
		rGPHCON = rGPHCON | (0xaaa0) ;     //设置GPH端口为UART口,详情见S3C2440手册输入输出端口  
    	rGPHUP  = 0x0;                     //使能上拉功能
    	
	    /*2、传输帧格式设置*/
	    rULCON0=0x03;   //不采用红外线传输模式,无奇偶校验位,1个停止位,8个数据位
	    
	    /*3、传输协议设置*/
		rUFCON0=0x00;   // 不使用FIFO  
        rUMCON0=0x00;   //不使用自动流控制
        rUCON0=0x245;   //发送中断为电平方式,接收中断为边沿方式,禁止超时中断,允许产生错误状态中断,禁止回送模式,禁止中止		
                        //信号,传输模式为中断请求模式,接收模式也为中断请求模式。
                        
        /*4、波特率生成设置*/
        rUBRDIV0=( (int)(pclk/16/baud+0.5) -1 );  //根据波特率计算UBRDIV0的值,通过加上0.5,提高精度。
        
	 	Delay(10);
     }
     else if(UartNum == 1)
     {
		rGPHCON = rGPHCON & (~(0xffff)) ; //UART1: RXD1<==>GPH5  TXD1<==>GPH4
		rGPHCON = rGPHCON | (0xaaa0) ;    //设置GPH端口为UART口
    	rGPHUP  = 0x0;                    // 使能上拉功能
		rULCON1=0x3;		 
		rUFCON1=0x0;    
        rUMCON1=0x0;   
        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')//判断发送的字符是不是'\n'(换行)
		{
		    while(!(rUTRSTAT0 & 0x2));  //等待,直到发送缓冲区为空
//		    Delay(10);	            //超级中断的响应速度较慢 
		    WrUTXH0('\r');              //发送回车符
		}
										//如果发送的字符不是'\n'(换行)
		while(!(rUTRSTAT0 & 0x2));      //等待,直到发送缓冲区为空
//		Delay(10);
		WrUTXH0(ch);                    //发送字符
   	}
	else			//使用UART1
    {
		if(ch=='\n')//判断发送的字符是不是'\n'(换行)
	    {
		    while(!(rUTRSTAT1 & 0x2));   //等待,直到发送缓冲区为空
//		    Delay(10);	                 //等待
		    rUTXH1='\r';
	    }
	    while(!(rUTRSTAT1 & 0x2));  //Wait until THR is empty.
//	    Delay(10);
	    WrUTXH1(ch);
    }	
}

//====================================================
// 语法格式:char myUart_ReceiveByte(void)
// 功能描述: 接收字节数据
// 入口参数: 无
// 出口参数: 接收的字节数据
//====================================================================

char myUart_ReceiveByte(void)
{
    if(UartNum==0)
    {       
        while(!(rUTRSTAT0 & 0x1)); //判断接收缓冲区是否有有效数据,有数据时UTRSTAT0.1=1
        						   //等待接收数据
        return RdURXH0();
    }
    else if(UartNum==1)
    {       
        while(!(rUTRSTAT1 & 0x1)); //等待接收数据
        return RdURXH1();
    }
    return 0;
}

//====================================================
// 语法格式:void myUart_Send (char *str)
// 功能描述: 发送字符串
// 入口参数: 字符串指针
// 出口参数: 无
//====================================================================
void myUart_Send (char *str)
{
    myUart_Init(0,115200);//每次发送字符串时,都初始化串口UART
	while (*str)//发送字符串,直到字符串的结束符‘0’(对应ASCII的0,即空操作),停止发送字符
	myUart_SendByte(*str++);//*str++  1、先发送指针*str指向字符
							//        2、指针str=str+1,指向下个字符
}	


//====================================================
// 语法格式:void myUart_receive(char *string)
// 功能描述: 接收字符串
// 入口参数: 字符串指针
// 出口参数: 无
//===================================================================
void myUart_receive(char *string)
{
	 char *string2 ;
     char c;
     string2 = string;
     myUart_Init(0,115200);
     while((c = myUart_ReceiveByte())!='\r')//'\r'--回车,当有回车按下,表示字符串输入结束
     {
        if(c=='\b')//'\b'--退格,当有TAB键按下,在SecureCRT显示退格
        {
            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);
}

 

          原计划:通过逻辑分析仪监测2440与PC机的uart通信,但是uart采用RS232模式,只支持点对点,不支持一对多。所以无法实现监测。目前通过监测2440的TXD对应的RS232发送端,了解数据发送过程。
       在main()执行下面程

        myUart_Printf("hailin\n");
        myUart_SendByte(0x35);

       利用逻辑分析仪查看2440的TXR端 的波形如下:(监测到发送端与程序一致。)

       

    通道0设置如下:

   

 

五、uart传输分析

       uart传输格式:1起始位 +8位数据位+1位停止位。RS232逻辑是负逻辑,即+12V为逻辑0,-12V为逻辑1;而2440的uart逻辑是正逻辑。而下图是2440的TXD端经过max3232芯片转换为RS232负逻辑,即显示逻辑0实质是2440发送的逻辑1。

2440发送0x68(即h)数据,发送顺序:以字节形式先LSB发送后MSB发送。发送数据0001,0110 。

      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值