您的位置 首页 传感器

单片机分时思维

下面说的单片机应用也主要是家电控制方面,也就是现在的工作。其它应用不在讨论范围。才识有限,也敬请前辈们勘误,指教。先用一个小例子引…

下面说的单片机使用也主要是家电操控方面,也便是现在的作业。其它使用不在评论规模。学识有限,也敬请长辈们订正,指导。

先用一个小比如引出今日的主题,幻想一下,一个根本的家电操控板,必定或多或少的会包括 : LED 或许 数码管显现, 按键, 继电器或许可控硅的输出 这3部分。数码管需求 10ms到20ms的动态扫描,按键也需求 20ms左右的延时消抖,有没有意识到,其实这些时刻是一同在进行的。回想一下咱们的教科书怎样教 按键 的延时消抖的?没错,死循环,必定是原地踏步死循环,用指令来计时。这样很天然的引发一个问题,单片机在原地踏步死循环的话,那么其它的作业怎样办?如数码管的动态扫描怎样办?唯有等按键扫描之后再进行了,这样出来的作用,数码管必定会闪耀的,扫描时刻过长了,缩短按键消抖时刻也不是处理方法,幻想假如咱们还有其它许多作业也是一同做的呢?处理方法之一,便是今日的主题,分时扫描的思维。当然不会是仅有的方法,只不过俺一向在用,觉得这个是十分不错的思维,能够处理许多实践问题。斗胆妄言一下,分时扫描的思维也是单片机编程最中心的思维了,信不信就由你自己判别了。

程序的履行环境

用的是纯汇编,由于用习气的汇编,以致于整个脑袋都是汇编的思维,某种程度上说,C的废码确实是多了一点,关于实践工业用的单片机ROM和RAM都不是很足够的情况下,代码仍是要求尽量精简的。所以俺一向都在汇编的苦海中沉浮着……阐明一点,俺用的是EMC的单片机(Elan公司的),风闻中最烂的单片机,所以代码不值的去学,也正是这个原因,希望我想表达的思维能表达清楚, 阿门!

中心思维的完成

其实是几个进程,

榜首, 用TCC中止来计时,TCC的中止时刻断一点,我习气是 125us ,为了解红外遥控的码,这个时刻是需求的。TCC计时是适当准的,尽量使用。

第二, 在TCC的中止服务程序里边放3个(数量自定)记时器(说白了便是计数器),我的习气是 2ms 5ms 500ms 这3个是作为基准时刻,提供给整个体系来调用的,所以有必要精确一点,实践用示波器调一下就OK了,不难。

第三, 在主程序的循环里边放一个专门处理时刻的子程序。(注:单片机是不会停的,永远在不断循环的跑,这个跟校园学的形似有点不同,俺面试的时分被问过这个问题 ….) 将一切的时刻处理都放在时刻处理子程序里边做,这样是十分便利的,一个单片机体系最起码需求处理 10~20个不同的时刻,也需求10~20个计时器了,并且适当多要求一同不同步作业的,假如每个都独自的话是适当的费事。

第四, “程序是跑着来等,而不是站着来等”,这话看来有点玄,一个跟俺一同进去公司的工程师评论的时分说到的这个问题,俺觉得这个也是分时体系的一个比较重要的思维,所以也这样叫,下面有细说。

第五, 下面用程序来说话,注释尽量详细,能够不必看代码,直接看注释就能够了。

(一)先中止服务程序部分:

每 125us 中止一次

;——————-发生几个基准时刻—————————

int_2ms:

djz ref_2ms (1)

jmp int_5ms

mov a,@16 ; 康复原始数据

mov ref_2ms,a

bs flag_time,flag_2ms (2)

int_5ms:

djz ref_5ms

jmp ref_time_end

mov a,@40 125us×40=5ms

mov ref_5ms,a

bs flag_time,flag_5ms

int_500ms:

djz ref_500ms

jmp ref_time_end

mov a,@100

mov ref_500ms,a

bs flag_time,flag_500ms

ref_time_end:

nop

(1) ef_2ms寄存器不断的减1,每次中止减1,总共减 16次,所以这儿经过的时刻是 125us × 16 = 2ms,这个便是所谓的计时/计数器 了。这样就能够靠一个体系的TCC中止,来完成咱们需求的许多个守时时刻。

(2)置 2ms 计时完毕标志,这个是提供给时刻处理程序用的,这是一个计时器的结构,下面的5ms计时彻底相同。

这儿解释一下:bs flag_time,flag_2ms,其间bs是将某一方位1的指令,该指令的意思是,将 flag_timg寄存器里边第flag_2ms方位1,建立一个溢出标志,后边的程序能够经过读这个标志,就知道 2ms 是否现已计时到了

这程序还用了一个块的结构,比较便利的,不过跟今日的主题无关,今后抑郁的时分再上来写写这个。上面的程序便是中止服务程序里边的计时器,别离守时 2ms 5ms 500ms,计时完毕溢出是flag_time 标志来记载的,程序经过读这个标志就能够知道守时的时刻是否现已到了。

(二)下面看那个一致的时刻服务子程序

;——————-时刻处理子程序—————————–

time_proc:

jbs flag_time,flag_5ms 判别5ms是否到

