发新帖本帖赏金 1.00元(功能说明)我要提问
12下一页
返回列表
打印
[技术讨论]

为什么STC8H系列时钟输出频率不对?

[复制链接]
2043|29
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 tyw 于 2022-11-5 16:47 编辑

最近一个项目选了STC8H3K64S4 32引脚的芯片作为主控芯片,现在发现很多地方都不对,12位AD转换值对不上,实测电压和AD值根本对不上,偏差0.76左右;硬件PWM输出频率也对不上,频率值和设置值也相差0.76倍左右,然后现在所有的程序都屏蔽掉,测时钟分频输出到P5.4引脚,发现时钟输出也不对!无论是内部RC还是外部晶振,都对不上,好郁闷啊!

STC8H系列 1259页.pdf (17.85 MB)


                      tyw  注

使用特权

评论回复

相关帖子

沙发
henangongda123|  楼主 | 2022-11-5 16:37 | 只看该作者
       /******* 系统时钟选择操作 *******/
/***********************************************************
函数名: Clk_Init()
功  能: 时钟初始化
参  数: 无
返回值: 无
/**********************************************************/
void Clk_Init(void)
{
        P_SW2 |= 0x80;              //使能访问特殊寄存器
        CKSEL = 0x00;               //系统时钟选择内部高速RC振荡器(ISP下载选择12M)
        CLKDIV = 0x00;              //配置主时钟分频系数为1(12M)
        MCLKOCR = 0x78;             //配置主时钟输出到P5.4引脚,分频系数120
        P_SW2 &= (~0x80);           //关闭访问特殊寄存器
}


使用特权

评论回复
板凳
henangongda123|  楼主 | 2022-11-5 16:43 | 只看该作者
上面几行代码是把12M主时钟分频120后输出到P5.4引脚,理论上应该得到100KHz的方波信号,然而神奇的事情发生了,同样的代码,下载到STC8H3K64S4 32、48引脚的单片机,输出的是130KHz左右的方波,下载到STC8H1K08 20引脚的单片机输出的是260KHz左右的方波信号,反正就是不100KHz,不知道为啥?有懂的吗?求指教,谢谢!

使用特权

评论回复
地板
coody| | 2022-11-5 17:09 | 只看该作者
可以向STC技术人员寻求帮忙。这种太基本的问题,别人都没碰到,所以应该还是跟你的操作有关。
还有,为什么不下载STC官方的例程试试?有编译好的HEX文件,直接下载测试即可。
你也可以先测试串口通信,如果频率有超过2%的误差,串口就有可能乱码。
STC的内部时钟常温下精度一般在0.3%之内。

更或者,你可以使用外部晶振看看。

使用特权

评论回复
5
henangongda123|  楼主 | 2022-11-5 17:10 | 只看该作者
上面的代码不变,固定用STC8H1K08 TSSOP-20的单片机继续测试,发现,ISP下载时选择6MHz的主频RC振荡器,P5.4输出的是200KHz左右的方波,而选择30MHz时,输出的是330KHz左右的方波

使用特权

评论回复
6
henangongda123|  楼主 | 2022-11-5 17:15 | 只看该作者
coody 发表于 2022-11-5 17:09
可以向STC技术人员寻求帮忙。这种太基本的问题,别人都没碰到,所以应该还是跟你的操作有关。
还有,为什么 ...

AD都出现了那么大误差,所以我在找原因,不敢在继续搞串口,这样的时钟误差,串口不用搞了,郁闷,哪里能下载到HXE,我试试,谢谢指点~

使用特权

评论回复
7
henangongda123|  楼主 | 2022-11-5 17:16 | 只看该作者
coody 发表于 2022-11-5 17:09
可以向STC技术人员寻求帮忙。这种太基本的问题,别人都没碰到,所以应该还是跟你的操作有关。
还有,为什么 ...

总共就5行代码。。。

使用特权

