- Forums
- Resources
- About
- Groups
Close
(今天很对不起,写了两个小时的文章,发表的时候生态圈掉线了,等我重新登录进来,所有内容都没了。。。为了赶时间没有在Word上存稿,结果就忘了生态圈这个BUG了,很尴尬。)
上一贴我们说明了外部时钟输出的基本功能,就是选择时钟源输出、SPB时钟分频输出两个部分。该分频器可以称为DIV分频器,8位的分频因子。分频因子从0-255,以我们上上贴给出的默认100MHzSPB时钟为例,得到的最小时钟频率为392KHz。这个分频精度对于一般的处理器,看门狗是够用的,最低端的51单片机时钟都有12MHz。但是对于一般的开关电源这个频率还是有点高,开关电源也就十几到一百KHz。因此为了得到更大的输出频率范围,该模块增加了分数分频的功能。今天我们就来介绍这部分内容。
图1:分数分频模块基本结构
今天要讲的是分数分频模块,这同样是在外部时钟输出当中的一部分。这个分频模块要比上一贴的8位分频精度要高,因为是10位的。
该模块有两种工作模式:
(1)正常模式:分数分频器的寄存器FDR位域FDR.result类似于一个向上计数器,每次SPB时钟到来后result+1,直到result达到3FF(1024)溢出,位域FDR.step为result的重载值,公式为:
公式一:正常模式分频公式
(2)分数分频模式:每次result+step直到溢出,result保存的是result+step的值。因此我们可以考虑每次溢出后result的值都为0,所以计算时取result初值为0。也就是说result从0开始,每次SPB时钟来临后累加step直到溢出。我们可以得到计算公式为:
公式二:分数分频模式分频公式,其中n=step
这种工作模式的好处是,每个SPB时钟周期对应的是step个计数。也就是相比较于正常模式,最小时钟周期缩小了step倍,对应的输出时钟精度就提高了step倍。所以分数分频模式相较于计数器分频模式要精度更高。
接下来就直接上代码了,不再解释了。
//FDR寄存器联合结构体定义,同上一贴,由ILLD给出
typedef union
{
unsigned int U;
signed int I;
Ifx_SCU_FDR_Bits B;
} Ifx_SCU_FDR;
//FDR寄存器位域定义
typedef struct _Ifx_SCU_FDR_Bits
{
unsigned int STEP:10; /*step值 */
unsigned int reserved_10:4; /*保留 */
unsigned int DM:2; /*模式选择 */
unsigned int RESULT:10; /*result值 */
unsigned int reserved_26:5; /*保留 */
unsigned int DISCLK:1; /*模块使能/禁用 */
} Ifx_SCU_FDR_Bits;
以下也是沿用上一贴的风格,对函数的输入参数进行定义,分别有模块使能/禁用、模式选择两个参数。
//模块使能禁用
typedef enum
{
IfxScuCcu_EXTCLK_FDR_EN = 0, //模块使能,DM设置有效
IfxScuCcu_EXTCLK_FDR_OFF = 1, //模块禁用
} IfxScuCcu_EXTCLK_FDRDIS;
//工作模式定义
typedef enum
{
IfxScuCcu_EXTCLK_DM_OFF0 = 0, //模块禁用
IfxScuCcu_EXTCLK_DM_NM = 1, //正常模式
IfxScuCcu_EXTCLK_DM_FD = 2, //分数分频模式
IfxScuCcu_EXTCLK_DM_OFF1 = 3, //模块禁用
} IfxScuCcu_EXTCLK_DM;
接下来是函数体定义:
void IfxScuCcu_CLKout_FDR(IfxScuCcu_EXTCLK_FDRDIS fdrdis, IfxScuCcu_EXTCLK_DM fdrdm, float32 fSPB, float32 fOUT)
{
uint16 password = IfxScuWdt_getSafetyWatchdogPassword();
IfxScuWdt_clearSafetyEndinit(password);
uint16 fdrstep;
Ifx_SCU_FDR FDR;
FDR.B.CLKDIS = fdrdis;//使能模块
if(FDR.B.CLKDIS==IfxScuCcu_EXTCLK_FDR_EN)
{
FDR.B.DM = fdrdm;
switch(FDR.B.DM)
{
case IfxScuCcu_EXTCLK_DM_OFF0:
default;
case IfxScuCcu_EXTCLK_DM_NM:
fdrstep=1024-fSPB/(2*fOUT); //正常模式,step作为result重载值
FDR.B.STEP=fdrstep;
default;
case IfxScuCcu_EXTCLK_DM_FD:
fdrstep=1024*2*fSPB/OUT; //分数分频模式,step作为累加因子
FDR.B.STEP=fdrstep;
default;
case IfxScuCcu_EXTCLK_DM_OFF1:
default;
}
}
else _nop();
IfxScuWdt_setSafetyEndinit(password);
}
最后在主函数写入:
float32 getspb;
getspb=IfxScuCcu_getSpbFrequency();//获取SPB时钟
IfxScuCcu_CLKout(IfxScuCcu_EXTCLK_fSPB,1,IfxScuCcu_EXTCLK_NSEL_NINV);//选择SPB作为时钟源
IfxScuCcu_CLKout_FDR(IfxScuCcu_EXTCLK_FDR_EN,IfxScuCcu_EXTCLK_DM_FD,getspb,8000000);//分数分频模式,输出8MHz时钟。
(好了,今天就这么多,以上内容已经不如刚开始那么完整了,只能等以后再补充了。本来写的很完美,结果出这种事情,真是欲哭无泪啊,最近老干这种蠢事。)
我把内容都补充了,这个函数同上一贴一样,等到周六增加一贴实验的内容。会把代码和调试结果记录下来上传。希望我的hightec给点力。。。
只有注册用户才能在此添加评论。 如果您已经注册,请登录。 如果您还没有注册,请注册并登录。