此外,C51编译器本身还提供了丰富的库函数,用户可以根据需要随时调用,从而大大提高编程效率。
函数定义的一般形式为:
函数类型 函数名(形参列表)
{ 局部变量定义
函数体
}
在用户的角度看来,有两类函数可以调用:用户自定义的函数和标准库函数。
通常情况下,C51的函数不能被递归调用,也不能应用导致递归调用的结构。
重入函数特性允许你声明一个重入函数,使得该函数能够被递归调用。 实际上,当多个进程需要同时使用同一个函数时,这个函数就应定义成重入函数。当一个重入函数被调用运行时,另外的一个进程可以中断此运行过程,然后再次调用此重入函数。
定义重入函数的方法就是在函数声明时,用关键字“reentrant”进行声明。
例如:
#include //包含特殊功能寄存器库
#include //包含I/O函数库
extern serial_initial();
int fac(int n) reentrant
{
int result;
if (n == 0)
result=1;
else
result=n*fac(n-1);
return(result);
}
main()
{
int fac_result;
serial_initial();
fac_result=fac(11);
printf(“%d\n”,fac_result);
}
重入函数在实时应用中,在中断服务程序代码和非中断程序代码必须共用一个函数的场合中经常用到。
需要注意的是,可以选择哪些必须的函数为重入函数而不需将全部程序声明为重入函数。把全部程序声明为重入函数,将增加目标代码的长度并减慢运行速度。
中断系统对于单片机系统来说十分重要,C51编译器支持用C语言编写中断函数,从而减轻了用汇编语言编写中断服务程序的繁琐程度。中断服务程序的一般格式如下:
函数类型 函数名(形参列表) interrupt n [using m];
中断函数类型一般为void。
interrupt后面的n是中断号,取值为0~4,编译器从8n+3处产生一条长跳转指令,转向中断号为n的中断服务程序。
using m用于选择不同的工作寄存器组。m的取值范围为0~3,分别对应与低128字节内部RAM区中的四组寄存器。
该项为可选项。
编写MCS-51中断函数注意如下:
C51编译器对中断函数编译时会自动在程序开始和结束处加上相应的内容,具体如下:
中断函数定义示例:
#include
unsigned char status;
bit flag;
void service_int1( ) interrupt 2 using 2 /* INT1中断服务程序,使用第2组工作寄存器 */
{
flag=1; /* 设置标志 */
status=p1; /* 存输入口状态 */
}
C51提供了可直接调用的库函数。调用这些库函数可以使程序代码简单、结构清晰、易于调试和维护。
(1)crol和cror: 将char型变量循环向左(右)移动指定位数后返回。
(2)irol和iror: 将int型变量循环向左(右)移动指定位数后返回。
(3)lrol和lror: 将long型变量循环向左(右)移动指定位数后返回。
(4)nop: 相当于插入汇编指令nop
(5)testbit: 相当于JBC Label测试该位变量并跳转同时清除该位
(6)chkfloat: 测试并返回浮点数状态
上面所列举的本征函数的说明都包含在头文件
中,因此若想使用上述本征函数,必须在源程序开头包涵该头文件即:#include 。
一般源程序中都包涵该头文件。即:#include
包含了这个头文件后,就可以在程序中使用这些特殊功能寄存器及其位, P0 = 0x01;
#define XBYTE ((unsigned char volatile xdata *) 0)
如:memccpy,strcat,strcmp等。这样可以很方便的对缓冲区进行处理。
如:extern char *strcat (char *s1, char *s2);
注意: 除了上面介绍的几种常用的头文件,C51的头文件还包括ctype.h,assert.h,errno.h,float.h,ltmits.h,rtx51tny.h,srom.h,setjmp.h,stdarg.h等以上所介绍的头文件在keil目录下的C51\INC文件夹中。
C51最基本的算术运算符有五种:
A、 +
B、 -
C、 *
D、 /
E、 %
C51提供6种关系运算符
< (小于)
>(大于)
<= (小于或等于)
>= (大于或等于)
== (测试等于)
!= (测试不等于)
(1) 关系运算符的优先级低于算术运算符
(2) 关系运算符的优先级高于赋值运算符
C51提供三种逻辑运算符:
&& 逻辑与
| | 逻辑或
! 逻辑非
C51提供了如下位操作运算符:
& 按位求与
| 按位求或
^ 按位求异或
~ 按位求反
<< 位左移
>> 位右移
示例:
#include /*包含的头文件*/
#include
#define ADC XBYTE[0x4000] /*定义需访问的绝对地址*/
#define CON8255 XBYTE[0x2003]
#define PA8255 XBYTE[0x2000]
#define PB8255 XBYTE[0x2001]
uchar code disp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
• 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; /*7段LED译码表*/
uchar data ad_w_l,ad_w_h;
void delay(uchar t) /*延时子程序*/
{uchar i,j;
for(i=0;i<=100;i++);
for(j=0;j<=t;j++);
}
void dis_p(uchar disp_h,disp_l) /*两位LED数码显示子程序*/
{PB8255=disp[disp_l];
PA8255=0xf7;
delay(100);
PB8255=disp[disp_h];
PA8255=0xfb;
delay(100);
}
void main(void)
{uchar temp1;
CON8255=0x89;
IT0=1;
EX0=1;
EA=1;
ADC=temp1;
while(1) /*主程序中的主体循环*/
{dis_p(ad_w_h,ad_w_l);}
}
adint() interrupt 0 using 1 /*外部中断0中断服务子程序*/
{uchar adc_w,temp; /*变量的定义*/
EA=0;
adc_w=ADC;
if(adc_w>=255){adc_w=adc_w-5;}
temp=adc_w/5;
ad_w_h=temp/10;
ad_w_l=temp%10;
EA=1;
ADC=adc_w;
}