Red Point

十年饮冰 , 热血难凉 ; 山高万仞 , 只登一步

  博客园 :: 首页 :: 博问 :: 闪存 :: :: :: :: 管理 ::

转载于: http://blog.csdn.net/yx_l128125/article/details/7703653

 

Uart工作原理:

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

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

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

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

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

 

异步通信:

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

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

 

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

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

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

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

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

 

波特率:

是衡量数据传送率的指标:记录每秒中传送的二进制位数。例如:数据传送速率为120字符、每秒。而每一个字符为10位,则其传送的波特率为10*120=1200位/秒=1200波特率

 

UART基本原理

通用异步收发器,简称UART,即“Universal Asynchronous Receiver Transmitter”,它用来传输串行数据;

 

发送数据时:

CPU将并行数据写入UART,UART按照一定的格式在一根电线上串行发出;

接收数据时:

UART检测另一根电线上的信号,将串行数据放在缓冲区中,CPU可读取UART获得的这些数据。

 

UART驱动程序设计

UART初始化:1.发送数据;2.接收数据;

UART初始化:1.设置波特率; 2.设置数据传输格式;3.选择通道工作模式;

一.设置波特率:(UBRDIV)

在s3c2440中,通过UBRDIV(p352)寄存器可以设定UART的波特率。Uart0、Uart1、Uart2分别对应UBRDIV0,UBRDIV1、UBRDIV2

      到底UBRDIV寄存器中的值与波特率有何关系?

      UBRDIV=(int)UART clock / (buad  rate *16))-1

(UART clock:PCLK or FCLK/ n or UEXTCLK)

如波特率为115200bps,UART时钟为40MHZ

UBRDIV =(int) (40MHZ /(115200*16))-1

 

二.设置数据传输格式(ULCON)

在s3c2440中,通过ULCON(page341),可以设置传输格式(有多少个数据位、是否使用校验位、是奇校验还是偶校验,有多少个停止位、是否使用流量控制)

Uart0、Uart1、Uart2分别对应ULCON0、ULCON1、ULCON2.

 

三.设置通道工作模式(UCON)

在s3c2440中,通过UCON(page342),可以设置UART通道的工作模式,(中断模式、查询模式、或DMA模式)

Uart0、Uart1、Uart2分别对应UCON0、UCON1、UCON2.

这三步都属于初始化:初始化完成之后à发送或/接收数据

 

发送数据:

将要发送的数据写UTXHn, UART会将保存到缓冲区中,并自动发出去。

UTXH0、UTXH1、UTXH2

 

接收数据:

当UART收到数据时(UTRSTATn寄存器bit[0]被置1),CPU读取URXHn寄存器,即可获得数据。

URXH0、URXH1、URXH2寄存器中读取数据

 

