公选课《单片机基础及应用》主讲:张宏伟一、C及C51语言概述二、C51基础知识三、C程序的规范化设计一、C及C51语言概述常用编程语言用什么语言最好?这主要取决于应用领域,每种语言都有自已的长处和不足。1)汇编语言和C语言在单片机及工控领域用较多。另外C语言也是一种通用语言,是学C++/c#的起点。2)C++系统编程等多个方面,最常用的编译器是VC。3)C#/Java网络编程方面新兴的。4)VB通用。C及C51语言的特点语言简洁,使用方便灵活。可移植性好。表达能力强。表达方式灵活。可进行结构化程序设计。可以直接操作计算机硬件。生成的目标代码质量高。什么是ANSICANSI就是美国国家标准协会(AmericanNationalStandardsInstitute)ANSIC就是美国国家标准协会制定的一个C语言的标准。单片机C语言和ANSIC的区别和联系“单片机C语言”通常和ANSIC间关系只是存在一个交集。也就是说,它们分别都存在着自己的特定内容。由于ANSIC是一般C的基础,所以某些“单片机C语言”可能会舍去部分ANSIC中的标准,以简化编译。但反过来,某些“单片机C语言”还会增加一些单片机特有的语言特性,以方便针对单片机的编程二、C51基础知识1、标识符2、关键字3、C51编译器所支持的数据类型4、C51对内部资源的定义5、常量6、变量7、数组8、运算符9、C51绝对地址访问10、C51的基本语句11、中断服务程序1、标识符标识符是用来标识源程序中某个对象的名字,这些对象可以是函数、变量、数组等。C语言对大小些敏感,如“Timer1”、“TIMER1”是完全不同定义的标识符。标识符由字符串、数字和下划线等组成,注意的是第一个字符必须是字母或下划线。标识符在命名时应当简单,含义清晰,这样有助于阅读理解程序。2、关键字关键字则是编程语言保留的特殊标识符,它们具有固定名称和含义,在程序编写中不允许标识符与关键字亦同。在KEILuVision2中的关键字除了有ANSIC标准的32个关键字外还根据51单片机的特点扩展了相关的关键字。关键字用途说明bit位标量声明声明一个位标量或位类型的函数sbit位标量声明声明一个可位寻址变量sfr特殊功能寄存器声明声明一个特殊功能寄存器sfr16特殊功能寄存器声明声明一个16位的特殊功能寄存器data存储器类型说明直接寻址的内部数据存储器bdata存储器类型说明可位寻址的内部数据存储器idata存储器类型说明间接寻址的内部数据存储器pdata存储器类型说明分页寻址的外部数据存储器xdata存储器类型说明外部数据存储器code存储器类型说明程序存储器interrupt中断函数说明定义一个中断函数reentrant再入函数说明定义一个再入函数using寄存器组选择选择单片机的工作寄存器组_at_绝对地址说明为非位变量指定存储空间绝对地址small存储模式选择参数及局部变量放入可直接寻址的内部RAMcompact存储模式选择参数及局部变量放入分页外部数据存储区large存储模式选择参数及局部变量放入分页外部数据存储区关键字:数据类型长度值域unsignedchar单字节0~255signedchar单字节-128~+127unsignedint双字节0~65535signedint双字节-32768~+32767unsignedlong四字节0~4294967295signedlong四字节-2147483648~+2147483647float四字节±1.175494E-38~±3.402823E+38*1~3字节对象的地址bit位0或1sfr单字节0~255sfr16双字节0~65535sbit位0或13、KEILC51编译器所支持的数据类型1)char字符类型char类型的长度是一个字节,通常用于定义处理字符数据的变量或常量。unsignedchar:0~255。signedchar:字节中最高位字节表示数据的符号,“0”表示正数,“1”表示负数,负数用补码表示。所能表示的数值范围是-128~+127。unsignedchar常用于处理ASCII字符或用于处理小于或等于255的整型数。2)int整型int整型长度为两个字节,用于存放一个双字节数据。signedint:-32768~+32767unsignedint:0~655353)long长整型long长整型长度为四个字节,用于存放一个四字节数据。分有signedlong和unsignedlong4)float浮点型float浮点型在十进制中具有7位有效数字,是符合IEEE-754标准的单精度浮点型数据,占用四个字节。5)*指针型指针型本身就是一个变量,在这个变量中存放的指向另一个数据的地址。6)bit位标量C51编译器的扩充数据类型利用bit位标量可定义一个位标量,但不能定义位指针,也不能定义位数组。它的值是一个二进制位,不是0就是1,类似高级语言中的Boolean类型中的True和False。7)sfr特殊功能寄存器sfr也是一种扩充数据类型占用一个内存单元,值域为0~255。利用它可以访问51单片机内部的所有特殊功能寄存器。其用法:sfr特殊功能寄存器名=特殊功能寄存器地址常数;如sfrP1=0x90;/*定义P1I/O口,其地址90H*/。如用P1=255/*把FFH送入P1中(对P1端口的所有引脚置高电平)*/。8)Sfr1616位特殊功能寄存器sfr16占用两个内存单元,值域为0~65535。sfr16和sfr一样用于操作特殊功能寄存器,所不同的是它用于操作占两个字节的寄存器。用法:sfr16特殊功能寄存器名=特殊功能寄存器地址常数;如8052的T2定时器,可以定义为:sfr16T2=0xCC;/*这里定义8052定时器2,地址为T2L=CCH,T2H=CDH*/9)sbit可寻址位sbit是C51中的一种扩充数据类型,利用它可以访问芯片内部RAM中的可寻址位或特殊功能寄存器中的可寻址位。9)sbit可寻址位sbit的用法有三种:(1)sbit位变量名=位地址例如:sbitP1_1=0x91;(2)sbit位变量名=特殊功能寄存器名^位位置例如:sfrP1=0x90;sbitP1_1=P1^1;/*P1_1为P1中的P1.1引脚*/(3)sbit位变量名=字节地址^位位置(位序号)例如:sbitP1_1=0x90^1;4、C51对内部资源的定义MCS-51内部资源定义函数是MCU中寄存器的地址映射。MCS-51单片机提供128字节的SFR寻址区,地址为80H~FFH,51单片机中,除了程序计数器PC和4组通用寄存器组之外,其他所有的寄存器均为SFR,并位于片内特殊寄存器区。这个区域可位寻址、字节寻址或字寻址,用来控制定时/计数器、I/O口、串行口等部件。特殊功能寄存器在C51语言中的声明,由几个关键字来完成。4、C51对内部资源的定义MCS-51单片机所有标准的寄存器的使用都是已经由C51头文件定义完成,编程人员可以直接使用符号的定义。在使用C51已定义的寄存器符号时,要用预编译命令#include将有关“头文件”包括到源文件中。4、C51对内部资源的定义Keil软件中提供实现此功能的头文件很多,如“reg51.h”、“reg52.h”、“AT89X51.H”、“AT89X52.H”等,可自行选型。使用MCS-51内部资源定义时要用到“reg51.h”文件,因此源文件开头应有以下预编译命令:#includereg51.h或#include”reg51.h”。思考:这两种格式有何不同?4、C51对内部资源的定义寻找头文件时候的路径顺序不同使用尖括号,先去找系统库目录使用分号,先去找当前目录为了更快的找到头文件,加快编译速度,建议:自定义头文件用引号系统头文件用尖括号例1:利用MCS-51单片机的P1引脚P1.0引接一只LED,送“0”点亮,送“1”灭。则要求点亮,程序如下:例1:利用MCS-51单片机的P1引脚P1.0引接一只LED,送“0”点亮,送“1”灭。则要求点亮,程序如下:#include“reg51.h”sbitP1_0=P1^0;voidmain(){P1_0=0;}main()函数:也称为主函数。C语言都是从main()函数开始执行的。前面加了一个void是说明该函数是没有返回值的。#include代表的是加载头文件,头文件是C编译器中带的已经定义的函数的集合或自定义的一个函数的集合。程序中加载一个reg51.h的文件,那么打开reg51.h里边的内容是什么呢?如编码器在C盘下C51文件夹内,则REG51.h文件的路径是C:\Keil\C51\INC\reg51.h。例如:P1定义为sfrP1=0x90;上例中,符号P1(代表P1锁存器)已经在头文件“reg51.h”中有定义。P1_0表示P1.0引脚,它没有被事先定义好,所以需要使用sbit进行定义。注意:AT89X51.H头文件中有P1_0的位定义。例1:利用MCS-51单片机的P1引脚P1.0引接一只LED,送“0”点亮,送“1”灭。则要求点亮,程序如下:#includeat89X52.hvoidmain(){P1_0=0;}思考:如果点量8个灯,如何编程序。5、常量常量是在程序运行过程中不能改变值的量,而变量是可以在程序运行过程中不断变化的量。变量的定义可以使用所有C51编译器支持的数据类型常量的数据类型只有整型、浮点型、字符型、字符串型和位标量。5、常量1)整型常量整型常量可以表示为:十进制,如123、0、-89等。十六进制则以0x开头如0x34,-0x3B等。长整型就在数字后面加字母L,如104L等。5、常量2)浮点型常量:可分为十进制和指数表示形式。十进制由数字和小数点组成,如0.888,3345.345,0.0等,整数或小数部分为0,可以省略但必须有小数点。常量可用在不必改变值的场合,如固定的数据表,字库等。常量的定义方式有几种:#difineFalse0x0;//用预定义语句可以定义常量#difineTrue0x1;//这里定义False为0,True为1//在程序中用到False编译时自动用0替换,同理True替换为1unsignedintcodea=100;//这一句用code把a定义在程序存储器中并赋值constunsignedintc=100;//用const定义c为无符号int常量并赋值以上两句它们的值都保存在程序存储器中,而程序存储器在运行中是不允许被修改的,所以如果在这两句后面用了类似a=110,a++这样的赋值语句,编译时将会出错。6、变量变量就是一种在程序执行过程中其值能不断变化的量。要在程序中使用变量必须先用标识符作为变量名,并指出所用的数据类型和存储模式,这样编译系统才能为变量分配相应的存储空间。6、变量定义一个变量的格式如下:[存储种类]数据类型[存储器类型]变量名表在定义格式中除了数据类型和变量名表是必要的,其它都是可选项。存储种类是指变量在程序执行过程中的作用范围。存储种类有四种:自动(auto),外部(extern),静态(static)和寄存器(register),缺省类型为自动(auto)6、变量存储器类型的说明就是指定该变量在C51硬件系统中所使用的存储区域,并在编译时准确的定位。KEIL所能认别的存储器类型存储器类型说明地址data直接访问内部数据存储器(128字节),访问速度最快00H-7FHbdata可位寻址内部数据存储器(16字节),允许位与字节混合访问20H-2FHidata间接访问内部数据存储器(256字节),允许访问全部内部地址00H-FFHpdata分页访问外部数据存储器(256字节),用MOVX@Ri指令访问00H-FFHxdata外部数