\插播一条:
自己在今年整理一套单片机单片机相关论文800余篇
论文制作思维导图
原理图+源代码+开题报告+正文+外文资料
想要的同学私信找我。
分享两种单片机编程思想
分层思想
分层的思想,并不是什么神秘的东西,事实上很多做项目标工程师自身自己也会在用。看了不少帖子都发现没有提及这个东西,然而分层构造确是很有用的东西,参透后会有一种豁然开朗的感觉。假如说我不懂LCD怎么驱动,那好办,看一下datasheet,参照一下阿他人的程序,很快就能够做出来。但是假如不懂程序设计的思想的话,会给你做项目标过程中带来很多很多的困惑。
参照了市面上林林种种的嵌入式书籍,MCS-51,AVR ,ARM 等都有看过,但是没有发现有哪本是介绍设计思想的,就算有也是凤毛麟角。写程序不难,但是程序如何才能写的好,写的快,那是须要点经历积攒的。构造化模块化的程序设计的思想,使最根本的要求。
然而这么将这个抽象的概念使用到工程实战当中恩?那须要在做项目标过程中经历磨难,将一些东西总结出来,抽象升华为理论,对经历的积攒和技术的传播都大有裨益。所以在下出来献丑一下,总结一些东西。
就我个人的经历而谈,有两个设计思想是非常重要的。
一个就是“时长片轮的设计思想”,这个对现实中中攻克多任务问题非常有用,通常能够用这个东西来判断一个人是单片机进修者,还是一个单片机工程师。这个必需掌握。(下文将介绍)。
第二个就是“分层屏蔽的设计思想”即分层思想。下面用扫描键盘程序例子作为引子,引出今天说的东西。
问题的提出
单片机进修板一般为了简略起见,将按键分配的很好,例如整个 4*4 的键盘矩阵分配到 P1 口上面,8条控制线,刚好。这样的话程序也非常好写。只须要简略的:
KEY_DAT= P1;
端口的数据就读进来了。
诚然,实际没有这么好的事情。在现实中的项目应用当中,单片机引脚的复用相当厉害,这跟那些所谓的单片机进修板就有很大的区别了。
另外一个理由,一般设计来说,是“软件配合硬件”的设计流程,简略点说就是,先确定好硬件原理图,硬件布线,最后才是软件的开发,由于硬件修改起来比较麻烦,相对来说软件修改的时候比较好改。这个就是中国传统的阴阳均衡哲学原理。硬件设计和软件设计原本就是鱼和熊掌的关系,两者不可兼得。方便了硬件设计,很可能给写软件带来很大的麻烦。
反过来说,方便了软件设计,硬件设计也会相当的麻烦。假如硬件设计和软件设计同时方便了,那独有两种可能,一是这个设计方案非常简略,二是设计师已经到达了一个非常高的境界。我们不考虑那么多情况,单纯从常用的现实中应用的角度来看问题。
硬件为了布线的方便,很多时候会可能将IO口分配到不同的端口上面,例如上面说的4*4键盘,8根线分别分配到 P0 P1 P2 P3 上面去了。那么,开发板的那些扫描键盘程序能够去见鬼了。怎么扫按键?我想起了我刚初始进修的时候,分成3段非常相似的程序,一个一个按键的扫描的经历......
或许有人不甘心,“那些东西我花了很长时长进修的,也用的好好的,怎么能说一句不用就不用?”虽然有点残忍,但是我还是想说“兄弟,承受现实吧,现实是残酷的......”
不过,人差别于低等动物的区别,是人会创造,在碰到艰难的时候会想办法攻克,于是我们初始了沉思......
最后我们引入初中数学学的“映射”的概念来攻克问题。根本思想就是,将不同端口的按键映射到相同端口上面。
按键扫描程序如何分成3个层
最底层的是硬件层,完成端口扫描,20ms延时消抖,将端口的数据映射到一个KEY_DAT寄存器上面,KEY_DAT作为对上层驱动层的一个接口。
中间的一层是驱动层,驱动层只对 KEY_DAT 寄存器的数值进行操作。简略点说,我们没论底层的硬件是怎么接线的,在驱动层都不须要关怀,只须要关怀 KEY_DAT 这个寄存器的数值是什么就能够了。这样出来的间接效果就是“屏蔽了底层硬件的差异”,所以驱动层写的程序就能够通用了。
驱动层的另外一个功能是为了上层提供音讯接口。我们用了类似window程序的音讯的概念。这里能够提供一些按键音讯,例如:按下音讯,松开音讯,长按键音讯,长按键的时候的步进音讯,等等。
应用层属于最上层的程序,这里就是依据项目标不同分别写按键功能程序。它运用的是驱动层提供的音讯接口。在应用层写程序的思想就是,我不管下层是怎么工作的,我只关怀按键音讯。有按键音讯来的时候我就执行功能,没有音讯来的时候,我就什么也不做。
下面用一个简略的常用的例子,证明我们这个设计思想的用法。
秒表调整时长的时候,要求按着某个按键不放,时长能不间断的向上增加。这个东西很实用,现实中的家电中用途很广泛。
在看下面的东西之前,大家能够想一下,这东西难吗?相信大家都会很响亮的答复,“不难!!”,然而我再问:“这东西麻烦吗?”我相信很多人肯定会说“很麻烦!!” 这不禁让我想起初始学单片机的时候写这种按键的那程序,乱七八糟的构造。假如不相信的话,能够自己用51写一下哦,那样就愈加能体会本文说的分层构造的优越性。
项目要求:
两个按键,分别分配在P10 和P20,分别是“加”“减”按键,要求长按键的时候达到不间断加和不间断减的功能。
实践:
假设按键上拉,没有按键的时候高电平,有按键的时候低电平,另外,为了突出问题,这里没有将延时消抖的程序写上去,在现实中项目中应该加上。C语言函数参数的传递多种多样,这里作为例子,用了最简略的全局变量来传递参数,当然你也能够用 unsigned charReadPort(void)返回一个读键结果,甚至还能够 void ReadPort(unsigned char*pt) 用一个指针变量传递地址而到达直接修变更量的目标。方法是多种多样的,这个决定于每个人的程序格调。
初始写硬件层程序,完成映射
#defineKYE_MIN 0X01
#defineKEY_PLUS 0X01
unsignedchar KeyDat;
voidReadPort(void)
if (P1 & KEY_PLUS == 0 )
KeyDat |= 0x01 ;
if (P2 & KEY_MIN == 0 )
KeyDat |= 0x02 ;
C语言应该很容易看懂吧?假如 KEY_PLUS 按下,P10口读到低电平,则 P1 &KEY_PLUS 的结果为 0 (xxxx xxx0 & 0000 0001),满足if 的条件,进入KeyDat |=0x01 是将 KeyDat 的bit0 置一,也就是说,将 KEY_PLUS 映射到 KeyDat 的 bit0
KEY_MIN是同样的道理映射到 KeyDat 的 bit1,假如 KeyDat 的 bit0 为 1 ,则证明 KEY_PLUS 按下,反则亦然。
不须要想的很神秘,映射就是这么一回事。假如还有其他按键的话,用同样办法,将他们全部映射到 KeyDat 上面。
2)驱动层程序编写
假如将 KeyDat想象成 P1 口,那么这个跟进修板那规范的扫描程序不就是一样了吗?对的,这个就是底层映射的目标了。
3)应用层程序编写
依据音讯,硬件层是必需别离出来,然而驱动层和应用层的要求就不那么严格了,事实上一些简略的项目没有必要将这两层别离开来,依据现实中应用灵敏应对就能够了。
其实这样写程序是很方便移植的,依据板子的不同而适当的修改一下硬件层那个 ReadPort 函数就完成了,驱动层和应用层很多代码能够不经过修改直接用,很能提高开发效率的。当然这个按键程序会存在一定的问题,特别是遇到常闭按键和点触按键的混合运用的场合。这个留给大家自己去想了,反正问题总是能找得到攻克办法的,只管方法有好有坏。
时间片轮设计思想
先用一个小例子引出今天的主题,想象一下,一个根本的家电控制板,肯定或多或少的会包括 :LED 或者 数码管显示,按键, 继电器或者可控硅的输出 这3局部。数码管须要 10ms到20ms的动态扫描,按键也须要20ms左右的延时消抖,有没有意识到,其实这些时长是同时在进行的。
回想一下咱们的教科书怎么教 按键 的延时消抖的?没错,死循环,绝对是原地踏步死循环,用指令来计时。这样很自然的引发一个问题,单片机在原地踏步死循环的话,那么其它的工作怎么办?如数码管的动态扫描怎么办?
唯有等按键扫描之后再进行了,这样出来的效果,数码管肯定会闪烁的,扫描时长过长了,缩短按键消抖时长也不是攻克办法,想象假如咱们还有其它很多工作也是同时做的呢?攻克办法之一,就是今天的主题,分时扫描的思想。当然不会是唯一的办法,只不过俺一直在用,觉得这个是非常不错的思想,能够攻克很多现实中问题。大胆妄言一下,分时扫描的思想也是单片机编程最核心的思想了,信不信就由你自己判断了。
核心思想的实现过程
第一、用RTC中断来计时,RTC的中断时长短一点,我习惯是125us ,为了解红外遥控的码,这个时长是须要的。RTC计时是相当准的,尽量利用。
第二、在RTC的中断效劳程序里面放3个(数量自定)记时器(说白了就是计数器),我的习惯是 2ms 5ms 500ms 这3个是作为基准时长,提供给整个系统来调用的,所以必需精确一点,现实中用示波器调一下就OK了,不难。
第三、在主程序的循环里面放一个专门处理时长的子程序。(注:单片机是不会停的,永远在不断循环的跑,这个跟学校学的貌似有点不同,俺面试的时候被问过这个问题 ….) 将所有的时长处理都放在时长处理子程序里面做,这样是非常方便的,一个单片机系统最起码须要处理 10~20个不同的时长,也须要10~20个计时器了,而且相当多要求同时不同步工作的,假如每个都单独的话是相当的麻烦。
第四、“程序是跑着来等,而不是站着来等”,这话看来有点玄,一个跟俺一起进去公司的工程师探讨的时候提到的这个问题,俺觉得这个也是分时系统的一个比较重要的思想,所以也这样叫,下面有细说。
第五、下面用程序来说话,注释尽量详细,能够不用看代码,直接看注释就能够了。
先中断服务程序部分
每 125us 中断一次,产生几个基准时间。
(1) ref_2ms寄存器不断的减1,每次中断减1,一共减 16次,所以这里经过的时长是 125us × 16 = 2ms,这个就是所谓的计时/计数器 了。这样就能够靠一个系统的RTC中断,来达到我们须要的很多个定时时长。
(2)置2ms 计时完毕标志,这个是提供给时长处理程序用的,这是一个计时器的框架,下面的5ms计时完全相同。
这程序还用了一个块的框架,比较方便的,不过跟今天的主题没关,以后郁闷的时候再上来写写这个。上面的程序就是中断效劳程序里面的计时器,分别定时 2ms 5ms 500ms,计时完毕溢出是flag_time 标志来记录的,程序通过读这个标志就能够知道定时的时长是否已经到了。
下面看那个统一的时间服务子程序
上面用了按键20ms消抖的计时器作为例子,假如了解之后就能够发现,我们能够完全模仿那个计时器而在下面放很多很多的计时器,则每5ms 进来一下,每个计时器都同时在计数了,谁先计算完毕就先关掉自己,置相应的标志给其它程序调用,而对其它计时器完全没有影响!这样,我们能够在这里放很多个计时器了,一般来说,十来二十个是没有问题的,完全满足一个单片机系统对多个时长的需求了。
单个计时器的构造很简略,先判断允许计时标志是否进入计时,其次一个专用的寄存器在加1或者减1,加/减相应的数值之后也就是相应的时长到了,关掉计时器,置相应须要用到的标志。
到这里差不多了,俺们须要的时长都能够出来了,这样做是不是非常方便?咱们再来看看在这段时长里单片机在做了什么东西?独有中断计时够 5ms 或者 500ms ,那个溢出标志才有效,才能进入上面的计时程序,其它时长都是在做其它事情。而且进入上面的计时器的时候,能够看出,并不是在那里死循环,只是单纯的加减一下寄存器就退出了,整个过程耗时极其短,看代码不同吧,5us到 20us左右吧,对主程序的执行没有什么影响。
下面看看具体怎么调用
最开始谈过的按键的消抖时间处理问题,现在就用上面介绍的办法来看具体怎么解决问题。
大略是这样的:判断什么时候有健,没有的话跳出,有的话初始延时消抖的计时,第二次进来的时候直接由标志位控制过去判断时长时候够。
同样是等待,这里就是最后一点所说的,咱这是跑着来等,不是站着来等。跟死循环定时比较,在没有定时到20ms 的这段时长里面单片机在做什么?死循环的话,肯定就是在原地等,什么都不做,而看看上面的程序,他只是判断是否定时够,详细的定时在统一的时长子程序里面做,判断没有到时长的话就跳出了,继续跑其它的程序,直到当时长到了,单片机判断出flag_delay,key_flow 合乎条件,初始进入按键处理程序了,在这个期间,单片机都在做其它事情,只是一个主循环跑回来判断一次,所以单片机完全有空跑其它的程序,而没有将时长都耗在消抖上面。
主程序循环体
这个就是用到的循环体了,所有功能都做成子程序形式了,须要就挂上去就能够了,比较方便,这样一个总的循环体,单片机就是在不断的执行这个循环体,假如整个程序都采用上面说的分时扫的思想的话,一周循环回来的时长是相当短的,其实是不是跟电脑的思想有点像呢?
电脑再快也并不是同时处理多个任务,而且每次处理一个,然后非常快的速度来循环处理,让我们感觉上他是在同时处理多个程序那样,我想,我最终想表达的思想也就是这个罢了。有这个思想支撑下,单片机的程序变得比较容易上手了,剩下的只是集中精力去用程序来实现我们的思想罢了,当然,这里只是说一种可行的办法罢了,不是说独有这种办法。
编写程序是一门艺术,写出来很容易,写得精巧却很难。
END
【文章福利】:小编整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!~点击绿色通讯软件搜索wujidanpianji加入(需要自取)
说了这么多,大家记得留意下方评论第一条(或者私信我)有干货~
-END-
*本文系网络转载,版权归原作者所有,如有侵权请联系删除
到此这篇单片机的代码怎么编写(单片机代码怎么读懂)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/59654.html