找回密码
 注册
关于网站域名变更的通知
查看: 22132|回复: 185
打印 上一主题 下一主题

浅谈-单片机程序“设计思想”

  [复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-9-4 14:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
本帖最后由 行者~ABC 于 2020-10-29 10:53 编辑
- [, I$ d  b6 v1 s5 m
5 G0 O" ^4 L& w/ G

浅谈-单片机程序“设计思想”

随便写下的一点东西,本来打算去发表,不过想想还是算了,不是什么重要的东西,不过这个东西确实很有用。文章烂的去组织和修改了,随便看看吧。

分层的思想,并不是什么神秘的东西,事实上很多做项目的工程师本身自己也会在用。看了不少帖子都发现没有提及这个东西,然而分层结构确是很有用的东西,参透后会有一种恍然大悟的感觉。如果说我不懂LCD怎么驱动,那好办,看一下datasheet,参考一下阿别人的程序,很快就可以做出来。但是如果不懂程序设计的思想的话,会给你做项目的过程中带来很多很多的困惑。

参考了市面上各种各样的嵌入式书籍,MCS-51,AVR ,ARM 等都有看过,但是没有发现有哪本是介绍设计思想的,就算有也是凤毛麟角。写程序不难,但是程序怎么样才能写的好,写的快,那是需要点经验积累的。结构化模块化的程序设计的思想,使最基本的要求。然而这么将这个抽象的概念运用到工程实践当中恩?那需要在做项目的过程中经历磨难,将一些东西总结出来,抽象升华为理论,对经验的积累和技术的传播都大有裨益。所以在下出来献丑一下,总结一些东西。

- X2 ~+ Z7 e: q5 i! p$ }

% u% u' g& o, E) Z4 G

就我个人的经验而谈,有两个设计思想是非常重要的。

一个就是“时间片轮的设计思想”,这个对实际中解决多任务问题非常有用,通常可以用这个东西来判断一个人是单片机学习者,还是一个单片机工程师。这个必须掌握。由于网上介绍这个的帖子也不少,所以这里就不多说了。

第二个就是我今天想说的主题“分层屏蔽的设计思想”。下面用扫描键盘程序例子作为引子,引出今天说的东西。

问题的提出

单片机学习板一般为了简单起见,将按键分配的很好,例如整个 4*4 的键盘矩阵分配到 P1 口上面,8条控制线,刚好。这样的话程序也非常好写。只需要简单的

KEY_DAT = P1;

端口的数据就读进来了。

诚然,现实中没有这么好的事情。在实际的项目应用当中,单片机引脚的复用相当厉害,这跟那些所谓的单片机学习板就有很大的差别了。

另外一个原因,一般设计来说,是“软件配合硬件”的设计流程,简单点说就是,先确定好硬件原理图,硬件布线,最后才是软件的开发,因为硬件修改起来比较麻烦,相对来说软件修改的时候比较好改。这个就是中国传统的阴阳平衡哲学原理。硬件设计和软件设计本来就是鱼和熊掌的关系,两者不可兼得。方便了硬件设计,很可能给写软件带来很大的麻烦。反过来说,方便了软件设计,硬件设计也会相当的麻烦。如果硬件设计和软件设计同时方便了,那只有两种可能,一是这个设计方案非常简单,二是设计师已经达到了一个非常高的境界。我们不考虑那么多情况,单纯从常用的实际应用的角度来看问题。

硬件为了布线的方便,很多时候会可能将IO口分配到不同的端口上面,例如上面说的4*4键盘,8根线分别分配到 P0 P1 P2 P3 上面去了。那么,开发板的那些扫描键盘程序可以去见鬼了。怎么扫按键?我想起了我刚开始学习的时候,分成3段非常相似的程序,一个一个按键的扫描的经历......

或许有人不甘心,“那些东西我花了很长时间学习的,也用的好好的,怎么能说一句不用就不用?”虽然有点残忍,但是我还是想说“兄弟,接受现实吧,现实是残酷的......”

不过,人区别于低等动物的差别,是人会创造,在碰到困难的时候会想办法解决,于是我们开始了沉思......

最后我们引入初中数学学的“映射”的概念来解决问题。基本思想就是,将不同端口的按键映射到相同端口上面。

这样按键扫描程序就分成3个层次了。

1)最底层的是硬件层,完成端口扫描,20ms延时消抖,将端口的数据映射到一个KEY_DAT寄存器上面,KEY_DAT作为对上层驱动层的一个接口。

2)中间的一层是驱动层,驱动层只对 KEY_DAT 寄存器的数值进行操作。简单点说,我们无论底层的硬件是怎么接线的,在驱动层都不需要关心,只需要关心 KEY_DAT 这个寄存器的数值是什么就可以了。这样出来的间接效果就是“屏蔽了底层硬件的差异”,所以驱动层写的程序就可以通用了。

