[Cortex-M0技术交流] 用C++模板计算波特率的值, PLL值

[复制链接]
AB663831 发表于 2011-5-26 18:49 | 显示全部楼层
怎么这么难啊
xukaiming 发表于 2011-5-29 22:52 | 显示全部楼层
确实好东西.......
yumeixue2006 发表于 2011-5-31 20:09 | 显示全部楼层
确实好东西.......有写C++代码吗?
adlubin 发表于 2011-7-22 10:29 | 显示全部楼层
这个很难啊
delong_z 发表于 2011-7-27 21:27 | 显示全部楼层
:L看不懂。
看来只有等高人把模块和头文件做好了,我们等着用现成的了。
电子write_cai 发表于 2011-7-28 20:13 | 显示全部楼层
yuyzy001 发表于 2011-8-2 19:17 | 显示全部楼层
呆板书生 发表于 2012-1-16 07:13 | 显示全部楼层
只有一个字,服
hotpower 发表于 2012-1-16 08:24 | 显示全部楼层
酒鬼最近好像很忙。
 楼主| X-Hawk 发表于 2012-7-27 16:31 | 显示全部楼层
本帖最后由 X-Hawk 于 2012-7-27 19:45 编辑

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

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

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

完整代码

  1. #include <stdio.h>


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

  8. template<unsigned int a, unsigned int b>
  9. struct algo_max
  10. {
  11.         enum{ v = (a < b ? b : a) };
  12. };
  13. template<unsigned int a, unsigned int b>
  14. struct algo_min
  15. {
  16.         enum{ v = (a < b ? a : b) };
  17. };
  18. template<unsigned int a, unsigned int b>
  19. struct algo_abs
  20. {
  21.         enum{ v = (a < b ? b - a : a - b) };
  22. };


  23. template
  24. <
  25.         unsigned int clk_bak,
  26.         unsigned int NO_bak,
  27.         unsigned int NF_bak,
  28.         unsigned int NR_bak,
  29.         unsigned int FCO,
  30.         unsigned int NO,
  31.         unsigned int fin,
  32.         unsigned int clk,
  33.         unsigned int NF,
  34.         unsigned int NF_max,
  35.         bool loop
  36. >
  37. struct clk2pll_NO_NF
  38. {
  39.         enum{ NR = (FCO == 0 ? 0 : fin*NF/(FCO?FCO:1)) };
  40.         enum{ clk_temp_new = ((NR == 0 || NO == 0) ? 0 : fin*NF/(NR?NR:1)/(NO?NO:1)) };
  41.        
  42.         enum{ better =
  43.                 (NR >= 2 && NR <= 33)
  44.                 && (unsigned int)algo_abs<clk_temp_new, clk>::v < (unsigned int)algo_abs<clk_bak, clk>::v };

  45.         enum{ clk_new1 = (better ? clk_temp_new : clk_bak) };
  46.         enum{ NO_new1 = (better ? NO : NO_bak) };
  47.         enum{ NF_new1 = (better ? NF : NF_bak) };
  48.         enum{ NR_new1 = (better ? NR : NR_bak) };
  49.        
  50.         typedef clk2pll_NO_NF<clk_new1, NO_new1, NF_new1, NR_new1, FCO, NO, fin, clk,
  51.                 NF+1, NF_max, (NF <= NF_max)> type;
  52.         enum{ clk_new = type::clk_new };
  53.         enum{ NO_new = type::NO_new };
  54.         enum{ NF_new = type::NF_new };
  55.         enum{ NR_new = type::NR_new };       
  56. };

  57. template
  58. <
  59.         unsigned int clk_bak,
  60.         unsigned int NO_bak,
  61.         unsigned int NF_bak,
  62.         unsigned int NR_bak,
  63.         unsigned int FCO,
  64.         unsigned int NO,
  65.         unsigned int fin,
  66.         unsigned int clk,
  67.         unsigned int NF,
  68.         unsigned int NF_max
  69. >
  70. struct clk2pll_NO_NF<clk_bak, NO_bak, NF_bak, NR_bak, FCO, NO, fin, clk, NF, NF_max, false>
  71. {
  72.         enum{ clk_new = clk_bak };
  73.         enum{ NO_new = NO_bak };
  74.         enum{ NF_new = NF_bak };
  75.         enum{ NR_new = NR_bak };
  76. };

  77. template
  78. <
  79.         unsigned int clk_bak,
  80.         unsigned int NO_bak,
  81.         unsigned int NF_bak,
  82.         unsigned int NR_bak,
  83.        
  84.         unsigned int fin,
  85.         unsigned int clk,
  86.         unsigned int NO,
  87.         unsigned int NO_min,
  88.         unsigned int NO_max,
  89.         unsigned int direction,
  90.         bool loop
  91. >
  92. struct clk2pll_NO
  93. {

  94.         enum{
  95.                 FCO = clk*NO,
  96.                 NF_max = algo_min<FCO/1600000, 513>::v,
  97.                 NF_min = algo_max<FCO/15000000, 2>::v };
  98.        
  99.         typedef clk2pll_NO_NF<clk_bak, NO_bak, NF_bak, NR_bak, FCO, NO, fin, clk,
  100.                 NF_min, NF_max, (NF_min <= NF_max)> type;
  101.        
  102.         enum{ clk_new1 = type::clk_new };
  103.         enum{ NO_new1 = type::NO_new };
  104.         enum{ NF_new1 = type::NF_new };
  105.         enum{ NR_new1 = type::NR_new };
  106.        
  107.         typedef clk2pll_NO<clk_new1, NO_new1, NF_new1, NR_new1,
  108.                 fin, clk, NO+direction, NO_min, NO_max, direction,
  109.                 (NO+direction >= NO_min && NO+direction <= NO_max)> type_next;
  110.        
  111.         enum{ clk_new = type_next::clk_new };
  112.         enum{ NO_new = type_next::NO_new };
  113.         enum{ NF_new = type_next::NF_new };
  114.         enum{ NR_new = type_next::NR_new };       

  115. };

  116. template
  117. <
  118.         unsigned int clk_bak,
  119.         unsigned int NO_bak,
  120.         unsigned int NF_bak,
  121.         unsigned int NR_bak,
  122.        
  123.         unsigned int fin,
  124.         unsigned int clk,
  125.         unsigned int NO_min,
  126.         unsigned int NO_max,
  127.         unsigned int direction,
  128.         bool loop
  129. >
  130. struct clk2pll_NO<clk_bak, NO_bak, NF_bak, NR_bak, fin, clk, 3, NO_min, NO_max, direction, loop>
  131. {
  132.         enum{ NO = 3 };
  133.         typedef clk2pll_NO<clk_bak, NO_bak, NF_bak, NR_bak,
  134.                 fin, clk, NO+direction, NO_min, NO_max, direction,
  135.                 (NO+direction >= NO_min && NO+direction <= NO_max)> type_next;
  136.                
  137.         enum{ clk_new = type_next::clk_new };
  138.         enum{ NO_new = type_next::NO_new };
  139.         enum{ NF_new = type_next::NF_new };
  140.         enum{ NR_new = type_next::NR_new };       
  141. };
  142. template
  143. <
  144.         unsigned int clk_bak,
  145.         unsigned int NO_bak,
  146.         unsigned int NF_bak,
  147.         unsigned int NR_bak,
  148.        
  149.         unsigned int fin,
  150.         unsigned int clk,
  151.         unsigned int NO,
  152.         unsigned int NO_min,
  153.         unsigned int NO_max,
  154.         unsigned int direction
  155. >
  156. struct clk2pll_NO<clk_bak, NO_bak, NF_bak, NR_bak, fin, clk, NO, NO_min, NO_max, direction, false>
  157. {
  158.         enum{ clk_new = clk_bak };
  159.         enum{ NO_new = NO_bak };
  160.         enum{ NF_new = NF_bak };
  161.         enum{ NR_new = NR_bak };
  162. };
  163. template
  164. <
  165.         unsigned int clk_bak,
  166.         unsigned int NO_bak,
  167.         unsigned int NF_bak,
  168.         unsigned int NR_bak,
  169.        
  170.         unsigned int fin,
  171.         unsigned int clk,
  172.         unsigned int NO_min,
  173.         unsigned int NO_max,
  174.         unsigned int direction
  175. >
  176. struct clk2pll_NO<clk_bak, NO_bak, NF_bak, NR_bak, fin, clk, 3, NO_min, NO_max, direction, false>
  177. {
  178.         enum{ clk_new = clk_bak };
  179.         enum{ NO_new = NO_bak };
  180.         enum{ NF_new = NF_bak };
  181.         enum{ NR_new = NR_bak };
  182. };


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

  190.         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;
  191.         typedef clk2pll_NO<
  192.                 type0::clk_new, type0::NO_new, type0::NF_new, type0::NR_new,
  193.                 fin, clk, NO_pre, NO_min, NO_max, -1, (NO_pre >= NO_min && NO_pre <= NO_max)> type;
  194.        
  195.         enum
  196.         {
  197.                 OUT_DV = (type::NO_new == 1 ? 0 :
  198.                         type::NO_new == 2 ? 1 :
  199.                         type::NO_new == 4 ? 3 :
  200.                         0),
  201.                 IN_DV = type::NR_new - 2,
  202.                 FB_DV = type::NF_new - 2
  203.         };
  204.        
  205.         enum
  206.         {
  207.                 PLLCON = (NO_min > NO_max || type::clk_new == 0 ? 0 : (OUT_DV << 14) + (IN_DV << 9) + FB_DV),
  208.                 output_clock = (NO_min > NO_max ? 0 : type::clk_new)
  209.         };
  210. };

  211. template<unsigned int clk>
  212. struct clk2pll<0, clk>
  213. {
  214.         enum {
  215.                 PLLCON = 0,
  216.                 output_clock = 0
  217.         };
  218. };
  219. template<unsigned int fin>
  220. struct clk2pll<fin, 0>
  221. {
  222.         enum
  223.         {
  224.                 PLLCON = 0,
  225.                 output_clock = 0
  226.         };
  227. };



  228. int main()
  229. {
  230.         typedef clk2pll<12000000, 48000000> clk_t;
  231.         printf("PLLCON = 0x%08x, output clock = %d\n",
  232.                         clk_t::PLLCON,
  233.                         clk_t::output_clock);
  234.         return 0;
  235. }

john_lee 发表于 2012-7-27 17:02 | 显示全部楼层
陈工又发力了,顶,我要抄袭,整合到 look 工程向导里,陈工有意见不?:D
 楼主| X-Hawk 发表于 2012-7-27 17:05 | 显示全部楼层
陈工又发力了,顶,我要抄袭,整合到 look 工程向导里,陈工有意见不?:D
john_lee 发表于 2012-7-27 17:02

李老师能用是咱的荣幸啊。
请随便使用,任意目的(商业/非商业,修改,分发)都支持!
zxs2000 发表于 2012-7-30 14:56 | 显示全部楼层
xukaiming 发表于 2013-4-10 12:19 | 显示全部楼层
专顶牛贴
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部
快速回复 在线客服 返回列表 返回顶部