打印
[51单片机]

给大家提供一个51的软延时例程.

[复制链接]
7277|38
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
datouyuan|  楼主 | 2016-7-8 16:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#define  MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
#define  MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )

#define FOSC        16.6//11.0592    //
#define MACHINE_NUM 1                //定时器
#define M_NUM       1                //程序  SH88F2051 程序是1T,定时器1T/12T可选

#define COVERT(T) ( (T*FOSC+M_NUM) / (M_NUM*2) -1 )

#if (M_NUM==1)
        #define d_1ms() do{ uint8 x=30; do{ d_uS(33.0); }while(--x); }while(0)
#else
        #if(M_NUM==12)
                #define d_1ms() do{ d_uS(333.0);d_uS(333.0); d_uS(333.0); }while(0)
        #else

        #endif
#endif

#define d_uS(us) do{ uint8 cnt1=MIN(MAX(COVERT(us),1),256); do{}while(--cnt1); }while(0)
        //Note:实际延时效果C51                12M         4<= us <= 514(uS)
        //Note:实际延时效果88F54        16.6M        1<= us <= 31(uS)
#define d_mS(ms) do{ uint16 cnt2=ms; do{ d_1ms(); }while(--cnt2); }while(0)

相关帖子

沙发
datouyuan|  楼主 | 2016-7-8 16:22 | 只看该作者
//使用示范
d_uS(10);                //延时10us
d_mS(1000);                //延时1秒
uint8 i=10;d_uS(i);//虽然能编译,但延时不准,参数不能为变量
uint8 i=10;d_mS(i);//这还算准确.
使用这例程,只要把晶振频率改成你实际的晶振频率,就可以产生比较准确的软延时了.

例如标准51这样修改.
#define FOSC        11.0592    //
#define MACHINE_NUM 12         //定时器
#define M_NUM       12         //程序  SH88F2051 程序是1T,定时器1T/12T可选


使用特权

评论回复
板凳
datouyuan|  楼主 | 2016-7-8 16:31 | 只看该作者
本帖最后由 datouyuan 于 2016-7-8 17:31 编辑

注意假如在88F54使用内振,1T的情况下.(请仔细看注释)
d_uS(0.1);//实际只会延时1uS
d_uS(100);//实际只会延时31uS
d_uS(4.5);//实际会延时4.5uS
假如在标准51使用12M,12T的情况下.(请仔细看注释)
d_uS(0.1);//实际只会延时4uS
d_uS(100);//实际会延时100uS
d_uS(5.5);//实际会延时5uS
d_uS(10000);//实际会延时514uS

使用特权

评论回复
地板
datouyuan|  楼主 | 2016-7-8 16:34 | 只看该作者
我觉得使用定义的方式做软延时,比使用函数的方式好.延时更准确.

使用特权

评论回复
5
伍戈123| | 2016-7-8 22:49 | 只看该作者
好方法。借鉴一下

使用特权

评论回复
6
datouyuan|  楼主 | 2016-7-11 15:15 | 只看该作者
怎么没人,这里还是有些技巧的.

自己顶起.

使用特权

评论回复
7
datouyuan|  楼主 | 2016-7-11 15:23 | 只看该作者
我每接触一个新的mcu,首先要想了解的是端口操作,软延时,开关中断等.

有了上面的定义,可以很方便的在STC 中颖或别的品牌的51MCU移植.

你所需要的是仅仅是填写晶振频率,定时器机器周期,程序机器周期这3个数值.

同样,可以按照上面的技巧配置串口,定时器.

使用特权

评论回复
8
我是楼主呀| | 2016-11-9 18:32 | 只看该作者
谢谢

使用特权

评论回复
9
linqing171| | 2016-11-9 21:02 | 只看该作者
本帖最后由 linqing171 于 2016-11-9 21:04 编辑
datouyuan 发表于 2016-7-8 16:31
注意假如在88F54使用内振,1T的情况下.(请仔细看注释)
d_uS(0.1);//实际只会延时1uS
d_uS(100);//实际只会延 ...

