找回密码
 立即注册
查看: 2038|回复: 12

STC8H1K08T外部晶振和PLL144M问题

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-03-30 20:18:10

11

主题

45

回帖

236

积分

中级会员

积分
236
发表于 2023-10-2 13:39:08 | 显示全部楼层 |阅读模式
本帖最后由 firefly2k 于 2023-10-2 13:46 编辑

我使用的芯片是STC8H1K08T-Beta ( 固件版本号: 7.2.1U),使用外部晶振和PLL 144M有问题

使用内部IRC 24M(STC8H1K08T-Beta内部IRC不可调好像只能是24M),可以正常运行(uart和PWM时钟源都是用的内部24M)。我外接12M晶振,测量晶振已经起振,我下面代码想要实现主时钟24M,PLL 144M给PWM用。下面代码初始化后,uart波特率只有之前的1/6,PWM输出也只是之前的1/6(与144M的预期差的更远)。

我不知道是STC8H1K08T-Beta不支持还是我的软件初始化有问题,请指正
晶振初始化代码如下:

        P_SW2 = 0x80;
        XOSCCR = 0xC0;                //启动外部晶振
        while (!(XOSCCR & 1));        //等待时钟稳定
        CLKDIV = 3;                       //PLL/2/3=24M MCLK/3
        CLKSEL = 0xC5;                  //外部高速时钟,144M,PLL/2 CKMS=1;HSIOCK=1 MCK2SE=01 PLL/2;MCKSEL=01 外部晶振
        PLLCR        = 0x80;             //ENCKM=1 PLL;PCKI=00 12M
        HSCLKDIV = 0;



回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15630
发表于 2023-10-2 14:18:21 | 显示全部楼层
1, 你节后申请 [免费+包邮送]的 STC8H1K08T-33I-TSSOP20
2, 你外部挂 32768晶振, 2个外挂电容 15pF
===用外部 32768 自动校准内部时钟到
      【11.0592MHz, 12MHz】
      【22.1184MHz, 24MHz
      【30MHz, 33.1776MHz

截图202310021421344540.jpg

http://www.stcmcudata.com/STC8F-DATASHEET/STC8H.pdf


截图202310021422546845.jpg

利用外部 32768 RTC 晶振时钟,自动校准内部高速IRC时钟,STC8H数据手册 内容 - 触摸按键/80mA大电流LED数码管自动刷新显示/段码LCD/RTC实时时钟/低功耗 - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15630
发表于 2023-10-2 14:24:39 | 显示全部楼层
7.2                  范例程序1.2.1                     自动校准内部高速IRCHIRC
例如:校准的目标频率为22.1184MHz,校准误差范围为±0.5%
则需要将CREHF设置为0,CRECNT设置为(16*22118400)/32768=10800(2A30H),
即将CRECNTH设置为2AH,CRECNTL设置为30H,CRERES设置为10800 * 0.5%=54(36H)


//测试工作频率为11.0592MHz
#include "stc8h.h"//头文件见下载软件
#define       CNT22M             (16 * 22118400L) / 32768)                     //校准目标频率为22.1184M
#define       RES22M             (CNT22M *5 / 1000)                              //设置校准误差为0.5%
void main()
{
         P_SW2 |= 0x80;//使能访问XFR
         P0M0 = 0x00;
         P0M1 = 0x00;
         P1M0 = 0x00;
         P1M1 = 0x00;
         P2M0 = 0x00;
         P2M1 = 0x00;
         P3M0 = 0x00;
         P3M1 = 0x00;
         P4M0 = 0x00;
         P4M1 = 0x00;
         P5M0 = 0x00;
         P5M1 = 0x00;
X32KCR = 0xc0;                                                                           //启动外部32K晶振
while (!(X32KCR & 1));                                                               //等待时钟稳定
         IRCBAND &= ~0x03;
         IRCBAND |= 0x02;                                                                      //选择27M频段
         CLKSEL = 0x00;                                                                          //选择内部高速HIRC为系统时钟
         CRECNTH = CNT22M >>8;                                                      //设置目标校准值
         CRECNTL = CNT22M;
         CRERES = RES22M;                                                                  //设置校准误差
         CRECR = 0x90;                                                                            //使能CRE功能,并设置校准周期为4ms
         while (1)
         {
                   if (CRECR& 0x01)
                   {
//频率自动校准完成
                   }
         }
}

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15630
发表于 2023-10-2 14:29:15 | 显示全部楼层
截图202310021426406860.jpg

其实
1,直接用内部高速IRC-24MHz 给 CPU 跑;
2,IRC-24MHz / 2 = 12MHz 给 PLL时钟输入;
3,12MHz 的 PLL时钟输入 * 12 = 144MHz 时钟输出给 PWM;
截图202310021430399354.jpg

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15630
发表于 2023-10-2 14:35:13 | 显示全部楼层
7.2.1                     自动校准内部高速IRCHIRC
例如:校准的目标频率为22.1184MHz,校准误差范围为±0.5%
则需要将CREHF设置为0,CRECNT设置为(16*22118400)/32768=10800(2A30H),
即将CRECNTH设置为2AH,CRECNTL设置为30H,CRERES设置为10800 * 0.5%=54(36H)

