[Kinetis] 【Kinetis分享】+KL46的时钟系统

[复制链接]
3670|13
 楼主| 强仔00001 发表于 2014-12-8 11:53 | 显示全部楼层 |阅读模式
本帖最后由 强仔00001 于 2014-12-8 13:07 编辑

         前几天拿到了一套飞思卡尔的开发套件,是万利电子出品的。做工很赞,很高大上。首先我从它的时钟系统入手。去官网下了个数据手册和参考手册下来。
         主要是看数据手册的时钟模块。一看手册,真晕了,时钟系统好复杂。整个时钟系统由 MCGOSC RTC 几部分组成,此外还与 SIM 有关系,这是因为 SIM 控制了大多数模块的时钟门控。这个跟STM32也是类似的,要用到那个外设,先要把相应的时钟打开。
下面我自己用例程工程,配置了时钟,并且把总线时钟频率二分频输出到PTC3口上输出,如下图可以看出PTC3有个复用功能是时钟输出。
QQ截图20141207232717.png
然后我从官网下载一些KL46 Demo板的源代码。然后就找到同一型号的芯片的例程。这个例程刚好满足的要求,用PTC3输出时钟,例程还有串口的程序,这部分用不到,我就注释了。我用了Keil v5.1的编译环境。大家注意的是从keil v5版本开始,芯片的支持包要用户选择下载。具体的方法如下:
QQ截图20141208011228.png QQ截图20141208011323.png QQ截图20141208011415.png
把例程打开后:
QQ截图20141208011723.png
我这里是用Jlink V8进行仿真和下载程序的,所以工程的配置还要设置一下才能用,方法如下:
QQ截图20141208011952.png QQ截图20141208012034.png QQ截图20141208012146.png
成功仿真器连上板子的的仿真接口后会出现红框里的信息,仿真接口模式要选择SW模式。
接着就是配置flash
QQ截图20141208012203.png
QQ截图20141208012228.png
要想在PTC3口输出时钟还要做一下工作:
大家可以看到这里有个条件编译,要把这个参数填进去预定义方框才行,或者你可以直接将ENABLE_CLKOUT改为1,这样编译器就会编译这部分代码,在编译器预定义方框打开的步骤如图:
QQ截图20141208012750.png
QQ截图20141208012023.png
做完这些工作就可以编译工程和下载程序进行验证了:
主程序很简单,代码如下:
  1. int main (void)
  2. {
  3.             char ch;
  4.         
  5. #ifdef CMSIS  // If we are conforming to CMSIS, we need to call start here
  6.     start();
  7. #endif
  8.         
  9.           printf("\n\rRunning the platinum project.\n\r");

  10.         while(1)
  11.         {
  12.                 //ch = in_char();
  13.                 //out_char(ch);
  14.         }
  15. }
首先程序会执行start();进行一些系统的初始化。
我们来看看start();的内部吧:
  1. void start(void)
  2. {
  3.                 /* Disable the watchdog timer */
  4.     SIM_COPC = 0x00;
  5. #ifndef CMSIS    // If conforming to CMSIS, we do not need to perform this code


  6.         /* Copy any vector or data sections that need to be in RAM */
  7.         common_startup();
  8. #endif

  9.         /* Perform clock initialization, default UART initialization,
  10.          * initializes clock out function, and enables the abort button
  11.          */
  12.                         // common_startup();
  13.              sysinit();
  14.         
  15.         printf("\n\r\n\r");
  16.         
  17.         /* Determine the last cause(s) of reset */
  18.         outSRS();        
  19.         
  20.         /* Determine specific Kinetis L Family device and revision */
  21.         cpu_identify();
  22.         
  23. #ifndef CMSIS    // If conforming to CMSIS, we do not need to perform this code
  24.         /* Jump to main process */
  25.         main();

  26.         /* No actions to perform after this so wait forever */
  27.         while(1);
  28. #endif
  29. }