驱动层的另外一个功能是为了上层提供消息接口。我们用了类似window程序的消息的概念。这里可以提供一些按键消息,例如:按下消息,松开消息,长按键消息,长按键的时候的步进消息,等等。

3)应用层。这里就是根据项目的不同分别写按键功能程序,属于最上层的程序。它使用的是驱动层提供的消息接口。在应用层写程序的思想就是,我不管下层是怎么工作的,我只关心按键消息。有按键消息来的时候我就执行功能,没有消息来的时候,我就什么也不做。

下面用一个简单的常用的例子,说明我们这个设计思想的用法。

秒表调整时间的时候,要求按着某个按键不放,时间能连续的向上增加。这个东西很实用,实际的家电中用途很广泛。

在看下面的东西之前,大家可以想一下,这东西难吗?相信大家都会很响亮的回答,“不难!!”,然而我再问:“这东西麻烦吗?”我相信很多人肯定会说“很麻烦!!” 这不禁让我想起开始学单片机的时候写这种按键的那程序,乱七八糟的结构。如果不相信的话,可以自己用51写一下哦,那样就更加能体会本文说的分层结构的优越性。

项目要求:

两个按键,分别分配在P10 和P20,分别是“加”“减”按键,要求长按键的时候实现连续加和连续减的功能。

实战:

假设:

按键上拉,没有按键的时候高电平,有按键的时候低电平,另外,为了突出问题,这里没有将延时消抖的程序写上去,在实际项目中应该加上。C语言函数参数的传递多种多样,这里作为例子,用了最简单的全局变量来传递参数,当然你也可以用 unsigned char ReadPort(void) 返回一个读键结果,甚至还可以 void ReadPort(unsigned char *pt) 用一个指针变量传递地址而达到直接修改变量的目的。方法是多种多样的,这个决定于每个人的程序风格。

1)开始写硬件层程序,完成映射

#define KYE_MIN 0X01

#define KEY_PLUS 0X01

unsigned char KeyDat;

void ReadPort(void)

{

if (P1 & KEY_PLUS == 0 ){

KeyDat |= 0x01 ;

}

if (P2 & KEY_MIN == 0 ){

KeyDat |= 0x02 ;

}

}

C语言应该很容易看懂吧?如果 KEY_PLUS 按下,P10口读到低电平,则 P1 & KEY_PLUS 的结果为 0 ,满足if 的条件,进入KeyDat |= 0x01 是将 KeyDat 的bit0 置一,也就是说,将 KEY_PLUS 映射到 KeyDat 的 bit0

KEY_MIN 是同样的道理映射到 KeyDat 的 bit1

如果 KeyDat 的 bit0 为 1 ,则说明 KEY_PLUS 按下,反则亦然。

不需要想的很神秘,映射就是这么一回事。如果还有其他按键的话,用同样办法,将他们全部映射到 KeyDat 上面。

2)驱动层程序编写

如果将 KeyDat想象成 P1 口,那么这个跟学习板那标准的扫描程序不就是一样了吗?对的,这个就是底层映射的目的了。

3)应用层程序编写

根据消息

硬件层是必须分离出来,然而驱动层和应用层的要求就不那么严格了,事实上一些简单的项目没有必要将这两层分离开来,根据实际应用灵活应对就可以了。其实这样写程序是很方便移植的,根据板子的不同而适当的修改一下硬件层那个 ReadPort 函数就完成了,驱动层和应用层很多代码可以不经过修改直接用,很能提高开发效率的。当然这个按键程序会存在一定的问题,特别是遇到常闭按键和点触按键的混合使用的场合。这个留给大家自己去想了,反正问题总是能找到解决办法的,尽管方法有好有坏。

结束语

以按键为媒介,介绍了程序设计当中的“分层屏蔽”的思想的原理和应用,按键只是一个例子,其实分层的思想普遍存在着程序设计当中。细心留意一下的话发现其实window,linux,网络的tcp/ip 结构全部都是分层的。这东西不是绣花枕头,而是实际用在工程上面的,只是平时不多见帖子介绍,或者没有人特意这样来总结,又或者是有经验的工程师作为藏在心中的法宝吧,这个就不得而知。不过好东西应该共享,菜鸟应该共勉,一起来学飞吧。

5 S0 g! g- m# F% }, k
1 q4 d: K' L+ j5 t2 ~+ Q" R' d

该用户从未签到