[html] view plain copy
 
  1. Main.c  
  2.   
  3. <span style="color:#000000;">#define   GLOBAL_CLK           1  
  4.   
  5. #include <stdlib.h>  
  6.   
  7. #include <string.h>  
  8.   
  9. #include "def.h"  
  10.   
  11. #include "option.h"  
  12.   
  13. #include "2440addr.h"  
  14.   
  15. #include "2440lib.h"  
  16.   
  17. #include "2440slib.h"  
  18.   
  19. #include "mmu.h"  
  20.   
  21. #include "profile.h"  
  22.   
  23. #include "memtest.h"  
  24.   
  25.    
  26.   
  27. static void cal_cpu_bus_clk(void);  
  28.   
  29. void Set_Clk(void);  
  30.   
  31. /*************************************************  
  32.   
  33. Function name: delay  
  34.   
  35. Parameter    : times  
  36.   
  37. Description    :延时函数  
  38.   
  39. Return          : void  
  40.   
  41. Argument     : void  
  42.   
  43. Autor & date : Daniel  
  44.   
  45. **************************************************/  
  46.   
  47. void delay(int times)  
  48.   
  49. {  
  50.   
  51.     int i,j;  
  52.   
  53.     for(i=0;i<times;i++)  
  54.   
  55.        for(j=0;j<400;j++);  
  56.   
  57. }  
  58.   
  59. /*************************************************  
  60.   
  61. Function name: Main  
  62.   
  63. Parameter    : void  
  64.   
  65. Description     : 主功能函数,实现了串口的收发功能  
  66.   
  67.                首先想串口发送十次“hello world”,  
  68.   
  69. Return            : void  
  70.   
  71. Argument     : void  
  72.   
  73. Autor & date : Daniel  
  74.   
  75. **************************************************/  
  76.   
  77. void Main(void)  
  78.   
  79. {       
  80.   
  81.     int i;  
  82.   
  83.     int Scom=0;  
  84.   
  85.     Set_Clk();  
  86.   
  87.     beep_init();  
  88.   
  89.       
  90.   
  91.     /*设置波特率、数据位、停止位、校验位*/  
  92.   
  93.     Uart_Init(0,115200);  
  94.   
  95.     Uart_Select(Scom);  
  96.   
  97.     for(i=0;i<10;i++)  
  98.   
  99.     Uart_Printf("\nHello World!\n");  
  100.   
  101.       
  102.   
  103.     while(1)  
  104.   
  105.     {  
  106.   
  107.       while(Uart_GetKey()=='r')  
  108.   
  109.       {  
  110.   
  111.           for(i=0;i<10;i++)  
  112.   
  113.           beep_run();  
  114.   
  115.           Uart_Printf("\nBeep Quit!\n");  
  116.   
  117.       }  
  118.   
  119.        }  
  120.   
  121.    
  122.   
  123. }       
  124.   
  125.        
  126.   
  127. /*************************************************  
  128.   
  129. Function name: Set_Clk()  
  130.   
  131. Parameter    : void  
  132.   
  133. Description     : 设置CPU的时钟频率  
  134.   
  135. Return            : void  
  136.   
  137. Argument     : void  
  138.   
  139. Autor & date : Daniel  
  140.   
  141. **************************************************/  
  142.   
  143. void Set_Clk(void)  
  144.   
  145. {  
  146.   
  147.        int i;  
  148.   
  149.        U8 key;  
  150.   
  151.        U32 mpll_val = 0 ;  
  152.   
  153.        i = 2 ;                  //don't use 100M!  
  154.   
  155.                                //boot_params.cpu_clk.val = 3;  
  156.   
  157.        switch ( i ) {  
  158.   
  159.        case 0:     //200  
  160.   
  161.               key = 12;  
  162.   
  163.               mpll_val = (92<<12)|(4<<4)|(1);  
  164.   
  165.               break;  
  166.   
  167.        case 1:     //300  
  168.   
  169.               key = 13;  
  170.   
  171.               mpll_val = (67<<12)|(1<<4)|(1);  
  172.   
  173.               break;  
  174.   
  175.        case 2:     //400  
  176.   
  177.               key = 14;  
  178.   
  179.               mpll_val = (92<<12)|(1<<4)|(1);  
  180.   
  181.               break;  
  182.   
  183.        case 3:     //440!!!  
  184.   
  185.               key = 14;  
  186.   
  187.               mpll_val = (102<<12)|(1<<4)|(1);  
  188.   
  189.               break;  
  190.   
  191.        default:  
  192.   
  193.               key = 14;  
  194.   
  195.               mpll_val = (92<<12)|(1<<4)|(1);  
  196.   
  197.               break;  
  198.   
  199.        }  
  200.   
  201.          
  202.   
  203.        //init FCLK=400M, so change MPLL first  
  204.   
  205.        ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);   //set the register--rMPLLCON  
  206.   
  207.        ChangeClockDivider(key, 12);    //the result of rCLKDIVN [0:1:0:1] 3-0 bit  
  208.   
  209.        cal_cpu_bus_clk();    //HCLK=100M   PCLK=50M  
  210.   
  211. }  
  212.   
  213. /*************************************************  
  214.   
  215. Function name: cal_cpu_bus_clk  
  216.   
  217. Parameter    : void  
  218.   
  219. Description     : 设置PCLK\HCLK\FCLK的频率  
  220.   
  221. Return            : void  
  222.   
  223. Argument     : void  
  224.   
  225. Autor & date : Daniel  
  226.   
  227. **************************************************/  
  228.   
  229. static void cal_cpu_bus_clk(void)  
  230.   
  231. {  
  232.   
  233.        static U32 cpu_freq;  
  234.   
  235.     static U32 UPLL;  
  236.   
  237.          
  238.   
  239.        U32 val;  
  240.   
  241.        U8 m, p, s;  
  242.   
  243.          
  244.   
  245.        val = rMPLLCON;  
  246.   
  247.        m = (val>>12)&0xff;  
  248.   
  249.        p = (val>>4)&0x3f;  
  250.   
  251.        s = val&3;  
  252.   
  253.    
  254.   
  255.        //(m+8)*FIN*2不要超出32位数!  
  256.   
  257.        FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;     //FCLK=400M  FIN=12000000  
  258.   
  259.          
  260.   
  261.        val = rCLKDIVN;  
  262.   
  263.        m = (val>>1)&3;  
  264.   
  265.        p = val&1;       
  266.   
  267.        val = rCAMDIVN;  
  268.   
  269.        s = val>>8;  
  270.   
  271.          
  272.   
  273.        switch (m) {  
  274.   
  275.        case 0:  
  276.   
  277.               HCLK = FCLK;  
  278.   
  279.               break;  
  280.   
  281.        case 1:  
  282.   
  283.               HCLK = FCLK>>1;  
  284.   
  285.               break;  
  286.   
  287.        case 2:  
  288.   
  289.               if(s&2)  
  290.   
  291.                      HCLK = FCLK>>3;  
  292.   
  293.               else  
  294.   
  295.                      HCLK = FCLK>>2;  
  296.   
  297.               break;  
  298.   
  299.        case 3:  
  300.   
  301.               if(s&1)  
  302.   
  303.                      HCLK = FCLK/6;  
  304.   
  305.               else  
  306.   
  307.                      HCLK = FCLK/3;  
  308.   
  309.               break;  
  310.   
  311.        }  
  312.   
  313.          
  314.   
  315.        if(p)  
  316.   
  317.               PCLK = HCLK>>1;  
  318.   
  319.        else  
  320.   
  321.               PCLK = HCLK;  
  322.   
  323.          
  324.   
  325.        if(s&0x10)  
  326.   
  327.               cpu_freq = HCLK;  
  328.   
  329.        else  
  330.   
  331.               cpu_freq = FCLK;  
  332.   
  333.                 
  334.   
  335.        val = rUPLLCON;  
  336.   
  337.        m = (val>>12)&0xff;  
  338.   
  339.        p = (val>>4)&0x3f;  
  340.   
  341.        s = val&3;  
  342.   
  343.        UPLL = ((m+8)*FIN)/((p+2)*(1<<s));  
  344.   
  345.        UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;  
  346.   
  347. }  
  348.   
  349. </span>   