//测试工作频率为11.0592MHz
#include "stc8h.h"                                                                                //头文件见下载软件
#define       CNT22M             (16 * 22118400L) / 32768)                     //校准目标频率为22.1184M
#define       RES22M             (CNT22M *5 / 1000)                              //设置校准误差为0.5%
void main()
{
         P_SW2 |= 0x80;                                                                            //使能访问XFR
         P0M0 = 0x00;
         P0M1 = 0x00;
         P1M0 = 0x00;
         P1M1 = 0x00;
         P2M0 = 0x00;
         P2M1 = 0x00;
         P3M0 = 0x00;
         P3M1 = 0x00;
         P4M0 = 0x00;
         P4M1 = 0x00;
         P5M0 = 0x00;
         P5M1 = 0x00;
         X32KCR = 0xc0;                                                                           //启动外部32K晶振
         while (!(X32KCR & 1));                                                               //等待时钟稳定
         IRCBAND &= ~0x03;
         IRCBAND |= 0x02;                                                                      //选择27M频段
         CLKSEL = 0x00;                                                                          //选择内部高速HIRC为系统时钟
         CRECNTH = CNT22M >>8;                                                      //设置目标校准值
         CRECNTL = CNT22M;
         CRERES = RES22M;                                                                  //设置校准误差
         CRECR = 0x90;                                                                            //使能CRE功能,并设置校准周期为4ms
         while (1)
         {
                   if (CRECR& 0x01)
                   {
                                                                                                                //频率自动校准完成
                   }
         }
}


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15630
发表于 2023-10-2 14:38:09 | 显示全部楼层
24.2.1                     使能高级PWM的高速模式(异步模式)

//测试工作频率为24MHz
#include "stc8h.h"
#include "intrins.h"
#define       FOSC                           24000000UL
#define       HSCK_MCLK             0
#define       HSCK_PLL                 1
#define       HSCK_SEL                 HSCK_PLL
#define       PLL_96M                     0
#define       PLL_144M                  1
#define       PLL_SEL                     PLL_144M
#define       CKMS                          0x80
#define       HSIOCK                      0x40
#define       MCK2SEL_MSK        0x0c
#define       MCK2SEL_SEL1        0x00
#define       MCK2SEL_PLLD2     0x04
#define       MCK2SEL_PLLD4     0x08
#define       MCKSEL_MSK          0x03
#define       MCKSEL_HIRC         0x00
#define       MCKSEL_XOSC        0x01
#define       MCKSEL_X32K          0x02
#define       MCKSEL_IRC32K     0x03
#define       ENCKM                      0x80
#define       PCKI_MSK                 0x60
#define       PCKI_D1                     0x00
#define       PCKI_D2                     0x20
#define       PCKI_D3                     0x40
#define       PCKI_D4                     0x60
void delay()
{
         int     i;
         
         for    (i=0; i<100; i++);
}
char ReadPWMA(char addr)
{
         chardat;
         
         while(HSPWMA_ADR & 0x80);                                                //等待前一个异步读写完成
         HSPWMA_ADR= addr | 0x80;                                                   //设置间接访问地址,只需要设置原XFR地址的低7
                                                                                                                //HSPWMA_ADR寄存器的最高位写1,表示读数据
         while(HSPWMA_ADR & 0x80);                                                //等待当前异步读取完成
         dat    = HSPWMA_DAT;                                                              //读取异步数据
         
         returndat;
}
void WritePWMA(char addr, chardat)
{
         while(HSPWMA_ADR & 0x80);                                                //等待前一个异步读写完成
         HSPWMA_DAT= dat;                                                                 //准备需要写入的数据
         HSPWMA_ADR= addr & 0x7f;                                                 //设置间接访问地址,只需要设置原XFR地址的低7
                                                                                                                //HSPWMA_ADR寄存器的最高位写0,表示写数据
}
void main()
{
         P_SW2|= 0x80;                                                                            //使能访问XFR
         
         //选择PLL输出时钟
#if     (PLL_SEL == PLL_96M)
         CLKSEL&= ~CKMS;                                                                  //选择PLL96M作为PLL的输出时钟
#elif (PLL_SEL == PLL_144M)
         CLKSEL|= CKMS;                                                                      //选择PLL144M作为PLL的输出时钟
#else
         CLKSEL&= ~CKMS;                                                                  //默认选择PLL96M作为PLL的输出时钟
#endif
         
         //选择PLL输入时钟分频,保证输入时钟为12M
         PLLCR&= ~PCKI_MSK;
#if     (FOSC == 12000000UL)
         PLLCR|= PCKI_D1;                                                                   //PLL输入时钟1分频
#elif (FOSC == 24000000UL)
         PLLCR|= PCKI_D2;                                                                   //PLL输入时钟2分频
#elif (FOSC == 36000000UL)
         PLLCR|= PCKI_D3;                                                                   //PLL输入时钟3分频
#elif (FOSC == 48000000UL)
         PLLCR|= PCKI_D4;                                                                   //PLL输入时钟4分频
#else
         PLLCR|= PCKI_D1;                                                                   //默认PLL输入时钟1分频
#endif
         //启动PLL
         PLLCR|= ENCKM;                                                                    //使能PLL倍频
         
         delay();                                                                                          //等待PLL锁频
         //选择HSPWM/HSSPI时钟
#if     (HSCK_SEL == HSCK_MCLK)
         CLKSEL&= ~HSIOCK;                                                             //HSPWM/HSSPI选择主时钟为时钟源
#elif (HSCK_SEL == HSCK_PLL)
         CLKSEL|= HSIOCK;                                                                  //HSPWM/HSSPI选择PLL输出时钟为时钟源
#else
         CLKSEL&= ~HSIOCK;                                                             //默认HSPWM/HSSPI选择主时钟为时钟源
#endif
         HSCLKDIV= 0;                                                                            //HSPWM/HSSPI时钟源不分频
         
         HSPWMA_CFG= 0x03;                                                             //使能PWMA相关寄存器异步访问功能
         
         //通过异步方式设置PWMA的相关寄存器
         WritePWMA((char)&PWMA_CCER1,0x00);
         WritePWMA((char)&PWMA_CCMR1,0x00);                           //CC1为输出模式
         WritePWMA((char)&PWMA_CCMR1,0x60);                           //OC1REF输出PWM1(CNT<CCR时输出有效电平1)
         WritePWMA((char)&PWMA_CCER1,0x05);                           //使能CC1/CC1N上的输出功能
         WritePWMA((char)&PWMA_ENO,0x03);                                //使能PWM信号输出到端口
         WritePWMA((char)&PWMA_BKR,0x80);                                //使能主输出
         WritePWMA((char)&PWMA_CCR1H,200 >> 8);                    //设置输出PWM的占空比
         WritePWMA((char)&PWMA_CCR1L,200);
         WritePWMA((char)&PWMA_ARRH,1000 >> 8);                    //设置输出PWM的周期
         WritePWMA((char)&PWMA_ARRL,1000);
         WritePWMA((char)&PWMA_DTR,10);                                    //设置互补对称输出PWM的死区
         WritePWMA((char)&PWMA_CR1,0x01);                                 //开始PWM计数
         
         P2M0= 0;
         P2M1= 0;
         P3M0= 0;
         P3M1= 0;
         
         P2= ReadPWMA((char)&PWMA_ARRH);                               //异步方式读取寄存器
         P3= ReadPWMA((char)&PWMA_ARRL);
         
         while(1);
}



