第3章单片机C51语言程序设计基础.ppt
第3章 单片机C51语言程序设计基础,3.1 语句与流程控制 3.2 函数 3.3 本章小结 3.4 实训三 简易十字路口交通信号灯控制,返回首页,教学提示,C51 语言程序是由函数组成的。函数是C51 语言的基本模块。用C51语言设计程序就是编写函数。从来源看,函数可分为用户自定义函数和标准库函数两大类。在一个C51 语言程序中有且只能有一个名为main的主函数。C51 语言程序的执行部分是由语句组成的。程序的各种主要功能都是由语句实现的。C 语言的语句可分为流程控制语句、表达式语句、复合语句、空语句。本章重点介绍C51语言中语句的使用方法以及C51语言中新增的函数类型中断函数和重入函数。,教学要求,掌握C51语言基本语句的使用方法,包括赋值语句、函数调用语句、复合语句、空语句;掌握C51语言分支语句的使用方法,包括if语句、switch语句;掌握C51语言循环语句的使用方法,包括while语句、dowhile语句、for语句;掌握辅助控制语句break、continue的使用方法;理解中断函数和重入函数的使用方法;掌握常用标准库函数的使用方法。,3.1 语句与流程控制,3.1.1 基本语句 3.1.2 分支语句 3.1.3 循环语句 3.1.4 辅助控制语句,3.1.1 基本语句,基本语句主要用于顺序结构程序的编写。在C51语言中,语句的结束符为分号。,1.赋值语句,在任何合法的赋值表达式的尾部加上一个分号就构成了赋值语句。赋值语句的一般形式为变量=表达式;,赋值语句的作用是先计算赋值号右边表达式的值,然后将该值赋给赋值号左边的变量。,赋值语句是一种可执行语句,应当出现在函数的可执行部分。,在C51语言中,若函数仅进行某些操作而不返回函数值,这时函数的调用可作为一条独立的语句,称为函数调用语句。其一般形式为函数名(实际参数表);,2.函数调用语句,【例3.1】从键盘输入一个3位整数,将其反向输出。例如,输入127,输出应为721。,在C51语言中,把多条语句用一对大括号括起来组成的语句称为复合语句。复合语句又称为“语句块”,其一般格式为 语句1;语句2;语句n;,3.复合语句,注意:大括号之后不再加分号。,复合语句虽然可由多条语句组成,但它是一个整体,相当于一条语句,凡可以使用单一语句的位置都可以使用复合语句。在复合语句内,不仅可以有执行语句,还可以有变量定义(或说明)语句。,如果一条语句只有语句结束符号“;”则称为空语句。,4.空语句,空语句在执行时不产生任何动作,但仍有一定的作用。比如,预留位置或用来作为空循环体。但是,在程序中随意加分号也会导致逻辑上的错误,需要慎用。,3.1.2 分支语句,为了便于理解,图3.2给出一个简单的单片机应用系统。,图3.2 简单的单片机应用系统,1.if语句,if语句的一般形式为:if(表达式)语句;其中,if 是关键字,表达式两侧的圆括号不可少,最后的语句可以是C51语言任意合法的语句。,图3.3给出了if语句的执行过程。可见,if语句是一种单分支语句。,【例3.2】基于图3.2,编程实现下列功能:按下K1键,发光二极管全亮;弹起K1键后,发光二极管全灭。,图3.3 if语句的执行过程,2.if-else语句,if-else语句的一般形式为:if(表达式)语句1;else 语句2;其中,语句1、语句2可以是C51语言中任意合法的语句。,注意:else不是一条独立的语句,只是if语句的一部分,在程序中else必须与if配对,共同组成一条if-else 语句。,【例3.3】基于图3.2,编程实现下列功能:开机后,全部发光二极管不亮。只有当K1键与K2键同时按下,发光二极管才全亮;否则发光二极管全灭。,图3.4给出了if-else语句的执行过程。可见,if-else语句是一种二分支语句。,图3.4 if-else语句的执行过程,3.if-else-if语句,if-else-if语句的一般形式:if(表达式1)语句1;else if(表达式2)语句2;else语句3;if-else-if语句又称为嵌套的if-else语句,其中,语句1、语句2、语句3可以是C51语言中任意合法的语句。,图3.5给出了if-else-if语句的执行过程。可见,只要一直嵌套下去,if-else-if语句可实现多分支程序设计要求。,【例3.4】基于图3.2,编程实现下列功能:分别用按键K1、K2、K3、K4控制发光二极管D0、D1、D2、D3的亮灭。当键按下时点亮对应的发光二极管;当键弹起时熄灭对应的发光二极管。4个按键的优先权从K1到K4依次减小,若4个按键都按下,则只有D0亮。,图3.5 if-else-if语句的执行过程,4.switch语句,switch语句的一般形式:switch(表达式)case 常量表达式1:语句1;case 常量表达式2:语句2;case 常量表达式n:语句n;default:语句n+1;,图3.6给出了switch语句的执行过程。,图3.6 switch语句的执行过程,【例3.5】基于图3.2,编程实现下列功能:开机后,全部LED 不亮。D0的亮灭仅受K1键控制,与其他按键无关,即不管其他按键处在什么状态,只要按下K1键就点亮D0,弹起K1键就熄灭D0。同理,要求D1的亮灭仅受K2键控制,D2的亮灭仅受K3键控制,D3的亮灭仅受K4键控制。,5.在switch 语句中使用break 语句,break 语句又称为间断语句,其作用是使程序的执行立即跳出switch 语句,从而使switch 语句真正起到分支的作用。,为了解决【例3.5】中存在的问题,必须在switch 语句中使用break 语句,即在每个语句的后面添加一条“break;”语句。,使用break 语句后,switch 语句的一般格式:switch(表达式)case 常量表达式1:语句1;break;case 常量表达式2:语句2;break;case 常量表达式n:语句n;break;default:语句n+1;,使用break 语句后,switch 语句的执行过程如图3.7所示。,【例3.6】在switch语句中使用break语句,对例3.5进行改写。,图3.7 使用break语句后switch语句的执行过程,3.1.3 循环语句,在程序设计中经常会遇到需要重复执行的操作,如延时、累加、累乘、数据传递等,利用循环结构来处理各类重复操作既简单又方便。C51 语言中提供了3种语句来实现循环结构,分别是while 语句、do-while 语句和for 语句。其中,while语句又称为“当”型循环,do-while语句又称为“直到”型循环。,1.while 语句,while 语句的一般形式:while(表达式)循环体其中,“表达式”可以是C51语言中任意合法的表达式,其作用是控制循环体是否执行;“循环体”是循环语句中需要重复执行的部分,可以是一条简单的可执行语句,也可以是用大括号括起来的复合语句。,while 语句的执行过程如图3.8所示。while 语句的特点是:先判断,后执行。,(1)要定义循环控制变量。(2)要确定循环变量的初值、终值、增量(步长)。(3)要保证每执行一次循环体,循环控制变量的值按增量向终值靠近一些,即要避免死循环。,图3.8 while 语句的执行过程,【例3.7】基于图3.2,编程实现下列功能:开机后,全部发光二极管不亮;按下K1键,D0闪烁;松开K1键,D0停止闪烁并熄灭。,while 语句的使用注意事项:,2.do-while 语句,do-while 语句的一般格式:do 循环体 while(表达式);其中,“表达式”可以是C51语言中任意合法的表达式,其作用是控制循环体是否执行;“循环体”可以是C51语言中任意合法的可执行语句;最后的“;”不可丢,表示do-while 语句结束。,do-while 语句的执行过程如图3.9所示。do-while 语句的特点是:先执行,后判断。,【例3.8】基于图3.2编写程序,用do-while语句实现下列功能:开机后,全部发光二极管不亮;按下K1键,D0闪烁;松开K1键,D0停止闪烁并熄灭。,图3.9 do-while 语句的执行过程,3.for 语句,for 语句的典型应用形式:for(循环变量初值;循环条件;循环变量增值)循环体,for语句的一般形式:for(表达式1;表达式2;表达式3)循环体其中,“表达式1”、“表达式2”、“表达式3”可以是C51语言中任意合法的表达式,3个表达式之间用“;”隔开,其作用是控制循环体是否执行;循环体可以是C51语言中任意合法的可执行语句。,for 语句的执行过程如图3.10所示。,(1)for 语句中的表达式可以部分或全部省略,但两个“;”不可省略。例如:for(;)D0=!D0;3个表达式均被省略,因缺少条件判断,循环将会无限制地执行,形成无限循环(通常称为死循环)。,在使用for语句时应注意以下两点:,图3.10 for语句的执行过程,(2)所谓省略,只是在for 语句中的省略。实际上是把所需表达式放在for的循环体中或for的语句前面。下面几种for 语句的表达方式是等价的。,表达方式1(正常情况):sum=0;for(i=1;i=100;i+)sum+=i;表达方式2(省略表达式1):sum=0;i=1;for(;i=100;i+)sum+=i;表达方式3(省略表达式3):sum=0;for(i=1;i=100;)sum+=i;i+;表达方式4(省略表达式1和表达式3):sum=0;i=1;for(;i=100;)sum+=i;i+;,【例3.9】基于图3.2编程实现下列功能:开机后,全部LED不亮;按下K1键,D0闪烁;松开K1键,D0停止闪烁并熄灭。,4.循环的嵌套,在编写程序时,嵌套循环的书写要采用缩进形式,使程序层次分明,例如:for(i=1;i=10;i+)/外层循环 for(j=1;j=10;j+)/中层循环 for(k=1;k=10;k+)/内层循环循环语句,在一个循环体内又完整地包含了另一个循环称为循环嵌套。循环的嵌套可以有多层,但每一层循环在逻辑上必须是完整的。,在进行循环嵌套时,应注意以下几点:,【例3.10】利用双层循环打印99乘法表。,(1)内外循环的循环变量不应相同。(2)内外循环不应交叉。(3)只能从循环体内转移到循环体外,反之不行。,5.几种循环的比较,(1)3种循环可相互替代处理同一问题。(2)do-while循环至少执行一次循环体,而while及for 循环则不然。(3)while 及do-while 循环多用于循环次数不可预知的情况,而for 循环多用于循环次数可以预知的情况。,3.1.4 辅助控制语句,在循环过程中,有时不一定要执行完所有的循环后才终止,每次循环也不一定要执行完循环体中的所有语句,可能在一定的条件下跳出循环或进入下一轮循环。为了方便对程序流程的控制,除了前面介绍的流程控制语句外,C51 语言还提供了两种辅助控制语句:break 和continue 语句。,1.break 语句,【例3.11】求其平方数小于100 的所有整数。,break 语句的一般形式:break;break 语句的功能是:终止所在的switch 语句;跳出本层循环体,从而提前结束本层循环。,2.continue 语句,【例3.12】求1100之间不能被3整除的数。,continue 语句的一般形式:continue;continue 语句的功能是:用于循环体内结束本次循环,接着进行下一次循环的判定。,3.2 函数,3.2.1 中断函数 3.2.2 重入函数 3.2.3 标准库函数,C51语言程序是由一个个函数构成的。所谓函数,是指可以被其他程序调用的具有特定功能的一段相对独立的程序。引入函数的主要目的有两个:一是为了解决代码的重复;二是结构化模块化编程的需要。,C51语言中函数定义的一般格式:,其中,大括号以外的部分称为函数头;大括号以内的部分称为函数体。如果函数体内无语句,则称之为空函数。空函数不执行任何操作,定义它的目的只是为了以后程序功能的扩充。,returntypefuncname(args)small|compact|largereentrantinterrupt nusing n局部变量定义可执行语句,用C51语言设计程序,就是编写函数。在构成C51语言设计程序的若干个函数中,有且仅有一个是主函数main()。因为C51 语言程序的执行都是从main()函数开始的,也是在main()函数中结束整个程序运行的,其他函数只有在执行main()函数的过程中被调用才能被执行。,从函数的定义格式可以看出,C51语言在4个方面对标准C语言的函数进行了扩展:指定函数的存储模式;指定函数是可再入的;指定函数是一个中断函数;指定函数所用的工作寄存器组。,同变量一样,函数也必须先定义后使用。所有函数在定义时都是相互独立的,一个函数中不能再定义其他函数,但可以相互调用。函数调用的一般规则是:主函数可以调用其他普通函数;普通函数之间可以相互调用;普通函数不能调用主函数。,从用户使用的角度看,函数可以分成两大类:标准库函数和用户自定义函数。下面重点介绍C51语言中新增的中断函数、重入函数和常用的标准库函数。,3.2.1 中断函数,51系列单片机通常有5个中断源,为了方便使用,C51语言对它们进行了编号,见表3-1。,表3-1 51系列单片机的中断源及其编号,当CPU正在执行一个特定任务时,可能有更紧急的事情需要CPU处理,这就涉及中断优先级。高优先级中断可以中断正在处理的低优先级中断程序,因此最好给每种不同优先级程序分配不同的工作寄存器组,以达到压栈保护的目的。,中断函数的定义格式:函数类型 函数名()interrupt 中断编号 using 工作寄存器组编号 可执行语句,例如,下列程序片段为定时器/计数器0的中断服务程序,指定使用第2组工作寄存器。unsigned int CNT1;unsigned char CNT2;void Timer()interrupt 1 using 2if(+CNT1=1000)/CNT1计数到1000CNT2+;/CNT2开始计数CNT1=0;/CNT1清零,在编写中断函数时,应特别注意以下几点:(1)中断函数为无参函数,即不能在中断函数中定义任何变量,否则将导致编译错误。(2)中断函数没有返回值,即应将中断函数定义为void类型。(3)中断函数不能直接被调用,否则将导致编译错误。(4)中断函数使用浮点运算时要保存浮点寄存器的状态。(5)如果在中断函数中调用了其他函数,则被调用函数所使用的寄存器组必须与中断函数相同。(6)由于中断的产生不可预测,中断函数对其他函数的调用可能形成递归调用,必要时可将被中断函数调用的其他函数定义成再入函数。,有关51系列单片机的中断控制及中断函数编写,将在第4章详细讲述。,3.2.2 重入函数,在主函数和中断函数中都可调用的函数容易产生问题。51系列单片机一般使用寄存器传递函数参数,局部变量一般存放在片内RAM中。由于片内RAM的容量很小(只有128B),函数再入时会破坏或覆盖上次调用的数据。为此,C51语言提供了关键字reentrant,用于将相应的函数指定为可重入函数。所谓重入函数,是指可以在函数体内间接调用其自身的函数。,重入函数可以被递归调用和多重调用,而不用担心变量被覆盖,因为每次函数调用中的局部变量都会被单独保存起来。,【例3.13】重入函数的定义与使用。,重入函数的定义格式:函数类型 函数名(形参列表)reentrant局部变量说明可执行语句,3.2.3 标准库函数,根据51系列单片机本身的特点,C51语言编译系统在C语言的基础上又扩展了以下几种库函数:(1)C51S.LIB:Small模式,无浮点运算。(2)C51FPS.LIB:Small模式,有浮点运算。(3)C51C.LIB:Compact模式,无浮点运算。(4)C51FPC.LIB:Compact模式,有浮点运算。(5)C51L.LIB:Large模式,无浮点运算。(6)C51FPL.LIB:Large模式,有浮点运算。,所谓标准库函数,是指由编译系统提供的、用户可以直接调用的函数。在程序设计中,多使用库函数使程序代码简单,结构清晰,易于调试和维护。,每个库函数都在相应的头文件中给出了函数原型声明。在使用库函数时,必须在源程序的开头处用#include命令将有关的头文件包含进来,例如:#include#include void main(),值得注意的是,C51语言中的某些库函数的参数和调用格式与标准C语言有所不同,如isdigit()函数的返回值类型是bit而不是int。,在C51语言中,调用标准库函数的方式有以下两种:(1)作为表达式的一部分。例如,求y=|x|+3可以通过调用abs()函数来实现:y=abs(x)+3;(2)作为独立的语句完成某种操作。例如:printf(*n);可以在标准输出设备上输出一行5个连续的“*”号。,Keil C51提供了相当丰富的标准库函数,并把它们分门别类地归属到不同的头文件中(表3-2)。标准库函数的原型、功能描述、返回值、重入属性以及应用举例在Keil C51集成开发环境提供的帮助文档中均可以查到。,以数学类库函数abs()为例,查阅标准库函数的方法,(1)在Keil C51集成开发环境下,单击工程管理器中的Books标签,即可看到Keil C51提供的帮助文档,如图3.15所示。,图3.15 Keil C51的帮助文档,(2)在图3.15所示的界面中,双击C51库函数(C51 Library Functions)选项,打开C51库函数帮助窗口,如图3.16所示。,图3.16 Keil C51的库函数,(3)在图3.16的左侧窗口找到abs并单击,则在图3.16的右侧窗口中可以看到有关库函数abs()的介绍内容,包括该函数所属的头文件、函数原型、功能描述、再入属性以及应用举例等,如图3.17所示。,图3.17 库函数abs()的帮助文档,限于篇幅,对Keil C51的标准库函数在此不一一进行介绍,感兴趣的读者可以参阅有关的专业书籍。,【例3.16】标准输入函数scanf()的使用。,【例3.17】标准库函数的综合使用。,【例3.15】字符串复制函数strcpy()、字符串合并函数strcat()的使用。,【例3.14】标准输出函数printf()的使用。,3.3 本章小结,2.C51语言的基本语句有赋值语句、函数调用语句、复合语句、空语句。,1.作为结构化程序设计语言的一种,C51语言同样具有顺序、分支、循环3种基本结构,并提供了丰富的可执行语句形式来实现这3种基本结构。,3.C51语言的流程控制语句有if语句、switch语句、while语句、do-while语句、for语句。,4.C51语言的辅助控制语句有break、continue。,5.所谓函数,是指可以被其他程序调用的具有特定功能的一段相对独立的程序。引入函数的主要目的有两个:一是为了解决代码的重复问题;二是结构化模块化编程的需要。C51语言在4个方面对标准C语言的函数进行了扩展:指定函数的存储模式;指定函数是可再入的;指定函数是一个中断函数;指定函数所用的工作寄存器组。,6.C51语言提供了丰富的标准库函数。,3.4 实训三 简易十字路口交通信号灯控制,简易十字路口交通信号灯控制仅考虑以下简单情况:若东西方向为放行线,则南北方向为禁止线;反之亦然。交通信号灯的变化是固定的,变化规律见表3-3。,表3-3 简易十字路口交通信号灯的变化规律,1.硬件电路设计,图3.23 系统硬件电路,2.软件设计,根据图3.23,当Pl口有关引脚输出高电平1时,则点亮相应的“信号灯”;当Pl口有关引脚输出低电平0时,则熄灭相应的“信号灯”。为了实现交通运行状态的控制要求,Pl口输出的控制码有4种,见表3-4。,表3-4 不同运行状态时的控制码,根据交通灯的运行状态,主程序流程图如图3.24所示。,图3.24 主程序流程图,思考与练习,1.C51语言中有几种基本语句?2.C51语言中有几种流程控制语句?简述它们的执行过程。3.C51语言中的辅助控制语句break、continue的作用是什么?4.在使用中断函数时应注意哪些事项?5.在什么情况下应将函数定义为再入函数?6.在实训三中,放行线的实际情况是黄灯亮时绿灯灭,要实现这一功能应如何修改程序?7.在实训三中,如果让黄灯闪烁,应如何修改程序?,第3章 结束,