天天看點

ARM9(S3C2440) UART

                                資料通信的方式

資料通信的方式基本分為:

(1)、并行通信:多條資料線将資料的各位同屬傳送。

                      特點:傳輸速度快,适用于短距離通信。

(2)、串行通信:一條資料線将資料一位一位的順序傳送。

                      特點:線路簡單,低成本,适用于遠距離通信。

          一:  異步通信:

                          以一個字元為傳輸機關,通信中兩個字元間的時間間隔是不固定的,然而同一個字元中的兩個相鄰位之間的時間間隔是固定的。

            二: 通信協定

                          指雙方約定的一些規則。在異步通訊時,對資料格式有如下的約定:有空閑位,起始位,資料位,奇偶校驗位,停止位。  

ARM9(S3C2440) UART

     (1)、起始位:先發送一個邏輯信号“0”信号,表示傳輸字元的開始。

     (2)、資料位:緊接在起始位之後。資料位的個數可以是4,5,6,7,8等,從最低位開始傳送,靠時鐘定位。

     (3)、奇偶校驗位:資料位加上這一位後,使得“1”的資料位應為偶數(偶校驗)或奇數(奇校驗),以此校驗資料傳送的正确性。

     (4)、停止位:他是一個字元資料的結束标志。

     (5)、空閑位:處于邏輯“1”狀态,表示目前線路上沒有資料傳送。

               波特率

       衡量資料傳送速率的名額:記錄每秒傳送的二進制位數。

       例如資料傳送速率為120字元/秒,而一個字元為10位,則其傳送的波特率為10*120=1200位/秒=1200波特。

               傳送方式

ARM9(S3C2440) UART

                    UART基本原理

    Universal Asynchronous Receiver Transimitter,簡稱UART,通用異步收發器,它用來串行傳輸資料。

  發送時:CPU将資料并行寫入UART,UART按照一定的格式在一根信号線上串行發送;

  接收時:UART檢測另一根信号線上的信号,将串行資料放在緩沖區中,CPU可讀取UART獲得的這些資料。

ARM9(S3C2440) UART
ARM9(S3C2440) UART

                      UART驅動程式設計

ARM9(S3C2440) UART
ARM9(S3C2440) UART
ARM9(S3C2440) UART
ARM9(S3C2440) UART
ARM9(S3C2440) UART
ARM9(S3C2440) UART
ARM9(S3C2440) UART
ARM9(S3C2440) UART

         發送資料

 将要發送的資料寫入UTXHn,UART會将它儲存到緩沖區中,并自動發送出去。

ARM9(S3C2440) UART

        接收資料

     當UART接收到資料時(UARTSTATn寄存器bit[0]被置1,),CPU讀取URXHn寄存器,即可獲得資料。

ARM9(S3C2440) UART
ARM9(S3C2440) UART

實驗主要代碼:

main.c

#define GLOBAL_CLK  1

#include <stdlib.h>

#include <string.h>

#include "def.h"

#include "option.h"

#include "2440addr.h"

#include "2440lib.h"

#include "2440slib.h"

#include "mmu.h"

#include "profile.h"

#include "memtest.h"

static void cal_cpu_bus_clk(void);

void Set_Clk(void);

void beep_init(void);

void beep_run(void);

void delay(int times)

{

    int i,j;

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

       for(j=0;j<400;j++);

}

void Main(void)

    int i;

    int Scom=0;

    Set_Clk();

    beep_init();

    Uart_Init(0,115200);     //在2440lib.c檔案中下面列出了

    //序列槽通道選擇

    Uart_Select(Scom);

    //序列槽發送資料

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

    Uart_Printf("\nHello World!\n");

void Set_Clk(void)

{

 int i;

 U8 key;

 U32 mpll_val = 0 ;

 i = 2 ;              //don't use 100M!

                   //boot_params.cpu_clk.val = 3;

 switch ( i ) {

 case 0: //200

  key = 12;

  mpll_val = (92<<12)|(4<<4)|(1);

  break;

 case 1: //300

  key = 13;

  mpll_val = (67<<12)|(1<<4)|(1);

  break;

 case 2: //400

  key = 14;

  mpll_val = (92<<12)|(1<<4)|(1);

  break;

 case 3: //440!!!

  key = 14;

  mpll_val = (102<<12)|(1<<4)|(1);

  break;

 default:

  key = 14;

  mpll_val = (92<<12)|(1<<4)|(1);

  break;

 }

 //init FCLK=400M, so change MPLL first

 ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);   //set the register--rMPLLCON

 ChangeClockDivider(key, 12);    //the result of rCLKDIVN [0:1:0:1] 3-0 bit

 cal_cpu_bus_clk();    //HCLK=100M   PCLK=50M

}

static void cal_cpu_bus_clk(void)

{

 static U32 cpu_freq;

    static U32 UPLL;

 U32 val;

 U8 m, p, s;

 val = rMPLLCON;

 m = (val>>12)&0xff;

 p = (val>>4)&0x3f;

 s = val&3;

 //(m+8)*FIN*2 不要超出32位數!

 FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;     //FCLK=400M  FIN=12000000

 val = rCLKDIVN;

 m = (val>>1)&3;

 p = val&1; 

 val = rCAMDIVN;

 s = val>>8;

 switch (m) {

 case 0:

  HCLK = FCLK;

  break;

 case 1:

  HCLK = FCLK>>1;

  break;

 case 2:

  if(s&2)

   HCLK = FCLK>>3;

  else

   HCLK = FCLK>>2;

  break;

 case 3:

  if(s&1)

   HCLK = FCLK/6;

  else

   HCLK = FCLK/3;

  break;

 }

 if(p)

  PCLK = HCLK>>1;

 else

  PCLK = HCLK;

 if(s&0x10)

  cpu_freq = HCLK;

 else

  cpu_freq = FCLK;

 val = rUPLLCON;

 m = (val>>12)&0xff;

 p = (val>>4)&0x3f;

 s = val&3;

 UPLL = ((m+8)*FIN)/((p+2)*(1<<s));

 UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;

}

void beep_init(void)

{

    rGPBCON &= ~(0x3<<0);

    rGPBCON |=  (0x1<<0);

}

void beep_run(void)

{

    rGPBDAT |= (0x1<<0);

    delay(5000);

    rGPBDAT &= (0x0<<0);

    delay(5000);

}

一些main函數中調用到的函數:

2440lib.c

....................

//***************************[ UART ]******************************

static int whichUart=0;

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        1001000101

    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++);   //短暫延時

}

ARM9(S3C2440) UART
ARM9(S3C2440) UART
ARM9(S3C2440) UART

void Uart_Select(int ch)

{

    whichUart = ch;

}

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

//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_start,va_end成對出現

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

void Uart_SendString(char *pt)

{

    while(*pt)

        Uart_SendByte(*pt++);

}

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

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;

    }      

}