jmp time_500ms_proc 没有的话判别500ms

time_5ms_proc:

bc flag_time,flag_5ms 5ms现已到了,进入服务程序,先清掉那个标志,这样下次再过5ms才答应进来这儿。

;—————— 按键延时部分——————— ;这儿用这个做比如

key_delay_proc:

jbs flag_delay,key_start ; 按键延时开端标志,这个用来操控是否进入计时,答应计时标志

jmp key_delay_end

djz reg_key ; 预先设置的延时时刻,每5秒减一次,这儿预设的值是4,也便是说 5ms * 4 = 20ms

jmp key_delay_end 有减到0的话直接跳出

bs flag_delay,key_flow 时刻到,置需求用的标志

mov a,@4 ; 从头置数据下次用。

mov reg_key,a

key_delay_end:

nop

;———————500ms处理部分————————

time_500ms_proc:

jbs flag_time,flag_500ms

ret

bc flag_time,flag_500ms

这儿放需求的计时器

Ret

上面用了按键20ms消抖的计时器作为比如,假如了解之后就能够发现,咱们能够彻底仿照那个计时器而在下面放许多许多的计时器,则每5ms 进来一下,每个计时器都一同在计数了,谁先核算完毕就先关掉自己,置相应的标志给其它程序调用,而对其它计时器彻底没有影响!这样,咱们能够在这儿放许多个计时器了,一般来说,十来二十个是没有问题的,彻底满意一个单片机体系对多个时刻的需求了。

单个计时器的结构很简单,先判别答应计时标志是否进入计时,然后一个专用的寄存器在加1或许减1,加/减购相应的数值之后也便是相应的时刻到了,关掉计时器,置相应需求用到的标志。

到这儿差不多了,俺们需求的时刻都能够出来了,这样做是不是十分便利?咱们再来看看在这段时刻里边单片机在做了什么东西?只要中止计时够 5ms 或许 500ms ,那个溢出标志才有用,才干进入上面的计时程序,其它时刻都是在做其它工作。并且进入上面的计时器的时分,能够看出,并不是在那里死循环,仅仅单纯的加减一下寄存器就退出了,整个进程耗时极端短,看代码不同吧,5us到 20us左右吧,对主程序的履行没有什么影响。

(三)下面看看详细怎样调用

最开端谈过的按键的消抖时刻处理问题,现在就用上面介绍的方法来看详细怎样处理问题。按键的处理也是重要的根底学识,不过不在本次的评论规模,所以仅仅单单的评论怎样处理时刻问题,而关于按键的一些问题,下次有时机持续评论吧,hoho~~~

scan_key:

jbc flag_key,first_on ; 用来操控跳转的

jmp have_key

jbs port6,1 假定P61高电平是有键

jmp key_end

;————————————-

bs flag_key,first_on 榜首次按键的标志

bs flag_delay,key_start 发动计时器开端守时20ms消抖

have_key:

jbs flag_delay,key_flow 等候守时完毕溢出

jmp key_end

大概是这样的:判别时分有健,没有的话跳出,有的话开端延时消抖的计时,第2次进来的时分直接由标志位操控曩昔判别时刻时分够。

同样是等候,这儿便是终究一点所说的,咱这是跑着来等,不是站着来等。跟死循环守时比较,在没有守时到20ms 的这段时刻里边单片机在做什么? 死循环的话,必定便是在原地等,什么都不做,而看看上面的程序,他仅仅判别是否守时够,详细的守时在一致的时刻子程序里边做,判别没有到时刻的话就跳出了,持续跑其它的程序,直到当时刻到了,单片机判别出flag_delay,key_flow 契合条件,开端进入按键处理程序了,在这个期间,单片机都在做其它工作,仅仅一个主循环跑回来判别一次,所以单片机彻底有空跑其它的程序,而没有将时刻都耗在消抖上面。

(四)看看我的主程序循环体

start:

call clear_all_ram 清空RAM

call initialize 初始化

loop:

eni 开中止

wdtc 清看门狗

call scan_proc 调用扫描LED和按键程序

call ir_data_proc 调用红外处理程序

call time_proc 调用时刻一致处理程序

call output_proc 调用输出处理程序

jmp loop

这个便是我用的循环体了,一切功用都做成子程序方式了,需求就挂上去就能够了,比较便利,这样一个总的循环体,单片机便是在不断的履行这个循环体,假如整个程序都选用上面说的分时扫的思维的话,一周循环回来的时刻是适当短的,其实是不是跟电脑的思维有点像呢?电脑再快也并不是一同处理多个使命,并且每次处理一个,然后十分快的速度来循环处理,让咱们感觉上他是在一同处理多个程序那样,我想,我终究想表达的思维也便是这个罢了。

啰啰唆唆的说了一堆,也不知道是否能看懂,或许是否去看。不知道我对分时扫描这个概念是否了解错了呢?在我看来,有这个思维支撑下,单片机的程序变得比较简单上手了,剩余的仅仅集中精力去用程序来完成咱们的思维罢了,当然,这儿仅仅说一种可行的方法罢了,不是说只要这种方法,假如我们有好的思维也共享一下哦,编写程序是一门艺术,写出来很简单,可是写得好,写得精巧,那就很难了。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/chuanganqi/268356.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部