找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STC单片机唤醒定时器时间如何调整?

[复制链接]
跳转到指定楼层
楼主




如图:给PCON|0x02时,单片机进入掉电模式,当WKTCH和WKTCL赋值过后,单片机唤醒启动.

WKTCH最大赋值为0X7F,WKTCL最大赋值为0XFF;
最大赋值运行时为15s,断电15s后单片机又启动,请问假如我想断电一个星期怎么设置,比如山区有一个检测仪器检测空气质量,一个星期只需要检测一次,那么检测完的其他时间给单片机断电,以延长单片机电池的运行时间。

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

使用道具 举报

沙发
ID:277550 发表于 2021-11-9 17:10 | 只看该作者
a=7*24*60*60= 604800  (秒)
a/15=40320(个周期),一个无符号整数变量,够用


void main(){
    unsigned int a=0;
    WKTCH=0xff; //包含使能位在内了。
    WKTCL=0xff;
    while(1){
         PCON|=2;
         _nop_(); _nop_(); _nop_(); _nop_();
         if(++a<40320){
             continue;
         }
        //这1个星期了,该干嘛
    }
}
回复

使用道具 举报

板凳
ID:624769 发表于 2021-11-9 17:38 | 只看该作者
你这是STC的手册,

首先,掉电换醒定时器,非常的不准, 说是32.768K的晶振频率,实际上,很多在36K左右,我见过最离谱的有38K,都能做红外载波发生器了。所以,如果你要用这个做长眠的话……,最好做个采样测试(比如for循环40次,就是理论上的 10分钟,看看相差多少,再调整一下,妥了之后,乘以1008,就是1个星期了),不然你定1个星期,最后极有可能5天就醒了。
回复

使用道具 举报

地板
ID:450037 发表于 2021-11-10 08:33 | 只看该作者
devcang 发表于 2021-11-9 17:10
a=7*24*60*60= 604800  (秒)
a/15=40320(个周期),一个无符号整数变量,够用

我不太懂啊,程序是这样的,PCON|=2,打开CPU掉电模式,系统唤醒定时器在运行,此时已经运行了无数次WHILE(1)函数,当15S过后,不是立即开启CPU吗?为什么会与IF语句做比较呢?
回复

使用道具 举报

5#
ID:450037 发表于 2021-11-10 10:05 | 只看该作者
188610329 发表于 2021-11-9 17:38
你这是STC的手册,

首先,掉电换醒定时器,非常的不准, 说是32.768K的晶振频率,实际上,很多在36K左右 ...

是的,这是STC手册。那个C8051F020是另外一个项目的。这个STC是我自学的一个开发板上的。我学了看门狗与自启动这一块,但是时间上我想能控制多久就多久。按上面一楼写的程序,没有运行成功。
回复

使用道具 举报

6#
ID:624769 发表于 2021-11-10 10:12 来自手机 | 只看该作者
zhangzhao2423 发表于 2021-11-10 10:05
是的,这是STC手册。那个C8051F020是另外一个项目的。这个STC是我自学的一个开发板上的。我学了看门狗与 ...

你除了定时器唤醒,还打算被其他,比如外部中断之类的随时唤醒么?
即,睡了之后,不到一周不起,
还是,如果没有突发事件,就睡一周,有突发事件就处理,完了之后接着睡,或完了之后重新开始睡一周,这三种情况的哪种?
回复

使用道具 举报

7#
ID:450037 发表于 2021-11-10 10:53 | 只看该作者
188610329 发表于 2021-11-10 10:12
你除了定时器唤醒,还打算被其他,比如外部中断之类的随时唤醒么?
即,睡了之后,不到一周不起,
还是 ...

只被定时器唤醒,定时醒,定时睡,外面打雷下雨不管。按时休息工作。且只被定时器控制
回复

使用道具 举报

