单片机的C语言编程称为C51编程,应用C51编程具有以下优点:(1)C51编译器管理内部寄存器和存贮器的分配,编程时,无需考虑不同存储器的寻址和数据类型等细节问题;(2)程序有规范的结构,可分成不同的函数,这种方式具有良好的模块化结构,使已编好程序容易移植;(3)有丰富的子程序库可直接引用,具有较强的数据处理能力,从而大大减少用户编程的工作量;(4)C语言和汇编语言可以交叉使用。汇编语言程序代码短、运行速度快、但复杂运算编程耗时。用汇编语言编写与硬件有关的部分程序,用C语言编写与硬件无关的运算部分程序,充分发挥两种语言的长处,提高开发效率。第4章单片机的C语言编程4.1C51程序结构特点同标准C一样,C51的程序是由函数组成。C语言的函数以“{”开始,以“}”结束。其中必须有一个主函数main(),程序的执行从主函数main()开始,调用其他函数后返回主函数main(),最后在主函数中结束整个程序,而不管函数的排列顺序如何。C语言的语句规则:1.每个变量必须先说明后引用。2.C语言程序一行可以书写多条语句,但每个语句必须以“;”结尾,一个语句也可以多行书写。3.C语言的注释用/*……*/表示。4.“{”花括号必须成对,位置随意,多个花括号可同行书写,也可逐行书写。C语言程序的组成结构:全局变量说明/*可被各函数引用*/main()/*主函数*/{局部变量说明/*只在本函数引用*/执行语句(包括函数调用语句);}fun1(形式参数表)/*函数1*/形式参数说明{局部变量说明执行语句(包括调用其他函数语句)}…funn(形式参数表)/*函数n*/形式参数说明{局部变量说明执行语句}标识符用来标识源程序中某个对象的名字,这些对象可以是语句、数据类型、函数、变量、数组等。标识符区分大小写,第一个字符必须是字母或下划线。C51中有些库函数的标识符是以下划线开头的,所以一般不要以下划线开头命名标识符。C51编译器规定标识符只有32个字符在编译时有效,因此在编写源程序时标识符的长度不要超过32个字符。关键字是编程语言保留的特殊标识符,在C语言的程序编写中不允许标识符与关键字相同。KeilC51编译器的关键字除了有ANSIC标准的32个关键字外还根据51单片机的特点扩展了相关的关键字。4.2C51的标识符和关键字关键字用途说明auto存储种类说明用以说明局部变量,缺省值为此break程序语句退出最内层循环体case程序语句switch语句中的选择项char数据类型说明单字节整型数或字符型数据const存储类型说明在程序执行过程中不可更改的常量值continue程序语句转向下一次循环default程序语句switch语句中的失败选择项do程序语句构成do…while循环结构double数据类型说明双精度浮点数else程序语句构成if…else选择结构enum数据类型说明枚举extern存储种类说明在其他程序模块中说明了的全局变量float数据类型说明单精度浮点数for程序语句构成for循环结构goto程序语句构成goto转移结构if程序语句构成if…else选择结构ANSIC标准关键字(1)ANSIC标准关键字(2)关键字用途说明int数据类型说明基本整型数long数据类型说明长整型数register存储种类说明使用CPU内部寄存的变量return程序语句函数返回short数据类型说明短整型数signed数据类型说明有符号数,二进制数据的最高位为符号位sizeof运算符计算表达式或数据类型的字节数static存储种类说明静态变量struct数据类型说明结构类型数据switch程序语句构成switch选择结构typedef数据类型说明重新进行数据类型定义union数据类型说明联合类型数据unsigned数据类型说明无符号数据void数据类型说明无类型数据volatile数据类型说明该变量在程序执行中可被隐含地改变while程序语句构成while和do…while循环结构KeilC51编译器扩展的关键字(1)关键字用途说明_at_地址定位为变量定义存储空间绝对地址alien函数特性说明声明与PL/M51兼容的函数bdata存储器类型说明可位寻址的内部RAMbit位标量声明声明一个位标量或位类型的函数code存储器类型说明程序存储器空间compact存储器模式使用外部分页RAM的存储模式data存储器类型说明直接寻址的8051内部数据存储器idata存储器类型说明间接寻址的8051内部数据存储器interrupt中断函数声明定义一个中断函数large存储器模式使用外部RAM的存储模式pdata存储器类型说明“分页”寻址的8051外部数据存储器_priority_多任务优先声明RTX51的任务优先级reentrant再入函数声明定义一个再入函数sbit位变量声明声明一个可位寻址变量sfr特殊功能寄存器声明声明一个特殊功能寄存器(8位)KeilC51编译器扩展的关键字(2)关键字用途说明sfr16特殊功能寄存器声明声明一个16位的特殊功能寄存器small存储器模式内部RAM的存储模式_task_任务声明定义实时多任务函数using寄存器组定义定义8051的工作寄存器组xdata存储器类型说明8051外部数据存储器4.3C51的数据类型C51的数据有常量和变量之分。常量——在程序运行中其值不变的量。变量——在程序运行中其值可以改变的量。定义一个变量,编译系统就会自动为它安排一个存贮区,具体的地址值,用户不必在意。一个变量由变量名和变量值构成.变量名:存贮单元地址的符号表示。变量的值:变量所在地址单元存放的内容。数据类型:数据的长度。C51编译器支持数据类型数据类型长度值域位型bit1Bit0或1字符型signedchar1Byte-128~+127unsignedchar1Byte0~255整形signedint2Byte-32768~+32767unsignedint2Byte0~65535signedlong4Byte-2147483648~+2147483647unsignedlong4Byte0~4294967295实型Float4Byte1.176E-38~3.40E+38指针型data/idata/pdata1Byte1字节地址code/xdata2Byte2字节地址通用指针3Byte其中1字节为储存器类型编码,2,3字节为地址偏移量访问SFR的数据类型sbit1Bit0或1sfr1Byte0~255sfr162Byte0~6553516:1511C51增加的特殊的数据类型1.bit位标量bit位标量是C51编译器的一种扩充数据类型,利用它可定义一个位标量。它的值是一个二进制位,不是0,就是1。bit位变量名例:bitlock;/*将lock定义为位变量*/lock=1;16:15122.sfr特殊功能寄存器MCS-51系列单片机片内有21个特殊功能寄存器(SFR),分散在片内RAM区的0x80~0xFF地址范围内。对SFR的操作只能用直接寻址方式。为了能直接访问这些特殊功能寄存器,C51提供了定义sfr的方法。sfr是一种C51扩充数据类型,占用一个内存单元,值域为0~255。语法如下:sfr特殊寄存器名=寄存器地址16:1513例如:sfrP1=0x90P1=255定义一个特殊功能寄存器变量“P1”,0x90是指51单片机的P1端口地址90H,变量P1即指51单片机的P1端口。在后面的语句中可以用P1=255(对P1端口的所有引脚置高电平)之类的语句操作特殊功能寄存器。16:1514例:sfrPSW=0xD0;/*定义程序状态字PSW,因MCS-51单片机的PSW地址为D0H*/sfrTMOD=0x89;/*定义定时/计数器方式控制寄存器TMOD,因MCS-51单片机的TMOD地址为89H*/sfrSCON=0x98;/*定义串口控制寄存器SCON,因MCS-51单片机的SCON地址为8H*/16:15153.sfr1616位特殊功能寄存器sfr16也是一种C51扩充数据类型,用于定义存在于MCS-51单片机内部RAM的16位特殊功能寄存器,如定时器T0和T1。sfr16型数据占用2个内存单元,取值范围为0~65535。16:1516sbit也是一种C51扩充数据类型,利用sbit访问芯片内部可寻址的特殊功能寄存器中的位。定义方法有如下三种:(1)sbit特殊功能寄存器位名=位地址将位的绝对地址赋给位变量,位地址必须位于80H~FFH(特殊功能寄存器的位地址)之间。4.sbit可寻址位16:1517(2)sbit特殊功能寄存器位名=特殊功能寄存器名^位位置当可寻址位位于特殊功能寄存器中时,可采用这种方法。位位置是一个0~7之间的常数。(3)sbitsbit特殊功能寄存器位名=字节地址^位位置这种方法是以一个常数(字节地址)作为基地址,该常数必须在80H~FFH(特殊功能寄存器的字节地址)之间。位位置是一个0~7之间的常数。16:1518例:sfrPSW=0xD0;/*首先定义程序状态字PSW,因MCS-51单片机的PSW地址为D0H*/sbitOV=PSW^2;/*在前面定义了PSW后,OV位于PSW的第2位*/sbitAC=0xD0^6;/*D0H是程序状态字PSW的字节地址,辅助进位标志位AC位于PSW的第6位*/sbitRS0=0xD0^3;/*工作寄存器组控制位RS0位于PSW的第3位*/sbitCY=0xD7;/*进位标志位Cy的绝对位地址为D7H*/对位变量的定义C51对位变量的定义方法有三种:1.定义bit类型变量如bitmn;mn为位变量,其值只能是“0”或“1”,其位地址C51自行安排在可位寻址区的bdata区。2.采用字节寻址变量.位的方法如bdataintibase;/*ibase定义为整型变量*/sbitmybit=ibase^15;/*mybit定义为ibase的D15位*/这里位是运算符“^”相当于汇编中的“·”,其后的最大取值依赖于该位所在的变量的类型,如定义为char最大值只能为7。3.对特殊功能寄存器的位的定义方法1:使用头文件及sbit定义符;多用于无位名的可寻址位。如#includereg51.hsbitP1_1=P1^1;/*P1_1为P1口的第1位*/sbitac=ACC^7;/*ac定义为累加器A的第7位*/方法2:使用头文件reg51.h,再直接用位名称。例如#includereg51.hRS1=1;RS0=0;方法3:用字节地址位表示如sbitOV=0xD0^2;方法4:用寄存器名.位定义如sfrPSW=0xd0;/*定义PSW地址为d0H*/sbitCY=PSW^7;/*CY为PSW·7*/16:1521例5-2特殊功能寄存器的访问。#include”reg51.h”sbitP10=P1^0;/*定义P10为P1口第0位,即P1.0口*/sbitP12=P1^2;/*定义P12为P1口第2位,即P1.2口*/voidmain(){P10=1;/*置位P1.0口*/P12=0;/*复位P1.2口*/PSW=0x08;/*程序状态字置0x08*/……}----应用实例C5l编译器除了能支持以上这些基本数据类型之外,还能支持一些复杂的组合型数据类型,如数组类型、指针类型、结构类型、联合类型等这些复杂的数据类型。使用头文件C51建有头文件reg51.h、reg52.h,在该头文件中对51或52系列单片机所有的特殊功能寄存器的进行了sfr定义,对特殊功能寄存器的有位名称的可寻址位进行了sbit定义,因此,只要用包含语句#includereg51.h就可以直接引用特殊功能寄存器名,或直接引用位名称。要特别注意:在引用时特殊功能寄存器或者位名称必须大写。4.4数据的存储类型和存储模式同ANSIC一样,C51规定变量必须先定义后使用。C51对变量的进行定义的格式如下:[存储种类]数据类型[存储器类型]变量名表其中,存储种类和存储器类型是可选项。存储类型是C51中增加的。一、变量