每一家的流水线都不一样。每个项目的优化等级也可能不同。还是实际情况下测试为准吧。
keil3 for arm和keil4 for arm,同样的优化等级下,你的那个while差两倍。别问我怎么知道的,我当时也是这样写的。临时变量多用了一次寄存器倒腾。仔细看了一遍,你这个没有问题。我当时是做成了个函数,而且没有开color优化。

使用特权

评论回复
10
xydzx| | 2016-11-10 11:24 | 只看该作者
嵌入式学习3026827905

使用特权

评论回复
11
datouyuan|  楼主 | 2016-11-10 17:45 | 只看该作者
linqing171 发表于 2016-11-9 21:02
每一家的流水线都不一样。每个项目的优化等级也可能不同。还是实际情况下测试为准吧。
keil3 for arm和kei ...

我这个是用于51的mcu的,不能用于arm,arm应该用定时器做软延时。

我使用过的51型号MCU,有STC、中颖、华邦、atmel、NXP,最近在使用十速的。
编译器用keil7、8、9版本,优化等级随便设定。不管怎么编译,延时都是非常准确的,完全符合计算要求。(要填写正确晶振频率,定时器机器周期,程序机器周期这3个数值)。

使用特权

评论回复
12
一个拥抱| | 2016-11-10 21:57 | 只看该作者
datouyuan 发表于 2016-7-11 15:15
怎么没人,这里还是有些技巧的.

自己顶起.

因为烧录软件自带延时函数

使用特权

评论回复
13
qianggewen2018| | 2018-6-4 11:13 | 只看该作者
看什么场合吧,还有个办法就是用时间继电器,可以用户手动调节延时参数,不用改程序

使用特权

评论回复
14
ayb_ice| | 2018-6-4 13:05 | 只看该作者
这哪里好,用定时器比这好多了

使用特权

评论回复
15
datouyuan|  楼主 | 2021-8-31 15:13 | 只看该作者
ayb_ice 发表于 2018-6-4 13:05
这哪里好,用定时器比这好多了

定时器是比较好,不受中断的影响。但是很多51单片机定时器比较少(只有2个),为了移植方便,空操作软延时适用面更广。

使用特权

评论回复
16
ayb_ice| | 2021-8-31 16:00 | 只看该作者
本帖最后由 ayb_ice 于 2021-8-31 16:02 编辑
datouyuan 发表于 2021-8-31 15:13
定时器是比较好,不受中断的影响。但是很多51单片机定时器比较少(只有2个),为了移植方便,空操作软延时 ...

利用系统滴答定时器很容易扩展VS级延时(不改变他在项目中原有的功能),再短的直接NOP了
一个宏定义轻易实现任意数NOP插入
比如:
__nops(6);
插入6个NOP指令

使用特权

评论回复
17
datouyuan|  楼主 | 2021-8-31 16:26 | 只看该作者
本帖最后由 datouyuan 于 2021-8-31 16:39 编辑

在AT89C2051外振12MHz下插入6个NOP,移植到SH88F2051内振16.6MHz就要插入16.6*6个NOP。
换其它型号还会不同。d_us(6)会根据mcu的情况生成对应的nop。

使用特权

评论回复
18
datouyuan|  楼主 | 2021-8-31 16:29 | 只看该作者
ayb_ice 发表于 2021-8-31 16:00
利用系统滴答定时器很容易扩展VS级延时(不改变他在项目中原有的功能),再短的直接NOP了
一个宏定义轻易实现 ...

虽然大部分需求相差几倍的nop没问题,但总有点不放心。

使用特权

评论回复
19
ayb_ice| | 2021-8-31 16:54 | 只看该作者
datouyuan 发表于 2021-8-31 16:26
在AT89C2051外振12MHz下插入6个NOP,移植到SH88F2051内振16.6MHz就要插入16.6*6个NOP。
换其它型号还会不同 ...

这不小意思吗
#define vs  *12//@12MHZ,单周期51

__nops(1vs);
__nops(3vs);

使用特权

评论回复
20
ayb_ice| | 2021-8-31 16:57 | 只看该作者
datouyuan 发表于 2021-8-31 16:26
在AT89C2051外振12MHz下插入6个NOP,移植到SH88F2051内振16.6MHz就要插入16.6*6个NOP。
换其它型号还会不同 ...

这种做法误差太快,循环控制导致误差太大

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

31

主题

1083

帖子

9

粉丝