8#
ID:450037 发表于 2021-11-10 11:27 | 只看该作者
188610329 发表于 2021-11-10 10:12
你除了定时器唤醒,还打算被其他,比如外部中断之类的随时唤醒么?
即,睡了之后,不到一周不起,
还是 ...

是的,只被定时器唤醒,掉电一个星期后再唤醒,不受其他影响。
回复

使用道具 举报

9#
ID:624769 发表于 2021-11-10 13:52 | 只看该作者
本帖最后由 188610329 于 2021-11-10 15:36 编辑

先说明一下, 定时唤醒,只能最多睡15秒左右,就会醒,这是硬件限制,没有办法,我们能做的,就像逼不爱午睡的小孩午睡,你醒了,我安抚一下,接着再把被子一蒙头,你给我继续睡,直到睡够午睡时间。所以要睡一周,就是反复醒了睡的过程,程序大致如下,你可以参考。实验时可以改小 i 和 j 的数字。更快的观察到效果。

void    main()
{
          uchar i,j;
          while(1)
          {
                  LED0 = !LED0; //此处 你需要定期执行的程序, 这里用 翻转LED0 代替
                  i = 168;   // 一周168小时
                  while(--i)
                  {
                         j = 240;  //每小时有 60分钟,即 240 个 15秒
                         while(--j)
                         {
                               WKTCH =0xff;       //WKTCL 不需要管,不需要那些鸡毛蒜皮的时间
                               PCON  |= 0x02;
                                _nop_();
                               LED2   = !LED2;     //次处用来确定每15秒醒来,正式使用时去掉
                         }
                         LED1  =  !LED1;       //次处用来确定每小时醒来,正式使用时去掉
                  }
          }
}
回复

使用道具 举报

10#
ID:450037 发表于 2021-11-10 14:33 | 只看该作者
188610329 发表于 2021-11-10 13:52
先说明一下, 定时唤醒,只能最多睡15秒左右,就会醒,这是硬件限制,没有办法,我们能做的,就像逼不爱午 ...


不行啊,我先用J=5测试了一下,意思是一分钟之后就让他重启,但是它根本启动不了,我的理解是当断电后,唤醒定时器到时间重启单片机,单片机又重新开始运行,所以J始终是从5开始减到4,连3都没有减到,一直循环着。所以我在想有没有什么断电寄存器能把值保存一下,比如EEPRAM等,就是这个程序不会写。
回复

使用道具 举报

11#
ID:624769 发表于 2021-11-10 15:00 | 只看该作者
zhangzhao2423 发表于 2021-11-10 14:33
不行啊,我先用J=5测试了一下,意思是一分钟之后就让他重启,但是它根本启动不了,我的理解是当断电后 ...

首先,掉电,不是断电,掉电是指,单片机进入不怎么用电的状态,单片机本身还是通着电的,所以不需要Eeprom之类的保存任何东西,内存里的东西不会丢失,其次,都说了,先加个LED观察状态,你这代码唯独没有观察状态,你怎么知道掉电成功没成功?
到时间,是从 PCON = 0x02 下一句开始执行,不存在重新开始执行。

最后,你说让 j= 5; 那么 j=5 在哪里? 你看看我给你的代码 j = 240; 在什么地方? 改动代码前,你是不是应该先对代码进行理解?
回复

使用道具 举报

12#
ID:450037 发表于 2021-11-10 15:37 | 只看该作者
188610329 发表于 2021-11-10 15:00
首先,掉电,不是断电,掉电是指,单片机进入不怎么用电的状态,单片机本身还是通着电的,所以不需要Eepr ...


我刚刚把j=5放在mian函数最上面的,现在把它放到while函数里面,加了个LED翻转显示灯,还是不行,j=5运行时实际一直在翻转着。根本没有走出while函数
回复

使用道具 举报

