找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机程序设计-时基 通过定时器中断计数的方式定时的实现

  [复制链接]
跳转到指定楼层
楼主
在一个程序中的很多地方都需要定时,如LED闪烁、按键消抖和通讯等待等。通过阻塞CPU的方式定时,程序性能极差;通过硬件定时器定时,性能好,定时非常准确,但定时器资源有限;通过定时器中断计数的方式定时,性能好,定时较准确,使用非常灵活。本文主要描述通过定时器中断计数的方式定时的实现。


2.定时器中断计数
初始化?个定时器,1ms中断?次。定义?个uint32_t变量,每中断?次,变量加1,变量溢出后
变为0。
定时器初始化和中断服务程序
  1. uint32_t volatile time_base_ms;  //volatile关键字防?编译器优化
  2. void timer_init(void)
  3. {
  4.   //初始化定时器
  5.   time_base_ms = 0;
  6. }
  7. // 定时器中断服务程序
  8. void Timer_hander(void) interrupt 19
  9. {
  10.   ++time_base_ms;
  11. }
复制代码



3.获取当前时刻
定时器开启之后,变量time_base_ms开始计数,每加1表示时间过去1ms。在访问变量
time_base_ms的 过程中有可能发?了中断,必须特殊处理。?法是,先读?次,再读?次并?较?
次,如果相等说明两次读的过程都没有发?中断,数据可靠;如果不相等,说明两次读有?次发?了
中断,下?次中断没有那么快到来,再读?次数据?定不会发?中断(系统时钟不太慢的情况下)。
  1. uint32_t time_current(void)
  2. {
  3.   uint32_t ret;

  4.   ret = time_base_ms;     // 读取计数,该过程可能中断

  5.   if(ret != time_base_ms){  // 读取计数,该过程可能中断;如果不相等,说明两
  6. 个过程有?个发?过中断
  7.     ret = time_base_ms;   // 读取计数,该过程没有中断
  8.   }

  9.   return ret;
  10. }
复制代码

4.定时的计算
计算过去某个时刻据当前时刻的时间,或者说过去的某个时刻据现在有多久。需要考虑过去某个
时刻到当前时刻变量time_base_ms有没有溢出。
  1. uint32_t time_timing_ms(uint32_t moment)
  2. {
  3.   uint32_t current_moment;
  4.   uint32_t ret;

  5.   current_moment = time_current();

  6.   if(current_moment >= moment){
  7.     ret = current_moment - moment;
  8.   }else{
  9.     ret = (0xffffffff - moment) + current_moment + 1;
  10.   }

  11.   return ret;
  12. }
复制代码

应用
led1每秒闪烁1次,led2每秒闪烁5次。

  1. void main()
  2. {
  3.   uint32_t led1_moment;
  4.   uint32_t led2_moment;
  5.   //初始化定时器
  6.   timer_init();
  7.   //记录当前时刻
  8.   led1_moment = time_current();
  9.   led2_moment = time_current();
  10.   while(1){
  11.     //检查时间是否过去500ms
  12.     if(time_timing_ms(led1_moment) > 500){
  13.       led1 = ~led1;
  14.       led1_moment = time_current();  //记录当前时刻
  15.     }
  16.     //检查时间是否过去100ms
  17.     if(time_timing_ms(led2_moment) > 100){
  18.       led2 = ~led2;
  19.       led2_moment = time_current();  //记录当前时刻
  20.     }
  21.    
  22.   }
  23. }
复制代码

示例:



评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:798322 发表于 2023-6-26 21:25 | 只看该作者
void Timer_hander(void) interrupt 19
这个中断号是不是有问题,然后时间应该是时间差比较100 500ms,单片机的定时和晶振有关。
回复

使用道具 举报

板凳
ID:479880 发表于 2023-6-29 11:03 来自手机 | 只看该作者
玲珑红豆 发表于 2023-6-26 21:25
void Timer_hander(void) interrupt 19
这个中断号是不是有问题,然后时间应该是时间差比较100 500ms,单 ...

代码不完全可用,只是用来说明思路
回复

使用道具 举报

地板
ID:475306 发表于 2023-7-28 10:02 | 只看该作者
小白没看懂啊,点亮那个IO口了啊?
回复

使用道具 举报

5#
ID:1090778 发表于 2023-8-5 14:35 | 只看该作者
小白没看懂啊,继续学习
回复

使用道具 举报

6#
ID:479880 发表于 2023-8-9 18:32 来自手机 | 只看该作者
KTTCO 发表于 2023-7-28 10:02
小白没看懂啊,点亮那个IO口了啊?

伪代码
回复

使用道具 举报

7#
ID:303735 发表于 2023-10-3 14:54 | 只看该作者
KTTCO 发表于 2023-7-28 10:02
小白没看懂啊,点亮那个IO口了啊?

初始化把LED1定义到想要输出的口就行了,
回复

使用道具 举报

8#
ID:1109233 发表于 2024-2-4 18:53 | 只看该作者
不完全可用,只是用来说明思路
回复

使用道具 举报

9#
ID:627251 发表于 2024-2-17 22:02 | 只看该作者
这代码... AI生成的吧
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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