找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 615|回复: 18
打印 上一主题 下一主题
收起左侧

stc8h单片机的延时为什么不准?

  [复制链接]
跳转到指定楼层
楼主
使用的是stc8h8k64u单片机,需要延时3秒,代码由stc-isp生成,延时程序名Delay3000ms(),
在keil调试,显示的却是54秒,(见图)。


程序下载运行,实测是4.5秒,相差太大了。
为什么keil调试显示是54?我用的是单片机内部晶振,频率调至12。

另外,我用以前在stc89c52时写的延时程序(载图中被注销的delay1ms(3000)),
在keil调试时显示是3秒,很准,但下载运行,根本看不出有延时效果。

stc单片机的延时怎么才能准?在keil 显示怎么才能准确?
以前在stc89c52和atmel 单片机上用的延时程序怎么才能继续使用?毕竟很好用。
请高手们帮助解惑!谢谢!

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:468878 发表于 2025-4-21 18:07 | 只看该作者
用STC的ISP软件直接生成延时试试。STC是有1T的模式,也有12T模式,会影响延时。Atmel的都是12T的。
回复

使用道具 举报

板凳
ID:401564 发表于 2025-4-21 18:09 | 只看该作者
超过1mS的延时,正常来说都是要用定时器或者PCA计数器来延时的,而不是让程序死等,虽然说你程序可能 很简单,不需要什么效率,但是,一个良好的编程习惯还是要有的
Keil是传统8051指令,跟STC的指令是不同的,除非你用硬件在线仿真
回复

使用道具 举报

地板
ID:1085441 发表于 2025-4-21 18:13 | 只看该作者
现在单片机都是1T的,还有中断等影响,我一般都是用示波器实测调整。
回复

使用道具 举报

5#
ID:584814 发表于 2025-4-21 19:55 | 只看该作者
降低stc8h的速度至stc89c52一样,这时你会发现又比较准了。
还有个办法就是外接晶振,加用示波器一类的辅助调节。
回复

使用道具 举报

6#
ID:1133081 发表于 2025-4-21 20:49 | 只看该作者

回复

使用道具 举报

7#
ID:654797 发表于 2025-4-22 07:19 | 只看该作者
指命的延时都不一样
回复

使用道具 举报

8#
ID:230500 发表于 2025-4-22 08:11 | 只看该作者
阻塞延时我很少用, 一般只用几个nop 延时;正常使用都是用定时器,   所以你这个情况没有试过也没有碰到过,   但是分析一下 主要是 编译器不能识别是1T还是12T, 默认都是以12T在模拟运行, 所以54/12=4.5秒 就是正常的; 另外4.5秒与软件设置的3秒有误差, 这个可能就是软件延时本身的误差, 或者程序中还有其他的地方影响到了延时; 比如定时器等等。  可以试试注释掉其他的所有函数,主程序就只写个延时点灯的测试下。
回复

使用道具 举报

9#
ID:879348 发表于 2025-4-22 13:27 | 只看该作者
ms级以上延时,开一个定时器才能准确,因为不同编译会产生不同效果,改一点代码又会改变
回复

使用道具 举报

10#
ID:134430 发表于 2025-4-22 17:04 | 只看该作者
首先感谢大家的回复指点!

我又进行了测试,情况如下:
1、我的程序很简单,只是一个电机的正反转控制,是从一个程序中拿出来的,用了调试限位开关的位置,
因此不会有其他程序的影响。

2、我的stc-isp的8051指令集与6楼朋友的不一样,分4个,Y1,3,5,6,  Y6对应stc8h,
奇怪的是Y3和Y5的延时程序代码完全一样。




3、在keil 上调试显示分别为   sec Y1:9    Y3:54   Y5:54   Y6:72,   都不是 3。
4、下载运行实测,为  Y1:1   Y3:4.5   Y6:9  秒
5、看资料,用户只要输入晶振频率数,单片机自动调整频率,我选择都是12
6、想上stc  官网寻求帮助


不行了,还是用stc89 或者atmel  吧。

截图31.png (78.82 KB, 下载次数: 0)

截图31.png
回复

使用道具 举报

11#
ID:1034262 发表于 2025-4-22 21:13 | 只看该作者
软仿真吧?那是12T模式的老51的时间。STC51大部分指令都1T的了。
回复

使用道具 举报

12#
ID:401564 发表于 2025-4-23 09:19 | 只看该作者
wh8010jky 发表于 2025-4-22 17:04
首先感谢大家的回复指点!

我又进行了测试,情况如下:

