ssfnpl 发表于 2025-9-18 00:38:30

烦请大佬们有时间帮看下AI8051U,PLL配置问题

想使用高速SPI,在配置PLL时遇到了以下问题:
1.使用AICube配置PLL,系统时钟使用PLL分频为22.1184,
程序无法运行,表现为使用定时器0中断进行点亮LED无反应且USB也无法识别了。



2:通过 查看数据手册和时钟图进行配置后,系统能运行,
但是主时钟使用PLL/2 再使用CLKDIV/4,通过主时钟输出(MCLKODIV)2分在P5.6输出,
示波示测得频率是8.33MHz,
正常的频率不应该是:主时钟输入频率选择 PLL96M/2=48M,CLKDIV2分频后(48/2)=24,
主时钟2分频输出 24/2=12M, 示波器应该则得频率为12M才对啊!但是现在测得频率是8.33M。

以下是配置的程序:


////////////////////////////////////////
// 时钟初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void CLK_Init(void)
{
//    CLK_SYSCLK_Divider(10);             //切换主时钟前先将系统时钟降频

//    HIRC_22M1184();                     //选择内部预置的频率
//      
#if 0
      IRCBAND                              //IRC频段选择寄存器 USB时钟选择寄存器 以及频段选择
      HIRCCR            //内部高速IRC控制寄存器
      IRCDB                              //IRC时钟恢复振荡到稳定需要等的时间
      IRCBAND             //IRC频段选择
      IRTRIM                              //IRC频率调整
      USBCLK                              //USB时钟选择寄存器   必须使用内部48M高速IRC
      CLKSEL                              //时钟选择寄存器
      CLKDIV                              //时钟分频寄存器
      
      IRC48MCR                        //内部48M振荡器控制寄存器
      HSCLKDIV                        //高速时钟分频寄存器
      SPI_CLKDIV                        //SPI 时钟分频寄存器
      
      HIRCCR   ENHIRC    //内部高速振荡器寄存器
      
      
      
      
**示例*****选择22.1184MHz*****      
      CLKDIV = 0x04;               
      IRTRIM = CHIPID11;//   CHIPID11; 是出厂时的专属校准值
      VRTRIM = CHIPID13;
      IRCBAND &= ~0x03;
      IRCBAND |= 0x02;
         CLKDIV = 0x00;

*************选择48M***********
      IRC48MCR = 0x80;                //启动内部48M IRC
      while(!(ICR48MCR&1));   //等待时钟稳定
      CLKDIV = 0x02;                        //时钟2分频
      CLKSEL = 0x0C;                        //选择48M
      
      
#endif      
//      IRCBAND = 0X01;   //选择10MHZ 频段6 10 27 47M
//      CLKDIV = 0x00;
//      
      // AI 8051U 最高工作频率为 42MHZ 高速SPI
      P2SR |= 0xF8;      //P2.7 6 5 4 3 开启快速IO模式

#define                T22M_ADDR      CHIPID11//22.1184MHz
#define                VRT27M_ADDR      CHIPID23
      
//*****选择22.1184MHz*****      
//      CLKDIV = 0x04;                        // 选择输入 时钟进行分频给系统作为运行频率
      IRTRIM = T22M_ADDR;   //   CHIPID 是出厂时的专属校准值
      VRTRIM = VRT27M_ADDR;      // 27 M 频段
//      IRCBAND &= ~0x03;
//      IRCBAND |= 0x02;
//         CLKDIV = 0x00;
      
      
      IRCBAND|= 0x81;//USB时钟 48M   频段10MHZ      
      USBCLK = 0x00;    //PLL频段10MHZ         输入1分频 (8-16M)不追频
//      CLKSEL |= 0x48;          //时钟选择寄存器 PLL 输出96M 为高速时钟源 主时钟PLL/2
    CLKSEL = 0x08;    //选择PLL 输出96M 至CLKDIV
      CLKSEL |= 0x40;
    CLKDIV      = 0x02;          //系统工作时钟分频寄存器 96 / 2 = 48 / 2 = 22.1184
      
      HSCLKDIV = 0x04;                        //高速时钟分频寄存器 96/4 = 24
      SPI_CLKDIV = 0x02;                        //SPI 时钟分频寄存器 24 / 2 = 12
      
      //      IRCBAND                   //IRC频段选择寄存器 USB时钟选择寄存器 以及频段选择
//      IRCBAND|= 0x81;//USB时钟 48M   频段10MHZ
      IRC48MCR |= 0x80;//内部48M振荡器控制寄存器使能48MHZ
      while(!(IRC48MCR&1));//等待时钟稳定
      
      HIRCCR = 0x80;    //内部高速IRC控制寄存器 使能需等 HIRCST ==1 时钟稳定
      while(!(HIRCCR&1));    // 等待时钟稳定

    USBCLK |= 0x80;   //使能PLL   倍频
      delay_ms(1);
      
      
      

      
      
      
      
//    CLK_MCLK_HIRC();                  //选择内部高精度HIRC作为PLL输入时钟
//    CLK_PLL_Output96MHz();            //选择PLL的96M作为PLL的输出时钟
//    CLK_PLL_PreDivider2();            //PLL输入时钟4分频
//    CLK_PLL_Enable();                   //启动PLL
//    delay_ms(1);                        //等待PLL锁频

//    CLK_MCLK2_PLLD2();                  //选择PLL的输出2分频时钟作为主时钟

//    CLK_SYSCLK_Divider(1);            //设置系统时钟分频系数

//    CLK_SYSCLKO_SwitchP56();            //设置系统时钟输出端口: MCLKO (P5.6)
//    CLK_SYSCLKO_Divider(2);             //设置系统时钟分频系数

//    CLK_HSIOCK_PLL();                   //选择PLL输出时钟作为高速外设时钟源
//    CLK_HSIOCK_Divider(2);            //设置高速外设时钟预分频系数

//    CLK_SPICLK_Divider(1);            //设置SPI时钟预分频系数
//    CLK_I2SCLK_Divider(1);            //设置I2S时钟预分频系数
//    CLK_PWMACLK_Divider(1);             //设置PWMA时钟预分频系数
//    CLK_PWMBCLK_Divider(1);             //设置PWMB时钟预分频系数
//    CLK_TFPUCLK_Divider(1);             //设置TFPU时钟预分频系数

    //<<AICUBE_USER_CLOCK_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_CLOCK_INITIAL_END>>
}



