OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3290|回复: 8

单片机程序思路问题,怎么做延时触发?

[复制链接]

2

主题

5

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2015-2-3
在线时间
2 小时
发表于 2016-4-9 12:44:34 | 显示全部楼层 |阅读模式
10金钱
比如说我按下一个按钮,在我设定的时间后把某个LED点亮
很容易想到按下按钮之后启动定时器,在定时器中点亮LED
但是在这个项目中一是定时器资源稀少,二是定时器需要一直运行完成其他任务,三是可能同时有多个延时触发,因此这种方法不可行
如果设置标志位,然后在已运行的定时器中进行判断的话则延时不准确,因为定时器溢出的时间点是固定的
延时函数就更不用说了,有可能是延时两三秒,没有上操作系统因此没有任务挂起的状态
求助啊

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

58

主题

6294

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11553
金钱
11553
注册时间
2014-4-1
在线时间
1317 小时
发表于 2016-4-9 12:56:31 | 显示全部楼层

定时精度有什么要求?


回复

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2015-2-3
在线时间
2 小时
 楼主| 发表于 2016-4-9 12:58:30 | 显示全部楼层
xuande 发表于 2016-4-9 12:56
定时精度有什么要求?

点亮LED只是一个比喻,实际精度要0.1秒以内
都是长延时,0.5秒以上的
回复

使用道具 举报

58

主题

6294

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11553
金钱
11553
注册时间
2014-4-1
在线时间
1317 小时
发表于 2016-4-9 13:38:44 | 显示全部楼层
这精度都很粗。

一个思路:
先找出各个定时长度的最大公约数,也是最小时间长度,作为定时器的时长;
如果n个事件,则建立n个变量;
定时器计数满时(比如中断),n个变量加一,定时器复位继续运行;
检查每个变量,是否该动作。

回复

使用道具 举报

15

主题

786

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3223
金钱
3223
注册时间
2015-7-26
在线时间
811 小时
发表于 2016-4-9 14:46:47 | 显示全部楼层
本帖最后由 229382777@qq.com 于 2016-4-9 14:48 编辑

http://www.openedv.com/thread-62234-2-1.html
这个帖子的54楼拉到最下面有段代码,定时器中断里面只做一件事,1ms的定时器中断函数里面不断对一个变量进行加加,这个精度应该能满足你的需求,my_delay_ms函数根据这个每毫秒加一的基数进行计算,用结构体的方式定义时间变量,也不会让代码看起来很臃肿
我的博客:http://blog.csdn.net/itdo_just
回复

使用道具 举报

30

主题

1170

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1993
金钱
1993
注册时间
2016-2-16
在线时间
527 小时
发表于 2016-4-9 14:56:03 | 显示全部楼层
你定时器需要一直运行完成其他任务,那他有没有有规律的运行,就是每隔某个相同的时间,他就跑某个程序还是干某件事,在里面安排一个参数累加计时,在外面判断那个参数,如果时间到了就清零,重新计时啊。
回复

使用道具 举报

12

主题

228

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1730
金钱
1730
注册时间
2016-3-8
在线时间
678 小时
发表于 2016-4-9 16:44:43 | 显示全部楼层
本帖最后由 adlu 于 2016-4-9 16:47 编辑

如果是长定时,相当好办。
假设SysTick定时器已经开启,且计数周期是1ms。你要求按键按下后0.5秒点亮LED。
则可以这样处理:
定义一个变量u16 tim_cnt = 0;
在按键按下之后赋值 tim_cnt = 500;
定时器中断中
if (tim_cnt) {
    tim_cnt--;
    if (0==tim_cnt) LED = 1;// 在变量从1减到0的时候执行操作
}

在任意一个定时中断中都可以,只要它一直在运行,且周期固定,并使能了中断。
回复

使用道具 举报

12

主题

228

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1730
金钱
1730
注册时间
2016-3-8
在线时间
678 小时
发表于 2016-4-9 16:54:22 | 显示全部楼层
本帖最后由 adlu 于 2016-4-9 16:57 编辑

如果要执行的操作比较复杂,就把操作部分放到中断外处理。
定义一个变量u16 tim_cnt = 0;
在按键按下之后赋值 tim_cnt = 501;
定时器中断中的代码改为
f (tim_cnt>1) {
    tim_cnt--; // 在此,tim_cnt最小值是1,不会变成0
}

在main函数的while(1)循环中
if (1 == tim_cnt) { //在此清零,并执行想要的操作
   tim_cnt = 0;
   LED = 1;
}




回复

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2015-2-3
在线时间
2 小时
 楼主| 发表于 2016-4-9 20:34:28 | 显示全部楼层
看了下大家的答案,收获很大,准备采用这些方法了
还想钻牛角尖的问一下,如果想非常精确的延时,该用什么方法
固定定时器中断有一个缺点,就是延时会有一个小于定时器周期的误差
比如定时器1000溢出,我设置了标志位的时刻,定时器计数为500,那么在我设置完标志位后,定时器只需要再计数500就让我的标志位减了一,当然,在之后的过程中肯定是精确的了,如果定时器周期足够的小,这一点小误差可以忽略不计
我的要求误差已经可以满足了,这只是一点小探讨,大家勿怪啊!
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-18 21:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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