原创 【转】mini 2440的test 的串口操作

2011-10-14 14:51 1252 6 6 分类: EDA/ IP/ 设计与制造
  Mini2440有三个串口,USRT0,UART1,UART3。 
对串口的操作有三种:串口初始化,串口接收,串口发送 
1 串口初始化 
1)串口初始化函数 
void Uart_Init(int pclk,int baud) 

    int i; 
    if(pclk == 0) 
    pclk    = PCLK; 
    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 parity,1 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; 
    rUCON1  = 0x245; 
    rUBRDIV1=( (int)(pclk/16./baud+0.5) -1 ); 
//UART2 
    rULCON2 = 0x3; 
    rUCON2  = 0x245; 
    rUBRDIV2=( (int)(pclk/16./baud+0.5) -1 );     

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

l       串口时钟的设置 
pclk    = PCLK;使用PCLK作为串口的时钟。 
l       寄存器进行了设置 
主要是对三种寄存器进行了设置 
rUFCONn (n=0,1,2) —— 串口FIFO控制寄存器 
              rUMCONn (n=0,1)——串口调制控制寄存器 
rULCONn (n=0,1,2)——串口线性控制寄存器 
              rUCONn(n=0,1,2)——串口控制寄存器 
              rUBRDIVn(n=0,1,2)——串口Tx,Rx收发速率的设定 
2)串口的选择 
void Uart_Select(int ch) 

    whichUart = ch; 

2 串口发送 
串口发送数据通过判断rUTRSTATn (n=0,1,2)的第2位是不是为1来判断发送缓存是否为空。 
1)          串口发送字节   
void Uart_SendByte(int data) 

    if(whichUart==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(whichUart==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(whichUart==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; 
    }       
}         
首先是串口通道的选择;然后判断THR是否为空,直到等到发送缓存为空,退出while循环;再要发送的字节data放到发送缓存中。如果发送的数据是回车的话,直接发送转义字符/r,当然也要等到THR为空才可以发送。 
2)          串口发送字符串 
void Uart_SendString(char *pt) 

    while(*pt) 
        Uart_SendByte(*pt++); 

把字符串看作是字符数组,字符指针*pt来指代字符数组的首地址,读取指针指向的字符,这样就可以把发送的的字符串逐个进行字节发送了。 
2 串口接收 
串口接收通过判断rUTRSTATn (n=0,1,2)的第1位是不是为1来判断发送缓存是否为空。 
1)串口等待接收状态 
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. 

寄存器rUTRSTATn & 0x4   (n=0,1,2)来判断tx shifter是不是为空 
3)          接收字符 
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 ; 

寄存器rUTRSTATn & 0x1  (n=0,1,2)来判断Receive data ready?并把接收到的数据写到接收缓存里面。 
4)          接收字符串 
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; 
            Uart_SendByte(c); 
        } 
    } 
    *string='/0'; 
    Uart_SendByte('/n'); 

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 ; 

寄存器rUTRSTATn & 0x1       (n=0,1,2) 
来判断Receive data ready?并把接收到的数据写到接收缓存里面。否则返回空。与getchar类似,并且也是返回字符类型。 

5)          接收整形数字 
函数返回类型:整形 
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
)) 
            { 
                if(isupper(string
)) 
                    result = (result<<4) + string
 - 'A' + 10; 
                else 
                    result = (result<<4) + string
 - 'a' + 10; 
            } 
            else 
                result = (result<<4) + string
 - '0'; 
        } 
        result = minus ? (-1*result):result; 
    } 
    return result; 

首先以字符串的形式接收数据Uart_GetString(string); 
然后通过判断是不是以‘-’开头来确定是不是负数,是负数则minus=1;再通过以0x,oX开头或者以H,h结尾来判断是不是16进制,否则为10进制;如果是10进制,则通过atoi把字符串转化为数字,并加上正负,如果是16进制,判断是不是字母,再判断大小写字母分别进行转换。16进制也支持正负号。 
6)          接收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
 != '/0' ) 
      { 
           data = data * 10 ; 
           if( string
<'0'||string>'9' ) 
                 return -1 ; 
           data = data + ( string
-'0' ) ; 
           i++ ;           
      }     
       
      return data ; 

  只转化10进制的数字。首先用getchar接收单个字符存储在string中,然后把string转换为整型的data。并返回整形的data。 

3串口打印 
//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); 

va_list完成可变参数的操作 
具体实现如下 
n       由于无法列出传递函数的所有实参的类型和数目时,用省略号指定参数表 
void Uart_Printf(char *fmt,...) 
n       函数参数的传递原理 
函数参数是以数据结构:栈的形式存取,从右至左入栈. 
n       获取省略号指定的参数 
在函数体中声明一个va_list,然后用va_start函数来获取参数列表中的参数,使用完毕后调用va_end()结束。 
va_list ap; 
   char string[256]; 
va_start(ap,fmt); 
    vsprintf(string,fmt,ap); 
    Uart_SendString(string); 
    va_end(ap); 
va_start使ap指向第一个可选参数。va_end把ap指针清为NULL。函数体内可以多次遍历这些参数,但是都必须以va_start开始,并以va_end结尾。 
vsprintf(string,fmt,ap);实现向字符数组中写指定格式的内容

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条