回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-03-30 20:18:10

11

主题

45

回帖

236

积分

中级会员

积分
236
发表于 2023-10-2 15:06:51 | 显示全部楼层
本帖最后由 firefly2k 于 2023-10-2 15:12 编辑
神*** 发表于 2023-10-2 14:18
1, 你节后申请 [免费+包邮送]的 STC8H1K08T-33I-TSSOP20
2, 你外部挂 32768晶振, 2个外挂电容 15pF
===用 ...

敬业啊,今天竟然还有人上班回复问题
您的意思是我用beta版可能有问题?
另外,我需要输出高精度的PWM频率信号,您说的校准的方式可能精度达不到我的要求,我不太想用。我还是想要外挂12M晶振的模式
等我试完正式版的 STC8H1K08T-33I,有什么结果再跟您反馈下
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15630
发表于 2023-10-2 15:25:44 | 显示全部楼层
您的意思是我用beta版可能有问题?
===你用外部时钟,无问题
另外,我需要输出高精度的PWM频率信号,

您说的校准的方式可能精度达不到我的要求,我不太想用。我还是想要外挂12M晶振的模式
===无问题,12M * 8 = 96MHz 给 PWM做时钟输入



96MHz/4 = 24MHz 给  CPU
截图202310021525279145.jpg

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15630
发表于 2023-10-2 15:29:06 | 显示全部楼层
外部 12MHz * 12 = 144MHz 给 PWM做时钟输入
144MHz/4 = 36MHz 给 CPU,  
但 STC8H1K08T-33I-TSSOP20 是最高频率不要超过33.1776MHz
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-03-30 20:18:10

11

主题

45

回帖

236

积分

中级会员

积分
236
发表于 2023-10-2 15:31:36 | 显示全部楼层
本帖最后由 firefly2k 于 2023-10-2 15:33 编辑
神*** 发表于 2023-10-2 15:29
外部 12MHz * 12 = 144MHz 给 PWM做时钟输入
144MHz/4 = 36MHz 给 CPU,  
但 STC8H1K08T-33I-TSSOP20 是最 ...

谢谢,我刚刚换上正式版的了,但还是一样的问题,原115200波特率,现在只有19200。可能还是寄存器配置问题,我再按您提供的例程仔细查查
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 17:44 , Processed in 0.165088 second(s), 106 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表