1.2 简单C程序介绍
为了说明C语言源程序结构的特点,先看下面例1-1所示的程序。这个程序用C语言编写,其功能是:控制单片机内部的一个数据不断加1递增,用8个发光二极管显示变化过程;当按下开关时,蜂鸣器鸣叫。用Keil C51执行C程序时,由于单片机没有标准的显示输出设备,只能通过单片机的串行口进行仿真显示,需调用串行口初始化子函数init_rs232()。从这个例子中可以了解到组成一个C语言源程序的基本部分和书写格式。
【例1-1】
#pragma symbols code /* 定义编译环境:产生符号列表、产生汇编程序列表*/ #include<stdio.h> // 包含输入、输出库函数 sfr P0=0x80; // 定义特殊功能寄存器P0的地址 sfr P1=0x90; // 定义特殊功能寄存器P1的地址 sfr P4=0xe8; // 定义特殊功能寄存器P4的地址 sfr T2CON=0xc8; // 定义特殊功能寄存器T2CON的地址 sfr SCON=0x98; // 定义特殊功能寄存器SCON的地址 sfr RCAP2H=0xcb; // 定义特殊功能寄存器RCAP2H的地址 sbit kg=P4^3; // 定义开关的位地址 sbit fmq=P1^5; // 定义蜂鸣器的位址 void delay(int time) /* 延时子函数,单位为ms */ { unsigned char tt; // 定义辅助无符号字符变量tt while(time!=0){ // 循环执行,次数由变量time的值确定 --time; for(tt=0;tt<226;++tt){} // 内部循环执行226次 } } void init_rs232(void) // 串行口初始化子函数 { T2CON=0x34; // 定时器2作为波特率发生器,自动重装 SCON=0xda; // 方式3,9位数据,单机通信,允许接收,TB8=1 RCAP2H=0xff; } main() // 主函数 { unsigned char kk=0; // 定义辅助无符号字符变量kk init_rs232(); // 调用串行口初始化子函数,用于仿真显示 printf("Hello! I am C51\n"); // 仿真显示字符串"Hello! I am C51" printf("I will be your friend!\n");// 仿真显示"I will be your friend!" for(;;){ // 无限循环 kk=kk+1; // 变量kk加1 P0=kk; // 变量kk的值通过8个发光二极管显示,“0”——亮 printf("%bu\n",kk); // 仿真显示变量kk的值 if(kg==0){ fmq=0; } // 如果按下开关,蜂鸣器响 else{ fmq=1; } // 否则蜂鸣器不响 delay(1000); // 调用延时子函数,延时1000ms } }
和上面C语言程序对应的汇编语言程序如下。
ORG 0000H; 1——伪指令,表示程序存放的首地址 begin: MOV P0,R1; 2——将R1的数据送到P0口引脚,输出0V时发光二极管点亮 CALL DELAY; 3——调用0.5s延时子程序 INC R1; 4——将R1的数据加1 JB 0EBH,ddd; 5——如果未按下开关(P4.4=0EBH) ,跳到ddd CLR P1.5; 6——按下开关,引脚P1.5输出0V,蜂鸣器响 JMP begin; 7——跳到begin ddd: SETB P1.5; 8——未按下开关,引脚P1.5输出5V,蜂鸣器不响 JMP begin; 9——跳到begin ;--------------------- 10——延时子程序 DELAY: MOV R5,#04H; 11——R5=延时时间 H0: MOV R6,#0ffH; 12——R6=循环次数 H1: MOV R7,#0ffH; 13——R7=循环次数 H2: DJNZ R7,H2; 14——R7减1,如果不等于0,跳到H2 DJNZ R6,H1; 15——R6减1,如果不等于0,跳到H1 DJNZ R5,H0; 16——R5减1,如果不等于0,跳到H0 RET; 17——子程序结束标志 ;--------------------- END ; 18——伪指令,表示程序结束
通过上述例子,可知C语言程序具有以下基本结构特点。
(1)一个C语言程序一般由3个部分组成:预处理部分、子函数部分和主函数部分。
(2)预处理部分类似于汇编语言的伪指令,是在C语言程序执行前对编译器所下的指示,主要用于控制编译过程和定义变量。
(3)函数的主体必须以大括号“{}”包含其中。
(4)子函数部分类似于汇编语言的子程序,完成一些使用较频繁且比较通用的功能。子函数一般由自己编写,同时C语言提供大约100多个常用子函数(常称为库函数)。
(5)一个C语言程序不论由多少个部分组成,都有一个且只能有一个main函数,即主函数。
(6)一个C语言程序,总是从main()函数开始执行,而不论其在程序中的位置。当主函数执行完毕时,即程序执行完毕。
(7)如果调用库函数,需在预处理中进行说明。如printf为库函数,其函数声明在文件stdio.h中,在预处理中需加入#include<stdio.h>命令进行说明。
(8)每一个说明,每一个语句都必须以分号结尾。但预处理命令,函数头和花括号“}”之后不能加分号。
(9)标识符、关键字之间必须至少加一个空格以示间隔。若已有明显的间隔符,也可不再加空格来间隔。
(10)C语言程序注释有两种写法。一种以“//”开头,编译器会把“//”之后的文字全部当做注释,直到此行的尾端。另一种方式是用“/* ……… */”的形式,可以为C程序的任一部分做注释,在“/*”开始后,一直到“*/”为止,它中间的任何内容都被认为是注释,两者之间不限制行数。
(11)C语言程序行的书写格式自由。既允许一行内写几条语句,也允许一条语句分写在几行上。
(12)C语言程序区分字母大小写,所以不要将字母大小写混用,如main不可写成MAIN。