| 本帖最后由 gdmgb520 于 2011-9-18 17:46 编辑 
 函数调用
 
 DrvSYS_SelectIPClockSource(E_SYS_TMR0_CLKSRC,0);
 
 
 查看API手册可知,该函数的作用是给某个设备选择时钟源。该函数有两个参数,第一个参数指定外设,第二个指定时钟源。
 
 所以,该函数调用的作用是给Timer0选择外部12MHz时钟源。| 
 u8ClkSrcSel
 
 | 
 0 
 | 
 1 
 | 
 2 
 | 
 3 
 | 
 7 
 |  | 
 Watch Dog Timer 
 | 
 Reserved 
 | 
 Ext. 32K (*) 
 | 
 HCLK/2048 
 | 
 Internal 10K 
 | 
 X 
 |  | 
 ADC 
 | 
 External 12M 
 | 
 PLL 
 | 
 HCLK (*) 
 | 
 Internal 22M 
 | 
 X 
 |  | 
 Timer 
 | 
 External 12M 
 | 
 External 32K 
 | 
 HCLK 
 | 
 Reserved 
 | 
 Internal 22M 
 |  | 
 UART 
 | 
 External 12M 
 | 
 PLL 
 | 
 Reserved 
 | 
 Internal 22M 
 | 
 X 
 |  | 
 PWM 
 | 
 External 12M 
 | 
 External 32K 
 | 
 HCLK 
 | 
 Internal 22M 
 | 
 X 
 |  | 
 Frequency  Divider Output 
 | 
 External 12M 
 | 
 External 32K 
 | 
 HCLK 
 | 
 Internal 22M 
 | 
 X 
 |  | 
 I2S 
 | 
 External 12M 
 | 
 PLL 
 | 
 HCLK 
 | 
 Internal 22M 
 | 
 X 
 | 
 
 进一步查看该函数的内部结构:
 在 SYSCLK->CLKSEL1.TMR0_Sint32_t DrvSYS_SelectIPClockSource(E_SYS_IP_CLKSRC eIpClkSrc, uint8_t u8ClkSrcSel)
{
       switch(eIpClkSrc)
       {
              ……
              case E_SYS_TMR0_CLKSRC:
                  SYSCLK->CLKSEL1.TMR0_S = u8ClkSrcSel;
                     break;
              ……
              default:
                     return E_DRVSYS_ERR_IPSRC;
       }
       return E_SUCCESS;
}
这里我疑惑了。下面来一探其究竟。
 
 首先,SYSCLK 是什么
 #define SYSCLK      ((SYSCLK_T *) SYSCLK_BASE)
 可见,SYSCLK 是一个 SYSCLK_T 类型的指针,物理地址是 SYSCLK_BASE。
 
 
 1.SYSCLK_T结构体类型
 2.物理地址SYSCLK_BASEtypedef struct
{
SYSCLK_PWRCON_T    PWRCON;
SYSCLK_AHBCLK_T    AHBCLK;
SYSCLK_APBCLK_T    APBCLK;
SYSCLK_CLKSTATUS_T CLKSTATUS;
SYSCLK_CLKSEL0_T   CLKSEL0;
SYSCLK_CLKSEL1_T   CLKSEL1;
SYSCLK_CLKDIV_T    CLKDIV;
SYSCLK_CLKSEL2_T   CLKSEL2;
SYSCLK_PLLCON_T    PLLCON;
SYSCLK_FRQDIV_T    FRQDIV;
} SYSCLK_T;
又#define SYSCLK_BASE          (AHB_BASE       + 0x00200)
所以,SYSCLK_BASE代表的地址是0x5000_0x0200。#define AHB_BASE            ((     uint32_t)0x50000000)
 
 3.成员变量的地址
 
 而在SYSCLK_T 结构体中每个成员都是4字节,所以,CLKSEL1 成员变量位于该结构体中的 0x14位置。
 故,SYSCLK->CLKSEL1的实际地址就是0x5000_0214。从数据手册知道这就是CLKSEL1寄存器的地址。
 
 
 其次,SYSCLK->CLKSEL1.TMR0_S是什么
 在SYSCLK_T
 结构体定义中可以看到:
 而SYSCLK_CLKSEL1_T的定义如下:SYSCLK_CLKSEL1_T   CLKSEL1;
这东东看起来是一个结构体,但实际上这是C语言的位域定义(关于位域的具体内容可以参考《谭浩强 C语言 第三版 12.2节》)。从该定义中知道位域名TMR0_S占用3各位,8-10bit。typedef struct
{
__IO uint32_t  WDT_S:2;
__IO uint32_t  ADC_S:2;
__I  uint32_t  RESERVE1:4;
__IO
uint32_t  TMR0_S:3;
__I  uint32_t  RESERVE2:1;
__IO uint32_t  TMR1_S:3;
__I  uint32_t  RESERVE3:1;
__IO uint32_t  TMR2_S:3;
__I  uint32_t  RESERVE4:1;
__IO uint32_t  TMR3_S:3;
__I  uint32_t  RESERVE5:1;
__IO uint32_t  UART_S:2;
__IO uint32_t  CAN_S:2;
__IO uint32_t  PWM01_S:2;
__IO uint32_t  PWM23_S:2;
} SYSCLK_CLKSEL1_T;
 
 最后把以上各个片段拼起来:
 SYSCLK->CLKSEL1.TMR0_S = u8ClkSrcSel;
 SYSCLK :SYSCLK_T型结构体指针,该类型结构体包含10个变量,均为4字节,指向地址为0x50000000。
 CLKSEL1 :上述结构体的第六个成员变量,其类型是一个SYSCLK_CLKSEL1_T位域结构,该结构总长度为4字节。
 TMR0_S :CLKSEL1位域结构中的一个位域,8-10bit。
 
 
 至于你明白没有,反正我是明白了。
 不对的地方请指正啊。
 |