推荐
发表于 2021-5-31 15:57
如何学习单片机
: a; S( n; g! t4 m+ K* I) n前边提到过,单片机是一门实用技术,我们学习它已经不是为了应付考试了,我给大家总结了单片机的学习方法是:一个要领,四个步骤。
6 c$ `/ r0 ^- l6 A9 K: N% n3 U
学习单片机的要领就是:在实践中成长,In Doing We Learn!
4 Z* l) H4 q* j6 ~# u( N4 p6 l
' C+ C8 i( G3 E3 P1 f学射箭,你得去拉弓,整天只摆造型肯定不行;学游泳,你得下水扑腾,整天在岸上做模仿活动不行;学开车,你得坐车上去开,坐沙发上肯定学不会。同样的道理,学单片机,整天盯着单片机看肯定不行,你也必须得亲自动手去练。
6 I  G0 y& `, H1 q' J9 q( R3 [7 ~3 J  D6 f6 a$ a, z. ~7 a
没有不下水就学会游泳成为游泳健将的,没有不到车上练就能成为赛车手的,这点大家都清楚,可为什么总是那么多人学单片机的时候,总是要抱着一本书看呢。第一,我们小学中学甚至大学的学习模式都是如此,学什么东西主要都是靠看书;第二,很多人想实践不太清楚该怎么去实践。; r( V0 \5 D- m0 z* u% i
; W! t7 E1 r8 x  S% c
不是不让大家看书,而是看了一点以后,要马上去实践验证,然后再回头结合实践的结果,理解书上的内容。从这个地方,大家要得出一个结论来,就是在学实际技术过程中,和应付考试不同,书上的内容不需要你去硬性记忆,书是用来查的,不是用来记忆的。遇到问题,你学会翻书,知道该去哪里找,找到相关知识点,分析明白,领悟透彻即可,包括咱这本书也是一样,大家先看完一节课,然后马上就把这节课相应的实验做了,做实验的过程中,哪里有不懂的问题,随时翻阅书籍查找,再实验,再查找,反反复复的过程就可以把本节课的内容掌握。
0 o4 _4 d6 E! K$ O+ _$ K
1 m" g$ Y- g! y- O6 m下面,就是我总结的跟着我学习单片机的四个步骤。
1 h0 p3 T# t: ^( z$ [6 d5 w/ G7 s) h4 [5 ~
第一步,鹦鹉学舌。5 n' F( @- t" q9 q6 v; E& a, @& [# H
! `5 w& c7 x6 W7 k
刚出生的孩子叫“爸爸”“妈妈”的时候,他甚至不知道“爸爸”“妈妈”是什么意思,更不会理解这些声音是什么意思,但是我们带着孩子见到他爸爸就让他喊“爸爸”,见到妈妈就让他喊“妈妈”,见到爷爷就喊“爷爷”……慢慢的你会发现,次数多了,孩子就知道谁是爸爸,谁是妈妈,谁是爷爷,谁是奶奶了。/ a. c- P$ ?* o6 s% T: B, P( j% n6 y
$ b3 k) S) R9 C0 Q4 k5 g6 X# j
大家刚开始接触单片机的时候,也属于单片机行业的新生儿。单片机的样子,单片机外围的各种器件,单片机内部的各种结构,单片机用C语言的编程方法,初学者可能都没有见过。没关系,有些概念和方法你不理解也没有关系,甚至不需要你理解,你只需要跟着我去鹦鹉学舌式学习,第一遍学习某一节课的内容时,对于程序,大家就可以完全跟着抄下来,甚至抄两三遍,过一段你会发现,好多东西你也认识了,好多概念你慢慢的也理解清楚了,你也能大概看懂别人的小程序了,切忌觉得自己看会了,而简单复制粘贴。
1 J! K5 ~* ]1 {+ X! x
8 t, j7 z' [8 P  z' z- i, [% V第二步,照葫芦画瓢。# {$ g9 d( N/ e* t

3 @9 l/ l5 |1 u1 U. g" Z( }很多同学学习的时候喜欢看,看我做的视频,看我写的程序,甚至看别人的程序,都能看懂,觉得自己就会了,等到自己写程序的时候,感觉就是老鼠啃天,不知道从哪里下手了,这是初学者很容易犯的“眼高手低”这样一个毛病,所以第二步的内容就非常重要了。
0 G( y$ l4 n- ?) V
+ }  G4 [# v0 c' r# F( e5 P3 P我的要求是,每一位同学,在学完了当前课的内容,把第一步顺利完成以后,然后关掉视频教程,关掉源代码,自己通过看电路图和查找非源代码的其他任何资料,把当节课我写的程序代码重新默写出来,边写边多少理解那么一点点,不是纯粹的背诵,应该说是背诵加理解的结合体。甚至学过几节课以后,可以回头把前边曾经这样实现过的课程,再按照这种方法做一遍。千万不要认为这一步没必要,这一步是你能否学会单片机的一个关键步骤,在学完本教程之前,每一课内容都要这样做,如果每一个程序你都能够完美的完成,那么可以说,当节课的内容,百分之七八十你已经掌握了。
( h4 y3 H5 y2 @! t& w
1 |& O6 ?5 X8 D/ z& J第三步,他山之石可以攻玉。+ O8 q& N8 E. v) O
- h% [0 a) l+ I- d
单片机技术的最大特点就是可以通过修改程序来实现不同的功能,因此举一反三的能力就必不可少了。每一节课的例程后边,我一般都会布置一两个作业,大家尽量去独立完成这个作业。在完成这个作业的过程中,都可以参考我的程序思路,在这个基础上通过动脑思考去构建你自己的程序框架,最终将程序完成。
1 l- X2 F- c& K
  U  V" K0 c% [- r8 x2 G在我们工程师实际产品研发的时候,很多种情况下也是如此。比如一个产品,我们如果从0开始着手的话,可能会走很多弯路,所以我们通常的做法是寻找购买同类几款产品,然后先研究他们的各自优缺点,学习他们的长处,然后在同类产品基础上在来设计我们的产品,这就是他山之石可以攻玉。) J5 I7 E/ ^5 G6 L) m1 y9 b* R
+ e- {% j5 A1 i' T! j& x
初学者在学习的时候,往往遇到的问题很多,你应该想到,你遇到的问题,可能前辈们早就遇到过了,所以遇到问题后,不要慌张,首先利用谷歌或者百度这些搜索引擎搜索一下,要做什么新东西,先去网上找找相关资料了解一下,不管是编程还是硬件设计,多参考参考别人的东西,只要把别人的东西分析明白了,自己用起来,就可以成为自己的知识了。
% R7 L2 w! y7 n# I2 \8 k
% G% `$ K4 y! l3 I9 R& U/ E! P* B+ \2 Y第四步,理论实践结合,温故知新。
  D: x- m  x! W/ t9 h- ~, v
* k+ s' Q+ L1 ]% v当大家把所有的课程都按照前边三步完成后,这个时候不妨把书打开,看看书,通过自己实战的经验,再看书的时候,很多知识点会有一种恍然大悟的感觉。甚至视频教程,书籍,都可以反复看两遍,可能有的知识点当时学习的时候不明白,过了一段时间,回过头来再学习的时候,一下就明白了。

该用户从未签到

推荐
发表于 2021-5-28 16:48 | 只看该作者
程序设计是给出解决特定问题程序的过程,是软件构造活动中的重要组成部分。程序设计往往以某种程序设计语言为工具,给出这种语言下的程序。程序设计过程应当包括分析、设计、编码、测试、排错等不同阶段。专业的程序设计人员常被称为程序员。

该用户从未签到

推荐
发表于 2020-4-17 20:33 | 只看该作者
看看                           5 `0 m, N6 s2 d6 ~! q' O

该用户从未签到

5#
发表于 2019-9-4 15:54 | 只看该作者
说的不错,学习一下" @) @4 B1 e) I

该用户从未签到

6#
发表于 2019-9-5 00:22 | 只看该作者

该用户从未签到

8#
发表于 2019-9-23 09:47 | 只看该作者
感谢楼主的分享,希望楼主分享更多
  • TA的每日心情
    慵懒
    2020-6-15 15:38
  • 签到天数: 84 天

    [LV.6]常住居民II

    10#
    发表于 2019-10-3 09:45 | 只看该作者
    说的不错,学习一下

    该用户从未签到

    11#
    发表于 2019-10-3 10:53 | 只看该作者
    看看是不是真货
  • TA的每日心情
    慵懒
    2020-2-25 15:06
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    13#
    发表于 2019-10-7 14:21 | 只看该作者
    学习学习,共同进步。
    % |1 M3 }5 x5 u8 E- m) s
  • TA的每日心情
    奋斗
    2019-11-28 15:36
  • 签到天数: 2 天

    [LV.1]初来乍到

    14#
    发表于 2019-10-12 17:07 | 只看该作者
    谢谢分享经验

    该用户从未签到

    15#
    发表于 2019-10-18 15:26 | 只看该作者
    嘻嘻嘻嘻嘻错 的4 }' i& B, l* O

    该用户从未签到

    16#
    发表于 2019-10-29 08:18 | 只看该作者
    学习学习

    “来自电巢APP”

  • TA的每日心情
    慵懒
    2022-1-24 15:14
  • 签到天数: 30 天

    [LV.5]常住居民I

    17#
    发表于 2019-10-29 10:32 | 只看该作者
    学习一下           7 C+ G% x7 Z% Y# D+ q

    该用户从未签到

    18#
    发表于 2019-10-29 21:15 | 只看该作者
    我也想了解
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-6-22 03:04 , Processed in 0.093750 second(s), 25 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

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