原创 串口通信

2009-2-28 18:18 3138 5 5 分类: MCU/ 嵌入式

The Clock & Power management block consists of three parts: Clock control, USB control, and Power control.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


The Clock control logic in S3C2440A can generate the required clock signals including FCLK for CPU, HCLK for the AHB bus peripherals, and PCLK for the APB bus peripherals. The S3C2440A has two Phase Locked Loops (PLLs): one for FCLK, HCLK, and PCLK, and the other dedicated for USB block (48Mhz). The clock control logic can make slow clocks without PLL and connect/disconnect the clock to each peripheral block by software, which will reduce the power consumption.


 


点击看大图


FCLK, HCLK, and PCLK


FCLK is used by ARM920T.


HCLK is used for AHB bus, which is used by the ARM920T, the memory controller, the interrupt controller, the LCD controller, the DMA and USB host block.


PCLK is used for APB bus, which is used by the peripherals such as WDT, IIS, I2C, PWM timer, MMC interface, ADC, UART, GPIO, RTC and SPI.


The S3C2440A supports selection of Dividing Ratio between FCLK, HLCK and PCLK. This ratio is determined by HDIVN and PDIVN of CLKDIVN control register.



 


点击看大图


 


9782b84c-9f4c-4cc4-9780-5d586bb59efc.jpg


 


点击看大图


 


When you set MPLL&UPLL values, you have to set the UPLL value first and then the MPLL value. (Needs intervals approximately 7 NOP)


 


Baud-rate Generation


Each UART's baud-rate generator provides the serial clock for the transmitter and the receiver. The source clock for the baud-rate generator can be selected with the S3C2440A's internal system clock or UEXTCLK. In other words, dividend is selectable by setting Clock Selection of UCONn. The baud-rate clock is generated by dividing the source clock (PCLK, FCLK/n or UEXTCLK) by 16 and a 16-bit divisor specified in the UART baud-rate divisor register (UBRDIVn). The UBRDIVn can be determined by the following expression:


 


UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1


 


Where, UBRDIVn should be from 1 to (216-1), but can be set zero only using the UEXTCLK which should be smaller than PCLK.


For example, if the baud-rate is 115200 bps and UART clock is 40 MHz, UBRDIVn is:


       UBRDIVn   = (int)(40000000 / (115200 x 16) ) -1


                            = (int)(21.7) -1 [round to the nearest whole number]


                            = 22 -1 = 21


 


功能函数介绍:


 


1、系统时钟设置


void ChangeMPllValue(int mdiv,int pdiv,int sdiv)
{
    rMPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv;
}


 


// Modified for 2440.


void ChangeClockDivider(int hdivn_val,int pdivn_val)


{


       int hdivn="2", pdivn="0";


      


     // hdivn_val (FCLK:HCLK)ratio hdivn


     // 11           1:1       (0)


     // 12           1:2       (1)


     // 13           1:3       (3)


     // 14           1:4       (2)


     // pdivn_val (HCLK:PCLK)ratio pdivn


     // 11           1:1       (0)


     // 12           1:2       (1)


       switch(hdivn_val) {


              case 11: hdivn="0"; break;


              case 12: hdivn="1"; break;


              case 13:


              case 16: hdivn="3"; break;


              case 14:


              case 18: hdivn="2"; break;


       }


      


       switch(pdivn_val) {


              case 11: pdivn="0"; break;


              case 12: pdivn="1"; break;


       }


      


       //Uart_Printf("Clock division change [hdiv:%x, pdiv:%x]\n", hdivn, pdivn);


       rCLKDIVN = (hdivn<<1) | pdivn;


 


       switch(hdivn_val) {


              case 16:             // when 1, HCLK="FCLK/8".


                     rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<8);


              break;


              case 18:     // when 1, HCLK="FCLK/6".


                     rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<9);


              break;


       }


      


    if(hdivn!=0)


        MMU_SetAsyncBusMode();


    else


        MMU_SetFastBusMode();


}


点击看大图

 

点击看大图


 


2、串口初始化


void Port_Init0(void)
{


……


    //*** 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 = 0x2afaaa;
    rGPHUP  = 0x7ff;    // The pull up function is disabled GPH[10: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


    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++);


}


 


 


 


 

点击看大图


点击看大图


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();


    }


}


 


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');


}


4、发送函数


void Uart_SendByte(int data)


{


    if(whichUart==0)


    {


        if(data=='\n')


        {


            while(!(rUTRSTAT0 & 0x2));


            Delay(10);                 //because the slow response of hyper_terminal


            WrUTXH0('\r');


        }


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


        Delay(10);


        WrUTXH0(data);


    }


    else if(whichUart==1)


    {


        if(data=='\n')


        {


            while(!(rUTRSTAT1 & 0x2));


            Delay(10);                 //because the slow response of hyper_terminal


            rUTXH1 = '\r';


        }


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


        Delay(10);


        rUTXH1 = data;


    }  


    else if(whichUart==2)


    {


        if(data=='\n')


        {


            while(!(rUTRSTAT2 & 0x2));


            Delay(10);                 //because the slow response of hyper_terminal


            rUTXH2 = '\r';


        }


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


        Delay(10);


        rUTXH2 = data;


    }      


}  


5、延时函数


void Delay(int time)


{


      // time="0:" adjust the Delay function by WatchDog timer.


      // time>0: the number of loop time


      // resolution of time is 100us.


    int i,adjust=0;


    if(time==0)


    {


        time   = 200;


        adjust = 1;


        delayLoopCount = 400;


            //PCLK/1M,Watch-dog disable,1/64,interrupt disable,reset disable


        rWTCON = ((PCLK/1000000-1)<<8)|(2<<3);


        rWTDAT = 0xffff;                              //for first update


        rWTCNT = 0xffff;                              //resolution=64us @any PCLK


        rWTCON = ((PCLK/1000000-1)<<8)|(2<<3)|(1<<5); //Watch-dog timer start


    }


    for(;time>0;time--)


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


    if(adjust==1)


    {


        rWTCON = ((PCLK/1000000-1)<<8)|(2<<3); //Watch-dog timer stop


        i = 0xffff - rWTCNT;                     //1count->64us, 200*400 cycle runtime = 64*i us


        delayLoopCount = 8000000/(i*64);         //200*400:64*i=1*x:100 -> x="80000"*100/(64*i)  


    }


}


 

 


 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
5
关闭 站长推荐上一条 /3 下一条