mini 2440的test 的串口操作

 

  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);實現向字符數組中寫指定格式的內容
發佈了31 篇原創文章 · 獲贊 4 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章