最重要的是sysinit();函数,因为这个是初始化系统时钟的。
源代码如下:
  1. /********************************************************************/
  2. void sysinit (void)
  3. {
  4.         /* Enable all of the port clocks. These have to be enabled to configure
  5.          * pin muxing options, so most code will need all of these on anyway.
  6.          */
  7.         SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK
  8.                       | SIM_SCGC5_PORTB_MASK
  9.                       | SIM_SCGC5_PORTC_MASK
  10.                       | SIM_SCGC5_PORTD_MASK
  11.                       | SIM_SCGC5_PORTE_MASK );
  12.         
  13.         // Release hold with ACKISO:  Only has an effect if recovering from VLLS1, VLLS2, or VLLS3
  14.         // if ACKISO is set you must clear ackiso before calling pll_init
  15.         //    or pll init hangs waiting for OSC to initialize
  16.         // if osc enabled in low power modes - enable it first before ack
  17.         // if I/O needs to be maintained without glitches enable outputs and modules first before ack.
  18.         if (PMC_REGSC &  PMC_REGSC_ACKISO_MASK)
  19.         PMC_REGSC |= PMC_REGSC_ACKISO_MASK;
  20.         
  21. #ifdef ENABLE_CLKOUT
  22.         // Initialize trace clk functionality
  23.         clk_out_init();
  24. #endif

  25. #if defined(NO_PLL_INIT)
  26.         mcg_clk_hz = 21000000; //FEI mode
  27.         
  28.         SIM_SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK; // clear PLLFLLSEL to select the FLL for this clock source
  29.         
  30.         uart0_clk_khz = (mcg_clk_hz / 1000); // the uart0 clock frequency will equal the FLL frequency
  31.       
  32. #else
  33.        /* Ramp up the system clock */
  34.        /* Set the system dividers */
  35.        /* NOTE: The PLL init will not configure the system clock dividers,
  36.         * so they must be configured appropriately before calling the PLL
  37.         * init function to ensure that clocks remain in valid ranges.
  38.         */  
  39.         SIM_CLKDIV1 = ( 0
  40.                         | SIM_CLKDIV1_OUTDIV1(0)
  41.                         | SIM_CLKDIV1_OUTDIV4(1) );

  42.        /* Initialize PLL */
  43.        /* PLL will be the source for MCG CLKOUT so the core, system, and flash clocks are derived from it */
  44.        mcg_clk_hz = pll_init(CLK0_FREQ_HZ,  /* CLKIN0 frequency */
  45.                              LOW_POWER,     /* Set the oscillator for low power mode */
  46.                              CLK0_TYPE,     /* Crystal or canned oscillator clock input */
  47.                              PLL0_PRDIV,    /* PLL predivider value */
  48.                              PLL0_VDIV,     /* PLL multiplier */
  49.                              MCGOUT);       /* Use the output from this PLL as the MCGOUT */

  50.        /* Check the value returned from pll_init() to make sure there wasn't an error */
  51.        if (mcg_clk_hz < 0x100)
  52.          while(1);
  53.       
  54.        SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK; // set PLLFLLSEL to select the PLL for this clock source
  55.       
  56.        uart0_clk_khz = ((mcg_clk_hz / 2) / 1000); // UART0 clock frequency will equal half the PLL frequency
  57. #endif      

  58.         /*
  59.          * Use the value obtained from the pll_init function to define variables
  60.          * for the core clock in kHz and also the peripheral clock. These
  61.          * variables can be used by other functions that need awareness of the
  62.          * system frequency.
  63.          */
  64.         mcg_clk_khz = mcg_clk_hz / 1000;
  65.           core_clk_khz = mcg_clk_khz / (((SIM_CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> 28)+ 1);
  66.         periph_clk_khz = core_clk_khz / (((SIM_CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> 16)+ 1);
  67.         
  68.         /* Enable pin interrupt for the abort button - PTA4 */
  69.         /* This pin could also be used as the NMI interrupt, but since the NMI
  70.          * is level sensitive each button press will cause multiple interrupts.
  71.          * Using the GPIO interrupt instead means we can configure for an edge
  72.          * sensitive interrupt instead = one interrupt per button press.
  73.          */
  74.         enable_abort_button();
  75.         
  76.         
  77.         if (TERM_PORT_NUM == 0)
  78.         {
  79.             /* Enable the pins for the selected UART */
  80. #ifdef FREEDOM
  81.           /* Enable the UART_TXD function on PTA1 */
  82.           PORTA_PCR1 = PORT_PCR_MUX(0x2);
  83.          
  84.           /* Enable the UART_TXD function on PTA2 */
  85.           PORTA_PCR2 = PORT_PCR_MUX(0x2);
  86. #endif

  87. #ifdef BACES
  88.           /* Enable the UART_TXD function on PTA1 */
  89.           PORTA_PCR1 = PORT_PCR_MUX(0x2);
  90.          
  91.           /* Enable the UART_TXD function on PTA2 */
  92.           PORTA_PCR2 = PORT_PCR_MUX(0x2);
  93. #endif         
  94.          
  95. #ifdef FIREBIRD        
  96.           /* Enable the UART_TXD function on PTA1 */
  97.           PORTA_PCR1 = PORT_PCR_MUX(0x2);
  98.          
  99.           /* Enable the UART_TXD function on PTA2 */
  100.           PORTA_PCR2 = PORT_PCR_MUX(0x2);
  101. #endif
  102.          
  103. #ifdef TOWER         
  104.          
  105.           /* Enable the UART_TXD function on PTA14 */
  106.             PORTA_PCR14 = PORT_PCR_MUX(0x3); // UART0 is alt3 function for this pin
  107.                   
  108.             /* Enable the UART_RXD function on PTA15 */
  109.             PORTA_PCR15 = PORT_PCR_MUX(0x3); // UART0 is alt3 function for this pin
  110. #endif
  111.          
  112.          
  113.          
  114.           SIM_SOPT2 |= SIM_SOPT2_UART0SRC(1); // select the PLLFLLCLK as UART0 clock source
  115.         }
  116.           if (TERM_PORT_NUM == 1)
  117.           {
  118.                 /* Enable the UART_TXD function on PTC4 */
  119.                   PORTC_PCR4 = PORT_PCR_MUX(0x3); // UART1 is alt3 function for this pin
  120.                   
  121.                   /* Enable the UART_RXD function on PTC3 */
  122.                   PORTC_PCR3 = PORT_PCR_MUX(0x3); // UART1 is alt3 function for this pin
  123.           }
  124.         
  125.         if (TERM_PORT_NUM == 2)
  126.           {
  127.                  /* Enable the UART_TXD function on PTD3 */
  128.                   PORTE_PCR16 = PORT_PCR_MUX(0x3); // UART2 is alt3 function for this pin
  129.                   
  130.                   /* Enable the UART_RXD function on PTD2 */
  131.                   PORTE_PCR17 = PORT_PCR_MUX(0x3); // UART2 is alt3 function for this pin
  132.           }
  133.         
  134.           /* UART0 is clocked asynchronously to the core clock, but all other UARTs are
  135.          * clocked from the peripheral clock. So we have to determine which clock
  136.          * to send to the UART_init function.
  137.          */
  138.         if (TERM_PORT_NUM == 0)
  139.             uart0_init (UART0_BASE_PTR, uart0_clk_khz, TERMINAL_BAUD);
  140.         else if (TERM_PORT_NUM == 1)
  141.               uart_init (UART1_BASE_PTR, periph_clk_khz, TERMINAL_BAUD);
  142.         else if (TERM_PORT_NUM == 2)
  143.             uart_init (UART2_BASE_PTR, periph_clk_khz, TERMINAL_BAUD);
  144.         else
  145.           while(1);
  146. }
好长的代码;P。
不过它的流程都跟其他的MCU大同小异。
首先关闭看门狗。
然后打开这里是打开所有GPIO的时钟,这些打开外设的时钟寄存器手册上也有说明,如下图:
QQ截图20141208013657.png
然后程序主要的部分是PLL配置了:
  1. /* Initialize PLL */
  2.        /* PLL will be the source for MCG CLKOUT so the core, system, and flash clocks are derived from it */
  3.        mcg_clk_hz = pll_init(CLK0_FREQ_HZ,  /* CLKIN0 frequency */
  4.                              LOW_POWER,     /* Set the oscillator for low power mode */
  5.                              CLK0_TYPE,     /* Crystal or canned oscillator clock input */
  6.                              PLL0_PRDIV,    /* PLL predivider value */
  7.                              PLL0_VDIV,     /* PLL multiplier */
  8.                              MCGOUT);       /* Use the output from this PLL as the MCGOUT */

  9.        /* Check the value returned from pll_init() to make sure there wasn't an error */
  10.        if (mcg_clk_hz < 0x100)
  11.          while(1);
  12.       
  13.        SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK; // set PLLFLLSEL to select the PLL for this clock source
填进去pll_init函数里的几个参数,是可以改的,可以找到相应的头文件修改。
这里他的一些PLL参数如下图:
QQ截图20141208014651.png
这个参数把时钟设到最大48M,这里用户可以根据自己的需求来修改。
剩下的就是其他功能模块的初始化了。
现在就下载程序下去进行验证了,下面附上测试图:
IMG_20141208_020820.jpg
IMG_20141208_015744.jpg

补上高大上的板板靓照
IMG_20141208_130318.jpg IMG_20141208_130329.jpg IMG_20141208_130339.jpg

gaoyang9992006 发表于 2014-12-8 12:49 | 显示全部楼层
无图无真相,高大上的图呢?
gaoyang9992006 发表于 2014-12-8 12:49 | 显示全部楼层
无图无真相,高大上的图呢?
 楼主| 强仔00001 发表于 2014-12-8 13:08 | 显示全部楼层
gaoyang9992006 发表于 2014-12-8 12:49
无图无真相,高大上的图呢?

板板的靓照:
IMG_20141208_130339.jpg IMG_20141208_130329.jpg IMG_20141208_130318.jpg
gaoyang9992006 发表于 2014-12-8 13:10 | 显示全部楼层
高大上名不虚传
 楼主| 强仔00001 发表于 2014-12-8 16:44 | 显示全部楼层
gaoyang9992006 发表于 2014-12-8 13:10
高大上名不虚传

;P;P没把你吓着吧
yqg80 发表于 2014-12-9 14:06 | 显示全部楼层
高不知道有多噶,图倒是很大:lol
 楼主| 强仔00001 发表于 2014-12-9 16:10 | 显示全部楼层
yqg80 发表于 2014-12-9 14:06
高不知道有多噶,图倒是很大

:lol今晚继续分享
WAMCNCN 发表于 2015-5-3 23:40 | 显示全部楼层
系统初始化打开了ABCDE时钟,在主函数里,不再打开1次,不能用
 楼主| 强仔00001 发表于 2015-5-5 19:42 | 显示全部楼层
WAMCNCN 发表于 2015-5-3 23:40
系统初始化打开了ABCDE时钟,在主函数里,不再打开1次,不能用

你遇到了问题??
WAMCNCN 发表于 2015-5-5 21:24 | 显示全部楼层

解决了:lol
 楼主| 强仔00001 发表于 2015-5-7 16:25 | 显示全部楼层

好样的,不错呀
wenjie321 发表于 2017-1-11 10:10 | 显示全部楼层
板载仿真器能用吗?怎么用的
wenjie321 发表于 2017-1-12 22:07 | 显示全部楼层
有没有这款板子的官方代码发我一份,发我邮箱81258612@qq.com
您需要登录后才可以回帖 登录 | 注册

本版积分规则

65

主题

799

帖子

8

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