单片机C语言教程:C51函数

发布者:Blissful567最新更新时间:2013-03-04 来源: 21IC 关键字:单片机  C语言教程  C51函数 手机看文章 扫描二维码
随时随地手机看文章

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

 一.函数定义

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

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

{

函数体

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

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

二.函数的调用

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

函数名 (实际参数表) “函数名”就是指被调用的函数。实际参数表能为零或多个参数,多个参数时要用逗

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

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

1.函数语句

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

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

2.函数参数 “函数参数”这种方式是指被调用函数的返回值当作另一个被调用函数的实际参

数,如 temp=StrToInt(CharB(16));CharB 的返回值作为 StrToInt 函数的实际参数传递。

3.函数表达式

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

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

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

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

extern 类型标识符 函数的名称(形式参数表); 函数的定义和说明是完全不一样的,在编译的角度上看函数的定义是把函数编译存放在

ROM 的某一段地址上,而函数说明是告诉编译器要在程序中使用那些函数并确定函数的地 址。如果在同一文件中被调函数的定义在主调函数之前,这个时候能不用说明函数类型。也就 是说在 main 函数之前定义的函数,在程序中就能不用写函数类型说明了。能在一个函 数体调用另一个函数(嵌套调用),但不允许在一个函数定义中定义另一个函数。还要注意 的是函数定义和说明中的“类型、形参表、名称”等都要相一致。[page]

三.中断函数

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

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

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

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

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

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

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

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

n 指明所使用的中断号。n 的取值范围为 0-31,但具体的中断号要取决于芯片的型号,像 AT89c51 实际上就使用 0-4 号中断。每个中断号都对应一个中断向量,具体地址为 8n+3, 中断源响应后处理器会跳转到中断向量所处的地址执行程序,编译器会在这地址上产生一个 无条件跳转语句,转到中断服务函数所在的地址执行程序。下表是 51 芯片的中断向量和中 断号。

表 9-1 AT89c51 芯片中断号和中断向量
 AT89c51 芯片中断号和中断向量

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

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

(之前有在这脚装过一按钮)为低,这个时候 P1.7 上的 LED 就会熄灭。放开 P3.2 上的按钮后,

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

#include

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;

}

关键字:单片机  C语言教程  C51函数 引用地址:单片机C语言教程:C51函数

上一篇:单片机C语言教程:C51数组的使用
下一篇:单片机低功耗设计杂谈

推荐阅读最新更新时间:2024-03-16 13:19

PIC单片机1X4独立键盘C语言程序
/******************************************** *** 功能:1X4按键 *** 实验内容:按下S1 S2 S3 S4 数码管分别显示出0 1 2 3 *** 开发板连接方法:把J3的的跳线帽跳到1-2(左边) *********************************************/ #include pic.h //包含单片机内部资源预定义 __CONFIG(0xFF32); //芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关,加密,4M晶体HS振荡 const unsigned char TABLE = {0x3f,0x6,0x5b,0x4
[单片机]
基于AVR单片机的12864液晶(ks0108)驱动程序及仿真
#include iom16v.h #include avrdef.h #define EN 0 #define RS 1 #define CS1 2 #define CS2 3 unsigned char yang ={ 0xEF,0xFB,0xEF,0xFC,0x2F,0xFF,0x00,0x00,0x6F,0xFF,0xEF,0xDC,0xFF,0xEF,0xBD,0x73, 0x1D,0xBC,0xAD,0xDF,0xB5,0xE7,0x39,0xB8,0xBD,0x7F,0xBF,0xBF,0x3F,0xC0,0xFF,0xFF }; unsigned char ying ={ 0
[单片机]
基于AVR<font color='red'>单片机</font>的12864液晶(ks0108)驱动程序及仿真
MCU产品产销两旺,纳思达Q3净利预增265.35%-443.57%
10月11日,纳思达披露2021年三季度业绩预告,预计2021年前三季度归属于上市公司股东的净利润6.3亿元-7.3亿元,比上年同期增长51.8%-75.9%;基本每股收益0.5857元-0.6786元。预计2021年第三季度归属于上市公司股东的净利润2.05亿元–3.05亿元,比上年同期增长265.35%-443.57%;基本每股收益0.1905元–0.2835元。 纳思达称,业绩变动主要原因如下: 1、打印机业务 虽然今年前三季度通用耗材业务承压,但公司原装打印机和原装耗材业务增长趋势明显,具体来看: 利盟(Lexmark)打印机业务随着疫情缓解以及企业级战略合作伙伴的批量供货,利盟(Lexmark)经营业绩呈现出稳中向好
[手机便携]
<font color='red'>MCU</font>产品产销两旺,纳思达Q3净利预增265.35%-443.57%
SAM4E单片机之旅——19、CAN间通信
CAN协议具有良好的可靠性,在工业中应用广泛。这次就先熟悉CAN的基本功能。 开发板有两个CAN,每个CAN有8个信箱。这次内容是从CAN0的信箱0发送数据到CAN1的信箱0。 除本次使用的功能外,CAN还有远程帧、强大的错误处理功能。 一、电路 CAN总线上的逻辑数值是用显性电平和隐性电平表示的。“显性”的意思是指在同时传输显性电平和隐性电平时,总线上呈现的是显性电平。显性电平表示逻辑“0”,隐性电平表示逻辑“1”。 在使用CAN的过程中,需要使用一个CAN收发器进行电平的转换与解释。开发板使用的CAN收发器为SN65HVD234,其接线如下图所示: 其中CANTXx和CANRXx引脚可以复用为CAN的外设。而在使用
[单片机]
SAM4E<font color='red'>单片机</font>之旅——19、CAN间通信
基于MB90092的机载视频标识卡设计
  机载视频记录系统用于记录飞行中人员、装备的各种信息,在训练、实战中发挥重要作用。为使飞行员及地面指挥人员能够更直观、确切地了解飞行各时刻的状态信息及便于判读,我们为其加装了标识卡系统。记录时可根据需要叠加适当标识,如汉字、图形、实时时钟等信息。   在实际系统设计中,我们选择了富士通(FUJITSU)公司生产的专用字符叠加芯片MB90092,采用AT89C51单片机对其控制;考虑到机载系统的特殊性,我们利用RS-232串行接口通过计算机进行标识卡预先标识的写入、控制设置。整个系统适应性较强,地勤人员可根据不同的任务很方便的进行预先修改,可以显示中文及任意图形。              图1 MB90092的功能框图
