打印
[Kinetis]

飞思卡尔KL03内部48M晶振精度疑惑

[复制链接]
5065|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jiaduo|  楼主 | 2015-1-27 13:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 jiaduo 于 2015-1-27 13:45 编辑

看datasheet说内部的irc48mhz晶振精度在1%,但是我实际使用中,使用IRC48M做TPM0时钟源,输出PWM发现有偏差,根据偏差计算得到的实际时钟为46Mhz左右。也就是说我用46Mhz这个晶振值计算TPM0加载值比较准确。。
。。所以有疑惑。现在贴出代码。

主函数部分
int main(void)
{
        kl03_SystickInit();
        kl03_led_init();
       
        kl03_tpm0_epwm_init(SystemCoreClock-(3000000-650000),847000,50);
        while(1){
        }
}

时钟初始化部分
void SystemInit (void)
{
        SIM->COPC = 0;        /* disable watchdog */
        //RCM_MR = 0xff;
        MCG->C1 = 0;
        MCG->C2 = 0;
        MCG->SC = 0;        /* HIRC mode */
        SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0)|SIM_CLKDIV1_OUTDIV4(1);        /* core clock 1div ,bus clock 2div */
        MCG_MC = (1<<7);
        while((MCG->S & MCG_S_CLKST_MASK));         
        
  SystemCoreClock = __SYSTEM_CLOCK;
}

TPM0输出部分


/**
*@brief:init the TPM0 for Edge-Aligned PWM (EPWM) Mode ,CH0 output(PTB11)
*                         using module clock.
*@param:tpm_clock - tpm clock cycles(MCGPCLK)        hz - freq(max = tpm_clock/prescale/2 min = tpm_clock/pre/65536) cycle - 0~100
*/
void kl03_tpm0_epwm_init(uint32_t tpm_clock,uint32_t hz,uint32_t duty_cycle)
{
        uint32_t modulo;
        uint32_t cnv;
        /* clock source config & enable clock */
        SIM->SOPT2 &= ~SIM_SOPT2_TPMSRC_MASK;
        SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1);        /* select MCGPCLK  as  clock source for the TPM counter clock */
        SIM->SCGC6 |= (1<<24);        /* TPM0 clock enable */
        SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK;
        /* gpio config */
        PORTB->PCR[11] &= 0;
        PORTB->PCR[11] |= PORT_PCR_MUX(2);        /* TPM0_CH0        */
        /* tpm0 config */
        TPM0->SC &= ~TPM_SC_CPWMS_MASK; /* LPTPM counter operates in up counting mode */
        TPM0->SC &= ~TPM_SC_PS_MASK;
        TPM0->SC |= TPM_SC_PS(0); /* 1 prescale */
        TPM0->CONF &= ~TPM_CONF_TRGSEL_MASK;
        TPM0->CONF |= TPM_CONF_TRGSEL(8);        /* select TPM0 overflow trigger */
        TPM0->CONF |= (1<<18);        /* reload on overflow */
        /* channel 0 config */
        TPM0->CONTROLS[0].CnSC &= ~TPM_CnSC_MSB_MASK;
        TPM0->CONTROLS[0].CnSC &= ~TPM_CnSC_MSA_MASK;
        TPM0->CONTROLS[0].CnSC &= ~TPM_CnSC_ELSA_MASK;
        TPM0->CONTROLS[0].CnSC &= ~TPM_CnSC_ELSB_MASK;
        TPM0->CONTROLS[0].CnSC |= ((1<<5)|(1<<3));/* MSB , ELSB set ,Edge-aligned PWM High-true pulses (clear Output on match, set Output on reload) */
        
        modulo  = tpm_clock/hz-1;
        cnv  = modulo*duty_cycle/100;
        TPM0->MOD = TPM_MOD_MOD(modulo);        /* modulo value ,overflow if counter match the value */
        TPM0->CONTROLS[0].CnV = TPM_CnV_VAL(cnv);        /*         match value */        
        
        /* enable the tpm0 */
        TPM0->SC &= ~TPM_SC_CMOD_MASK;
        TPM0->SC |= TPM_SC_CMOD(1);        /*        LPTPM counter increments on every LPTPM counter clock */
}

期待你们解决

相关帖子