2440lib.c

[html] view plain copy
 
  1. #include "def.h"  
  2.   
  3. #include "option.h"  
  4.   
  5. #include "2440addr.h"  
  6.   
  7. #include "2440lib.h"  
  8.   
  9. #include "2440slib.h"  
  10.   
  11.    
  12.   
  13. #include <stdarg.h>  
  14.   
  15. #include <string.h>  
  16.   
  17. #include <stdlib.h>  
  18.   
  19. #include <stdio.h>  
  20.   
  21. #include <ctype.h>  
  22.   
  23. static int whichUart=0;  
  24.   
  25.    
  26.   
  27. void Port_Init0(void)  //IO端口初始化  
  28.   
  29. {  
  30.   
  31.        //*** PORT H GROUP  
  32.   
  33.   //Ports  :  GPH10 GPH9 GPH8 GPH7 GPH6 GPH5 GPH4 GPH3 GPH2 GPH1  GPH0 //Signal : CLKOUT1 CLKOUT0 UCLK nCTS1 nRTS1 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0  
  34.   
  35.     //Binary :   10   ,  10     10 , 11    11  , 10   10 , 10   10 , 10    10  
  36.   
  37.      rGPHCON = 0x00faaa;  
  38.   
  39.      rGPHUP  = 0x7ff;    // The pull up function is disabled GPH[10:0]  
  40.   
  41. }  
  42.   
  43.    
  44.   
  45. void Uart_Init(int pclk,int baud)  
  46.   
  47. {  
  48.   
  49.     int i;  
  50.   
  51.     if(pclk == 0)  
  52.   
  53.     pclk    = PCLK;  
  54.   
  55.     rUFCON0 = 0x0;   //UART channel 0 FIFO control register, FIFO disable  
  56.   
  57.     rUMCON0 = 0x0;   //UART chaneel 0 MODEM control register, AFC disable(AFC:流量控制)  
  58.   
  59.    //UART0  
  60.   
  61.     rULCON0 = 0x3;   //Line control register : Normal,No parity,1 stop,8 bits  
  62.   
  63.      //    [10]       [9]     [8]        [7]        [6]      [5]         [4]           [3:2]        [1:0]  
  64.   
  65.      // Clock Sel,  Tx Int,  Rx Int, Rx Time Out, Rx err, Loop-back, Send break,  Transmit Mode, Receive Mode  
  66.   
  67.      //     0          1       0    ,     0          1        0           0     ,       01          01  
  68.   
  69.      //   PCLK       Level    Pulse    Disable    Generate  Normal      Normal        Interrupt or Polling  
  70.   
  71.     rUCON0  = 0x245;   // Control register  
  72.   
  73.     rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 );   //Baud rate divisior register 0  
  74.   
  75.     for(i=0;i<100;i++);  
  76.   
  77. }  
  78.   
  79.    
  80.   
  81. //===================================================================  
  82.   
  83. void Uart_Select(int ch)  
  84.   
  85. {  
  86.   
  87.     whichUart = ch;  
  88.   
  89. }  
  90.   
  91. //=====================================================================  
  92.   
  93. void Uart_SendByte(int data)  
  94.   
  95. {  
  96.   
  97.     if(whichUart==0)  
  98.   
  99.     {  
  100.   
  101.         if(data=='\n')  
  102.   
  103.         {  
  104.   
  105.             while(!(rUTRSTAT0 & 0x2));  
  106.   
  107.            // Delay(1);                 //because the slow response of hyper_terminal  
  108.   
  109.             WrUTXH0('\r');  
  110.   
  111.         }  
  112.   
  113.         while(!(rUTRSTAT0 & 0x2));   //不为换行符时,Wait until THR is empty.  
  114.   
  115.       //  Delay(1);  
  116.   
  117.         WrUTXH0(data);//往寄存器写数据  
  118.   
  119.     }  
  120.   
  121.     else if(whichUart==1)  
  122.   
  123.     {  
  124.   
  125.         if(data=='\n')  
  126.   
  127.         {  
  128.   
  129.             while(!(rUTRSTAT1 & 0x2));  
  130.   
  131.             //Delay(1);                 //because the slow response of hyper_terminal  
  132.   
  133.             rUTXH1 = '\r';  
  134.   
  135.         }  
  136.   
  137.         while(!(rUTRSTAT1 & 0x2));   //Wait until THR is empty.  
  138.   
  139.         //Delay(1);  
  140.   
  141.         rUTXH1 = data;  
  142.   
  143.     }     
  144.   
  145.     else if(whichUart==2)  
  146.   
  147.     {  
  148.   
  149.         if(data=='\n')  
  150.   
  151.         {  
  152.   
  153.             while(!(rUTRSTAT2 & 0x2));  
  154.   
  155.             //Delay(1);                 //because the slow response of hyper_terminal  
  156.   
  157.             rUTXH2 = '\r';  
  158.   
  159.         }  
  160.   
  161.         while(!(rUTRSTAT2 & 0x2));   //Wait until THR is empty.  
  162.   
  163.         //Delay(1);  
  164.   
  165.         rUTXH2 = data;  
  166.   
  167.     }         
  168.   
  169. }                 
  170.   
  171.    
  172.   
  173. //====================================================================  
  174.   
  175. void Uart_SendString(char *pt)  
  176.   
  177. {  
  178.   
  179.     while(*pt)  
  180.   
  181.         Uart_SendByte(*pt++);  
  182.   
  183. }  
  184.   
  185. //=====================================================================  
  186.   
  187. //If you don't use vsprintf(), the code size is reduced very much.  
  188.   
  189. void Uart_Printf(char *fmt,...)  
  190.   
  191. {  
  192.   
  193.     va_list ap;  
  194.   
  195.     char string[256];  
  196.   
  197.    
  198.   
  199.     va_start(ap,fmt);//va_start、 va_end成对出现,ap指向fmt之后的参数  
  200.   
  201.     vsprintf(string,fmt,ap);//把ap之后的参数拷贝进string  
  202.   
  203.     Uart_SendString(string);  
  204.   
  205.     va_end(ap);  
  206.   
  207. }  


