片机C语言程序设计.ppt
第7章 单片机C语言程序设计,教学目标7.1 单片机C51语言概述7.2 C51语言基本语法 7.3 C51语言程序设计本章小结思考题与习题,7.1 单片机C51语言概述,7.1.1 单片机支持的高级语言,7.1.2 C51语言特点,7.1.1 单片机支持的高级语言,程序设计高级语言,PL/MBASICC51,是能够利用单片机所有特性直接控制硬件的唯一语言,对于一些需要直接控制硬件的场合,汇编语言是必不可少的。但汇编语言不是一种结构化的程序设计语言,对于较复杂的单片机应用系统,它的编写效率很低。,语言适用于简单编程而对编程效率、运行速度要求不高的场合,8052单片机内固化有BASIC语言解释器。是一种结构化的语言,很象PASCAL,PL/M编译器好象汇编器一样产生紧凑的机器代码,可以说是高级汇编语言,但它不支持复杂的算术运算,无丰富库函数支持,学习PL/M无异于学习一种新的语言。是一种通用的程序设计语言,其代码率高,数据类型及运算符丰富,并具有良好的程序结构,适用于各种应用的程序设计,是目前使用最广的单片机编程语言。,汇编语言,BASIC,PL/M,C51语言,单片机的C语言编程称为C51编程,C51语言本身不依赖机器硬件,不要求编程者对硬件深入了解,应用C51编程具有以下优点:,1语言简洁、紧凑,使用方便、灵活。,2运算符、数据结构丰富。,3结构化程序设计。,4可以直接对计算机硬件进行操作。,5生成的目标代码质量高,程序执行效率高。,6可移植性好。,7.1.2 C51语言特点,用C语言开发系统可以大大缩短开发周期,明显增强程序的可读性,便于改进和扩充。而针对8051的C51语言日趋成熟,成为了专业化的实用高级语言。,1.对单片机的指令系统不要求了解,仅要求对8051 的存贮器结构有初步了解;2.寄存器分配、不同存贮器的寻址及数据类型等细节可由编译器管理;3.程序有规范的结构,可分成不同的函数,这种方式可使程序结构化;4.提供的库包含许多标准子程序,具有较强的数据处理能力;5.由于具有方便的模块化编程技术,使已编好程序可容易地移植;,C-51与ASM-51相比,有如下优点:,7.2 C51语言基本语法,7.2.1 C51语言的函数及程序结构,7.2.2 C51语言的数据类型及存储类型,7.2.3 C51语言的运算符,7.2.4 C51语言的语句,C51语言的指针,7.2.7 中断函数、头文件及绝对地址访问,7.2.5 C51语言的数组,实战1,实战2,实战3,实战4,实战5,实战6,实战7,C51函数的一般格式 类型 函数名(参数表)声明语句;执行语句;,同C语言程序一样,C51采用函数结构,每个C51语言程序由一个或多个函数组成。,7.2.1 C51语言的函数及程序结构,其中,函数往往由“函数定义”和“函数体”两个部分组成。函数定义部分包括有函数类型、函数名、形式参数说明等,函数名后面必须跟一个圆括号(),形式参数在()内定义。函数体由一对花括号“”组成,在“”的内容就是函数体。如果一个函数内有多个花括号,则最外层的一对“”为函数体的内容。函数体内包含若干语句,一般由两部分组成:声明语句和执行语句。声明语句用于对函数中用到的变量进行定义。也可能对函数体中调用的函数进行声明。执行语句由若干语句组成,用来完成一定功能。当然也有的函数体仅有一对“”,其中内部既没有声明语句,也没有执行语句。这种函数称为空函数。,C语言的语句规则:1.每个变量必须先说明后引用。2.书写时格式十分自由,一行可以书写多条语句,一个语句也可以多行书写。但每个语句必须以“;”结尾。3.注释用/*/或者/表示。4.“”花括号必须成对,位置随意,多个花括号可同行书写,也可逐行书写。5.区分大小写字母。为层次分明,增加可读性,同一层的“”花括对齐,采用逐层缩进方式书写。,与一般C语言的结构相同:,1、C51语言的函数以“”开始,以“”结束,3、有且只有一个main()函数,以main()函数为程序入口,中间可以调用其他函数,最后在main()函数结束,2、程序体中包含若干语句还可以包含若干函数,均以;号结束。,4、函数放置顺序可随意,但是调用之后的函数需要先声明。,C语言程序的组成结构:全局变量说明/*可被各函数引用*/main()/*主函数*/局部变量说明/*只在本函数引用*/执行语句(包括函数调用语句);fun1(形式参数表)/*函数1*/形式参数说明 局部变量说明 执行语句(包括调用其他函数语句)funn(形式参数表)/*函数n*/形式参数说明 局部变量说明 执行语句,uchar keyscan(void)/按键扫描函数,返回4个按键值 XXXXXXX;return key;/返回按键值:key,void main(void)uchar i;while(1)i=keyscan();/按键扫描函数,uchar keyscan(void)/按键扫描函数,返回4个按键值 XXXXXXX;return key;/返回按键值:key,uchar keyscan(void);/声明函数,void main(void)uchar i;while(1)i=keyscan();/按键扫描函数,7.2 C51语言基本语法,C51语言的函数及程序结构,C51语言的数据类型及存储类型,7.2.3 C51语言的运算符,7.2.4 C51语言的语句,C51语言的指针,7.2.7 中断函数、头文件及绝对地址访问,7.2.5 C51语言的数组,实战1,实战2,实战3,实战4,实战5,实战6,实战7,7.2.2 C51语言的数据类型及存储类型,C51的数据有常量和变量之分。在程序运行中其值不变的量。可以为十进制数、十六进制数(用0 x表示,汇编后缀H)、字符(括起)和字符串型常量(“”括起)。用符号表示常量,符号常用大写表示,此符号需用宏定义指令(#define)对其进行定义(相当于汇编的“EQU”伪指令)。#define AA 100;相当于AA EQU 100,常量,数值型常量:,符号型常量:,在程序运行中其值可以改变的量,常用小写字母表示。一个变量由两部分组成:变量名和变量值。定义一个变量,编译系统就会自动为它安排一个存贮区,具体的地址值,用户不必在意。,变量,在C51中,变量在使用前必须对变量进行定义,指出变量的数据类型和存储模式。以便编译系统为它分配相应的存储单元。定义的格式如下:,C51的变量声明的一般格式如下 数据类型 存储类型 变量名=初值;,例如:unsigned char code Flag=0 x0f;声明一个无符号的char型变量Flag,赋初值0 x0f;所在的存储空间在的ROM中。,C语言中的基本数据类型,类型,符号,关键字,数的表示范围,所占位数,整型,字符型,实型,有,无,(signed)int,16,-3276832767,(signed)short,16,-3276832767,(signed)long,32,-21474836482147483647,16,unsigned int,065535,32,04294967295,unsigned long int,unsigned short int,16,065535,有,float,32,有,char,8,-128127,无,unsigned char,8,0255,1.176E383.40E+38,一、C51的数据类型:,表明该数据有无符号、位数多少位,整数还是小数等信息,(续)C51的数据类型扩充定义,sfr:特殊功能寄存器声明sfr16:sfr的16位数据声明sbit:特殊功能位声明bit:位变量声明,例:sfr SCON=0 x98;sfr16 T2=0 xCC;sbit OV=PSW2;bit keyscanflag=1;,二、C51数据的存储类型:,指明变量所处的单片机的存储器区域情况。,MCS-51存储器结构图(a)程序存储器地址分配;(b)数据存储器地址分配,FFH,1FH,00FFH,C51的变量声明的一般格式如下 数据类型 存储类型 变量名=初值,;例如:unsigned char code Flag=0 x0f;就是声明一个无符号的char型变量Flag,并给他赋初值为0 x0f;并且声明他所在的存储空间在片内统一编址的ROM中。声明中,如果没有存储类型,则数据默认的存储空间为data型,也就是在片内RAM中。,char data var;/*字符变量var定位在片内RAM区char code MSG=ENTER PARAMETER:/*字符数组定位在程序存贮区*/unsigned long xdata array100;/*无符号长型数组在片外RAM区,每 元素占4bytes*/float idata x,y,z;/*实型变量x,y,z,在片内用间址访问的内部RAM区*/bit lock;/*位变量lock定位在片内RAM可位寻址区*/unsigned int pdata dimension;/*无符号整型变量dimension定位在分页的外部RAM区*/unsigned char xdata vector 1044;/*无符号字符型三 维数组,定位在片外RAM区*/,7.2 C51语言基本语法,7.2.1 C51语言的函数及程序结构,7.2.2 C51语言的数据类型及存储类型,C51语言的运算符,7.2.4 C51语言的语句,C51语言的指针,7.2.7 中断函数、头文件及绝对地址访问,7.2.5 C51语言的数组,实战1,实战2,实战3,实战4,实战5,实战6,实战7,与C语言基本相同:+-*/%(加 减 乘 除 取余)=(位右移 位左移)&|(按位与 按位或)(按位异或 按位取反),7.2.3 C51语言的运算符,(&)逻辑与 和(&)按位与有什么区别?,即判断&两侧的表达式是否都为真,都为真则此&表达式值为真;即将&两侧的数用二进制展开,每一位都求与运算最后得到的二进制数即为结果;逻辑与结果只讲真和假,而按位与得出的却是实实在在的一个数,9=00001001(&)8=00001000 00001000,1(&)0 0,9(&)8 1,&是逻辑与:,&是按位与:,C51的左右移动命令()与汇编指令环移有什么区别?,C51语言的左右移位都是逻辑移位,也就是不循环,左移总是补0,但右移就不同了,如果被移位的变量是一个有符号变量,右移是补符号位,也就是最高位是1就补1,是0就补0,如果被移位的数是一个无符号变量,则右移补0。xy,表示将数据x左移y位,低位补0高位丢弃,汇编指令移位都是循环移位,数据不丢失。,A,1,0,1,1,1,1,0,1,RL A,i,1,0,1,1,1,1,0,1,i 1,0,0,7.2 C51语言基本语法,7.2.1 C51语言的函数及程序结构,7.2.2 C51语言的数据类型及存储类型,7.2.3 C51语言的运算符,C51语言的语句,C51语言的指针,7.2.7 中断函数、头文件及绝对地址访问,7.2.5 C51语言的数组,实战1,实战2,实战3,实战4,实战5,实战6,实战7,1、控制语句 if()else 条件语句 for()循环语句 while()循环语句 do-while()循环语句switch/case 多分支选择句continue 结束本次循环语句break 终止执行循环语句goto 跳转语句return 从函数返回值语句,7.2.4 C51语言的语句,2、空语句它仅是由一个分号“;”构成,什么也不做,用于消耗机器周期,类似NOP3、表达式语句 一个表达式和一个分号构成,如sum=x+y;4、复合语句 一些语句用括起来就构成复合语句5、函数调用语句 调用已经定义过的函数,7.2 C51语言基本语法,7.2.1 C51语言的函数及程序结构,7.2.2 C51语言的数据类型及存储类型,7.2.3 C51语言的运算符,7.2.4 C51语言的语句,C51语言的指针,7.2.7 中断函数、头文件及绝对地址访问,C51语言的数组,实战1,实战2,实战3,实战4,实战5,实战6,实战7,7.2.5 C51语言的数组,数组是同一类型的一组变量的有序集合,利用数组名加下标形式引用数组各个元素。,一维 数据类型 数组名 常量表达式;,多维 数据类型 数组名 常量表达式1.,常量表达式N;,定义一维或多维数组的方式:,unsigned int xcount 10;/定义无符号整形数组,有10 个数据单元float outnum 10,10;/定义浮点型数组,有100 个数据单元,7.2 C51语言基本语法,7.2.1 C51语言的函数及程序结构,7.2.2 C51语言的数据类型及存储类型,7.2.3 C51语言的运算符,7.2.4 C51语言的语句,C51语言的指针,7.2.7 中断函数、头文件及绝对地址访问,7.2.5 C51语言的数组,实战1,实战2,实战3,实战4,实战5,实战6,实战7,7.2.6 C51语言的指针,一、指针与指针变量 内存中每一个单元都有一个地址编号,指针就是存储单元地址,存储这个地址的变量称为指针变量。,指针的值:,指针的类型:,指针的定义:,指针存放的是某个变量在内存中的地址,指针的类型就是该指针所指向的变量的类型,被指数据类型 被指存贮类型*指针变量名;,被指数据类型 被指存贮类型*指针变量名;,C51中提供了两个专门的运算符:*指针运算符&取地址运算符,取地址运算符“&”放在变量的前面,通过它取得变量的地址。例如:设变量x的内容为12H,地址为2000H p=&x;/实现将x变量的地址2000H送给指针变量p,指针变量p指向变量x,以后可以通过*p访问变量x。指针运算符“*”放在指针变量前面,通过它实现访问以指针变量的内容为地址所指向的存储单元。例如:x=*p;/实现把地址为2000H的存储单元的内容送给变量x,注:汇编语言程序中对符号地址n和m需用EQU伪指令进行地址定义。C语言应对变量n、m和指针变量P需进行类型定义。表中&为取地址运算符,*为取内容运算符。,下面表格表示两种语言将m单元的内容送n单元的对照语句。,7.2 C51语言基本语法,7.2.1 C51语言的函数及程序结构,7.2.2 C51语言的数据类型及存储类型,7.2.3 C51语言的运算符,7.2.4 C51语言的语句,C51语言的指针,中断函数、头文件及绝对地址访问,7.2.5 C51语言的数组,实战1,实战2,实战3,实战4,实战5,实战6,实战7,一、C51的包含的头文件,C51强大功能及高效率在于提供了丰富的可以直接调用的库函数,包括I/O操作、内存分配、字符串操作、数据类型转换、数学计算等函数,都在相应的头文件里面。通常有:reg51.h math.h ctype.h stdio.h stdlib.h absacc.h instins.h,7.2.7 头文件、中断函数及绝对地址访问,包含的头文件的方法,#include#include,reg51.h-51的特殊寄存器定义reg52.h-52的特殊寄存器定义absacc.h-包含访问8051不同存储区的宏定义ctype.h-字符转换和分类程序intins.h-包含左右环移、空操作等汇编程序math.h-数学程序stdlib.h-存储器分配程序stdio.h-流输入和输出程序string.h-字符转操作程序,缓冲区操作程序,二、中断服务程序,void 函数名(void)interrupt n using m,二、中断服务程序,void 函数名(void)interrupt n using m,三、绝对地址访问 C51对存贮器和外接I/O口的绝对地址访问可以通过指针访问,也可以通过库函数访问。1.通过指针访问绝对地址,*ziweima=0 x01;/指针就是变量的地址,前加*表示该地址的变量,将01H送给指针所指向的片外RAM8002H单元,uchar xdata*ziweima=0 x8002;/定义了一个指向片外RAM8002H单元的指针,uchar类型说明指针所指向的单元的内容是无符号八位的,2.通过库函数访问绝对地址 利用绝对地址访问的头文件absacc.h可对不同的存贮区进行访问。该头文件的函数有:CBYTE(访问code区ROM字符型)DBYTE(访问data区字符型)PBYTE(访问pdata或外部I/O口)XBYTE(访问xdata或外部I/O口),例:#include#define ziweima XBYTE0 x8002ziweima=0 x01;,7.3 C51语言程序设计实战,实战1 从点亮一个LED开始实战2 闪烁一个LED实战3 玩转流水灯实战4 中断控制流水灯实战5 定时器控制流水灯实战6 计数器控制流水灯实战7 片外RAM数据读取控制流水灯,实战1、P1.0发光二极管阴极,二极管阳极通过电阻接VCC,向引脚送0则该二极管发光。要求点亮P1.0上的发光二极管(0亮1灭)。,修改程序,P1.0输出方波,发光二极管闪烁,b、汇编语言实现,c、C51语言实现,a、Proteus仿真图,a、Proteus仿真图,c、C51语言实现,b、汇编语言实现,实战2、P1.0发光二极管阴极,二极管阳极通过电阻接VCC,向引脚送0则该二极管发光。要求P1.0输出方波,发光二极管L1闪烁。,修改程序,P1口八个发光二极管循环左右移,b、汇编语言实现,c、C51语言实现,a、Proteus仿真图,a、Proteus仿真图,b、汇编语言实现,c、C51语言实现方法一,c、C51语言实现方法二,实战3、P1.0P1.7接8个发光二极管阴极,二极管阳极通过电阻接VCC,向引脚送0则该二极管发光,要求P1口八个发光二极管循环左移点亮,再循环右移点亮。,修改程序,发光二极管循环左右移花样,b、汇编语言实现,c、C51语言实现,a、Proteus仿真图,a、Proteus仿真图,b、汇编语言实现,c、C51语言实现方法一:分别赋值,c、C51语言实现方法二:数组赋值,c、C51语言实现方法三:环移赋值,c、C51语言实现方法四:移位赋值,c、C51语言实现方法五:指针数组赋值,实战4、通过INT0向CPU申请中断,要求:初时最右边发光二极管点亮1个,每中断一次循环左移一位。,修改程序,利用INT1控制流水灯,修改程序,利用INT0、INT1分别控制流水灯左移和右移,b、汇编语言实现,c、C51语言实现,a、Proteus仿真图,a、Proteus仿真图,b、汇编语言实现,c、C51语言实现方法一,c、C51语言实现方法二,c、C51语言实现,实战5、初时最右边发光二极管点亮1个,定时器T0每定时1秒二极管循环左移一位。,b、汇编语言实现,c、C语言实现,a、Proteus仿真图,修改程序,利用T1每定时2秒控制流水灯,a、Proteus仿真图,b、汇编语言实现,c、C51语言实现,c、C51语言实现,实战6、初时最右边发光二极管点亮1个,用计数器T0每计3个数二极管循环左移一位。,b、汇编语言实现,c、C语言实现,a、Proteus仿真图,修改程序,利用T1计数5次控制流水灯,a、Proteus仿真图,b、汇编语言实现,c、C51语言实现,c、C51语言实现,实战7、通过INT0向CPU申请中断,每中断一次向片外RAM2000H开始的位置送1个流水灯控制数据,并将数据送P1口控制八个发光二极管。,b、汇编语言实现(略),c、C语言实现,a、Proteus仿真图,a、Proteus仿真图,c、C51语言实现,c、C51语言实现,