XMC1000的时钟介绍

   XMC1100/XMC1200/XMC1300 系 列 内 部 有 一 个 64MHz 的 高 速 时 钟 (DCO1) 和 一 个
32.768kHz 的低速时钟 (DCO2)。在工程中的 system_XMC1x00.c 文件的 SystemInit()
函数中初始化系统时钟。 上电复位后, PCLK=MCLK=8MHz, 通过 SystemInit()把时钟初
始化为 PCLK=64MHz, MCLK=32MHz. 也就是说 DCO1 通过 Fractional divider( IDIV=1,
FDIV=0)后,直接作为 PCLK,然后通过 1/2 分频后作为 MCLK。

  在DAVE中,需要调用的函数是:

__WEAK void SystemInit(void)
{    
  SystemCoreSetup();   设置Flash等待固定时间
  SystemCoreClockSetup(); 从新设置时钟MCLK = 32MHz, PCLK = 64MHz ;并且更新滴答定时器时钟;
}

这个需要注意的是, PCLK 作为源时钟的外设有 CCU8, POSIF, CCU4, MATH, BCCU,因此
这些外设的时钟是 64MHz。而其他外设均有 MCLK 提供时钟,因此外设时钟是 32MHz 的。
XMC1400 时钟框图
  XMC1400 系列内部有一个 48MHz 的高速时钟(DCO1)和一个 32.768kHz 的低速时钟
(DCO2)。 另外芯片支持外部输入一个高速时钟 OSC_HP 以及低速时钟 OSC_LP. OSC_HP
和 DCO1 通过选择器成为 Double 的输入,经过 Double 变为 DCLK。一般情况下,可以选择
DCO1 通过选择器成为 Double 的输入,再 2 倍频后变为 96MHz 的 DCLK。而外部的
OSC_HP 用来校准内部的 DCO1,另外 OSC_HP 用来给 CAN 模块提供源时钟。 OSC_HP 外
部输入范围为 4~20MHz, 因此如果用它来作为 DCLK, DCLK 范围为 8~40MHz, 而 DCLK 通
过 2 分频后变为 MCLK, 因此如果用 OSC_HP 作为 MCU 主时钟源, MCU 主时钟最大只能
到 20MHz.

   在工程中的 system_XMC1x00.c 文件的 SystemInit()函数中初始化系统时钟。上电复位
后, PCLK=MCLK=8MHz, 通过 SystemInit()选择内部 DCO1 作为 DCLK,初始化
PCLK=96MHz, MCLK=48MHz. 也就是说 DCLK 通过 Fractional divider(IDIV=1, FDIV=0)
后,直接作为 PCLK,然后通过 1/2 分频后作为 MCLK。

   这个需要注意的是, PCLK 作为源时钟的外设有 CCU8, POSIF, CCU4, MATH, BCCU,因此
这些外设的时钟是 96MHz。而其他外设均有 MCLK 提供时钟,因此外设时钟是 48MHz 的。
MCLK 为 CPU 提供时钟。 另外 CAN 模块由于对时钟精度较高,由外部 OSC_HP 直接提供时

XMC1100/XMC1200/XMC1300 内部时钟精度和校准

   XMC1100/XMC1200/XMC1300 的时钟精度如下,对于一些对时钟精度不高的应用,这样的
时钟精度尚可,但是对于一些通讯的应用,时钟精度不高可能会导致数据收发出错。对于这种
情况,就需要做温度补偿。
   

时钟的频率漂移是和温度有一定关系,在常温下频率漂移最小,在温度上下两端频率漂移最
大。 由于芯片内部集成了温度传感器,因此可以利用温度传感器检测得到当前温度,然后计算
得到频率漂移,然后调整内部 DCO1 的频率寄存器值来调整 DCO1 频率。 通过温度补偿后,
内部 DCO1 的精度如下所示:

温度校准的应用笔记和例程见文档附件。 需要注意的是只有量产的芯片内部才集成了温度传感
器,因此支持这个校准功能。工程样片不支持这个功能。(芯片丝印上写有 EE 或 ES 的均为
工程样片)
XMC1400 内部时钟精度和校准
XMC1400 内部时钟在校准之前和 XMC1100/1200/1300 的时钟一样,在通过外部时钟校准后
可以达到+/-0.3%的精度。 用外部晶振校准内部 DCO1 的动作可以芯片内部的 oscillator
watchdog 自动完成,不需要软件干预