中断方式,串口发送:

[html] view plain copy
 
    1. #define    GLOBAL_CLK             1  
    2.   
    3. #include <stdlib.h>  
    4.   
    5. #include <string.h>  
    6.   
    7. #include "def.h"  
    8.   
    9. #include "option.h"  
    10.   
    11. #include "2440addr.h"  
    12.   
    13. #include "2440lib.h"  
    14.   
    15. #include "2440slib.h"  
    16.   
    17. #include "mmu.h"  
    18.   
    19. #include "profile.h"  
    20.   
    21. #include "memtest.h"  
    22.   
    23.    
    24.   
    25.    
    26.   
    27. void Uart0INT_init(void);  
    28.   
    29. static void __irq IRQ_ISR_UART0(void);  
    30.   
    31. void Set_Clk(void);  
    32.   
    33. static void cal_cpu_bus_clk(void);  
    34.   
    35. /*************************************************  
    36.   
    37. Function name: delay  
    38.   
    39. Parameter    : times  
    40.   
    41. Description     : 延时函数  
    42.   
    43. Return            : void  
    44.   
    45. Argument     : void  
    46.   
    47. Autor & date : Daniel  
    48.   
    49. **************************************************/  
    50.   
    51. void delay(int times)  
    52.   
    53. {  
    54.   
    55.     int i,j;  
    56.   
    57.     for(i=0;i<times;i++)  
    58.   
    59.        for(j=0;j<400;j++);  
    60.   
    61. }  
    62.   
    63. /*************************************************  
    64.   
    65. Function name: Main  
    66.   
    67. Parameter    : void  
    68.   
    69. Description     : 主功能函数  
    70.   
    71. Return            : void  
    72.   
    73. Argument     : void  
    74.   
    75. Autor & date : Daniel  
    76.   
    77. **************************************************/  
    78.   
    79. int Main(void)  
    80.   
    81. {       
    82.   
    83.     Set_Clk();  
    84.   
    85.     MMU_Init();  
    86.   
    87.     Uart0INT_init();  
    88.   
    89.        return 0 ;  
    90.   
    91. }       
    92.   
    93. /*************************************************  
    94.   
    95. Function name: Uart0INT_init()  
    96.   
    97. Parameter    : void  
    98.   
    99. Description     : 中断初始化函数,用于配置中断所需要的  
    100.   
    101.                几个寄存器  
    102.   
    103. Return            : void  
    104.   
    105. Argument     : void  
    106.   
    107. Autor & date : Daniel  
    108.   
    109. **************************************************/     
    110.   
    111. void Uart0INT_init(void)  
    112.   
    113. {  
    114.   
    115.     
    116.   
    117.   Uart_Init( 0,115200);  
    118.   
    119.   Uart_Select(0);  
    120.   
    121.     
    122.   
    123.   rPRIORITY = 0x00000000;     /*默认优先级*/  
    124.   
    125.   rINTMOD = 0x00000000;       /*默认IRQ中断*/  
    126.   
    127.     
    128.   
    129.   /*清中断*/  
    130.   
    131.   ClearSubPending(BIT_SUB_RXD0);  
    132.   
    133.   ClearPending(BIT_UART0);  
    134.   
    135.     
    136.   
    137.   /*设置UART的ISR*/  
    138.   
    139.   pISR_UART0 = (U32)IRQ_ISR_UART0;  
    140.   
    141.   EnableIrq(BIT_UART0);  
    142.   
    143.   EnableSubIrq(BIT_SUB_RXD0);  
    144.   
    145.    
    146.   
    147. }  
    148.   
    149. /*************************************************  
    150.   
    151. Function name: IRQ_ISR_UART0()  
    152.   
    153. Parameter    : void  
    154.   
    155. Description     : 中断服务子程序,该子程序的作用就是把  
    156.   
    157.                串口收到的数据发送到超级终端。  
    158.   
    159. Return            : void  
    160.   
    161. Argument     : void  
    162.   
    163. Autor & date : Daniel  
    164.   
    165. **************************************************/  
    166.   
    167. static void __irq IRQ_ISR_UART0(void)  
    168.   
    169. {  
    170.   
    171.         if(rSUBSRCPND & 0x1)  
    172.   
    173.            {  
    174.   
    175.                      rUTXH0 = rURXH0;  /*这里没考虑回车*/  
    176.   
    177.                      ClearSubPending(BIT_SUB_RXD0);  
    178.   
    179.               }  
    180.   
    181.            ClearPending(BIT_UART0);  
    182.   
    183. }  
    184.   
    185.    
    186.   
    187. /*************************************************  
    188.   
    189. Function name: Set_Clk()  
    190.   
    191. Parameter    : void  
    192.   
    193. Description     : 设置CPU的时钟频率  
    194.   
    195. Return            : void  
    196.   
    197. Argument     : void  
    198.   
    199. Autor & date : Daniel  
    200.   
    201. **************************************************/  
    202.   
    203. void Set_Clk(void)  
    204.   
    205. {  
    206.   
    207.        int i;  
    208.   
    209.        U8 key;  
    210.   
    211.        U32 mpll_val = 0 ;  
    212.   
    213.        i = 2 ;                  //don't use 100M!  
    214.   
    215.                                //boot_params.cpu_clk.val = 3;  
    216.   
    217.        switch ( i ) {  
    218.   
    219.        case 0:     //200  
    220.   
    221.               key = 12;  
    222.   
    223.               mpll_val = (92<<12)|(4<<4)|(1);  
    224.   
    225.               break;  
    226.   
    227.        case 1:     //300  
    228.   
    229.               key = 13;  
    230.   
    231.               mpll_val = (67<<12)|(1<<4)|(1);  
    232.   
    233.               break;  
    234.   
    235.        case 2:     //400  
    236.   
    237.               key = 14;  
    238.   
    239.               mpll_val = (92<<12)|(1<<4)|(1);  
    240.   
    241.               break;  
    242.   
    243.        case 3:     //440!!!  
    244.   
    245.               key = 14;  
    246.   
    247.               mpll_val = (102<<12)|(1<<4)|(1);  
    248.   
    249.               break;  
    250.   
    251.        default:  
    252.   
    253.               key = 14;  
    254.   
    255.               mpll_val = (92<<12)|(1<<4)|(1);  
    256.   
    257.               break;  
    258.   
    259.        }  
    260.   
    261.          
    262.   
    263.        //init FCLK=400M, so change MPLL first  
    264.   
    265.        ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);   //set the register--rMPLLCON  
    266.   
    267.        ChangeClockDivider(key, 12);    //the result of rCLKDIVN [0:1:0:1] 3-0 bit  
    268.   
    269.        cal_cpu_bus_clk();    //HCLK=100M   PCLK=50M  
    270.   
    271. }  
    272.   
    273. /*************************************************  
    274.   
    275. Function name: cal_cpu_bus_clk  
    276.   
    277. Parameter    : void  
    278.   
    279. Description     : 设置PCLK\HCLK\FCLK的频率  
    280.   
    281. Return            : void  
    282.   
    283. Argument     : void  
    284.   
    285. Autor & date : Daniel  
    286.   
    287. **************************************************/  
    288.   
    289. static void cal_cpu_bus_clk(void)  
    290.   
    291. {  
    292.   
    293.        static U32 cpu_freq;  
    294.   
    295.     static U32 UPLL;  
    296.   
    297.          
    298.   
    299.        U32 val;  
    300.   
    301.        U8 m, p, s;  
    302.   
    303.          
    304.   
    305.        val = rMPLLCON;  
    306.   
    307.        m = (val>>12)&0xff;  
    308.   
    309.        p = (val>>4)&0x3f;  
    310.   
    311.        s = val&3;  
    312.   
    313.    
    314.   
    315.        //(m+8)*FIN*2不要超出32位数!  
    316.   
    317.        FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;     //FCLK=400M  FIN=12000000  
    318.   
    319.          
    320.   
    321.        val = rCLKDIVN;  
    322.   
    323.        m = (val>>1)&3;  
    324.   
    325.        p = val&1;       
    326.   
    327.        val = rCAMDIVN;  
    328.   
    329.        s = val>>8;  
    330.   
    331.          
    332.   
    333.        switch (m) {  
    334.   
    335.        case 0:  
    336.   
    337.               HCLK = FCLK;  
    338.   
    339.               break;  
    340.   
    341.        case 1:  
    342.   
    343.               HCLK = FCLK>>1;  
    344.   
    345.               break;  
    346.   
    347.        case 2:  
    348.   
    349.               if(s&2)  
    350.   
    351.                      HCLK = FCLK>>3;  
    352.   
    353.               else  
    354.   
    355.                      HCLK = FCLK>>2;  
    356.   
    357.               break;  
    358.   
    359.        case 3:  
    360.   
    361.               if(s&1)  
    362.   
    363.                      HCLK = FCLK/6;  
    364.   
    365.               else  
    366.   
    367.                      HCLK = FCLK/3;  
    368.   
    369.               break;  
    370.   
    371.        }  
    372.   
    373.          
    374.   
    375.        if(p)  
    376.   
    377.               PCLK = HCLK>>1;  
    378.   
    379.        else  
    380.   
    381.               PCLK = HCLK;  
    382.   
    383.          
    384.   
    385.        if(s&0x10)  
    386.   
    387.               cpu_freq = HCLK;  
    388.   
    389.        else  
    390.   
    391.               cpu_freq = FCLK;  
    392.   
    393.                 
    394.   
    395.        val = rUPLLCON;  
    396.   
    397.        m = (val>>12)&0xff;  
    398.   
    399.        p = (val>>4)&0x3f;  
    400.   
    401.        s = val&3;  
    402.   
    403.        UPLL = ((m+8)*FIN)/((p+2)*(1<<s));  
    404.   
    405.        UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;  
    406.   
    407. }  
posted on 2017-03-31 17:26  Red_Point  阅读(240)  评论(0)    收藏  举报