1、在实际工程项目中,一个程序通常由许多子程序模块组成,每个模块实现一个特定的功能。在C语言中,这个模块由一个函数来表示。一个C程序一般由一个主函数和几个其他函数组成。主函数可以调用其他函数,其他函数也可以相互调用,但是其他函数不能调用主函数。在我们的51单片机程序中,还有一个中断服务函数,在相应的中断到来时自动调用,不需要也可以由其他函数调用。
2、函数调用的一般形式是:函数名(参数列表);函数名是需要调用的函数的名称,实参列表是根据实际需求传递给调用函数的参数列表。当不需要传递参数时,只保留括号,当传递多个参数时,参数之间要用逗号隔开。
3、那么我举个例子来看看函数调用在让程序结构更加连贯方面的作用。回顾图6-1所示的程序流程图和为实现它而编写的程序代码,这个主要功能的结构是比较复杂的。
【资料图】
4、很难一目了然的看到它的实现过程。那么如果我们用单独的函数来实现两个最重要的东西,数码管的——秒计数和动态扫描功能呢?看节目。
5、#包含reg52.h
6、sbit add r0=p1^0;
7、sbit addr 1=p1^1;
8、sbit addr 2=p1^2;
9、sbit addr 3=p1^3;
10、sbit enled=p1^4;
11、无符号char码LedChar[]={//数码管显示字符换算表。
12、0xC0、0xF9、0xA4、0xB0、0x99、0x92、0x82、0xF8、
13、0x80、0x90、0x88、0x83、0xC6、0xA1、0x86、0x8E
14、};
15、无符号烧焦buff[6]={//数码管的显示缓冲区,初始值为0xFF,保证启动时不亮。
16、0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x ff
17、};
18、void SecondCount();
19、void led refresh();
20、void main(){
21、ENLED=0;//使能U3,选择控制数码管。
22、addr 3=1;//因为ADDR0-2的值需要动态改变,所以不需要初始化。
23、TMOD=0x 01;//将T0设置为模式1。
24、TH0=0xFC//将初始值0xFC67赋给T0,时序为1 ms。
25、TL0=0x67
26、TR0=1;//开始T0
27、while (1){
28、If (TF0==1){ //判断T0是否溢出。
29、TF0=0;//在//T0溢出后,清除中断标志。
30、TH0=0xFC//并再次赋予初始值
31、TL0=0x67
32、SecondCount();//调用第二个计数函数
33、led refresh();//调用显示刷新函数
34、}
35、}
36、}
37、/*秒计数功能,每秒执行一次,并转换成数码管显示字符*/
38、void SecondCount(){
39、静态无符号整数计数=0;//记录T0中断的次数。
40、静态无符号长整型秒=0;//记录经过的秒数。
41、cnt//计数值增加1。
42、If (cnt=1000){ //判断T0是否溢出1000次。
43、CNT=0;//达到1000次后,计数值清零。
44、sec//第二次计数增加1。
45、ledbuff[0]=ledchar[sec];
46、ledbuff[1]=ledchar[sec/10];
47、led buff[2]=ledchar[sec/100];
48、ledbuff[3]=ledchar[sec/1000];
49、led buff[4]=ledchar[sec/10000];
50、ledbuff[5]=ledchar[sec/100000];
51、}
52、}
53、/*数码管动态扫描刷新功能*/
54、void LedRefresh(){
55、静态无符号字符I=0;//动态扫描的索引
56、开关(i){
57、情况0:addr 2=0;addr 1=0;add r0=0;我;P0=led buff[0];打破;
58、情况1:addr 2=0;addr 1=0;add r0=1;我;P0=led buff[1];打破;
59、情况二:addr 2=0;ADDR1=1add r0=0;我;P0=led buff[2];打破;
60、情况三:addr 2=0;ADDR1=1add r0=1;我;P0=led buff[3];打破;
61、情况四:addr 2=1;addr 1=0;add r0=0;我;P0=led buff[4];打破;
62、情况5:addr 2=1;addr 1=0;add r0=1;I=0;P0=led buff[5];打破;
63、默认:break
64、}
65、}
66、我们来看看主函数的结构是不是清晰很多。——每1 ms做两件事,至于这两件事是什么,就让它们各自的功能来实现吧。还请注意一点:原程序
67、I,cnt,sec都添加了静态关键字,放入单独的函数后成为静态变量。因为原版
68、Main()永远不会结束,所以它们的值总是被保留,但是现在它们在各自的函数中,比如没有static。
69、修饰符以便每次调用函数时,其值都成为初始值,从而加深对静态变量的理解。当然,这是对程序功能的刻意划分,主要目的是解释函数的调用。对于这个程序,即使不划分功能,也并不复杂,但是如果继续学习,你就会明白划分功能函数的必要性。现在重点学习函数调用,有以下几点需要注意:1)调用函数时,不需要添加函数类型。我们在main函数中调用SecondCount()和LedRefresh(),不添加void。
70、2)调用函数与贝调用函数的关系,C
71、语言规定函数在被调用之前必须被定义或声明。这就意味着:在一个文件中,一个函数要先定义,然后才能调用,也就是调用函数要位于调用函数之下。
72、方。但是作为一般的编程规范,我们推荐main。
73、函数写在最前面(因为起大纲作用),然后定义每个函数函数,而中断函数写在文件的最后。那么如果主函数调用在它之后定义的函数呢?我们
74、在文件的开头,所有函数定义之前,打开一个叫做函数声明区的区域来声明被调用的函数,这样就可以随意调用函数了。如上面的例程所示。3)
75、在声明函数时,必须添加函数类型,函数的形参,最后加上分号表示结束。函数声明行和函数定义行唯一的区别是最后一个分号,其他的都必须一致。这
76、请特别注意。初学者很容易犯分号错误或者修改了定义行的形参却因为粗心忘记修改声明行的形参,导致程序编译失败。
本文到此结束,希望对大家有所帮助。
X 关闭
2022年中国家电行业一季度报告:国内累计销售额1540亿元
31省份新增本土确诊病例2971例、本土无症状感染者21355例
南方强降雨再起 北方周末暖热回归
南方地区将有明显降水过程 黄海南部海域有大雾
吴谢宇弑母案二审因“不可抗拒原因”中止审理
X 关闭
240余万吨!国家电投内蒙古公司圆满完成民生供暖煤供应工作
厨电行业逆势增长 集成洗碗机是集成灶行业的下一个风口吗?
梦天家居2021年度净利润1.83亿元 同比增长7.04%
亚振家居发布2021年年度亏损公告 营业收入同比下降11.53%
盾安环境9.71%股份转让悬而未决 一致行动人抛出减持计划