外设时钟 Gating 控制
在上电后, XMC1000 系列的所有外设时钟是关闭的, 因此使用外设之前需要把时钟先打开。

如果使用 LLD 开发, 通常在外设的初始化函数中会去使能时钟,因此无需用户关心

如果使用寄存器直接访问的方式, 则需要用户自己使能时钟。 例如下面代码使能 CCU4 时
钟。

XMC1000 的内部时钟校准方案
MCU 内部的 32MHz 高速晶振的频率会随着的外界温度变化产生漂移。 XMC1000 系列芯片内
部集成了温度传感器,可以检测到当前温度,我们可能根据检测到的温度,对芯片的高速晶振
进行补偿。我们提供同时 Keil 和 DAVE 下的例程实现时钟校准:
- 2_1_XMC1000_TSEDCO_KEIL.zip
- 2_2_XMC1000_TSEDCO_DAVE.zip
在初始化程序中,首先要调用 DCO_Trim()和 TSE_Calibration_Init(),然后再主循环中调用
TSE_DCO_Calibration(),就可以实现温度校准了。
注意:
只有 AA step 以后的产品内部才集成温度传感器和校准模块,而工程样片(芯片丝印带有
EE) 没有这些模块,因此只有 AA step 以后的量产产品才支持这个功能。

void DCO_Trim(void)
{
    DCOptr = (uint16_t *) 0x10000FEA;
    DCO_ID = *DCOptr;     //在程序验证的时候,DCO_ID读出值是4,此处可能存在错误,需要后续验证!!!!

    // DCO Workaround
    if ((DCO_ID == 0x0000) || (DCO_ID == 0xFFFF))
    {
        Config_ptr = (uint16_t *)DCO_Config;//经过分析,DCO_Config地址可能保存的是出厂时振荡器的频率值;  //即ANA_DCO_TSE_ADJ_RT下的频率调整值;
        DCO_adj = (*Config_ptr >> 12);
        Adj_val = Trim_table[DCO_adj];
        SCU_GENERAL->PASSWD = 0x000000C0UL; // disable bit    protection
        SCU_ANALOG->ANAOFFSET = 4 + Adj_val;
        SCU_GENERAL->PASSWD = 0x000000C3UL; // enable bit    protection
    }
} //  End of function DCO_Trim

void TSE_Calibration_Init (void)
{
    int32_t TSE1, TSE2;

    // Enable Temperature sensor
    SCU_ANALOG->ANATSECTRL = 0x01;

    TSE1 = *((uint8_t*)ANA_DCO_TSE_ADJ_RT);
    TSE2 = *((uint8_t*)ANA_DCO_TSE_ADJ_HT);

    // Check for device parameters
    if((TSE1 == 0) && (TSE2 == 0))
    {
        var_ANA_DCO_TSE_ADJ_RT = 25;
        var_ANA_DCO_TSE_ADJ_HT = 115;
    }
    else
    {
        var_ANA_DCO_TSE_ADJ_RT = TSE1;
        var_ANA_DCO_TSE_ADJ_HT = TSE2;
    }
}

void TSE_DCO_Calibration (void)
{
    int32_t a,b,c,d,e;
    int32_t ADJL_OFFSET;

    a = *((uint8_t*)ANA_DCO_ADJ_LOW_HT);
    b = *((uint8_t*)ANA_DCO_ADJ_LOW_RT);
    d = var_ANA_DCO_TSE_ADJ_RT;
    e = var_ANA_DCO_TSE_ADJ_HT;

    // Get current temperature and convert to celcius
    c = XMC1000_CalcTemperature();
    c = c - 273;

    // Calculate the offset value做线性拟合,计算出频率误差
    ADJL_OFFSET = ((a-b)*(c-d) + ((e-d)>>1) + b*(e-d))/(e-d);
    ADJL_OFFSET = ADJL_OFFSET + Adj_val;

    // Configure the offset value into ANAOFFSET register
    if(ADJL_OFFSET >= 0 && ADJL_OFFSET <= 8)
    {
        SCU_GENERAL->PASSWD = PASSWD_OPEN_ACCESS;
        WR_REG(SCU_ANALOG->ANAOFFSET, SCU_ANALOG_ANAOFFSET_ADJL_OFFSET_Msk, SCU_ANALOG_ANAOFFSET_ADJL_OFFSET_Pos, ADJL_OFFSET);
    }
}
 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值