评论回复
8
henangongda123|  楼主 | 2022-11-5 20:22 | 只看该作者
/**********************************************************************
**********************************************************************/
//加载头文件
#include "STC8G.h"            //加载MCU头文件
#include "intrins.h"                            //加载nop指令头文件

//宏定义
#define uchar unsigned char
#define uint unsigned int
#define ushort unsigned short
#define ulong unsigned long

                                          /******* 系统时钟选择操作 *******/
/***********************************************************
函数名: Clk_Init()
功  能: 时钟初始化
参  数: 无
返回值: 无
/**********************************************************/
void Clk_Init(void)
{
        P_SW2 = 0x80;               //使能访问特殊寄存器
        CKSEL = 0x00;               //系统时钟选择内部高速RC振荡器(ISP下载选择12M)
        CLKDIV = 0x00;              //配置主时钟分频系数为1(12M)
        MCLKOCR = 0x78;             //配置主时钟输出到P5.4引脚,分频系数120
        P_SW2 = 0x00;               //关闭访问特殊寄存器
}

                                         /********* 端口初始化操作 **********/
/***********************************************************
函数名: Port_Init()
功  能: 端口初始化配置
参  数: 无
返回值: 无
/**********************************************************/
void Port_Init(void)
{
        P5M1 &= (~0x10);            //配置P5.4端口为输出方式
        P5M0 |= 0x10;               //配置端口推挽输出
}

/******************** 主函数 **************************/
void main(void)
{
        Clk_Init();                 //时钟初始化
        Port_Init();                //端口初始化
        while(1)
        {
               
        }
}


使用特权

评论回复
9
henangongda123|  楼主 | 2022-11-5 20:23 | 只看该作者
同样的代码,我把它下载到STC8G1K08A片子里,不管RC振荡器选12M还是24M,P5.4输出的PWM频率都是300KHz左右

使用特权

评论回复
10
lyjian| | 2022-11-5 22:35 | 只看该作者
不要写CLKDIV。ISP设定的系统时钟频率是CLKDIV分频后的频率,你把它改成了0,输出频率当然不对了。
要学会看规格书描述。

使用特权

评论回复

打赏榜单

henangongda123 打赏了 1.00 元 2022-11-06
理由:感谢帮忙~

11
henangongda123|  楼主 | 2022-11-6 11:12 | 只看该作者
lyjian 发表于 2022-11-5 22:35
不要写CLKDIV。ISP设定的系统时钟频率是CLKDIV分频后的频率,你把它改成了0,输出频率当然不对了。
要学会 ...

卧槽 好像还真是这个问题 丢 我都量产了不少 一直这样写的 额 之前对这个频率精度需求不太高,没怎么关注过。。。

使用特权

评论回复
12
henangongda123|  楼主 | 2022-11-6 11:13 | 只看该作者

ISP下载确实会自动修改这个寄存器值,程序启动后不应该再去修改。。。

使用特权

评论回复
13
coody| | 2022-11-6 11:14 | 只看该作者
正如10楼所说,选择内部时钟,MCU上电时会配置好颞部时钟,你的程序不要操作CLKDIV和CLKSEL,否则你就改变了内部频率。

使用特权

评论回复
14
henangongda123|  楼主 | 2022-11-6 11:44 | 只看该作者
coody 发表于 2022-11-6 11:14
正如10楼所说,选择内部时钟,MCU上电时会配置好颞部时钟,你的程序不要操作CLKDIV和CLKSEL,否则你就改变 ...

目前测试T0定时器是这样的,ISP设置好时钟主频后,程序不操作那2个寄存器,T0定时就对了,一旦操作就不对!然后再回到这个P5.4时钟PWM输出,分频120后依然得不到100KHz的PWM信号,如果按照下面这个图所示,CLKDIV寄存器是ISP操作,具体值又不知道,那确实得不到100KHz信号。。。

使用特权

评论回复
15
henangongda123|  楼主 | 2022-11-6 11:51 | 只看该作者
仔细又看了一下手册,感觉STC的手册关于这部分描述的也是有点矛盾,一方面强调有4个寄存器程序不能随意修改,但另一方面给出的示例确实有可以修改CLKDIV寄存器:

使用特权

评论回复
16
lyjian| | 2022-11-6 12:24 | 只看该作者
CLKDIV寄存器复位后的值做ISP后有显示,告诉你分频系数是多少。
这个分频系数就是CLKDIV复位值。看下载信息描述界面信息。

使用特权

评论回复
17
lyjian| | 2022-11-6 12:37 | 只看该作者
复位后可以先读CLKDIV值,这样就可以判断实际的IRC频率是多少。
实际IRC频率=ISP设置系统频率*复位后CLKDIV值(CLKDIV非0时)。

使用特权

评论回复
18
henangongda123|  楼主 | 2022-11-6 14:07 | 只看该作者
lyjian 发表于 2022-11-6 12:37
复位后可以先读CLKDIV值,这样就可以判断实际的IRC频率是多少。
实际IRC频率=ISP设置系统频率*复位后CLKDIV ...

很纳闷,这个寄存器我不写后,用STC8G1K08A的单片机测试,T0定时1ms正确,但是用STC8H的测试还是不行!好郁闷啊 之前都没遇到过这种情况

使用特权

评论回复
19
henangongda123|  楼主 | 2022-11-6 14:22 | 只看该作者
lyjian 发表于 2022-11-6 12:37
复位后可以先读CLKDIV值,这样就可以判断实际的IRC频率是多少。
实际IRC频率=ISP设置系统频率*复位后CLKDIV ...

目前的测试结果又推翻了刚才的验证,不知道是不是芯片买的有问题

使用特权

评论回复
20
henangongda123|  楼主 | 2022-11-6 14:23 | 只看该作者
/**********************************************************************
**********************************************************************/
//加载头文件
#include "STC8G.h"            //加载MCU头文件
#include "intrins.h"                            //加载nop指令头文件

//宏定义
#define uchar unsigned char
#define uint unsigned int
#define ushort unsigned short
#define ulong unsigned long

//引脚定义
sbit DO = P3^3;                                        //定义信号输出DO

//全局标志位

//全局变量

                                           /******* 系统时钟切换操作 *******/
/***********************************************************
函数名: Clk_Init()
功  能: 时钟初始化
参  数: 无
返回值: 无
/**********************************************************/
void Clk_Init(void)
{
        CLKDIV = 0x01;              //配置主时钟分频系数为1
}

                                         /********* 端口初始化操作 **********/
/***********************************************************
函数名: Port_Init()
功  能: 端口初始化配置
参  数: 无
返回值: 无
/**********************************************************/
void Port_Init(void)
{
        //SPI信号输出(P3.3)
        P3M1 &= (~0x08);            //配置P3.3端口为输出方式
        P3M0 |= 0x08;               //配置端口推挽输出
}

/***********************************************************
函数名: T0_Init()
功  能: 定时器0初始化,用于测量红外脉冲宽度
参  数: 无
返回值: 无
/**********************************************************/
void T0_Init(void)
{
        AUXR &= (~0x80);            //T0选择12T模式(系统时钟12分频),时钟频率为:12MHz/12=1MHz
        TMOD &= (~0x03);            //T0选择模式0(自动重装载模式)
        TL0 = 0x17;
        TH0 = 0xFC;                 //从0开始计时,计数一次耗时:(65535-64535=1000)*1us=1ms
        TR0 = 1;                    //开启定时器0
        ET0 = 1;                    //使能定时器0溢出中断
        EA = 1;                     //使能全局中断
}

void TM0_Isr(void) interrupt 1
{
        DO = ~DO;
}

/******************** 主函数 **************************/
void main(void)
{
//        Clk_Init();                 //时钟初始化
        Port_Init();                //端口初始化
        T0_Init();                  //T0定时器初始化
        while(1)
        {
               
        }
}

使用特权

评论回复
发新帖 本帖赏金 1.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

42

主题

2116

帖子

19

粉丝