[单片机]
简单的单片机I/O口扩展实例
扩展实例 简单的I/O口扩展通常是采用TTL或CMOS电路锁存器、三态门等作为扩展芯片,通过P0口来实现扩展的一种方案。它具有电路简单、成本低、配置灵活的特点。下图为采用74LS244作为扩展输入、74LS273作为扩展输出的简单I/O口扩展。 芯片及连线说明 图中电路中采用的芯片为TTL电路74LS244、74LS273。其中,74LS244为8缓冲线驱动器(三态输出),、为低电平有效的使能端。当二者之一为高电平时,输出为三态。74LS273为8D触发器,为低电平有效的清除端。当=0时,输出全为0且与其它输入端无关;CP端是时钟信号,当CP由低电平向高电平跳变时刻,D端输入数据传送到Q输出端。P0口作为双向8位数据线,既能
[单片机]
简单的<font color='red'>单片机</font>I/O口扩展实例
TM1650模块单片机源程序(子函数)
单片机源程序如下: #include STC12C5A.h #include tm1650.h void Delay_us(uint i) //us延时 { for(;i 0;i--) { _nop_(); // _nop_(); // _nop_(); } } void I2CStart(void) //开始信号 { CLK_H; DIO_H; Delay_us(5); DIO_L; } void I2Cask(void) //ACK信号 { uchar timeout = 1; CLK_H; Delay
[单片机]
一种单片机实现的嵌入式视频切换器
    摘要: 介绍一种以单片机为主控CPU的嵌入式视频切换器,简述其工作过程、硬件构成、软件设计。该切换器已成功地应用于湖南省地县电视会议系统中,实际应用表明,切换器工作可靠、成本低廉,具有很强的通用性和很高的实用价值。该切换器亦可用于普通的多媒体监控系统。     关键词: 89C51单片机  视频切换  嵌入式  I2C总线     随着多媒体通信技术的迅速发展,会议电视的理论研究和实用系统研制也得到了迅速发展。近年来,我国的会议电视业务也以超出人们想象的速度得到推广应用。视频矩阵切换电路是会议电视系统的关键部件。要求具有以下功能:     ·具有与多媒体电脑通讯的功能。可根据实际安装的不同需要,
[应用]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • ARM裸机篇--按键中断
    先看看GPOI的输入实验:按键电路图:GPF1管教的功能:EINT1要使用GPF1作为EINT1的功能时,只要将GPFCON的3:2位配置成10就可以了!GPF1先配 ...
  • 网上下的--ARM入门笔记
    简单的介绍打今天起菜鸟的ARM笔记算是开张了,也算给我的这些笔记找个存的地方。为什么要发布出来?也许是大家感兴趣的,其实这些笔记之所 ...
  • 学习ARM开发(23)
    三个任务准备与运行结果下来看看创建任务和任运的栈空间怎么样的,以及运行输出。Made in china by UCSDN(caijunsheng)Lichee 1 0 0 ...
  • 学习ARM开发(22)
    关闭中断与打开中断中断是一种高效的对话机制,但有时并不想程序运行的过程中中断运行,比如正在打印东西,但程序突然中断了,又让另外一个 ...
  • 学习ARM开发(21)
    先要声明任务指针,因为后面需要使用。 任务指针 volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • 学习ARM开发(20)
  • 学习ARM开发(19)
  • 学习ARM开发(14)
  • 学习ARM开发(15)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved