这里先介绍下软件定时器和硬件定时器的区别
硬件定时器:
CPU内部自带的定时器模块,通过初始化、配置可以实现定时,定时时间到以后就会执行相应的定时器中断处理函数。硬件定时器一般都带有其它功能,比如PWM输出、输入捕获等等功能。但是缺点是硬件定时器数量少!!
软件定时器:
软件定时器允许设置一段时间,当设置的时间到达之后就执行指定的功能函数,被定时器调用的这个功能函数叫做定时器的回调函数。回调函数的两次执行间隔叫做定时器的定时周期,简而言之,当定时器的定时周期到了以后就会执行回调函数。
在FreeRTOS中有专门的软件定时器功能,我们可以在MCU中简单的是实现“软件定时器”如下:
void timer_1000ms(void)
{
printf("timer_1000ms\r\n");
}
/*systick_ms在硬件定时器中每1ms加1*/
int main(void)
{
static timer_tick = 0;
timer_tick = systick_ms;
while()
{
if((systick_ms-timer_tick)>1000)
{
timer_tick = systick_ms;
timer_1000ms();
}
}
}
这就是简单的软件定时器,是的,这就是特别简洁版本的软件定时器。当然它是有缺点的,比如systick_ms每1ms加1,所以软件定时器的精度是ms为单位的,并且如果while(1)中有其他代码阻塞,软件定时器也会跟着阻塞的。
这个简单的软件定时器毕竟很"简陋",大家可以自行封装丰富一下,或者参考已经有的开源方案:MultiTimer,一款可无限扩展的软件定时器。
MultiTimer 是一个软件定时器扩展模块,可无限扩展你所需的定时器任务,取代传统的标志位判断方式, 更优雅更便捷地管理程序的时间触发时序。
开源地址:https://github.com/0x1abin/MultiTimer
MultiTimer的设计比较简洁,只有2个文件,并且只有4个函数,总共82行代码,稍微花一点功夫就可以理解明白。

