eydj2008
发表于 2014-5-16 20:52
期待更新。。。呵呵 讲讲后面程序应该怎么写,我们该用什么语言来完成想要的功能。
yklstudent
发表于 2014-5-16 21:25
mark期待楼主大作别让小弟失望啊
dong_abc
发表于 2014-5-17 01:38
跟着学习,电子出身,代码功底实在太弱!
这么多年都难以突破!
keer_zu
发表于 2014-5-17 08:06
本帖最后由 keer_zu 于 2014-5-17 08:59 编辑
从前面的分类看,C怎么也是3代以后的语言(1970-1980)。再看一下我前面的例子中我和我同事的代码,几乎就是第一代和第二代
早期语言写程序的特点(看16楼图):1.几乎很少使用参数传递,所有子程序几乎全部依靠共有全局变量来传递数据。2.共享全局变量带来的交叉耦合让这个代码调试起来非常费劲,因为每个函数都不是独立的,它依赖自身使用的大量全局变量。在MCU上,因为中断函数带来的并发性,如果有全局变量在中断内外都用到,那就会带来很多麻烦。这样的代码如果在多任务环境中将会更糟糕。3.再看看可读性,大量全局变量和全局标志位让代码的可读性非常差:首先是如此之多的变量和标志位所要表达的意图,再者他们分散得到处都是,即使不考虑并发性也让阅读的人摸不到头脑。4.看看扩展性和可维护性,如果有bug被测出,你定位问题将是极其困难的,因为这里的子程序没有内聚性,功能不独立,再加上可读性差,情况非常糟糕。如果要添加新功能,也是一件极其麻烦的事情,牵一发而动全身,要改的地方太多了。这样的编程方式也无法将项目做大。
你有这样的经历吗?刚开始做单片机的差不多都是这样的思维吧,除非之前有过其它领域的C开发经验。
keer_zu
发表于 2014-5-17 08:26
本帖最后由 keer_zu 于 2014-5-17 09:00 编辑
为什么三代以后的语言写的程序出现了二代前期以前的特点?我们可以将它称作“语言的返祖现象”(这个将在后边专门讨论,这个概念可是咱首次提出的哦,哈哈,臭美一下),说明一个问题:每一代语言的开发者都是针对当时成熟而又先进的软件思想完成的,它里面支持他所要实现的那种编程思想所具备的大部分特征。但是如果使用者自己没有理解这种新的思想,而不使用这些新的特征,就会出现这种“返祖”现象,就像我身边很多人使用C++的时候,完全是用C的思维在编程,那些面向对象的特征完全成了他们的限制,这也算是“返祖现象”,哈哈。
既然你发现了它的缺陷,既然你已经知道它的‘错’在哪里,那问题可以得到解决了吧!问题怎么解决,如何改进?别着急!接下来我们将会看语言的下一次革新,还会附上下一阶段的代码做为实例。我简直就是一部活生生的发展史了,哈哈
cbaax
发表于 2014-5-17 08:30
先收藏 坐等楼主连载
reposemind
发表于 2014-5-17 08:40
不错,有实践,有思考
likezk
发表于 2014-5-17 09:35
同样的感受啊,我的编程思路也是这么一步步升级过来的。从最初的全局变量满天飞,到后来的的功能划分,参数传递,再到后来的文件划分,接口驱动和应用部分分离。其中的一步步变化,都有着自己的所感所悟。不可否认,这种变化,也是伴随着器件的升级,也算是一种与时俱进吧。
你不可能在89c51的片子上用那么多的参数传递,毕竟ram有限,参数传递会降低效率,浪费空间,直接用全局变量,省时省力。后来在avr上,上K的RAM空间,有了奢侈的感觉。再后来的ARM,ram已经不再是瓶颈了。随着MCU工作频率的提升,程序规模的扩大,我们的关注点从如何节省一个字节的ram,转移到了如何保证程序的可读性,易扩展性上了。
yao1318
发表于 2014-5-17 09:46
收藏了,等着下会分解!
lh18753385
发表于 2014-5-17 09:46
mark
hwl1023
发表于 2014-5-17 11:17
期待楼主大作
keer_zu
发表于 2014-5-17 11:24
likezk 发表于 2014-5-17 09:35 static/image/common/back.gif
同样的感受啊,我的编程思路也是这么一步步升级过来的。从最初的全局变量满天飞,到后来的的功能划分, ...
确实如此,大家是在与时俱进的。现在那种存储空间小的早期架构MCU成本上已经没有任何优势,而32位且存储空间一直才扩大的新架构价格一降再降,当年为了应对受限资源所做的特殊化处理今天越来越没有意义,为了应对这种有限资源所做的纯粹代码上的技巧已经越来越边缘化,条件已经允许我们回归正途了。。。
elec921
发表于 2014-5-17 12:22
只写MCU-C的同事,学过了C++,或者C#或者其他的一门语言,会尝试改变原先的思路
intermec
发表于 2014-5-17 18:43
坐等听课~~~要是多些例子就好了,,
keer_zu
发表于 2014-5-17 19:32
插播【基础知识普及】
软件固有特性:复杂性等问题
【软件固有的复杂性】
* 问题域的复杂性 :
—— 非功能性需求(可用性,健壮性,成本,性能等)的加入。
—— 开发人员同用户之间沟通的困难。
—— 设计过程中的需求变更。
* 管理开发过程的困难性
* 软件中随处可见的灵活性
—— 这直接导致了软件开发领域不能像其他领域,可以对每个构件给出一个行业标
准,比如机械制造行业,软件行业却很少能如此。这导致开发者需要打造大部分
模块。
* 描述离散系统行为的问题
—— 无法用连续系统建模的方式,本身也不受物理规律支配。
【复杂系统的5个属性】
* 层次性:可以逐级划分子系统。
* 相对本原:不同观察者对同系统组件的本原性认识不同。
* 分离关注:根据“组件”内部之间关联程度高于“组件”间外部关联程度来划分组件。
* 共同模式:如细胞,管脉系统在动物和植物中都有。
* 稳定的中间形式: 复杂系统是演化而来的,曾经的‘复杂系统’或其他‘复杂系统’变成基
本组成。
【复杂系统的规范形式】
* 复杂系统的两种构成层次:1. 组成部分(Part of) 2. 是一种(Is a)
【控制复杂性的技巧】控制复杂性的核心技巧:分而治之* 算法分解 (自顶向下的结构化设计)强调了事件的顺序。* 面向对象的分解 : 强调了一些代理。
xiaopingt
发表于 2014-5-18 09:38
在嵌入式系统设计中,要充分体现各个功能模块的独立性。如果功能模块已经成功运用,下次拿来用就是,基本不需要再调试。用预编译实现,#if
#else,#endif.
xiaopingt
发表于 2014-5-18 09:42
在嵌入式系统编程中,一定要有编程的基本规范。多看看高手编程的习惯,你的水平才能提高!
loliweive
发表于 2014-5-18 09:50
长期关注楼主更新,,,过来人的经验对后来人是最有参考价值的。感谢!
keer_zu
发表于 2014-5-18 18:29
如果把之前的代码比作旧石器时代,接下来就是新石器时代了。
在开始分析07年的代码之前,先科普一下:
【普及基础知识】
第二代和第三代前期程序设计语言的程序结构:
和图2-1相比有不同吗?对了。子程序不再那么单一,它有了嵌套的结构。看看这个时期引入了什么特点:1.子函数调用支持嵌套。2.支持各种参数传递。3.程序拥有更丰富的控制结构。4.声明的可见性范围多样化。如全局变量和函数内部的局部变量。这个时候开始出现结构化程序设计。
keer_zu
发表于 2014-5-18 18:33
这个是07年,我管这个时期叫做:
【新石器时代】
这是07年中的一个研发项目,是一个电力抄表终端,下面代码是他的液晶显示屏(128x64)的菜单部分。
代码有点长,先看头文件:
menu.h
#include"display_leaf.h" //定义了显示叶子的函数
//字模数组
extern root_canshu[],root_shuju[],root_zhuangtai[],exit[],zhongduancanshu[],fukongcanshu[],celiangdian0[],
celiangdian0canshu[],celiangdian1canshu[],
celiangdian1[],celiangdian2[],celiangdian3[],zhongduanzhuangtai[],zhuzhantongxin[],fuhekongzhi[]
,tongxincanshu[],gaojingcanshu[],duankoucanshu[],biaoxieyi[],jibencanshu[],gongkongcanshu[]
,diankongcanshu[],dianzijishu[],biaojitongxin[],gongkongfangan[],diankongfangan[],diannengliang[],
xuliang[],shunshiliang[],huanyingshiyong[],celiangdian0shuju[],celiangdian1shuju[],celiangdian2shuju[],celiangdian3shuju[];
//--------------------------------------------------------------------------
//-------------------------------------------
//子界面编号数组
//-------------------------------------------
unsigned char Son0 ={1}; //对应界面0
unsigned char Son1 ={2,3,4,0};
unsigned char Son2 ={5,6,7,8,1};
unsigned char Son3 ={9,10,11,12,1};
unsigned char Son4 ={55,56,57,58,1};
unsigned char Son5 ={31,32,33,34,2};
unsigned char Son6 ={35,36,37,38,2};
unsigned char Son7 ={39,40,2};
unsigned char Son8 ={41,42,2};
unsigned char Son9 ={43,44,45,3};
unsigned char Son10 ={46,47,48,3};
unsigned char Son11 ={49,50,51,3};
unsigned char Son12 ={52,53,54,3};
//*****************
//以下是增加的叶子
//*****************
//-----------------------------------------------------------
//各个界面显示内容指针数组
//-----------------------------------------------------------
unsigned char *menu_char0={huanyingshiyong};
unsigned char *menu_char1={root_canshu,root_shuju,root_zhuangtai,exit}; //各元素枝指向对应行显示内容的字模数组
unsigned char *menu_char2={zhongduancanshu,fukongcanshu,celiangdian0canshu,celiangdian1canshu,exit};
unsigned char *menu_char3={celiangdian0shuju,celiangdian1shuju,celiangdian2shuju,celiangdian3shuju,exit};
unsigned char *menu_char4={zhongduanzhuangtai,zhuzhantongxin,biaojitongxin,fuhekongzhi,exit};
unsigned char *menu_char5={tongxincanshu,gaojingcanshu,duankoucanshu,biaoxieyi,exit};
unsigned char *menu_char6={jibencanshu,gongkongcanshu,diankongcanshu,gongkongfangan,exit};
unsigned char *menu_char7={jibencanshu,gaojingcanshu,exit};
unsigned char *menu_char8={jibencanshu,gaojingcanshu,exit};
unsigned char *menu_char9={diannengliang,xuliang,shunshiliang,exit};
unsigned char *menu_char10={diannengliang,xuliang,shunshiliang,exit};
unsigned char *menu_char11={diannengliang,xuliang,shunshiliang,exit};
unsigned char *menu_char12={diannengliang,xuliang,shunshiliang,exit};
//-----------------------------------------------------------
// 各行文字数量
//-----------------------------------------------------------
unsigned char char_num0 = {4};
unsigned char char_num1 = {2,2,2,2};
unsigned char char_num2 = {4,4,6,6,2};
unsigned char char_num3 = {6,6,6,6,2};
unsigned char char_num4 = {4,4,4,4,2};
unsigned char char_num5 = {4,4,4,3,2};
unsigned char char_num6 = {4,4,4,4,2};
unsigned char char_num7 = {4,4,2};
unsigned char char_num8 = {4,4,2};
unsigned char char_num9 = {3,2,3,2};
unsigned char char_num10 = {3,2,3,2};
unsigned char char_num11 = {3,2,3,2};
unsigned char char_num12 = {3,2,3,2};
//-----------------------------------------------------------
struct INTERFACE
{
//当前行号对应子菜单编号,和反显行,对于不需要反显示的无意义
//行号在每次进入新的界面时清零
unsigned char MAX_ROW_NUM; //该界面的最大行数
unsigned char **MENU_char; //指向一指针数组,该数组元素为指向各行显示内容的指针
unsigned char *Son_num; //指向当前界面子界面编号数组的指针
unsigned char *Row_num; //指向当前界面各行文字数量数组的指针
};
struct INTERFACE Windows =
{
{1,menu_char0,Son0,char_num0},
{4,menu_char1,Son1,char_num1},
{5,menu_char2,Son2,char_num2},
{5,menu_char3,Son3,char_num3},
{5,menu_char4,Son4,char_num4},
{5,menu_char5,Son5,char_num5},
{5,menu_char6,Son6,char_num6},
{3,menu_char7,Son7,char_num7},
{3,menu_char8,Son8,char_num8},
{4,menu_char9,Son9,char_num9},
{4,menu_char10,Son10,char_num10},
{4,menu_char11,Son11,char_num11},
{4,menu_char12,Son12,char_num12}
};
//叶子节点的数据结构
struct LEAF
{
unsigned char Father_num; //该叶子要返回的父亲界面号
void (*Display_leaf)(); //指向该叶子的显示函数的指针
};
struct LEAF leaf =
{
{5,display_tongxincanshu}, {5,display_gaojingcanshu},
{5,display_duankoucanshu}, {5,display_biaoxieyi},
{6,display_jibencanshu}, {6,display_gongkongcanshu},
{6,display_diankongcanshu}, {6,display_gongkongfangan},
{7,display_cljibencanshu}, {7,display_clgaojingcanshu},
{8,display_cljibencanshu}, {8,display_clgaojingcanshu},
{9,display_diannengliang}, {9,display_xuliang},
{9,display_shunshiliang}, {10,display_diannengliang},
{10,display_xuliang}, {10,display_shunshiliang},
{11,display_diannengliang}, {11,display_xuliang},
{11,display_shunshiliang}, {12,display_diannengliang},
{12,display_xuliang}, {12,display_shunshiliang},
{4,display_zhongduanzhuangtai}, {4,display_zhuzhantongxinzhuangtai},
{4,display_biaojitongxinzhuangtai},{4,display_fuhekongzhizhuangtai}
};
//-----------------------------------------函数--------------------------------------------------
void Display_char(unsigned char,unsigned char ,unsigned char *,unsigned char);
void Display_row(unsigned char,unsigned char ,unsigned char ,unsigned char *,unsigned char);
void Display_window(unsigned char,unsigned char);
//