CH573F 使用LSI时如何关闭外部晶振

目前的需求:

系统启动时采用60MHz主频,此时使用外部晶振,然后切换为LSI,大体流程如下

SetSysClock(CLK_SOURCE_PLL_60MHz);
// 做一些快速处理

SetSysClock(CLK_SOURCE_LSI); // 这里不起作用
//PWR_UnitModCfg(DISABLE, UNIT_SYS_HSE | UNIT_SYS_PLL);
while(1)
{
    //监控事务
}

现在发现使用 SetSysClock(CLK_SOURCE_LSI) 切换时钟不起作用。


另外如果上电后直接设置时钟为CLK_SOURCE_LSI,可以起作用,但是外部晶振依然在振荡,如果使用PWR_UnitModCfg
单独关闭UNIT_SYS_HSE,程序就不会运行了,如何处理?谢谢

您好我们测试直接设置是不启用的,需要进行切换。切换方式可以参考https://www.cnblogs.com/gscw/p/16646454.html


该实例测试是OK的,但是使能LSI后,示波器可以测试到外部晶振是起振的,因为应用电路对噪声比较敏感,如何关闭它?


1、main函数需要加上HIGHCODE,确保在操作完切换主频后又跳回main里面是在RAM中工作的,而不是FLASH中,请务必注意,原始博客没有添加。添加成功后的情况是进行灯的翻转是均匀亮灭的;

2、检测到外部32M起振是因为32M的寄存器的复位值是工作的,需要手动操作寄存器进行关闭:

    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
    SAFEOPERATE;
    R8_HFCK_PWR_CTRL &= ~(RB_CLK_PLL_PON | RB_CLK_XT32M_PON);       //关闭外部32M,需要在安全模式处理

3、使用内部32K工作需要确保外部32K不工作比较简单,直接对32K的GPIO进行翻转,如果在主频为内部32K时,则PA10/PA11的翻转应该是正常,我们这里验证也是没有问题的。


附:

/*Readme
        切换32K后,确保代码是运行在RAM中的,FLASH已经被修改了
        需要高频晶振不工作则需要调整32M的晶振
        注意操作晶振相关寄存器在安全模式处理
        可以直接跑32K(不跑60M),需要注意所以的操作均在RAM中运行(FLASH被修改),同时注意GPIO的初始化也需要在RAM中处理,默认例程封装好函数是在FLASH中处理的。
*/
#include "CH58x_common.h"
/*********************************************************************
 * @fn      DebugInit
 *
 * @brief   调试初始化
 *
 * @return  none
 */
void DebugInit(void)
{
    GPIOA_SetBits(GPIO_Pin_9);
    GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
    GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
    UART1_DefInit();
}
__HIGH_CODE
void test1(void){
#if 0                                           //外部32K,需要屏蔽PA10/PA11的IO翻转(32K晶振引脚)
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
    SAFEOPERATE;
    R8_CK32K_CONFIG |= RB_CLK_OSC32K_XT | RB_CLK_INT32K_PON | RB_CLK_XT32K_PON;
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
    SAFEOPERATE;
    R16_CLK_SYS_CFG |= RB_CLK_SYS_MOD;
    R8_SAFE_ACCESS_SIG = 0;
#else                                           //内部32K
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
    SAFEOPERATE;
    R8_CK32K_CONFIG &= ~(RB_CLK_OSC32K_XT | RB_CLK_XT32K_PON);
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
    SAFEOPERATE;
    R8_CK32K_CONFIG |= RB_CLK_INT32K_PON;
    R16_CLK_SYS_CFG |= RB_CLK_SYS_MOD;
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
    R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
    SAFEOPERATE;
    R8_HFCK_PWR_CTRL &= ~(RB_CLK_PLL_PON | RB_CLK_XT32M_PON);       //关闭外部32M,需要在安全模式处理
    R8_SAFE_ACCESS_SIG = 0;
#endif
#if 0
    while(1){
        mDelaymS(1);
        GPIOB_InverseBits(GPIO_Pin_4);
    }
#endif
}
__HIGH_CODE
void test2(void){
    while(1){
        mDelayuS(1000);
        GPIOB_InverseBits(GPIO_Pin_4);
        GPIOA_InverseBits(GPIO_Pin_10 | GPIO_Pin_11);
    }
}
__HIGH_CODE
int main()
{
    uint8_t      i;
    SetSysClock(CLK_SOURCE_PLL_60MHz);
    GPIOB_ModeCfg(GPIO_Pin_4,  GPIO_ModeOut_PP_5mA);   //设置模式 输出
    GPIOB_SetBits(GPIO_Pin_4);
    GPIOA_ModeCfg(GPIO_Pin_10 | GPIO_Pin_11,  GPIO_ModeOut_PP_5mA); //设置模式 输出,验证内部32k作为主频时,外部32k是不工作的。
    GPIOA_ResetBits(GPIO_Pin_10);
    GPIOA_SetBits(GPIO_Pin_11);
    mDelaymS(3000);     //等待60M稳定
    test1();
    test2();
    while(1);
}



感谢Lpc您的回复,还有以下几点疑惑:

  1. 代码中的SAFEOPERATE宏是什么?在官方示例中未搜索到

  2. 需要注意所以的操作均在RAM中运行(FLASH被修改),这里不理解为何LSI时必须跑在RAM中,FLASH为何被修改了?

  3. 有些函数,例如 void LowPower_Halt(void)有对PLL和HSE相关寄存器直接修改,例如:

    //R8_XT32M_TUNE = x32Mpw;
    //sys_safe_access_enable();
    //R8_PLL_CONFIG |= (1 << 5);
    //sys_safe_access_disable();

那么在关闭HSE时,这些代码直接注释掉是不是就可以了?目前测试是这样的。


1、SAFEOPERATE宏在573没有,直接不添加该行代码即可

2、在RAM中工作是为了运行的速度快一些,否则主频32K的运行速度比较慢,需要考虑代码的运行最优,所以不建议在FLASH中工作;

3、其他代码请按照上面提供的测试进行测试,博客也提供了573的代码,可以使用参考。


只有登录才能回复,可以选择微信账号登录