发新帖我要提问
12
返回列表
打印
[Cortex-M0技术交流]

用C++模板计算波特率的值, PLL值

[复制链接]
楼主: X-Hawk
手机看帖
扫描二维码
随时随地手机跟帖
21
AB663831| | 2011-5-26 18:49 | 只看该作者 回帖奖励 |倒序浏览
怎么这么难啊

使用特权

评论回复
22
xukaiming| | 2011-5-29 22:52 | 只看该作者
确实好东西.......

使用特权

评论回复
23
yumeixue2006| | 2011-5-31 20:09 | 只看该作者
确实好东西.......有写C++代码吗?

使用特权

评论回复
24
adlubin| | 2011-7-22 10:29 | 只看该作者
这个很难啊

使用特权

评论回复
25
delong_z| | 2011-7-27 21:27 | 只看该作者
:L看不懂。
看来只有等高人把模块和头文件做好了,我们等着用现成的了。

使用特权

评论回复
26
电子write_cai| | 2011-7-28 20:13 | 只看该作者

使用特权

评论回复
27
yuyzy001| | 2011-8-2 19:17 | 只看该作者
ding

使用特权

评论回复
28
呆板书生| | 2012-1-16 07:13 | 只看该作者
只有一个字,服

使用特权

评论回复
29
hotpower| | 2012-1-16 08:24 | 只看该作者
酒鬼最近好像很忙。

使用特权

评论回复
30
X-Hawk|  楼主 | 2012-7-27 16:31 | 只看该作者
本帖最后由 X-Hawk 于 2012-7-27 19:45 编辑

用模板计算PLL寄存器的值,
使用示例

int main()
{
        //用法
        //得到PLLCON寄存器的值      
        //        clk2pll<输入频率,输出频率>:PLLCON
        //得到实际输出频率(可用来预估精确度)
        //        clk2pll<输入频率,输出频率>:output_clock

        typedef clk2pll<22118400, 48000000> clk_t;
        printf("LLCON = 0x%08x, output clock = %d\n",
                        clk_t:LLCON,
                        clk_t:utput_clock);
        return 0;
}

完整代码

#include <stdio.h>


//PLL --
// 2 <= NF <= 513
// 2 <= NR <= 33
// NO, 1, 2, 2, 4
// 100M < FCO=FIN*NF/NR=clk*NO < 200M,  (120M < FCO preferred)
// 1.6M < FIN/NR=clk*NO/NF < 15M

template<unsigned int a, unsigned int b>
struct algo_max
{
        enum{ v = (a < b ? b : a) };
};
template<unsigned int a, unsigned int b>
struct algo_min
{
        enum{ v = (a < b ? a : b) };
};
template<unsigned int a, unsigned int b>
struct algo_abs
{
        enum{ v = (a < b ? b - a : a - b) };
};


template
<
        unsigned int clk_bak,
        unsigned int NO_bak,
        unsigned int NF_bak,
        unsigned int NR_bak,
        unsigned int FCO,
        unsigned int NO,
        unsigned int fin,
        unsigned int clk,
        unsigned int NF,
        unsigned int NF_max,
        bool loop
>
struct clk2pll_NO_NF
{
        enum{ NR = (FCO == 0 ? 0 : fin*NF/(FCO?FCO:1)) };
        enum{ clk_temp_new = ((NR == 0 || NO == 0) ? 0 : fin*NF/(NR?NR:1)/(NO?NO:1)) };
       
        enum{ better =
                (NR >= 2 && NR <= 33)
                && (unsigned int)algo_abs<clk_temp_new, clk>::v < (unsigned int)algo_abs<clk_bak, clk>::v };

        enum{ clk_new1 = (better ? clk_temp_new : clk_bak) };
        enum{ NO_new1 = (better ? NO : NO_bak) };
        enum{ NF_new1 = (better ? NF : NF_bak) };
        enum{ NR_new1 = (better ? NR : NR_bak) };
       
        typedef clk2pll_NO_NF<clk_new1, NO_new1, NF_new1, NR_new1, FCO, NO, fin, clk,
                NF+1, NF_max, (NF <= NF_max)> type;
        enum{ clk_new = type::clk_new };
        enum{ NO_new = type::NO_new };
        enum{ NF_new = type::NF_new };
        enum{ NR_new = type::NR_new };       
};

template
<
        unsigned int clk_bak,
        unsigned int NO_bak,
        unsigned int NF_bak,
        unsigned int NR_bak,
        unsigned int FCO,
        unsigned int NO,
        unsigned int fin,
        unsigned int clk,
        unsigned int NF,
        unsigned int NF_max
>
struct clk2pll_NO_NF<clk_bak, NO_bak, NF_bak, NR_bak, FCO, NO, fin, clk, NF, NF_max, false>
{
        enum{ clk_new = clk_bak };
        enum{ NO_new = NO_bak };
        enum{ NF_new = NF_bak };
        enum{ NR_new = NR_bak };
};

template
<
        unsigned int clk_bak,
        unsigned int NO_bak,
        unsigned int NF_bak,
        unsigned int NR_bak,
       
        unsigned int fin,
        unsigned int clk,
        unsigned int NO,
        unsigned int NO_min,
        unsigned int NO_max,
        unsigned int direction,
        bool loop
>
struct clk2pll_NO
{

        enum{
                FCO = clk*NO,
                NF_max = algo_min<FCO/1600000, 513>::v,
                NF_min = algo_max<FCO/15000000, 2>::v };
       
        typedef clk2pll_NO_NF<clk_bak, NO_bak, NF_bak, NR_bak, FCO, NO, fin, clk,
                NF_min, NF_max, (NF_min <= NF_max)> type;
       