移植步骤
uint64_t PlatformTicksGetFunc(void)
{
/* Platform implementation */
}
MultiTimerInstall(PlatformTicksGetFunc);
实例化一个定时器对象
MultiTimer timer1;
int MultiTimerStart(&timer1, uint64_t timing, MultiTimerCallback_t callback, void* userData);
int main(int argc, char *argv[])
{
...
while (1) {
...
MultiTimerYield();
}
}
具体就不做手把手教程如何移植了,在STM32F207移植好的工程开源地址:
开源地址:https://github.com/strongercjd/STM32F207VCT6/tree/master/23-Timer-MultiTimer
下面分析一下MultiTimer在移植的第一步,配置系统时间基准接口,安装定时器驱动
uint64_t PlatformTicksGetFunc(void)
{
/* Platform implementation */
}
MultiTimerInstall(PlatformTicksGetFunc);
看一下MultiTimerInstall函数原型
typedef uint64_t (*PlatformTicksFunction_t)(void);
static PlatformTicksFunction_t platformTicksFunction = NULL;
int MultiTimerInstall(PlatformTicksFunction_t ticksFunc)
{
platformTicksFunction = ticksFunc;
return 0;
}
这其实就是函数指针实现的回调函数,具体详解看之前的文章《回调函数》,其实就是给MultiTimer提供一个计数器。
除去回调函数,该开源项目还是单链表的很好的示例,学习数据结构是比较乏味的,这个开源项目是单链表很好的应用落地,不太懂的同学可以学习下。
下面摘取一下部分代码
链表的删除
for (; *nextTimer; nextTimer = &(*nextTimer)->next) {
if (timer == *nextTimer) {
*nextTimer = timer->next; /* remove from list */
break;
}
}
插入链表
for (nextTimer = &timerList;; nextTimer = &(*nextTimer)->next) {
if (!*nextTimer) {
timer->next = NULL;
*nextTimer = timer;
break;
}
if (timer->deadline < (*nextTimer)->deadline) {
timer->next = *nextTimer;
*nextTimer = timer;
break;
}
}
遍历链表
MultiTimer* entry = timerList;
for (; entry; entry = entry->next) {
/* Sorted list, just process with the front part. */
if (platformTicksFunction() < entry->deadline) {
return (int)(entry->deadline - platformTicksFunction());
}
/* remove expired timer from list */
timerList = entry->next;
/* call callback */
if (entry->callback) {
entry->callback(entry, entry->userData);
}
}
这篇文章不会详细讲解链表的操作,不懂的同学可以看之前文章《链表在STM32中的应用》。
当然MultiTimer也是有缺点的,比如一个定时器是1000ms,另一个定时器是500ms,调度时就会冲突,也没有定时器调度抢占,会随着其他代码的阻塞而阻塞。这种类似的问题不再详述,大家使用的时候多测测就好。
看了上面的操作,如果我们不叫软件定时器,叫它“任务”,是不是和FreeRTOS任务类似,感觉高端一些,甚至这篇文章标题可以修改为《一篇文章教你实现操作系统》,开个欢笑,不做标题党。
有些项目实时性要求高,需要任务抢占,所以需要使用FreeRTOS这样的操作系统,但它资源占用比例过大,不利于项目开发,在一般的小项目中也用不到RTOS的太多功能,使用上面的思路,你可以把每个任务设置不同的间隔时间周期性调用,如果有实时性要求很高的事件,就通过中断处理。
当然也可以使用开头的粗糙方法
if((systick_ms-timer_tick)>1000)
{
timer_tick = systick_ms;
timer_1000ms();
}
这样功能是可以实现的,但没有模块化,不利于代码的维护。我们可以借鉴MultiTimer思路封装一下软件接口。
并且,如果你的项目中,任务的个数是固定不变的,可以将MultiTimer中的链表拿掉,直接使用全局变量就可以,如果有额外的时间模仿FreeRTOS实现一些信号量,对列等,这就是自己的OS(无抢占)啊。(当然这属于重复造轮子,但对一些公司来讲,有适合自己业务的,最精简的代码框架是很有必要的)。
我简单粗糙的实现了一个,有兴趣的可以看一下
开源地址:https://github.com/strongercjd/STM32F207VCT6/tree/master/41-SoftwareTask
点击查看:C语言进阶专辑
我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些
Ⅰ软件测试基础一、软件测试基础理论1、软件测试的必要性所有的产品或者服务上线都需要测试2、测试的发展过程3、什么是软件测试找bug,发现缺陷4、测试的定义使用人工或自动的手段来运行或者测试某个系统的过程。目的在于检测它是否满足规定的需求。弄清预期结果和实际结果的差别。5、测试的目的以最小的人力、物力和时间找出软件中潜在的错误和缺陷6、测试的原则28原则:20%的主要功能要重点测(eg:支付宝的支付功能,其他功能都是次要的)80%的错误存在于20%的代码中7、测试标准8、测试的基本要求功能测试性能测试安全性测试兼容性测试易用性测试外观界面测试可靠性测试二、质量模型衡量一个优秀软件的维度①功能性功
我想找到在某些文本中找到一些(让它是两个)句子的好方法。什么会更好-使用正则表达式或拆分方法?你的想法?应JeremyStein的要求-有一些例子示例:输入:ThefirstthingtodoistocreatetheCommentmodel.We’llcreatethisinthenormalway,butwithonesmalldifference.IfwewerejustcreatingcommentsforanArticlewe’dhaveanintegerfieldcalledarticle_idinthemodeltostoretheforeignkey,butinthis
我在我的rails应用程序中安装了来自github.com的acts_as_versioned插件,但有一段代码我不完全理解,我希望有人能帮我解决这个问题class_eval我知道block内的方法(或任何它是什么)被定义为类内的实例方法,但我在插件的任何地方都找不到定义为常量的CLASS_METHODS,而且我也不确定是什么here,并且有问题的代码从lib/acts_as_versioned.rb的第199行开始。如果有人愿意告诉我这里的内幕,我将不胜感激。谢谢-C 最佳答案 这是一个异端。http://en.wikipedia
我正在寻找一个用ruby演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent
我正在使用ruby1.8.7。p=lambda{return10;}deflab(block)puts'before'putsblock.callputs'after'endlabp以上代码输出为before10after我将相同的代码重构到这里deflab(&block)puts'before'putsblock.callputs'after'endlab{return10;}现在我收到LocalJumpError:意外返回。对我来说,这两个代码都在做同样的事情。是的,在第一种情况下我传递了一个过程,在第二种情况下我传递了一个block。但是&block将该block转换为pro
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我最近开始学习Ruby,这是我的第一门编程语言。我对语法感到满意,并且我已经完成了许多只教授相同基础知识的教程。我已经写了一些小程序(包括我自己的数组排序方法,在有人告诉我谷歌“冒泡排序”之前我认为它非常聪明),但我觉得我需要尝试更大更难的东西来理解更多关于Ruby.关于如何执行此操作的任何想法?
我在Ruby中遇到了一个关于Dir[]和File.join()的简单程序,blobs_dir='/path/to/dir'Dir[File.join(blobs_dir,"**","*")].eachdo|file|FileUtils.rm_rf(file)ifFile.symlink?(file)我有两个困惑:首先,File.join(@blobs_dir,"**","*")中的第二个和第三个参数是什么意思?其次,Dir[]在Ruby中有什么用?我只知道它等价于Dir.glob(),但是,我对Dir.glob()确实不是很清楚。 最佳答案
我在Ruby中有一个哈希:hash=Hash.new里面有一些键值对,比如说:hash[1]="One"hash[2]="Two"如果散列包含键2,那么我想将“Bananas”添加到它的值中。如果散列没有键2,我想创建一个新的键值对2=>"Bananas"。我知道我可以通过首先使用has_key?检查散列是否具有key2来做到这一点,然后采取相应的行动。但这需要一个if语句和不止一行。那么是否有一种简单、优雅的单行代码可以实现这一目标? 最佳答案 这个有效:hash[2]=(hash[2]||'')+'Bananas'如果您希望所有
网站的日志分析,是seo优化不可忽视的一门功课,但网站越大,每天产生的日志就越大,大站一天都可以产生几个G的网站日志,如果光靠肉眼去分析,那可能看到猴年马月都看不完,因此借助网站日志分析工具去分析网站日志,那将会使网站日志分析工作变得更简单。下面推荐两款网站日志分析软件。第一款:逆火网站日志分析器逆火网站日志分析器是一款功能全面的网站服务器日志分析软件。通过分析网站的日志文件,不仅能够精准的知道网站的访问量、网站的访问来源,网站的广告点击,访客的地区统计,搜索引擎关键字查询等,还能够一次性分析多个网站的日志文件,让你轻松管理网站。逆火网站日志分析器下载地址:https://pan.baidu.