13#
ID:624769 发表于 2021-11-10 15:43 | 只看该作者
zhangzhao2423 发表于 2021-11-10 15:37
我刚刚把j=5放在mian函数最上面的,现在把它放到while函数里面,加了个LED翻转显示灯,还是不行,j=5运 ...

对的,永远不会走出 while(1)的,所以,我是让你把定期运行的代码放在 while(1) 里面的最上方的,代替LED0的位置的。
回复

使用道具 举报

14#
ID:624769 发表于 2021-11-10 15:45 | 只看该作者
zhangzhao2423 发表于 2021-11-10 15:37
我刚刚把j=5放在mian函数最上面的,现在把它放到while函数里面,加了个LED翻转显示灯,还是不行,j=5运 ...

换句说,加了一个星期 掉电唤醒的 while(1)  一个星期只会循环一次。这么说,理解了没?
回复

使用道具 举报

15#
ID:450037 发表于 2021-11-10 15:53 | 只看该作者
188610329 发表于 2021-11-10 15:45
换句说,加了一个星期 掉电唤醒的 while(1)  一个星期只会循环一次。这么说,理解了没?


已经成功了,把它放到while函数外面就可以了。谢谢
回复

使用道具 举报

16#
ID:624769 发表于 2021-11-10 16:10 | 只看该作者
zhangzhao2423 发表于 2021-11-10 15:53
已经成功了,把它放到while函数外面就可以了。谢谢

………………

那你想过没有,一周之后,怎么让他再睡下?
回复

使用道具 举报

17#
ID:450037 发表于 2021-11-11 09:00 | 只看该作者
188610329 发表于 2021-11-10 16:10
………………

那你想过没有,一周之后,怎么让他再睡下?

其实我觉得最主要的就是醒了,处理好数据后继续睡,然后隔一个星期再醒,这样周而复始。我今天就是处理这个问题。
回复

使用道具 举报

18#
ID:624769 发表于 2021-11-11 11:01 | 只看该作者
zhangzhao2423 发表于 2021-11-11 09:00
其实我觉得最主要的就是醒了,处理好数据后继续睡,然后隔一个星期再醒,这样周而复始。我今天就是处理这 ...

我想,你应该知道,主程序一旦运行进入了 while(1) 就永远不会出来,所以,如果,你把睡眠这部分,和你要执行的这部分,分别放在 while(1) 的内外…… , 那么,除了重新启动,你是无法让单片机周而复始的执行的。
回复

使用道具 举报

19#
ID:450037 发表于 2021-11-11 11:28 | 只看该作者
188610329 发表于 2021-11-11 11:01
我想,你应该知道,主程序一旦运行进入了 while(1) 就永远不会出来,所以,如果,你把睡眠这部分,和你要 ...

我知道,我想用定时器0来控制,我正在写这个程序,等会儿试运行看看。
回复

使用道具 举报

20#
ID:450037 发表于 2021-11-11 12:25 | 只看该作者
188610329 发表于 2021-11-11 11:01
我想,你应该知道,主程序一旦运行进入了 while(1) 就永远不会出来,所以,如果,你把睡眠这部分,和你要 ...


利用时间定时器给htime赋值,然后while语句执行,已经验证过了。,可以隔一段时间开,隔一段时间关
回复

使用道具 举报

21#
ID:624769 发表于 2021-11-11 12:43 | 只看该作者
行, 你睡觉和干活都在 while(1) 里就没问题了, 剩下的就是 htime 和 j 的调整, 以及htime 的计数逻辑了,if判断来讲,最好用 htime >= 240 代替  htime == 240
回复

使用道具 举报

22#
ID:450037 发表于 2021-11-11 13:26 | 只看该作者
188610329 发表于 2021-11-11 12:43
行, 你睡觉和干活都在 while(1) 里就没问题了, 剩下的就是 htime 和 j 的调整, 以及htime 的计数逻辑了, ...

嗯嗯,是的。我把它成大于等于
回复

使用道具 举报