沙发
energy1| | 2015-1-27 16:48 | 只看该作者
不太懂,帮顶一下

使用特权

评论回复
板凳
FSL_TICS_ZJJ| | 2015-1-28 13:48 | 只看该作者
楼主你好!
内部48Mhz是可以直接输出的,你可以输出来用示波器看看是不是准的。
具体配置在SIM_SOPT2[CLKOUTSEL] =111,IRC48M clock (IRC48M clock can be output to PAD only when chip VDD is 2.7-3.6 V)
你直接输出到CLKOUT引脚看看,偏差了多少。

使用特权

评论回复
地板
jiaduo|  楼主 | 2015-1-28 17:41 | 只看该作者
FSL_TICS_ZJJ 发表于 2015-1-28 13:48
楼主你好!
内部48Mhz是可以直接输出的,你可以输出来用示波器看看是不是准的。
具体配置在SIM_SOPT2[CLKOU ...

您好,我测试了。在clockout管脚上看到的IRC48M频率大小范围在47.6~48.5左右吧。
感觉比较准了吧。但是tpm输出确实不准
另外,今天做LPUART的实验,发现发送没问题115200.。接收不到数据,改为9600能接收数据,但是偶尔会丢数据。。。
所以感觉不太靠谱。。。。求解。LPUART代码
#include "kl03_uart.h"

uint32_t ctrl;
uint32_t data;
uint32_t stat;
uint32_t baud;
/**
*@brief:init the LPUART (8 N 1 Full-duplex TX - PTB1 RX - PTB2)
*@param:bps - baudrate       
*                                lpuart_clock - lpuart_clock clk(if clk=IRC48M,using SystemCoreClock)
*/
void kl03_lpuart_init(uint32_t lpuart_clock,uint32_t bps)
{
        uint32_t sbr;
        /* uart0 clock config & enable */
        SIM->SOPT2 &= ~SIM_SOPT2_UART0SRC_MASK;
        SIM->SOPT2 |= SIM_SOPT2_UART0SRC(1);        /* select IRC48M as lpuart clk source */
        SIM->SOPT5 &= ~SIM_SOPT5_UART0ODE_MASK;        /* open drain disabled */
        SIM->SOPT5 &= ~(SIM_SOPT5_UART0RXSRC_MASK|SIM_SOPT5_UART0TXSRC_MASK);        /* uart0 data source is tx & rx pins */
        SIM->SCGC5 |= (1<<20);        /* lpuart clock enable */
        SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK;
        /* port config */
        PORTB->PCR[1] = PORT_PCR_MUX(2);        /* alt2 function(tx) */
        PORTB->PCR[2] = PORT_PCR_MUX(2);        /* alt2 function(rx) */
        /* LPUART module config */
        LPUART->BAUD = (0XF<<24);        /* 1 stop bit osr = 15*/
        sbr = (lpuart_clock/((15+1)*bps))&0x1fff;
        LPUART->BAUD |= sbr;
       
        LPUART->CTRL = 0;       
        LPUART->CTRL = ((1<<18)|(1<<19));        /* 8 N no tx rx interrupt*/
       
        LPUART->STAT = 0;        /* LSB first */
        sbr = 10000;
        while(sbr--);        /* delay for stable */
       
        ctrl = LPUART->CTRL ;
        stat = LPUART->STAT;
        baud = LPUART->BAUD;
        data = LPUART->DATA;
}
/**
*@brief:uart0 tx char(polling)
*@param:ch - char to send
*/
void kl03_lpuart_put(uint8_t ch)
{
        LPUART->DATA = ch;
        while(!(LPUART->STAT & (1<<22)));
}
/**
*@brief:uart0 tx string
*@param:st - pointer of string
*/
void kl03_lpuart_puts(uint8_t *st)
{
        while(*st != '\0')
                kl03_lpuart_put(*st++);
}
/**
*@brief:uart0 rx char(polling with TIMEOUT)
*@param:char received
*@retval:1 - receiver success 0 -  timeout
*/
uint8_t kl03_lpuart_get(uint8_t *ch)
{
        uint32_t i = 4800000;
        while((!(LPUART->STAT & (1<<21))) && i--);
        LPUART->STAT |= (1<<19);        /* !!!note:clear the OR flag ,otherwise if receive byte too long,rx can't get byte anymore */
        if(i != 0xffffffff)
        {
                *ch = LPUART->DATA;
                return 1;
        }
        else
        {
                return 0;
        }
}


#ifdef PRINTF_REDIRECT
int fputc(int /*c*/c, FILE * /*stream*/stream)
{
        kl03_lpuart_put((uint8_t)c);
        return 0;
}
#endif

测试代码
#include "main.h"
#include "kl03_systick.h"
#include "kl03_led.h"
#include "kl03_tpm.h"
#include "kl03_vref.h"
#include "kl03_button.h"
#include "kl03_uart.h"

uint8_t ch;
int main(void)
{
        SIM->SOPT2 &= ~(0X7<<5);
        SIM->SOPT2 |= 0X7<<5;
        SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
        PORTA->PCR[12] = PORT_PCR_MUX(5);
       
        kl03_SystickInit();
        kl03_led_init();
       
        kl03_lpuart_init(SystemCoreClock,9600);        /* system IRC48M is not Accurate */
        printf("FRDM-KL03Z LPUART\r\n");
        while(1){
                if(kl03_lpuart_get(&ch))
                {
                        kl03_lpuart_put(ch);
                }
        }
}

使用特权

评论回复
5
jiaduo|  楼主 | 2015-1-28 17:42 | 只看该作者
FSL_TICS_ZJJ 发表于 2015-1-28 13:48
楼主你好!
内部48Mhz是可以直接输出的,你可以输出来用示波器看看是不是准的。
具体配置在SIM_SOPT2[CLKOU ...

楼主帮我看看代码吧。。感觉好奇怪。。回头请你吃雪糕哈。。。

使用特权

评论回复
6
FSL_TICS_ZJJ| | 2015-1-29 14:55 | 只看该作者
jiaduo 发表于 2015-1-28 17:41
您好,我测试了。在clockout管脚上看到的IRC48M频率大小范围在47.6~48.5左右吧。
感觉比较准了吧。但是tp ...

你好!
如果实际测下来IRC48M的频率范围是47.6~48.5之间,那么就是符合datasheet规定的1%误差范围了。
说明该频率正确。
当时如果你用于UART的话,你就要计算下配置后的波特率范围到底是多少?
因为正常波特率误差要求是1.5%范围内。
本身设置波特率的寄存器值和标准的波特率会有一点误差,然后再加上你模块时钟源的误差,就很可能会超出波特率的1.5%误差范围,所以你需要计算下。

使用特权

评论回复
7
FSL_TICS_ZJJ| | 2015-2-3 09:38 | 只看该作者
楼主问题解决了没有?
如果还有问题,欢迎继续交流。
如果问题解决了,还请帮我们及时结贴。

使用特权

评论回复
8
jiaduo|  楼主 | 2015-9-14 11:14 | 只看该作者
FSL_TICS_ZJJ 发表于 2015-2-3 09:38
楼主问题解决了没有?
如果还有问题,欢迎继续交流。
如果问题解决了,还请帮我们及时结贴。 ...

问题已经解决。谢谢

使用特权

评论回复
9
FSL_TICS_ZJJ| | 2015-9-14 11:25 | 只看该作者
jiaduo 发表于 2015-9-14 11:14
问题已经解决。谢谢

楼主如果问题解决了,还请帮我们及时结贴哦。

使用特权

评论回复
10
香水橙| | 2015-9-15 16:29 | 只看该作者
请楼主分享一下问题是怎么解决的?

使用特权

评论回复
11
du19901231| | 2016-3-29 19:16 | 只看该作者
楼主,你好,我有几个问题想请教
1、你用的开发环境是什么,KEIL,IAR还是飞思卡尔自己的开发环境
2、楼主要是用的KEIL能不能给我发个KL03的代码?我现在蒙蒙的,工程都还没有建起来呢。。。

使用特权

评论回复
12
519825192| | 2016-5-26 11:08 | 只看该作者
很有帮助

使用特权

评论回复
13
519825192| | 2016-5-27 17:02 | 只看该作者
不错

使用特权

评论回复
14
guiliang| | 2018-1-7 22:27 | 只看该作者
这个必须点赞的

使用特权

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

本版积分规则

5

主题

34

帖子

1

粉丝