为什么对仿真这么执着呢?
程序最终是要用来运行的,不是用来仿真的
设置一个u8全局变量,开启一个定时器中断,在中断对这个变量进行++运算,然后在所有函数中都可以通过读取这个变量来进行延时之类的时间操作
不推荐用上古时期的8051了,功能少,烧录不方便,片上资源少,运行速度慢,价格又高,资料也少,出了问题找不到相关资料,这都完美的避开了STC的所有优点
回复

使用道具 举报

13#
ID:1057978 发表于 2025-4-23 10:01 | 只看该作者
你还是用stc89吧,老老实实呆在舒适区,8h太新了,不适合你
回复

使用道具 举报

14#
ID:134430 发表于 2025-4-23 17:43 | 只看该作者
谢谢大家!继续学习。
回复

使用道具 举报

15#
ID:1042619 发表于 2025-4-24 14:17 | 只看该作者
必须直接设置3000ms,不能1ms 3000次,否则会累积3000个误差


8b0381a8b59509b5b4f04d4351c8576.jpg (62.39 KB, 下载次数: 0)

8b0381a8b59509b5b4f04d4351c8576.jpg
回复

使用道具 举报

16#
ID:1042619 发表于 2025-4-24 14:20 | 只看该作者
89系列太古老了,建议直接用Ai8051U,USB 型 1T 8051,支持32位和8位指令集, RMB2.3,支持硬件USB下载 硬件USB仿真
管脚兼容天王级别的:  89C52RC,  12C5A60S2
要兼容 8位8051指令集,  可以用 Keil C51/IAR/SDCC 编译器
===就相当于更强大的 8H8K64U
要兼容 32位8051指令集,可以用 Keil C251 编译器,双核兼容设计
===就相当于更强大的 32G12K128, 32G8K64
34K SRAM(2K edata, 32K xdata), 64K Flash
TFPU@120MHz, 硬件浮点/硬件三角函数 运算器
DMA支持PWM, DMA支持外设直接到外设, P2P
120MHz-PWM支持硬件移相,16位PWM; 真12位ADC
USB, 4组串口,12位ADC, 轨到轨比较器
QSPI, SPI, I2S, I2C,  TFT-i8080/M6800 接口
PDIP40,LQFP44,LQFP44




回复

使用道具 举报

17#
ID:292876 发表于 2025-4-24 22:35 | 只看该作者
程序中不要用delay1ms(XXX),初始化可以用倒无所谓!要么定时器开滴答做系统时间分片基准,要么定时器中做个时间基准。多任务分时执行时候,或RTOS时候,用delay1ms(XXX)都会出很多莫名其妙的问题,特别模拟SPI,I2C等通讯,要做好delay1ms(XXX)规划,能用硬SPI,I2C等外设,最好不要用模拟,出问题不好找出问题点啦!除非你能把握每一处细节,做到入微,那么用倒无所谓。目前MCU项目都做多任务的,delay1ms(XXX)能不用尽量别用,养好习惯
回复

使用道具 举报

18#
ID:108361 发表于 2025-4-25 10:07 | 只看该作者
ziyueboy 发表于 2025-4-24 22:35
程序中不要用delay1ms(XXX),初始化可以用倒无所谓!要么定时器开滴答做系统时间分片基准,要么定时器中做 ...

还在用89C52芯片的人,还谈啥非阻塞啊,RTOS啊
回复

使用道具 举报

19#
ID:595237 发表于 2025-4-25 12:02 | 只看该作者
晶振11.0592MHz请参考,自己调试一下

#include <intrins.h>

void Delay3000ms() {
    unsigned int i, j;
   
    for (i = 0; i < 628; i++) {       // 外层循环628次
        for (j = 0; j < 0x2A4; j++) { // 内层循环0x2A4(十进制676)次
            _nop_();                  // 每个空指令占用1个时钟周期
        }
    }
}




// 或使用更精确的定时器方法(推荐)
void Delay3000ms() {
    TMOD &= 0xF0;    // 设置定时器模式:T1为16位定时器模式
    TMOD |= 0x10;
    TH1 = 0xDC;      // 初始化定时值(11.0592MHz下,定时50ms)
    TL1 = 0x00;
   
    ET1 = 0;         // 禁用定时器中断
    TR1 = 1;         // 启动定时器
   
    for (unsigned int count = 0; count < 60; count++) { // 60*50ms=3000ms
        while (!TF1);  // 等待定时器溢出
        TF1 = 0;       // 清除溢出标志
        TH1 = 0xDC;    // 重载初值
        TL1 = 0x00;
    }
   
    TR1 = 0;         // 停止定时器
}

晶振12MHz

void Delay3000ms() //@12.000MHz
{
    unsigned char i, j, k;
   
    i = 224;
    do {
        j = 200;
        do {
            k = 200;
            do {
                // 空循环,由k--操作实现
            } while (--k);
        } while (--j);
    } while (--i);
}
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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