1. <em id="3qmea"><ol id="3qmea"></ol></em>
    2. <em id="3qmea"></em>
      中国领先的单片机及嵌入式资讯教程开发工具提供者!
      当前位置单片机教程网 >> 基础教程 >> 浏览文章

      第十四课 C51函数

      作者:佚名   来源:本站原创   点击数:  更新时间2007年07月14日   字体

      上一篇的最后一个例子中有用到函数其实一直出现在例子中的  main()也算是一个函数只不过它比较特殊编译时以它做为程序的开始段有了函数 C 语言就有?#22235;?#22359;化的优 点一般功能较多的程序会在编写程序时把每项单独的功能分成数个子程序模块每个子 程序就能用函数来实现函数还能被反复的调用因此一些常用的函数能做成函数库 以供在编写程序时直接调用从而更好的实现模块化的设计大大提高编程工作的效率 一函数定义

      通常 C 语言的编译器会?#28304;?#26631;准的函数库这些都是一些常用的函数Keil uv 中也不 例外标准函数已由编译器软件商编写定义使用者直接调用就能了而无需定义但是 标准的函数不足?#26376;?#36275;使用者的特殊要求因此 C 语言允许使用者根据需要编写特定功能的 函数要调用它必须要先对其进行定义定义的模式如下

      函数类型    函数名称形式参数表

      函数体

      函数类型是说明所定义函数返回值的类型返回值其实就是一个变量只要按变量

      类型来定义函数类型就行了如函数不需要返回值函数类型能写作void表示该函数没 有返回值注意的是函数体返回值的类型一定要和函数类型一致不然会造成错误函数名 称的定义在遵循 C 语言变量命名规则的同时不能在同一程序中定义同名的函数这将会造成 编译错误同一程序中是允许有同名变量的因为变量有全局和局部变量之分形式参数 是指调用函数时要传入到函数体内参与运算的变量它能有一个几个或没有当不需要 形式参数也就是无参函数括号内能为空或写入void表示但括号不能少函数体中 能包含有局部变量的定义和程序语句如函数要返回运算值则要使用 return 语句进行返 回在函数的号中也能什么也不写这?#32479;?#20102;空函数在一个程序项目中能写一些 空函数在以后的修改和升级中能方便的在这些空函数中进行功能扩充

      二函数的调用

      函数定义好以后要被其它函数调用了才能被执?#23567;C 语言的函数是能相互调用的 但在调用函数前必须对函数的类型进行说明就算是标准库函数也不例外标准库函数的 说明会被按功能?#30452;?#20889;在不一样的头文件中使用时只要在文件最前面用#include  预处理语 句引入相应的头文件如前面一直有使用的 printf 函数说明就是放在文件名为 stdio.h 的 头文件中调用就是指一个函数体中引用另一个?#35759;?#20041;的函数来实现所需要的功能这个时候函 数体称为主调用函数函数体中所引用的函数称为被调用函数一个函数体中能调用数个 其它的函数这些被调用的函数同样也能调用其它函数也能嵌套调用笔者本人认为 主函数只是相对于被调用函数而言在 c51 语言中有一个函数是不能被其它函数所调用的 它就是 main 主函数调用函数的一般形式如下:

      函数名  (?#23548;?#21442;数表) 函数名?#26412;?#26159;指被调用的函数?#23548;?#21442;数表能为零或多个参数多个参数时要用逗

      号隔开每个参数的类型位置应与函数定义时所的形式参数一一对应它的作用就?#21069;?#21442; 数传到被调用函数中的形式参数如果类型不对应就会产生一些错误调用的函数是无参函 数时不写参数但不能省后面的括号

      在以前的一些例子我们也能看不一样的调用方式

      1函数语句


      如  printf  ("Hello  World!\n"); 这是在 我们的第一个程序中出现的它以 "Hello

      World!\n"为参数调用 printf 这个库函数在这里函数调用被看作了一条语句

      2函数参数 函数参数这种方式是指被调用函数的返回值当作另一个被调用函数的?#23548;?#21442;

      数如 temp=StrToInt(CharB(16));CharB 的返回值作为 StrToInt 函数的?#23548;?#21442;数传递

      3函数表达式

      而在上一篇的例子中有 temp = Count();这样一句这个时候函数的调用作为一个运算 对象出现在表达式中能称为函数表达式例子中 Count()返回一个 int 类型的返回 值直接赋值给 temp注意的是这种调用方式要求被调用的函数能返回一个同类型的值 不然会出现不可预料的错误

      前面说到调用函数前要对被调用的函数进行说明标准库函数只要用#include  引入已 写好说明的头文件在程序就能直接调用函数了如调用的是自定义的函数则要用如下形 式编写函数类型说明

      类型标识符    函数的名称(形式参数表); 这样的说明方式是用在被调函数定义和主调函数是在同一文件中你也能把这些写到

      文件名.h 的文件中用#include "文件名.h"引入如果被调函数的定义和主调函数不是在同 一文件中的则要用如下的方式进行说明说明被调函数的定义在同一项目的不一样文件之上 其实库函数的头文件也是如此说明库函数的如果说明的函数也能称为外部函数

      extern    类型标识符    函数的名称(形式参数表); 函数的定义和说明是完全不一样的在编译的?#23884;?#19978;看函数的定义?#21069;?#20989;数编译存放在

      ROM  的某一段地?#39134;ϣ?#32780;函数说明是告诉编译器要在程序中使用那些函数并确定函数的地 址如果在同一文件中被调函数的定义在主调函数之前这个时候能不用说明函数类型也就 是说在 main 函数之前定义的函数在程序中就能不用写函数类型说明了能在一个函 数体调用另一个函数嵌套调用但不允许在一个函数定义中定义另一个函数还要注意 的是函数定义和说明中的类型形参表名称等?#23478;?#30456;一致

      三中断函数 中断服务函数是编写单片机应用程序不可缺少的中断服务函数只有在中断源请求响应

      中断时才会被执行这在处理突发事件和实时控制是十分?#34892;?#30340;例如电路中一个按钮 要求按钮后 LED 点亮这个按钮何时会被按下是不可预知的为了要捕获这个按钮的事件 通常会有三种方法一是用循环语句不断的?#22253;?#38062;进行查询二是用定时中断在间隔时间内 扫描按钮三是用外部中断服务函数?#22253;?#38062;进行捕获在这个应用中只有单一的按钮功能 那么第一种方式就能胜任了程序也很简单但是它会不停的在?#22253;?#38062;进行查询浪费了

      CPU 的时间?#23548;?#24212;用中一般都会还有其它的功能要求同时实现这个时候能根据需要选用第 二或第三种方式第三种方式占用的 CPU 时间最少只有在有按钮事件发生时中断服务函 数才会被执行其余的时间则是执行其它的任务

      如果你学习过汇编语言的话刚开始写汇编的中断应用程序时你一定会为出入堆栈的 问题而困扰过单片机c语言 语言扩展了函数的定义使它能直接编写中断服务函数你能不必考 虑出入堆栈的问题从而提高了工作的效率扩展的关键字是 interrupt它是函数定义时 的一个选项只要在一个函数定义后面加上这个选项那么这个函数就变成了中断服务函数

      在后面还能加上一个选项 using这个选项是指定选用 51 芯片内部 4 组工作寄存器中的


      那个组开始学习者能不必去做工作寄存器设定而由编译器自动选择避免产生不必要的错 误定义中断服务函数时能用如下的形式

      函数类型    函数名  (形式参数)  interrupt  n  [using  n]

      interrupt 关键字是不可缺少的由它告诉编译器该函数是中断服务函数并由后面的

      n 指明所使用的中断号n 的取值?#27573;?#20026; 031,但具体的中断号要取决于芯片的型号像 AT89c51 ?#23548;?#19978;就使用 04 号中断每个中断号都对应一个中断向量具体地址为 8n+3, 中断源响应后处理器会跳转到中断向量所处的地?#20998;?#34892;程序编译器会在这地?#39134;?#20135;生一个 无条件跳转语句转到中断服务函数所在的地?#20998;?#34892;程序下表是 51 芯片的中断向量和中 断号

      中断号

      中断源

      中断向量

      0

      外部中断 0

      0003H

      1

      定时器/计数器 0

      000BH

      2

      外部中断 1

      0013H

      3

      定时器/计数器 1

      001BH

      4

      串行口

      0023H

      表 91    AT89c51 芯片中断号和中断向量

      使用中断服务函数时应注意中断函数不能直接调用中断函数;不能通过形参传速参数; 在中断函数中调用其它函数两者所使用的寄存器组应相同限于篇幅其它与函数相关的知 识这里不能一一加以说明如变量的传递存储局部变量全部变量等?#34892;?#36259;的朋友可 以访?#26102;?#32773;的网站 阅读更多相关文章

      下面是简单的例子首先要在前面做好的实验电路中加多一个按钮接在 P3.212 引脚外 部中断 INT0和地线之间把编译好后的程序?#31456;?#21040;芯片后当接在 P3.2 引脚的按钮接下 时中断服务函数 Int0Demo 就会被执行把 P3 当前的状态反?#36710;?P1如按钮接下后 P3.7

      之前有在这脚装过一按钮为?#20572;?#36825;个时候 P1.7 上的 LED 就会熄灭放开 P3.2 上的按钮后

      P1LED 状态保持先前按下 P3.2 时 P3 的状态

      #include <at89x51.h>

      unsigned char P3State(void); //函数的说明中断函数不用说明

      void main(void)

      {

      IT0 = 0; //设外部中断 0 为低电平触发

      EX0 = 1; //允许响应外部中断 0

      EA = 1; //总中断开关

      while(1);

      }

      //外部中断 0 演示使用 2 号寄存器组

      void Int0Demo(void) interrupt 0 using 2


      {

      unsigned int Temp; //定义局部变量

      P1 = ~P3State(); //调用函数取得 p2 的状态反相后并赋给 P1

      for (Temp=0; Temp<50; Temp++); //延时    这里只是演示局部变量的使用

      }

      //用于返回 P3 的状态演示函数的使用

      unsigned char P3State(void)

      {

      unsigned char Temp;

      Temp = P3; //读取 P3 的引脚状态并保存在变量 Temp 中

      //这样只有一句语句实在没必要做成函数这里只是学习函数的基本使用方法

      return Temp;

      }

      发表评论告诉好友收藏此文关闭窗口

      文章评论

      相关文章

      ຣ11ѡ5app

        
        
        1. <em id="3qmea"><ol id="3qmea"></ol></em>
        2. <em id="3qmea"></em>

            
            
            1. <em id="3qmea"><ol id="3qmea"></ol></em>
            2. <em id="3qmea"></em>