23#
ID:450037 发表于 2021-11-11 15:46 | 只看该作者
188610329 发表于 2021-11-11 12:43
行, 你睡觉和干活都在 while(1) 里就没问题了, 剩下的就是 htime 和 j 的调整, 以及htime 的计数逻辑了, ...

运行下来有飘移,时间不准。我程序是关一个小时,开五分钟。动作是有,但是开启单片机的时间每次都向后延迟,误差累计的越来越大。
回复

使用道具 举报

24#
ID:624769 发表于 2021-11-11 16:12 来自手机 | 只看该作者
zhangzhao2423 发表于 2021-11-11 15:46
运行下来有飘移,时间不准。我程序是关一个小时,开五分钟。动作是有,但是开启单片机的时间每次都向后延 ...

你htime是哪里累加的?
pcon的循环,那个j确定是 u8定义么?
回复

使用道具 举报

25#
ID:450037 发表于 2021-11-12 10:07 | 只看该作者
188610329 发表于 2021-11-11 16:12
你htime是哪里累加的?
pcon的循环,那个j确定是 u8定义么?


不好意思,现在才回复。电脑崩了,才把它修复好,大白菜修复电脑是个好东西。
htime是这里给的。用的时间定时器。每1毫秒中断一次,单片机启动5分钟后休眠,这个没问题。


关键在于进入这里时,休眠时间一次比一次长。会不会是_nop_();和P33=~P33浪费了时间累积产生了误差啊


回复

使用道具 举报

26#
ID:624769 发表于 2021-11-12 12:06 | 只看该作者
zhangzhao2423 发表于 2021-11-12 10:07
不好意思,现在才回复。电脑崩了,才把它修复好,大白菜修复电脑是个好东西。
htime是这里给的。用的 ...

2个方案:

1) 宁可 count 变成 >=2000 的判断,  也要把 htime  用u8 来定义 变成150,

2)while(--j) 之前 TR0 =0;    htime = 0; 之后 TR0 = 1;
回复

使用道具 举报

27#
ID:450037 发表于 2021-11-12 13:50 | 只看该作者
188610329 发表于 2021-11-12 12:06
2个方案:

1) 宁可 count 变成 >=2000 的判断,  也要把 htime  用u8 来定义 变成150,

你意思说进入中断一次,htime的值累计也有误差,因为有count=0这个指令也耗时间是吧。
第二个方案感觉减少了定时误差。
回复

使用道具 举报

28#
ID:624769 发表于 2021-11-12 14:09 | 只看该作者
zhangzhao2423 发表于 2021-11-12 13:50
你意思说进入中断一次,htime的值累计也有误差,因为有count=0这个指令也耗时间是吧。
第二个方案感觉减 ...

我在另一个 关于中断的帖子里 提到过。
51系的单片机,属于8位机,一次只能处理8位数据,因此,如果有变量需要在 中断与主程序之间传递参数的话,这个变量,应当避免使用16位变量,(尤其是C编程的情况下)会出现你无法控制的错误。
而你htime 恰恰就是在中断和主程序之间传递参数的变量,那么他应该是 u8 而不应该是 u16。而count 仅仅只是在中断中使用,所以虽然16位耽误时间,但是不会产生你不可控的错误。

最后,htime 即便改成了u8 if判断中也要用 >=  而不能用==,这是原则问题(因为htime++ 不是在while(1)里面实施的)。而反过来,count >=   即便改成 == 也没有关系,因为 count++ 是在T0中断中实施的。
回复

使用道具 举报

29#
ID:450037 发表于 2021-11-12 14:18 | 只看该作者
188610329 发表于 2021-11-12 14:09
我在另一个 关于中断的帖子里 提到过。
51系的单片机,属于8位机,一次只能处理8位数据,因此,如果有变 ...

不管它了,我相信如果真的有一天需要用到这个功能的话,我会解决时间延迟的问题的。知道能实现这个定时启动停止就行了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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