        enum{ clk_new1 = type::clk_new };
        enum{ NO_new1 = type::NO_new };
        enum{ NF_new1 = type::NF_new };
        enum{ NR_new1 = type::NR_new };
       
        typedef clk2pll_NO<clk_new1, NO_new1, NF_new1, NR_new1,
                fin, clk, NO+direction, NO_min, NO_max, direction,
                (NO+direction >= NO_min && NO+direction <= NO_max)> type_next;
       
        enum{ clk_new = type_next::clk_new };
        enum{ NO_new = type_next::NO_new };
        enum{ NF_new = type_next::NF_new };
        enum{ NR_new = type_next::NR_new };       

};

template
<
        unsigned int clk_bak,
        unsigned int NO_bak,
        unsigned int NF_bak,
        unsigned int NR_bak,
       
        unsigned int fin,
        unsigned int clk,
        unsigned int NO_min,
        unsigned int NO_max,
        unsigned int direction,
        bool loop
>
struct clk2pll_NO<clk_bak, NO_bak, NF_bak, NR_bak, fin, clk, 3, NO_min, NO_max, direction, loop>
{
        enum{ NO = 3 };
        typedef clk2pll_NO<clk_bak, NO_bak, NF_bak, NR_bak,
                fin, clk, NO+direction, NO_min, NO_max, direction,
                (NO+direction >= NO_min && NO+direction <= NO_max)> type_next;
               
        enum{ clk_new = type_next::clk_new };
        enum{ NO_new = type_next::NO_new };
        enum{ NF_new = type_next::NF_new };
        enum{ NR_new = type_next::NR_new };       
};
template
<
        unsigned int clk_bak,
        unsigned int NO_bak,
        unsigned int NF_bak,
        unsigned int NR_bak,
       
        unsigned int fin,
        unsigned int clk,
        unsigned int NO,
        unsigned int NO_min,
        unsigned int NO_max,
        unsigned int direction
>
struct clk2pll_NO<clk_bak, NO_bak, NF_bak, NR_bak, fin, clk, NO, NO_min, NO_max, direction, false>
{
        enum{ clk_new = clk_bak };
        enum{ NO_new = NO_bak };
        enum{ NF_new = NF_bak };
        enum{ NR_new = NR_bak };
};
template
<
        unsigned int clk_bak,
        unsigned int NO_bak,
        unsigned int NF_bak,
        unsigned int NR_bak,
       
        unsigned int fin,
        unsigned int clk,
        unsigned int NO_min,
        unsigned int NO_max,
        unsigned int direction
>
struct clk2pll_NO<clk_bak, NO_bak, NF_bak, NR_bak, fin, clk, 3, NO_min, NO_max, direction, false>
{
        enum{ clk_new = clk_bak };
        enum{ NO_new = NO_bak };
        enum{ NF_new = NF_bak };
        enum{ NR_new = NR_bak };
};


template<unsigned int fin, unsigned int clk>
struct clk2pll
{
        enum{
                NO_min = algo_max<1, (100000000+clk-1)/(clk?clk:1)>::v,
                NO_max = algo_min<4, 200000000/(clk?clk:1)>::v,
                NO_pre = algo_max<NO_min, 120000000/(clk?clk:1)>::v };

        typedef clk2pll_NO<0, 0, 0, 0, fin, clk, NO_pre, NO_min, NO_max, +1, (NO_pre >= NO_min && NO_pre <= NO_max)> type0;
        typedef clk2pll_NO<
                type0::clk_new, type0::NO_new, type0::NF_new, type0::NR_new,
                fin, clk, NO_pre, NO_min, NO_max, -1, (NO_pre >= NO_min && NO_pre <= NO_max)> type;
       
        enum
        {
                OUT_DV = (type::NO_new == 1 ? 0 :
                        type::NO_new == 2 ? 1 :
                        type::NO_new == 4 ? 3 :
                        0),
                IN_DV = type::NR_new - 2,
                FB_DV = type::NF_new - 2
        };
       
        enum
        {
                PLLCON = (NO_min > NO_max || type::clk_new == 0 ? 0 : (OUT_DV << 14) + (IN_DV << 9) + FB_DV),
                output_clock = (NO_min > NO_max ? 0 : type::clk_new)
        };
};

template<unsigned int clk>
struct clk2pll<0, clk>
{
        enum {
                PLLCON = 0,
                output_clock = 0
        };
};
template<unsigned int fin>
struct clk2pll<fin, 0>
{
        enum
        {
                PLLCON = 0,
                output_clock = 0
        };
};



int main()
{
        typedef clk2pll<12000000, 48000000> clk_t;
        printf("PLLCON = 0x%08x, output clock = %d\n",
                        clk_t::PLLCON,
                        clk_t::output_clock);
        return 0;
}

使用特权

评论回复
31
john_lee| | 2012-7-27 17:02 | 只看该作者
陈工又发力了,顶,我要抄袭,整合到 look 工程向导里,陈工有意见不?:D

使用特权

评论回复
32
X-Hawk|  楼主 | 2012-7-27 17:05 | 只看该作者
陈工又发力了,顶,我要抄袭,整合到 look 工程向导里,陈工有意见不?:D
john_lee 发表于 2012-7-27 17:02

李老师能用是咱的荣幸啊。
请随便使用,任意目的(商业/非商业,修改,分发)都支持!

使用特权

评论回复
33
zxs2000| | 2012-7-30 14:56 | 只看该作者

使用特权

评论回复
34
xukaiming| | 2013-4-10 12:19 | 只看该作者
专顶牛贴

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则