我的代码简史:楼主从单片机coder到嵌入式programer的简单历程
之前和大家谈了一点UML在嵌入式开发中的使用,以及链表、哈希表等数据结构在实现对象之间的交互机制(设计模式)的一点简单实例。有很多朋友表示很感兴趣,21ic高手云集,有点班门弄斧的感觉,所以还望尽情拍砖。之前的帖子很乱,除了因为太随意没有准备外,更主要是因为本人也处于半瓶子阶段,所谈问题题目又太大。对此我只能凭借拙见,谈点个人的理解,由于本人是这方面的新手,凭借一己之热情,大放厥词,还请各位斧正。其实UML就是一个工具,提供了用例图、顺序图、活动图、类图、状态机图、部署图、包图等工具,辅助工程师完成:分析->设计->实施->测试的整个过程。每个过程都有细分,例如分析阶段:首先是需求分析,然后有系统分析,再次有对象结构分析等。需求分析阶段会使用到用例图、顺序图、状态机图、顺序图等,需求分析阶段的最重要的要素是软件的外部功能视图和使用场景等。其中前者使用用例图表述,它也提供了沟通用户和开发者的桥梁;后者用顺序图或状态机图等表述,提供了系统每个功能实现的可能路径。其他过程和需求分析阶段类似,这里篇幅所限就不再一一提及。UML就是这样同我们的设计过程关联起来的。
将面向对象的方法用于MCU是有必要的,也是可能的,当然也是很有效的。这样的努力最起码可以拉近mcu开发者同其他领域的C开发者之间的距离,弥补那道似乎难以逾越的鸿沟,比如看到linux内核代码时,你会发现原来如此亲切。当然,随着对面向对象方法的深入理解,你会发现C++也不再那么让你不知道如何使用,或者把C++用得像面向过程的语言一样。当然本人C++菜鸟,还望高手指教。
然而面向对象的方法也非一蹴而就,一朝搞定,它是一个循序渐进的过程,特别是应用与mcu这样的平台,好多东西是靠摸索出来的。如何开始,先从何处下手是个问题。
21ic同仁liufb提议:“正如《重构与模式》所说:如果想成为一名更优秀的软件设计师,了解优秀软件设计的演变过程比学习优秀设计本身更有价值,因为设计的演变过程中蕴藏着大智慧。”
我决定发掘一下我近十年以来的阶段性C代码,试图去发现一点什么,这个我之前还从未尝试过,能找到的一起的代码也寥寥无几。不过我觉得值得一试,那就从此开始吧。 先从发掘旧代码开始吧。版主,给个裤子鼓励一下吧。我要连载。
当然我也在探索,我会尝试从不同视角去说明这个题目。。。。。。一步一步来吧。 赞一个,可惜我没有这个板块加酷的权限 前排占座
看看能不能有对象 围观 坐等楼主继续 努力发掘,搜索N年前的邮箱,居然找到了当时在一款AT89X52单片机上的处女作。就从它开始入手了。
时代背景:2006年,郑州某小公司,之前的工作是修手机,然后是在某气体传感器公司焊接维护生产设备,再后来在这家小公司画电路板,然而软件才是我的最爱。好不容易boss开恩,让我参与到写代码的行列。之前的进度让在郑州这种蜗牛般的工作节奏的大氛围里面的boss也觉得忍无可忍,于是我加入了。哈哈
代码太长,截取一部分吧。里面只有我写的一个子函数,大部分是同事写的。
本帖最后由 keer_zu 于 2014-5-16 15:30 编辑
代码太长,截取一部分吧。里面只有我写的一个子函数,大部分是同事写的。由于做开始工作的同事不太会用多文件,所以这个项目的代码只有一个文件,连头文件都没有,整个文件有2600行代码。以下我将列举它的三大部分:
1.全局变量部分。
2.部分子函数。
3.main函数。
最后我将会用现在的眼光,结合大师(Grady Booch)的经典,分析一下这部分代码。 本帖最后由 keer_zu 于 2014-5-16 15:34 编辑
全局变量部分:bit FUN,Shift_on,Add_on,Sub_on,fun_flag;bit dspflagz1,dspflagz2,dspflagz3;unsigned char z1,z2,td3,working,DSP_m,DSP_n;unsigned char l1,l2,r,m;bitflagv,flagy,flags,flag0,flagx,beepflag1,beepflag2,flagt,flagw;bit working_on,function_on, AINTSYR_on,AINTSYW_on,BINTSYR_on,BINTSYW_on ;bitprogram_on,program_woking,up_flag,down_flag,up_on,down_on;unsigned char AINTSY_state, BINTSY_state, function_state;unsigned char tx1,tx2,tx3,tw,TX,t;unsigned char display_state ,x1,x2,w1,w2;unsigned char program_state,program_working;unsigned char clk_number;unsigned char code DS[]={0,33,63,86,100,86,63,33};unsigned chards_curtime={0x05,0x03,0x02,0x01,0x07,0x06};unsigned char clk_data={06,1,1,0,0,1};unsigned char set_time; sbit switch_work= 0xB0;sbit switch_function=0xB1;sbit switch_program=0xB2;sbit switch_up=0x90;sbit switch_down=0x91;sbit switch_AINTSYR=0x92;sbit switch_AINTSYW=0x93;sbit switch_BINTSYR=0x94;sbit switch_BINTSYW=0x95;sbit RS=0xA2;sbit RW=0xA1;sbitE=0xA0;sbit CS2=0xA3;sbit CS1=0xA4;sbit DACS1=0xA7;sbit DACS2=0xA6;sbit DACS3=0xA5;sbit ds_sclk=0xB3 ; /*初始化变量*/sbit ds_io=0xB4;sbit ds_rst=0xB5; 初评:除了最后是管脚定义外,前边都是全局的标志位或全局变量。 本帖最后由 keer_zu 于 2014-5-17 08:51 编辑
这个 void text(void)可是我的处女作啊
//////////////////////////////////////////////////////////////////////////////////////////////////////
void text(void)
{
bit Flag_add; /*加一标志*/
bit Flag_sub; /*减一标志*/
unsigned char max_value; /*各时间单位的最大值*/
unsigned char min_value; /*各时间单位的最小值*/
/*if(FUN==1)
{ */ /*定义标志位*/
if(switch_work==0) /*移位键*/
{
if(Shift_on==0)
{
Shift_on=1;
buzzer();
clk_number++;
if(clk_number>6)clk_number=1;
}
}
else
Shift_on=0;
if(switch_up==0) /*加一键*/
{
if(Add_on==0)
{
Add_on=1;
buzzer();
Flag_add=1;
}
}
else
Add_on=0;
if(switch_down==0) /*减一键*/
{
if(Sub_on==0)
{
Sub_on=1;
buzzer();
Flag_sub=1;
}
}
else
Sub_on=0;
switch(clk_number)
{
case 1: max_value=99;min_value=0;break;
case 2: max_value=12;min_value=1;break;
case 3: if(clk_data==1||
clk_data==3||
clk_data==5||
clk_data==7||
clk_data==8||
clk_data==10||
clk_data==12)
max_value=31; /*1,3,5,7,8,10,12*/
else if(
clk_data==4||
clk_data==6||
clk_data==9||
clk_data==11)
max_value=30; /*4,6,9,11*/
else if((clk_data%4==0)||clk_data==0)
max_value=29; /*闰年*/
else
max_value=28;
min_value=1;
break;
case 4: max_value=23;min_value=0;break;
case 5: max_value=59;min_value=0;break;
case 6: max_value=7;min_value=1;break;
}
if(Flag_add==1)
{
clk_data++;
Flag_add=0;
if(clk_data>max_value)
clk_data=min_value;
}
else if(Flag_sub==1)
{
clk_data--;
Flag_sub=0;
if(clk_data<min_value||clk_data==0xff)
clk_data=max_value;
}
if(switch_function==0)
{
if(function_on==0)
{
function_on=1;
FUN=0;
buzzer();
function_state=1;
fun0_flag=1;
set_time=(clk_data/10)*0x10+(clk_data%10);
set_time=(clk_data/10)*0x10+(clk_data%10);
set_time=(clk_data/10)*0x10+(clk_data%10);
set_time=(clk_data/10)*0x10+(clk_data%10);
set_time=(clk_data/10)*0x10+(clk_data%10);
set_time=(clk_data/10)*0x10+(clk_data%10);
}
}
else
{
function_on=0;
}
}
注:上面这个函数是我在51里面跑过的第一段代码,很有收藏价值,哈哈
//////////////////////////////////////////////////////////////////////////////////////////////////////
下边是我同事的一个函数,女工程师,女中豪杰,哈哈
//////////////////////////////////////////////////////////////////////////////////////////////////////
void check_switch()
{
if(FUN==0)
{
if(switch_work==0)
{
if(working_on==0)
{
working_on=1;
buzzer();
if(working==1)
{
working=0;
flag0=0;
}
else
{
working=1;
flag0=1;
}
}
}
else
{
working_on=0;
}
if(switch_function==0)
{
if(function_on==0)
{
function_on=1;
buzzer();
program_state=1;
if(function_state==1)
{
function_state=2;
}
else
{
if(function_state==2)
{
function_state=3;
}
else
{
if(function_state==3)
{
function_state=4;
FUN=1;
fun1_flag=1;
working=0;
flagx=1;
}
else
{
function_state=1;
}
}
}
}
}
else
{
function_on=0;
}
if(switch_program==0)
{
if(program_on==0)
{
program_on=1;
buzzer();
program_working=1;
flagv=1;
flagy=1;
flagt=1;
flagw=1;
}
}
else
{
program_on=0;
}
if(switch_up==0)
{
if(up_flag==0)
{
up_flag=1;
up_on=1;
buzzer();
}
}
else
{
up_flag=0;
}
if(switch_down==0)
{
if(down_flag==0)
{
down_flag=1;
down_on=1;
buzzer();
}
}
else
{
down_flag=0;
}
if(switch_AINTSYR==0)
{
if(AINTSYR_on==0)
{
AINTSYR_on=1;
buzzer();
if(AINTSY_state<=63)
{
AINTSY_state=AINTSY_state+1;
}
}
}
else
{
AINTSYR_on=0;
}
if(switch_AINTSYW==0)
{
if(AINTSYW_on==0)
{
AINTSYW_on=1;
buzzer();
if(AINTSY_state>=1)
{
AINTSY_state=AINTSY_state-1;
}
}
}
else
{
AINTSYW_on=0;
}
if(switch_BINTSYR==0)
{
if(BINTSYR_on==0)
{
BINTSYR_on=1;
buzzer();
if(BINTSY_state<=63)
{
BINTSY_state=BINTSY_state+1;
}
}
}
else
{
BINTSYR_on=0;
}
if(switch_BINTSYW==0)
{
if(BINTSYW_on==0)
{
BINTSYW_on=1;
buzzer();
if(BINTSY_state>=1)
{
BINTSY_state=BINTSY_state-1;
}
}
}
else
{
BINTSYW_on=0;
}
}
else
{
text();
}
}
初评:注意到没有,几乎没有用到参数传递,整个代码所有数据全是通过全局变量传递的。这个我将在后边做出分析。 最后是main函数:
void main()
{
init_working();/*初始化程序*/
start_t0:check_switch();
prepare_work();
if(fun0_flag==1){
ds_settime(set_time);
}
display();
goto start_t0;
}
呵呵,粗略看了下,大概是根据按键来调整时间的功能。
用了大量的标志来防止一次按下,多次响应的问题。第一次写代码能够写成这样,还是非常棒的。
期待后续。不过MAIN函数里面用goto 而不是用循环,有点费解,楼主最开始学的汇编吗? 咋沒有註釋啊 红金龙吸味 发表于 2014-5-16 16:06 static/image/common/back.gif
呵呵,粗略看了下,大概是根据按键来调整时间的功能。
用了大量的标志来防止一次按下,多次响应的问题。第 ...
除了那个Text()剩下都是别人写的 站在巨人的肩上才能看得更远,先找一个这样的肩膀吧。从关于代码演变的基础知识说起:
【基础知识普及】
Wegner将早期高级语言做了分类:
以上内容摘自GradyBooch《面向对象:分析与设计》 扩展一下Wegner的分类:
以上内容摘自Grady Booch《面向对象:分析与设计》
接下来看一下第一代和第二代早期程序设计语言的程序结构:
特点:
1. 所有子程序共用全局数据。
2. 共用数据带来大量交叉耦合。
3. 大量的标志位或者数据定义很难读懂它到底代表什么意思。 期盼|| 楼主代码贴太多了,会影响读者的 不错,我第一次写的流水灯代码都找不到了 哈哈哈 电子无聊大神 发表于 2014-5-16 19:19 static/image/common/back.gif
不错,我第一次写的流水灯代码都找不到了 哈哈哈
没有了 , 大侠?