void main(void)
{
    //<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
    // 在此添加用户主函数初始化代码
    //<<AICUBE_USER_MAIN_INITIAL_END>>

    SYS_Init();

    //<<AICUBE_USER_MAIN_CODE_BEGIN>>
    // 在此添加主函数中运行一次的用户代码
      
      MCLKOCR=0x82; //主时钟输出至P5.6 //SYSclk/2=8.33M示波器500ns
         
      
    //<<AICUBE_USER_MAIN_CODE_END>>

    while (1)
    {
      USBLIB_OUT_Done();            //查询方式处理USB接收的数据

      //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
      // 在此添加主函数中用户主循环代码
               
                        if(flag_200_ms)
                { flag_200_ms = 0; LED = !LED;

                }
//                delay_ms(300);
//                P2 = 0x80;
//                delay_ms(300);
//                P2 = ~P2;
               
      //<<AICUBE_USER_MAIN_LOOP_END>>
    }
}

////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
    EnableAccessXFR();                  //使能访问扩展XFR
    AccessCodeFastest();                //设置最快速度访问程序代码
    AccessIXramFastest();               //设置最快速度访问内部XDATA
    IAP_SetTimeBase();                  //设置IAP等待参数,产生1us时基

    P0M0 = 0x00; P0M1 = 0x00;         //初始化P0口为准双向口模式
    P1M0 = 0x00; P1M1 = 0x00;         //初始化P1口为准双向口模式
    P2M0 = 0x00; P2M1 = 0x00;         //初始化P2口为准双向口模式
    P3M0 = 0x00; P3M1 = 0x00;         //初始化P3口为准双向口模式
    P4M0 = 0x00; P4M1 = 0x00;         //初始化P4口为准双向口模式
    P5M0 = 0x00; P5M1 = 0x00;         //初始化P5口为准双向口模式
    P6M0 = 0x00; P6M1 = 0x00;         //初始化P6口为准双向口模式
    P7M0 = 0x00; P7M1 = 0x00;         //初始化P7口为准双向口模式

//      // AI 8051U 最高工作频率为 42MHZ 高速SPI
//      P2SR |= 0xF8;      //P2.7 6 5 4 3 开启快速IO模式
      
//      
//      CLKSEL &= ~0x80;
//      USBCLK &= 0x60;
//      USBCLK |= 0x00;// 00 02 04 06PLL输入分频
//      USBCLK |= 0x80;

    CLK_Init();                     //时钟模块初始化
    TIMER0_Init();                      //定时器0初始化
    USBLIB_Init();                      //USB库初始化

    //<<AICUBE_USER_INITIAL_CODE_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_INITIAL_CODE_END>>

    EnableGlobalInt();                  //使能全局中断
}







王昱顺 发表于 2025-9-18 13:48:23

PLL的那个96M和144M并不是输入任何频率都能锁定到的。必须要按他额定输入12M才行,你这个22.1184分频后的是11.0592Mhz。本质上96M和144M换算成一个几倍频描述更合适一些。
PLL那里不是写着44236800Hz嘛。
但是有个问题,你的PLL输入频率太低了,4分频后只有5.5296Mhz
这个会导致PLL工作不正常的,PLL是有一个要求的输入范围,再超出以后就工作不正常了

ssfnpl 发表于 2025-9-18 14:03:48

王昱顺 发表于 2025-9-18 13:48
PLL的那个96M和144M并不是输入任何频率都能锁定到的。必须要按他额定输入12M才行,你这个22.1184分频后的是 ...

{:woshou:}感谢提醒,我再认真看看。

神农鼎 发表于 2025-9-18 16:05:33

AI8051U的 PLL时钟输入要求 8MHz ~ 16MHz







ssfnpl 发表于 2025-9-18 16:41:46





打印寄存器结果好奇怪啊!

接收←IRCBAND:0X82--CLKSEL:0X40--CLKDIV:0X02--
                  USBCLK:0X00--CLKSEL:0X40

    CLKSEL = 0x08;    //选择PLL 输出96M 至CLKDIV
    CLKSEL |= 0x40;   //使能PLL为高速IO时钟源


ssfnpl 发表于 2025-9-18 16:42:47

神农鼎 发表于 2025-9-18 16:05
AI8051U的 PLL时钟输入要求 8MHz ~ 16MHz

{:woshou:}感谢指点。
页: [1]
查看完整版本: 烦请大佬们有时间帮看下AI8051U,PLL配置问题