公告

大中华汽车电子生态圈社区并入开发者社区- 更多资讯点击此

Tip / 登入 to post questions, reply, level up, and achieve exciting badges. Know more

cross mob

TC275调试日志——最小系统搭建:时钟输出函数2

TC275调试日志——最小系统搭建:时钟输出函数2

凌风2018_版主_
Level 4

(今天很对不起,写了两个小时的文章,发表的时候生态圈掉线了,等我重新登录进来,所有内容都没了。。。为了赶时间没有在Word上存稿,结果就忘了生态圈这个BUG了,很尴尬。)

上一贴我们说明了外部时钟输出的基本功能,就是选择时钟源输出、SPB时钟分频输出两个部分。该分频器可以称为DIV分频器,8位的分频因子。分频因子从0-255,以我们上上贴给出的默认100MHzSPB时钟为例,得到的最小时钟频率为392KHz。这个分频精度对于一般的处理器,看门狗是够用的,最低端的51单片机时钟都有12MHz。但是对于一般的开关电源这个频率还是有点高,开关电源也就十几到一百KHz。因此为了得到更大的输出频率范围,该模块增加了分数分频的功能。今天我们就来介绍这部分内容。

功能分频模块.png

图1:分数分频模块基本结构

今天要讲的是分数分频模块,这同样是在外部时钟输出当中的一部分。这个分频模块要比上一贴的8位分频精度要高,因为是10位的。

该模块有两种工作模式:

(1)正常模式:分数分频器的寄存器FDR位域FDR.result类似于一个向上计数器,每次SPB时钟到来后result+1,直到result达到3FF(1024)溢出,位域FDR.step为result的重载值,公式为:

计数公式.PNG

公式一:正常模式分频公式

(2)分数分频模式:每次result+step直到溢出,result保存的是result+step的值。因此我们可以考虑每次溢出后result的值都为0,所以计算时取result初值为0。也就是说result从0开始,每次SPB时钟来临后累加step直到溢出。我们可以得到计算公式为:

功能性分频公式.PNG

公式二:分数分频模式分频公式,其中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给点力。。。




0 点赞
3088 次查看
4 评论