本帖最后由 gdmgb520 于 2011-9-18 17:46 编辑
函数调用
DrvSYS_SelectIPClockSource(E_SYS_TMR0_CLKSRC,0);
查看API手册可知,该函数的作用是给某个设备选择时钟源。该函数有两个参数,第一个参数指定外设,第二个指定时钟源。
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
|
所以,该函数调用的作用是给Timer0选择外部12MHz时钟源。
进一步查看该函数的内部结构:int32_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->CLKSEL1.TMR0_S
这里我疑惑了。下面来一探其究竟。
首先,SYSCLK 是什么
#define SYSCLK ((SYSCLK_T *) SYSCLK_BASE)
可见,SYSCLK 是一个 SYSCLK_T 类型的指针,物理地址是 SYSCLK_BASE。
1.SYSCLK_T结构体类型typedef 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;
2.物理地址SYSCLK_BASE#define SYSCLK_BASE (AHB_BASE + 0x00200)
又#define AHB_BASE (( uint32_t)0x50000000)
所以,SYSCLK_BASE代表的地址是0x5000_0x0200。
3.成员变量的地址
而在SYSCLK_T 结构体中每个成员都是4字节,所以,CLKSEL1 成员变量位于该结构体中的 0x14位置。
故,SYSCLK->CLKSEL1的实际地址就是0x5000_0214。从数据手册知道这就是CLKSEL1寄存器的地址。
其次,SYSCLK->CLKSEL1.TMR0_S是什么
在SYSCLK_T
结构体定义中可以看到:SYSCLK_CLKSEL1_T CLKSEL1;
而SYSCLK_CLKSEL1_T的定义如下: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;
这东东看起来是一个结构体,但实际上这是C语言的位域定义(关于位域的具体内容可以参考《谭浩强 C语言 第三版 12.2节》)。从该定义中知道位域名TMR0_S占用3各位,8-10bit。
最后把以上各个片段拼起来:
SYSCLK->CLKSEL1.TMR0_S = u8ClkSrcSel;
SYSCLK :SYSCLK_T型结构体指针,该类型结构体包含10个变量,均为4字节,指向地址为0x50000000。
CLKSEL1 :上述结构体的第六个成员变量,其类型是一个SYSCLK_CLKSEL1_T位域结构,该结构总长度为4字节。
TMR0_S :CLKSEL1位域结构中的一个位域,8-10bit。
至于你明白没有,反正我是明白了。
不对的地方请指正啊。 |