《第6章 C语言编程与应用》由会员分享,可在线阅读,更多相关《第6章 C语言编程与应用(160页珍藏版)》请在金锄头文库上搜索。
1、18/13/20246.1概概述述6.251单片机单片机C语言编写的一般方法语言编写的一般方法6.3C51数据类型及在数据类型及在MCS-51中的存储方式中的存储方式6.4C51语言的程序结构语言的程序结构6.5C语言在语言在MCS-51单片机中的典型运用单片机中的典型运用第第6章章C语言编程与应用语言编程与应用8/13/2024128/13/20246.1概概述述传传统统开开发发单单片片机机系系统统主主要要用用汇汇编编语语言言编编写写系系统统程程序序。汇汇编编语语言言的的缺缺点点:可可读读性性和和结结构构较较差差,可可移移植植性性也也不不好好,跨跨硬硬件件平平台台移移植植几几乎乎不不可可能能
2、。采采用用汇汇编编语语言言编编写写单单片片机机应应用用程序的周期长,测试和排错比较困难,产品开发周期变长程序的周期长,测试和排错比较困难,产品开发周期变长。为为了了提提高高编编写写系系统统和和应应用用程程序序的的效效率率,改改善善程程序序的的可可读读性性和和可可移移植植性性,缩缩短短产产品品开开发发周周期期,采采用用高高级级语语言言的的开开发发平台来开发单片机系统已经成为时尚和趋势。平台来开发单片机系统已经成为时尚和趋势。基基于于高高级级语语言言开开发发平平台台进进行行单单片片机机开开发发,具具有有开开发发速速度度快快、语语言言简简洁洁易易读读、可可移移植植性性好好、可可进进行行结结构构化化程
3、程序序设设计计和和多多人人协协同同工工作作、可可进进行行脱脱离离硬硬件件平平台台的的软软件件仿仿真真等等优优点点。实实践践证证明明,采采用用高高级级语语言言开开发发单单片片机机系系统统的的效效率率要要比比用用汇汇编语言的高几倍甚至几十倍。编语言的高几倍甚至几十倍。8/13/2024238/13/2024单片机的单片机的高级语言高级语言包括:包括:Basic语言语言、PL/M语言语言和和C/C+语言语言。Basic语言主要应用在语言主要应用在MCS-51系列单片机系列单片机上,效果不是很理想,现在已经不再使用。上,效果不是很理想,现在已经不再使用。PL/M语言语言对硬件的控制能力和代码效率都很好
4、,但局限于对硬件的控制能力和代码效率都很好,但局限于Intel公司的单片机系列,移植性差。公司的单片机系列,移植性差。C/C+语言语言是目前单是目前单片机的主流编程语言。片机的主流编程语言。8/13/2024348/13/2024单片机单片机C语言编译器语言编译器不仅把开发者的不仅把开发者的C语言编译成语言编译成8051可以识别的机器码,更主要的是能够自动安排程可以识别的机器码,更主要的是能够自动安排程序存储器的空间,分配序存储器的空间,分配8051内部内部RAM与外部与外部RAM的空的空间、自动安排堆栈位置。这些事情都是汇编语言开发间、自动安排堆栈位置。这些事情都是汇编语言开发者必须自己作的
5、。者必须自己作的。C51编译器还可以把不同函数的数据编译器还可以把不同函数的数据实行覆盖有效利用片上有限的实行覆盖有效利用片上有限的RAM空间。空间。一般情况下只懂一般情况下只懂C语言不懂得单片机的指令集的开发语言不懂得单片机的指令集的开发者也能够用者也能够用C51编写完美的单片机程序。所以编写完美的单片机程序。所以开发者学开发者学习单片机而不懂习单片机而不懂C语言将在激烈的市场竞争中处于十分语言将在激烈的市场竞争中处于十分不利的地位。不利的地位。8/13/2024458/13/20241单片机应用系统开发的软硬件环境构成单片机应用系统开发的软硬件环境构成补充:补充:单片机应用系统开发的软硬件
6、环境单片机应用系统开发的软硬件环境当用户目标系统设计完成后,还需要应用软件支持,用户当用户目标系统设计完成后,还需要应用软件支持,用户目标系统才能成为一个满足用户要求的单片机应用系统。但目标系统才能成为一个满足用户要求的单片机应用系统。但该用户目标系统不具备自开发能力,需要借助于单片机仿真该用户目标系统不具备自开发能力,需要借助于单片机仿真器(也称单片机开发系统)完成该项工作。器(也称单片机开发系统)完成该项工作。8/13/2024568/13/2024一个典型的单片机系统开发环境组成如图所示。一个典型的单片机系统开发环境组成如图所示。单片机系统开发环境组成8/13/2024678/13/20
7、242单片机应用系统开发工具选择原则单片机应用系统开发工具选择原则全地址空间的仿真。全地址空间的仿真。不占用任何用户目标系统的资源。不占用任何用户目标系统的资源。必须实现硬断点,并且具有灵活的断点管理功能。必须实现硬断点,并且具有灵活的断点管理功能。硬件实现单步执行功能。硬件实现单步执行功能。可跟踪用户程序执行。可跟踪用户程序执行。可观察用户程序执行过程中的变量和表达式。可观察用户程序执行过程中的变量和表达式。可中止用户程序的运行或用户程序复位。可中止用户程序的运行或用户程序复位。系统硬件电路的诊断与检查。系统硬件电路的诊断与检查。支持汇编和高级语言源程序级调试。支持汇编和高级语言源程序级调试
8、。8/13/2024788/13/20243使用使用JTAG界面单片机仿真开发环境界面单片机仿真开发环境JTAG仿真开发环境如图所示。仿真开发环境如图所示。在在JTAG单片机仿真开发环境单片机仿真开发环境中,中,JTAG适配器提供了计算机通信口到单片机适配器提供了计算机通信口到单片机JTAG口的透口的透明转换,并且不出借明转换,并且不出借CPU和程序存储器给应用系统,使得仿和程序存储器给应用系统,使得仿真更加贴近实际目标系统。单片机内部已集成了基于真更加贴近实际目标系统。单片机内部已集成了基于JTAG协议调试和下载程序。协议调试和下载程序。8/13/2024898/13/2024在线编程目前有
9、两种实现方法:在线编程目前有两种实现方法:在系统编程(在系统编程(ISP)和和在应用在应用编程(编程(IAP)。)。ISP一般通过单片机专用的串行编程接口对单片机一般通过单片机专用的串行编程接口对单片机内部的内部的Flash存储器进行编程,而存储器进行编程,而IAP技术是从结构上将技术是从结构上将Flash存储存储器映射为两个存储体,当运行一个存储体上的用户程序时,可对器映射为两个存储体,当运行一个存储体上的用户程序时,可对另一个存储体重新编程,之后将控制从一个存储体转向另一个。另一个存储体重新编程,之后将控制从一个存储体转向另一个。ISP的实现一般需要很少的外部电路辅助实现,而的实现一般需要
10、很少的外部电路辅助实现,而IAP的实现更加的实现更加灵活,通常可利用单片机的串行口接到计算机的灵活,通常可利用单片机的串行口接到计算机的RS232口,通过口,通过专门设计的固件程序对内部的专门设计的固件程序对内部的FLASH存储器编程。存储器编程。4单片机的在线编程单片机的在线编程8/13/20249108/13/20246.251单片机单片机C语言编写的一般方法语言编写的一般方法KeelC51软件软件是目前最流行开发是目前最流行开发8051系列单片机的软件工系列单片机的软件工具具,这从近年来各单片机仿真机厂商纷纷宣布全面支持,这从近年来各单片机仿真机厂商纷纷宣布全面支持KeilC51即可看出
11、。即可看出。KeilC51提供了包括提供了包括C编译器、宏汇编、连接器、编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个通过一个集成开发环境(集成开发环境(Vision3IDEIntegrationDevelopEntironment )将这些部份组合在一起。掌握这一软件的使用将这些部份组合在一起。掌握这一软件的使用对于使用对于使用8051系列单片机的爱好者来说是十分必要的,即使不系列单片机的爱好者来说是十分必要的,即使不使用使用C语言而仅用汇编语言编程,其方便易用的集成环境、强语言而仅用汇编语言编程,
12、其方便易用的集成环境、强大的软件仿真调试工具也会令开发者事半功倍。大的软件仿真调试工具也会令开发者事半功倍。用用C语言编语言编写程序,离不开写程序,离不开KeilC51软件软件!8/13/202410118/13/2024Vision3IDE主要特性主要特性:Vision3IDE基于基于Windows的开发平台,包含一个高的开发平台,包含一个高效的编辑器、一个项目管理器和一个效的编辑器、一个项目管理器和一个MAKE工具。工具。Vision3IDE支持所有的支持所有的KeilC51工具,包括工具,包括C编译编译器、宏汇编器、连接器、宏汇编器、连接/定位器、目标代码到定位器、目标代码到HEX的转的
13、转换器。换器。Vision3IDE内嵌多种符合当前工业标准的开发工具,内嵌多种符合当前工业标准的开发工具,可以完成从工程建立、管理、编译连接、目标代码的生可以完成从工程建立、管理、编译连接、目标代码的生成、软件仿真、硬件仿真等完整的开发流程。成、软件仿真、硬件仿真等完整的开发流程。8/13/202411128/13/2024集成开发环境集成开发环境C51编译器和编译器和A51汇编器汇编器LIB51库管理器库管理器BL51链接器链接器/定位器定位器Vision3软件调试器软件调试器Vision3IDE硬件调试器硬件调试器RTX51实时操作系统实时操作系统Vision3IDE主要特性如下:主要特性
14、如下:8/13/202412138/13/20246.2.1建立您的第一个建立您的第一个KEILC51项目项目安安 装装 完完 keil软软 件件 后后 , 用用 户户 可可 以以 双双 击击 桌桌 面面“Vision3”运行图标进入运行图标进入IDE环境。环境。1.建立工程文件建立工程文件 在项目开发中,并不是只有一个用在项目开发中,并不是只有一个用C或汇编语言编写的源或汇编语言编写的源程序程序就行了的,还要为项目就行了的,还要为项目选择所用的选择所用的CPU,Keil支持数百支持数百种种CPU,而这些,而这些CPU的特性并不完全相同;还要的特性并不完全相同;还要确定编译、确定编译、汇编、连
15、接的参数,指定调试的方式汇编、连接的参数,指定调试的方式,有一些项目还会有,有一些项目还会有多个文件组成等。为了管理和使用方便,多个文件组成等。为了管理和使用方便,Keil使用工程使用工程(Project)这一概念这一概念,将上述参数设置和所需的所有文件都,将上述参数设置和所需的所有文件都加在一个工程中,只能对工程而不能对单一的源程序进行加在一个工程中,只能对工程而不能对单一的源程序进行编译编译(汇编汇编)和连接等操作。和连接等操作。8/13/202413148/13/2024(1)点击点击“ProjectNewProject.”菜单,出现一个对话框,选择工程要菜单,出现一个对话框,选择工程要
16、保存的路径,输入工程文件名。为了方便管理,通常我们将一个工程保存的路径,输入工程文件名。为了方便管理,通常我们将一个工程放在一个独立文件夹下,如保存到放在一个独立文件夹下,如保存到exam_1文件夹,工程文件的名字为文件夹,工程文件的名字为exam_1,如下图所示,然后单击,如下图所示,然后单击保存保存按钮。工程建立后,此工程名按钮。工程建立后,此工程名变为变为exam_l.uv2。8/13/202414158/13/2024(2)点击点击“保存保存”按钮后,出现下图所示对话框,这个按钮后,出现下图所示对话框,这个对话框要求选择目标对话框要求选择目标CPU(即所用芯片的型号即所用芯片的型号),
17、Keil支持支持的的CPU很多,很多,Keil软件的关键是程序代码的编写,而非用软件的关键是程序代码的编写,而非用户选择什么硬件,我们选择户选择什么硬件,我们选择Atmel公司的公司的89C52芯片。芯片。8/13/202415168/13/2024点击点击ATMEL前面的前面的“+”号,展开该层,点击其中的号,展开该层,点击其中的89C52。出现的界面上页图所示,右边。出现的界面上页图所示,右边【Description】栏栏里是对该型号单片机的基本说明,我们可以单击其他型里是对该型号单片机的基本说明,我们可以单击其他型号单片机浏览一下其功能特点,然后再点击号单片机浏览一下其功能特点,然后再点
18、击“确定确定”按按钮,弹出将钮,弹出将8051初始化代码复制到项目中的询问窗口,初始化代码复制到项目中的询问窗口,如下图所示。如下图所示。 8/13/202416178/13/2024(3)单击单击“否否”按钮,出现下图所示的窗口。如果需要重按钮,出现下图所示的窗口。如果需要重命名命名Target1和和SourceGroup1,在左侧,在左侧ProjectWorkspace区用鼠标左键选中区用鼠标左键选中Target1,再用鼠标左键单,再用鼠标左键单击击Target1,即可重新命名,即可重新命名Target1。用同样的方法可以修。用同样的方法可以修改改SourceGroup1,这里对此不做修改
19、。,这里对此不做修改。8/13/202417188/13/2024到此为止,我们还未建立好一个完整的工程,到此为止,我们还未建立好一个完整的工程,虽然工程名有了,但工程当中还没有源文件及代虽然工程名有了,但工程当中还没有源文件及代码,接下来我们添加文件及代码。码,接下来我们添加文件及代码。 8/13/202418198/13/2024(4)使用菜单使用菜单“FileNew”或者点击工具栏的新建文或者点击工具栏的新建文件按钮,新建文件后窗口界面如图件按钮,新建文件后窗口界面如图2-6所示。所示。8/13/202419208/13/2024此时光标在编辑窗口中闪烁,可以输入用户的应用程序,但此时这
20、此时光标在编辑窗口中闪烁,可以输入用户的应用程序,但此时这个新建文件与我们刚才建立的工程还没有直接的联系,单击保存,窗个新建文件与我们刚才建立的工程还没有直接的联系,单击保存,窗口界面如图口界面如图2-7所示,在所示,在【文件名文件名(N)】编辑框中,输入要保存的文件编辑框中,输入要保存的文件名,同时必须输入正确的扩展名。注意,如果用名,同时必须输入正确的扩展名。注意,如果用C语言编写程序,则语言编写程序,则扩展名必须为扩展名必须为.c;如果用汇编语言编写程序,则扩展名必须为;如果用汇编语言编写程序,则扩展名必须为.asm。这里的文件名不一定要和工程名相同,用户可以随意填写文件名,然这里的文件
21、名不一定要和工程名相同,用户可以随意填写文件名,然后单击后单击【保存保存】按钮。按钮。8/13/202420218/13/2024(5)回到编辑界面,单击回到编辑界面,单击【Target1】前面的前面的“+”号,然后在号,然后在【SourceGroup1】选项上,单击右键,弹出如下图所示的菜单。然后选选项上,单击右键,弹出如下图所示的菜单。然后选择择【AddFilestoGroupSourceGroup1】菜单项,对话框如图菜单项,对话框如图2-9所示。所示。8/13/202421228/13/2024 选中文件后的对话框选中文件后的对话框 8/13/202422238/13/2024图图2-
22、10将文件加入工程后的屏幕窗口将文件加入工程后的屏幕窗口选中选中【exam_1.c】,单击,单击【Add】按钮,再单击按钮,再单击【Close】按钮,然后我们再单击左侧按钮,然后我们再单击左侧【SourseGroup1】前面的前面的“+”号,屏幕窗口如图号,屏幕窗口如图2-10所示所示8/13/202423248/13/2024点亮一个二极管的控制系统硬件电路点亮一个二极管的控制系统硬件电路8/13/202424258/13/2024(6)在编辑窗口中输入点亮一个发光二极管的在编辑窗口中输入点亮一个发光二极管的C语言源程语言源程序:序:#include/52系列单片机头文件系列单片机头文件sb
23、itled1=P10;/声明单片机声明单片机P1口的第一位口的第一位voidmain()led1=0;/*点亮点亮LED发光二极管发光二极管while(1);/程序停止到这里程序停止到这里 8/13/202425268/13/2024程序输入完毕后保存,界面如下图程序输入完毕后保存,界面如下图 。8/13/202426278/13/2024程序输入完毕后保存,界面如下图程序输入完毕后保存,界面如下图。通过以上。通过以上(1)(6)步我们学习了如何在步我们学习了如何在Keil编译环境下建立一个工程。编译环境下建立一个工程。8/13/202427288/13/20242.工程的设置工程的设置见实验
24、指导书中实验一见实验指导书中实验一8/13/202428298/13/20243.软件仿真调试软件仿真调试见实验指导书中实验一见实验指导书中实验一8/13/202429308/13/2024编写并调试让二极管以间隔编写并调试让二极管以间隔1s的时间亮灭闪烁的程序。的时间亮灭闪烁的程序。 #include/52系列单片机头文件系列单片机头文件sbitled1=P10;/声明单片机声明单片机P1口的第一位口的第一位unsignedinti,j;/声明无符号整型变量声明无符号整型变量i,jvoidmain()/主函数主函数while(1)/大循环大循环led1=0;/点亮点亮LED发光二极管发光二极
25、管for(i=1000;i0;i-)/延时延时for(j=110;j0;j-);/led1=1;/关闭关闭LED发光二极管发光二极管for(i=1000;i0;i-)for(j=110;j0;j-); 8/13/202430318/13/2024再来看再来看P1口控制流水灯的电路口控制流水灯的电路8/13/202431328/13/2024如果我们要控制八个发光二极管先是二极管如果我们要控制八个发光二极管先是二极管D1、D3、D5、D7亮,然后是二极管亮,然后是二极管D2、D4、D6、D8亮,亮,则则程序程序为:为:#include/52系列单片机头文件系列单片机头文件unsignedinti
26、,j;/声明无符号整型变量声明无符号整型变量i,jvoidmain()/主函数主函数while(1)/大循环大循环P1=0x55;/点亮点亮LED发光二极管发光二极管for(i=1000;i0;i-)/延时延时for(j=110;j0;j-);/P1=0xAA;/关闭关闭LED发光二极管发光二极管for(i=1000;i0;i-)/延时延时for(j=110;j0;j-);8/13/202432338/13/20246.3.2C语言的标识符和关键字语言的标识符和关键字1标识符标识符标识符是用来标识源程序中某个对象的名字,这些对标识符是用来标识源程序中某个对象的名字,这些对象可以是语句、数据类型
27、、函数、变量、数组等等。象可以是语句、数据类型、函数、变量、数组等等。例如:例如:intcount;/count为整型变量的标识符为整型变量的标识符charname20;/name为包含为包含20个元素的数组的个元素的数组的标识符标识符 C51的标识符可以由字母、数字(的标识符可以由字母、数字(09)和下划线组成,最多)和下划线组成,最多可支持可支持32个字符。其中标识符的第一个字符必须为字母或下划线,个字符。其中标识符的第一个字符必须为字母或下划线,例如例如count2是正确的,而是正确的,而2count则是错误的。通常以下划线开头则是错误的。通常以下划线开头的标识符是编译系统专用的,因此在
28、编写的标识符是编译系统专用的,因此在编写C语言源程序时一般不语言源程序时一般不要使用以下划线开头的标识符。而且要使用以下划线开头的标识符。而且C语言是区分大小写的,语言是区分大小写的,name与与NAME是两个不同的标识符。是两个不同的标识符。 8/13/202433348/13/20246.3.2C语言的标识符和关键字语言的标识符和关键字2关键字关键字关键字是编程语言保留的特殊标识符,它们具有固关键字是编程语言保留的特殊标识符,它们具有固定名称和含义,在程序编写中不允许标识符与关键字定名称和含义,在程序编写中不允许标识符与关键字相同。相同。如如int、if、for等等等等。在。在KeilC5
29、1开发环境的文本编辑开发环境的文本编辑器中编写器中编写C程序,系统会把关键字以不同颜色显示。在程序,系统会把关键字以不同颜色显示。在C语言的程序编写中不允许标识符与关键字相同。与其语言的程序编写中不允许标识符与关键字相同。与其他计算机语言相比,他计算机语言相比,C语言的关键字较少,语言的关键字较少,ANSIC标标准共规定了准共规定了32个关键字,个关键字, 8/13/202434358/13/20246.3.2C语言的标识符和关键字语言的标识符和关键字表表6-1ANSIC标准关键字标准关键字序号序号关键字关键字用途用途说明说明1auto存储种类说明存储种类说明说明局部变量为自动变量,为默认值说
30、明局部变量为自动变量,为默认值2break程序语句程序语句退出最内层循环体退出最内层循环体3case程序语句程序语句switch语句中的选择项语句中的选择项4char数据类型声明数据类型声明声明字符型数据声明字符型数据5const存储类型声明存储类型声明在程序执行过程中不可更改的常量值在程序执行过程中不可更改的常量值6continue程序语句程序语句转向下一次循环转向下一次循环7default程序语句程序语句switch语句中的语句中的“其他其他”分支分支8do程序语句程序语句构成构成dowhile循环结构循环结构9double数据类型声明数据类型声明双精度浮点数双精度浮点数10else程序语
31、句程序语句构成构成ifelse选择结构选择结构11enum数据类型声明数据类型声明枚举枚举12extern存储种类声明存储种类声明在其他程序模块中声明了的全局变量在其他程序模块中声明了的全局变量13float数据类型声明数据类型声明单精度浮点数单精度浮点数14for程序语句程序语句构成构成for循环结构循环结构15goto程序语句程序语句构成构成goto转移结构转移结构8/13/202435368/13/20246.3.2C语言的标识符和关键字语言的标识符和关键字续表续表6-1ANSIC标准关键字标准关键字16if程序语句程序语句构成构成ifelse选择结构选择结构17int数据类型声明数据类
32、型声明整型整型数数18long数据类型声明数据类型声明长整型数长整型数19register存储种类声明存储种类声明寄存器变量寄存器变量20return程序语句程序语句函数返回函数返回21short数据类型声明数据类型声明短整型数短整型数22signed数据类型声明数据类型声明有符号数,二进制数据的最高位为符号位有符号数,二进制数据的最高位为符号位23sizeof运算符运算符计算表达式或数据类型的字节数计算表达式或数据类型的字节数24static存储种类声明存储种类声明静态变量静态变量25struct数据类型声明数据类型声明结构类型数据结构类型数据26switch程序语句程序语句构成构成swit
33、ch选择结构选择结构27typedef数据类型声明数据类型声明为系统固有的数据类型起别名为系统固有的数据类型起别名28union数据类型声明数据类型声明联合类型数据联合类型数据29unsigned数据类型声明数据类型声明无符号数据无符号数据30void数据类型声明数据类型声明无类型数据无类型数据31volatile数据类型声明数据类型声明该变量在程序执行中可被隐含地改变该变量在程序执行中可被隐含地改变32while程序语句程序语句构成构成while和和dowhile循环结构循环结构8/13/202436378/13/2024表表6-2 KeilC51编译器扩展的关键字编译器扩展的关键字 序号序
34、号关键字关键字用途用途说明说明1_at_地址定位地址定位为变量定义存储空间绝对地址为变量定义存储空间绝对地址2alien函数特性说明函数特性说明声明与声明与PL/M51兼容的函数兼容的函数3bdata存储器类型声明存储器类型声明可位寻址的内部可位寻址的内部RAM4bit数据类型声明数据类型声明定义一个位变量或位类型函数定义一个位变量或位类型函数5code存储器类型声明存储器类型声明程序存储器空间(程序存储器空间(ROM)6compact存储模式存储模式使用外部分页使用外部分页RAM的存储模式的存储模式7data存储器类型声明存储器类型声明直接寻址的内部直接寻址的内部RAM8idata存储器类型
35、声明存储器类型声明间接寻址的内部间接寻址的内部RAM9interrupt中断函数声明中断函数声明定义一个中断服务函数定义一个中断服务函数10large存储模式存储模式使用外部使用外部RAM的存储模式的存储模式11pdata存储器类型声明存储器类型声明分页寻址的外部分页寻址的外部RAM12_priority_多任务优先声明多任务优先声明规定规定RTX51或或RTX51Tiny的任务优先级的任务优先级13reentrant可重入函数声明可重入函数声明定义一个可重入函数定义一个可重入函数14sbit数据类型声明数据类型声明定义一个可位寻址的变量定义一个可位寻址的变量15sfr特殊功能寄存器声明特殊功
36、能寄存器声明声明一个声明一个8位的特殊功能寄存器位的特殊功能寄存器16sfr16特殊功能寄存器声明特殊功能寄存器声明声明一个声明一个16位的特殊功能寄存器位的特殊功能寄存器17small存储模式存储模式使用内部使用内部RAM的存储模式的存储模式18_task_任务声明任务声明定义实时多任务函数定义实时多任务函数19using寄存器组选择寄存器组选择选择工作寄存器组选择工作寄存器组20xdata存储器类型声明存储器类型声明外部外部RAM8/13/202437388/13/20246.3.3KeilC51中的基本数据类型中的基本数据类型KeilC51编译器具体支持的数据类型有:编译器具体支持的数据
37、类型有:位型位型(bit)、无符号字符无符号字符(unsignedchar)、有符号字符、有符号字符(singedchar)无符号整型无符号整型(unsignedint)、有符号整型有符号整型(signedint)无符号长整型无符号长整型(unsignedlong)、有符号长整型有符号长整型(signedlong)浮点型浮点型(float)和指针类型等。和指针类型等。8/13/202438398/13/20246.3.3KeilC51中的基本数据类型中的基本数据类型8/13/202439408/13/20241char字符类型字符类型char类型的长度是一个字节,通常用于定义处理字符数据类型的
38、长度是一个字节,通常用于定义处理字符数据的变量或常量。分无符号字符类型的变量或常量。分无符号字符类型unsignedchar和有符号和有符号字符类型字符类型signedchar,默认值为,默认值为signedchar类型。这很合适类型。这很合适MCS-51单片机,单片机,因为因为MCS-51单片机每次可处理单片机每次可处理8位数据。位数据。unsignedchar类型用字节中所有的位来表示数值,所以可类型用字节中所有的位来表示数值,所以可表达的数值范围是表达的数值范围是0255。signedchar类型用字节中最高类型用字节中最高位字节表示数据的符号,位字节表示数据的符号,“0”表示正数,表示
39、正数,“1”表示负数,表示负数,负数用补码表示。所能表示的数值范围是负数用补码表示。所能表示的数值范围是-128+127。2int整型整型int整型长度为两个字节,用于存放一个双字节数据。整型长度为两个字节,用于存放一个双字节数据。分有符号整型数分有符号整型数signedint和无符号整型数和无符号整型数unsignedint,默认,默认值为值为signedint类型。类型。8/13/202440418/13/20243long长整型长整型long长长整整型型长长度度为为四四个个字字节节,用用于于存存放放一一个个四四字字节节数数据。据。4float浮点型浮点型浮浮点点型型变变量量(float)
40、:浮浮点点型型变变量量为为32位位,占占4个个字字节节,许许多多复复杂杂的的数数学学表表达达式式都都采采用用浮浮点点变变量量数数据据类类型型。应应用符号位表示数的符号,用阶码和尾数表示数的大小。用符号位表示数的符号,用阶码和尾数表示数的大小。5*指针型指针型指指针针型型本本身身就就是是一一个个变变量量,在在这这个个变变量量中中存存放放指指向向另另一个数据的地址。一个数据的地址。这这个个指指针针变变量量要要占占据据一一定定的的内内存存单单元元,对对不不同同的的处处理理器器长长度度也也不不尽尽相相同同,在在C51中中它它的的长长度度一一般般为为13个个字节。具体可参考相关字节。具体可参考相关C语言
41、教程。语言教程。8/13/202441428/13/20246bit位变量位变量bit位变量是位变量是C51编译器的一种扩充数据类型,利用编译器的一种扩充数据类型,利用它可定义一个位变量,但不能定义位指针,也不能定它可定义一个位变量,但不能定义位指针,也不能定义位数组。它的值是一个二进制位,不是义位数组。它的值是一个二进制位,不是0就是就是1。类。类似于一些高级语言中的似于一些高级语言中的Boolean类型中的类型中的True和和False。7sfr特殊功能寄存器特殊功能寄存器sfr也是一种扩充数据类型,占用一个内存单元,值也是一种扩充数据类型,占用一个内存单元,值域为域为0255。利用它可以
42、访问利用它可以访问51单片机内部的所有特殊功能寄存单片机内部的所有特殊功能寄存器。如用器。如用sfrP1=0x90,这一句定这一句定P1为为P1端口在片端口在片内的寄存器,在后面的语句中我们用以用内的寄存器,在后面的语句中我们用以用P1=255(对(对P1端口的所有引脚置高电平)之类的语句来操作特殊端口的所有引脚置高电平)之类的语句来操作特殊功能寄存器。功能寄存器。8/13/202442438/13/20248sfr1616位特殊功能寄存器位特殊功能寄存器sfr16占用两个内存单元,值域为占用两个内存单元,值域为065535。sfr16和和sfr一一样样用用于于操操作作特特殊殊功功能能寄寄存存
43、器器,所所不不同同的的是是它它用用于于操操作作占占两两个个字字节节的的寄寄存存器器,可可用用于于定定时时器器T0和和T1。9sbit可寻址位可寻址位sbit同同位位是是C51中中的的一一种种扩扩充充数数据据类类型型,利利用用它它可可以以访访问问芯芯片片内内部部的的RAM中中的的可可寻寻址址位位或或特特殊殊功功能能寄寄存存器器中中的可寻址位。的可寻址位。例如:例如:sfrP1=0x90;sfrP1_1=P11;sfrP1_1=0x91;8/13/202443448/13/20248sfr1616位特殊功能寄存器位特殊功能寄存器sfr16占用两个内存单元,值域为占用两个内存单元,值域为065535
44、。sfr16和和sfr一一样样用用于于操操作作特特殊殊功功能能寄寄存存器器,所所不不同同的的是是它它用用于于操操作作占占两两个个字字节节的的寄寄存存器器,可可用用于于定定时时器器T0和和T1。9sbit可寻址位可寻址位sbit同同位位是是C51中中的的一一种种扩扩充充数数据据类类型型,利利用用它它可可以以访访问问芯芯片片内内部部的的RAM中中的的可可寻寻址址位位或或特特殊殊功功能能寄寄存存器器中中的可寻址位。的可寻址位。例如:例如:sfrP1=0x90;sfrP1_1=P11;sfrP1_1=0x91;8/13/202444458/13/2024在在8051单单片片机机系系统统中中,经经常常要
45、要访访问问特特殊殊功功能能寄寄存存器器中中的的某某些些位位,用用关关键键字字sbit定定义义可可位位寻寻址址特特殊殊功功能能寄寄存存器器的位寻址对象。定义方法有如下三种:的位寻址对象。定义方法有如下三种:(1)sbit位变量名位变量名=位地址位地址将位的绝对地址赋给位变量,位地址必须位于将位的绝对地址赋给位变量,位地址必须位于Ox80HxFFH之间。例如:之间。例如:sbitOV=0xD2;sbitCY=0XD7;8/13/202445468/13/2024(2)sbit位变量名位变量名=特殊功能寄存器名特殊功能寄存器名位位置位位置当可寻址位位于特殊功能寄存器中时,可采用这种当可寻址位位于特殊
46、功能寄存器中时,可采用这种方法。位位置是一个方法。位位置是一个07范围内的常数。例如:范围内的常数。例如:sfrSCON=0x98;/*定义定义SCON*/sbitRI=SCON0;/*定义定义SCON的各位的各位*/sbitTI=SCON1;sbitRB8=SCON2;shitTB8=SCON3;shitREN=SOON4;sbitSM2=SCON5;sbitSM1=SCON6;sbitSM0=SCON7;8/13/202446478/13/2024(3)sbit位变量名位变量名=字节地址字节地址位位置位位置这种方法是以一个常数这种方法是以一个常数(字节地址字节地址)作为基地址,该常作为基地
47、址,该常数必须在数必须在0x80H0xFF范围内。位位置是一个范围内。位位置是一个07范范围内的常数。例如:围内的常数。例如:sbitOV=0xD02;sbitCY=0xD07;8051单片机中的特殊功能寄存器和特殊功能寄存器可单片机中的特殊功能寄存器和特殊功能寄存器可寻址位,己被预先定义放在文件寻址位,己被预先定义放在文件reg51.h或或reg52.h中,中,在程序的开头只需加上在程序的开头只需加上#include或或#include即可。即可。另外,另外,sbit还可以访问还可以访问8051单片机片内单片机片内20H2FH范范围内的位对象。围内的位对象。C51编译器提供了一个编译器提供了
48、一个bdata存储器类存储器类型,允许将具有型,允许将具有bdata类型的对象放入类型的对象放入8051单片机片内单片机片内可位寻址区。例如可位寻址区。例如:8/13/202447488/13/2024intbdatabi_var1;/*在位寻址区定义一个整型变量在位寻址区定义一个整型变量bi_var1*/charbdatabc_array3;/*在位寻址区定义字符型数组整型变量在位寻址区定义字符型数组整型变量bc_array*/sbitbi_var1_bit0=bi_var10;/*使用位变量使用位变量bi_var1_bit0访问访问bi_var1第第0位位*/sbitbi_var1_bit
49、15=bi_var115;/*使用位变量使用位变量bi_var1_bit15访问访问bi_var1第第15位位*/sbitbc_array05=bc_array05;/*使用位变量使用位变量bc_array05访问访问bc_array0第第5位位*/8/13/202448498/13/20246.3.4变量的存储种类和存储器类型变量的存储种类和存储器类型变量是一种在程序执行过程中,其数值不断变化的量。同变量是一种在程序执行过程中,其数值不断变化的量。同ANSIC一样,一样,C51规定变量必须先定义后使用。规定变量必须先定义后使用。C51对变量对变量的进行定义的格式如下:的进行定义的格式如下:存
50、储种类存储种类数据类型数据类型存储器类型存储器类型变量名表变量名表其中,存储种类和存储器类型是可选项。其中,存储种类和存储器类型是可选项。8/13/202449508/13/2024存储种类是指变量在程序执行过程中的作用范围。变量的存储种类是指变量在程序执行过程中的作用范围。变量的存储种类有四种,分别为:存储种类有四种,分别为:自动(自动(auto)外部(外部(extern)静态(静态(static)寄存器(寄存器(register)8/13/202450518/13/2024使用外部种类存储符使用外部种类存储符extern定义的变量称为定义的变量称为外部变量外部变量。在一。在一个函数体内,要
51、使用一个已在该函数体外或别的程序模块文个函数体内,要使用一个已在该函数体外或别的程序模块文件中定义过的外部变量时,该变量在本函数体内要用件中定义过的外部变量时,该变量在本函数体内要用extern说明。说明。当片内当片内RAM资源紧张时,不建议将外部变量放在片内资源紧张时,不建议将外部变量放在片内RAM。8/13/202451528/13/2024使用使用存储种类说明符存储种类说明符static定义的变量称为定义的变量称为静态变量静态变量。静态变量。静态变量分为分为局部静态变量和全局静态变量局部静态变量和全局静态变量。局部静态变量局部静态变量是在两次函数调用之间仍能保持其值的局部变是在两次函数调
52、用之间仍能保持其值的局部变量。有些程序要求在多次调用之间仍然保持变量的值,使用自量。有些程序要求在多次调用之间仍然保持变量的值,使用自动变量无法作用到这一点。使用全局变量有时会带来意外的副动变量无法作用到这一点。使用全局变量有时会带来意外的副作用,这时可采用局部静态变量。作用,这时可采用局部静态变量。8/13/202452538/13/2024使用使用存储种类说明符存储种类说明符register定义的变量称为定义的变量称为寄存器变量寄存器变量。8051访问寄存器的速度最快,通常将使用频率最高的那些变量访问寄存器的速度最快,通常将使用频率最高的那些变量定义为寄存器变量。定义为寄存器变量。C51编
53、译器能自动识别程序中使用频率最编译器能自动识别程序中使用频率最高的变量,并自动将其作为寄存器变量,用户无需专门声明。高的变量,并自动将其作为寄存器变量,用户无需专门声明。8/13/202453548/13/20242.存储器类型存储器类型定义变量时,除了说明存储种类外,还允许说明变量的存储定义变量时,除了说明存储种类外,还允许说明变量的存储器类型。器类型。存储器类型存储器类型和和存储种类存储种类是完全不同的概念,存储器类是完全不同的概念,存储器类型指明该变量所处的单片机的内存空间。型指明该变量所处的单片机的内存空间。C51编译器可识别以编译器可识别以下存储器类型,如下表所示。下存储器类型,如下
54、表所示。8/13/202454558/13/2024存储器类型存储器类型描描述述data直接寻址的片内数据存储器低直接寻址的片内数据存储器低128B,访问速度,访问速度最快最快bdata可位寻址的片内数据存储器(地址可位寻址的片内数据存储器(地址20H2FH共共16B)允许位和字节混合访问)允许位和字节混合访问idata间接寻址片内数据存储器间接寻址片内数据存储器256B。允许访问片内。允许访问片内全部地址全部地址pdata分页寻址片外数据存储器分页寻址片外数据存储器256B,使用指令,使用指令MOVXRn访问,需要访问,需要2个指令周期个指令周期xdata寻址片外数据存储器寻址片外数据存储器
55、64KB,使用指令,使用指令MOVXDPTR访问访问code寻址程序存储器区寻址程序存储器区64KB,使用指令,使用指令MOVCA+DPTR访问访问8/13/202455568/13/2024图图6-14MCS-51单片机存储器结构示意图单片机存储器结构示意图8/13/202456578/13/2024如果在变量定义时省略了存储器类型标识符,如果在变量定义时省略了存储器类型标识符,C51编译器会编译器会选择默认的存储器类型。默认的存储器类型由选择默认的存储器类型。默认的存储器类型由SMALL、COMPACT和和LARGE存储模式存储模式指令决定。指令决定。8/13/202457588/13/2
56、0241)data区区对对data区的寻址是最快的,所以应该把使用频率高的变量放在区的寻址是最快的,所以应该把使用频率高的变量放在data区,由于空间有限,必须注意使用区,由于空间有限,必须注意使用data区,区,data区除了包含区除了包含程序变量外,还包含了堆栈和寄存器组程序变量外,还包含了堆栈和寄存器组data区。区。在在SMALL存储模式存储模式下,未说明存储器类型时,变量默认被定位下,未说明存储器类型时,变量默认被定位在在data区。区。8/13/202458598/13/20242)bdata区区当在当在DATA区的位寻址区定义变量,这个变量就可进行位寻区的位寻址区定义变量,这个变
57、量就可进行位寻址,并且声明位变量。这对状态寄存器来说十分有用,因为它址,并且声明位变量。这对状态寄存器来说十分有用,因为它可以单独使用变量的每一位,而不一定要用位变量名引用位变可以单独使用变量的每一位,而不一定要用位变量名引用位变量。量。3)idata区区idata区也可以存放使用比较频繁的变量,使用寄存器作为指区也可以存放使用比较频繁的变量,使用寄存器作为指针进行寻址。在寄存器中设置针进行寻址。在寄存器中设置8位地址进行间接寻址,与外部位地址进行间接寻址,与外部存储器寻址比较,它的指令执行周期和代码长度都比较短。存储器寻址比较,它的指令执行周期和代码长度都比较短。8/13/202459608
58、/13/20244)pdata和和xdata区区在这两个区声明变量和在其他区的语法是一样的,在这两个区声明变量和在其他区的语法是一样的,pdata区区只有只有256B,而,而xdata区可达区可达65536B5)code区区code区即区即8051的程序代码区,所以代码区的数据是不可改的程序代码区,所以代码区的数据是不可改变的,变的,8051的代码区不可重写。一般代码区中可存放数据表,的代码区不可重写。一般代码区中可存放数据表,跳转向量和状态表跳转向量和状态表8/13/202460618/13/2024C51编译器允许采用三种存储模式:编译器允许采用三种存储模式:小编译模式小编译模式SMALL
59、、紧、紧凑编译模式凑编译模式COMPACT、大编译模式、大编译模式LARGE。6.3.5存储模式存储模式8/13/202461628/13/2024一个变量的存储器模式确定了一个变量的存储器模式确定了未声明存储器类型未声明存储器类型的变量在内的变量在内存中的地址空间。在存中的地址空间。在SMALL模式下,该变量在模式下,该变量在8051单片机的内单片机的内部部RAM中;在中;在COMPACT和和LARGE模式下,该变量在模式下,该变量在8051单单片机的外部片机的外部RAM中。中。建议在编写源程序时,把存储模式设定为建议在编写源程序时,把存储模式设定为SMALL,再在程,再在程序中把序中把xd
60、ata、pdata和和idata等类型变量进行专门声明。等类型变量进行专门声明。8/13/202462638/13/20246.3.6MCS-51特殊功能寄存器特殊功能寄存器(SFR)的的C51定义定义 MCS-51单单片片机机中中,除除了了程程序序计计数数器器PC和和4组组工工作作寄寄存存器器组组外外,其其它它所所有有的的寄寄存存器器均均为为特特殊殊功功能能寄寄存存器器(SFR),分分散散在在片片内内RAM区区的的高高128字字节节中中,地地址址范范围围为为80H0FFH。SFR中中有有11个个寄寄存存器器具具有位寻址能力。有位寻址能力。为为了了能能直直接接访访问问这这些些SFR,KeilC
61、51提提供供了了一一种种自自主主形形式式的的定定义义方方法。特殊功能寄存器法。特殊功能寄存器C51定义的一般语法格式如下:定义的一般语法格式如下:sfrsfr-name=intconstant;“sfr”是是定定义义语语句句的的关关键键字字,其其后后必必须须跟跟一一个个MCS-51单单片片机机真真实实存存在在的的特特殊殊功功能能寄寄存存器器名名,“=”后后面面必必须须是是一一个个整整型型常常数数,不不允允许许带带有有运运算算符符的的表表达达式式,是是特特殊殊功功能能寄寄存存器器“sfr-name”的的字字节节地地 址址 , 这这 个个 常常 数数 值值 的的 范范 围围 必必 须须 在在 SF
62、R地地 址址 范范 围围 内内 , 位位 于于0x800xFF。例如:例如:sfrSCON=0x98;sfrTMOD=0x89;8/13/202463648/13/20246.3.3KeilC51中的基本数据类型中的基本数据类型KeilC51编译器具体支持的数据类型有:编译器具体支持的数据类型有:位型位型(bit)、无符号字符无符号字符(unsignedchar)、有符号字符、有符号字符(singedchar)无符号整型无符号整型(unsignedint)、有符号整型有符号整型(signedint)无符号长整型无符号长整型(unsignedlong)、有符号长整型有符号长整型(signedlo
63、ng)浮点型浮点型(float)和指针类型等。和指针类型等。8/13/202464658/13/20246.3.4变量的存储种类和存储器类型变量的存储种类和存储器类型变量是一种在程序执行过程中,其数值不断变化的量。同变量是一种在程序执行过程中,其数值不断变化的量。同ANSIC一样,一样,C51规定变量必须先定义后使用。规定变量必须先定义后使用。C51对变量对变量的进行定义的格式如下:的进行定义的格式如下:存储种类存储种类数据类型数据类型存储器类型存储器类型变量名表变量名表其中,存储种类和存储器类型是可选项。其中,存储种类和存储器类型是可选项。8/13/202465668/13/2024存储种类
64、是指变量在程序执行过程中的作用范围。变量的存储种类是指变量在程序执行过程中的作用范围。变量的存储种类有四种,分别为:存储种类有四种,分别为:自动(自动(auto)外部(外部(extern)静态(静态(static)寄存器(寄存器(register)8/13/202466678/13/2024存储器类型存储器类型描描述述data直接寻址的片内数据存储器低直接寻址的片内数据存储器低128B,访问速度,访问速度最快最快bdata可位寻址的片内数据存储器(地址可位寻址的片内数据存储器(地址20H2FH共共16B)允许位和字节混合访问)允许位和字节混合访问idata间接寻址片内数据存储器间接寻址片内数据
65、存储器256B。允许访问片内。允许访问片内全部地址全部地址pdata分页寻址片外数据存储器分页寻址片外数据存储器256B,使用指令,使用指令MOVXRn访问,需要访问,需要2个指令周期个指令周期xdata寻址片外数据存储器寻址片外数据存储器64KB,使用指令,使用指令MOVXDPTR访问访问code寻址程序存储器区寻址程序存储器区64KB,使用指令,使用指令MOVCA+DPTR访问访问8/13/202467688/13/2024C51编译器允许采用三种存储模式:编译器允许采用三种存储模式:小编译模式小编译模式SMALL、紧、紧凑编译模式凑编译模式COMPACT、大编译模式、大编译模式LARGE
66、。6.3.5存储模式存储模式8/13/202468698/13/2024一个变量的存储器模式确定了一个变量的存储器模式确定了未声明存储器类型未声明存储器类型的变量在内的变量在内存中的地址空间。在存中的地址空间。在SMALL模式下,该变量在模式下,该变量在8051单片机的内单片机的内部部RAM中;在中;在COMPACT和和LARGE模式下,该变量在模式下,该变量在8051单单片机的外部片机的外部RAM中。中。建议在编写源程序时,把存储模式设定为建议在编写源程序时,把存储模式设定为SMALL,再在程,再在程序中把序中把xdata、pdata和和idata等类型变量进行专门声明。等类型变量进行专门声
67、明。8/13/202469708/13/20246.3.6MCS-51特殊功能寄存器特殊功能寄存器(SFR)的的C51定义定义 MCS-51单单片片机机中中,除除了了程程序序计计数数器器PC和和4组组工工作作寄寄存存器器组组外外,其其它它所所有有的的寄寄存存器器均均为为特特殊殊功功能能寄寄存存器器(SFR),分分散散在在片片内内RAM区区的的高高128字字节节中中,地地址址范范围围为为80H0FFH。SFR中中有有11个个寄寄存存器器具具有位寻址能力。有位寻址能力。为为了了能能直直接接访访问问这这些些SFR,KeilC51提提供供了了一一种种自自主主形形式式的的定定义义方方法。特殊功能寄存器法
68、。特殊功能寄存器C51定义的一般语法格式如下:定义的一般语法格式如下:sfrsfr-name=intconstant;“sfr”是是定定义义语语句句的的关关键键字字,其其后后必必须须跟跟一一个个MCS-51单单片片机机真真实实存存在在的的特特殊殊功功能能寄寄存存器器名名,“=”后后面面必必须须是是一一个个整整型型常常数数,不不允允许许带带有有运运算算符符的的表表达达式式,是是特特殊殊功功能能寄寄存存器器“sfr-name”的的字字节节地地 址址 , 这这 个个 常常 数数 值值 的的 范范 围围 必必 须须 在在 SFR地地 址址 范范 围围 内内 , 位位 于于0x800xFF。例如:例如:
69、sfrSCON=0x98;sfrTMOD=0x89;8/13/202470718/13/20246.4C51的运算符和表达式的运算符和表达式C语言有丰富的运算符,绝大多数的操作都可以通过语言有丰富的运算符,绝大多数的操作都可以通过运算运算符符来处理。来处理。运算符就是完成某种特定运算的符号运算符就是完成某种特定运算的符号,包括,包括算术运算符、算术运算符、赋值运算符、逻辑运算符、关系运算符、位运算符、条件运赋值运算符、逻辑运算符、关系运算符、位运算符、条件运算符算符等。等。按照表达式中运算对象的个数又可将运算符分为按照表达式中运算对象的个数又可将运算符分为单目运单目运算符、双目运算符和三目运算
70、符算符、双目运算符和三目运算符。单目运算符只需要有一个。单目运算符只需要有一个运算对象,双目运算符要求有两个运算对象,三目运算符则运算对象,双目运算符要求有两个运算对象,三目运算符则要求有三个运算对象。要求有三个运算对象。表达式表达式是是由运算符和运算对象所组成的具有特定含义的式由运算符和运算对象所组成的具有特定含义的式子子。运算符和表达式可以组成。运算符和表达式可以组成C语言程序的各种语句。语言程序的各种语句。8/13/202471728/13/20246.4.1算术运算符算术运算符 算术运算符包括以下几种:算术运算符包括以下几种:+ + 加或加或取正值运算符取正值运算符- - 减或减或取负
71、值运算符取负值运算符* * 乘运算符乘运算符/ / 除运算符除运算符% % 取余运算符取余运算符+ + 自增运算符自增运算符- - 自减运算符自减运算符8/13/202472738/13/2024加、减、乘法运算符合一般的算术运算规则。加、减、乘法运算符合一般的算术运算规则。除法运算则有些特殊,如果是两个浮点数相除,其结果除法运算则有些特殊,如果是两个浮点数相除,其结果为浮点数,如为浮点数,如3.0/10.0所得值为所得值为0.3,而当两个整数相除时,而当两个整数相除时,所得值就是整数,如所得值就是整数,如7/3,值为,值为2,舍去小数部分。,舍去小数部分。取余运算符也是进行除法运算,只是结果
72、不是商而是余取余运算符也是进行除法运算,只是结果不是商而是余数。数。如8 % 5 = 3,即8除以5的余数是3 。像别的语言一样像别的语言一样C的运算符也有优先级和结合性,也可的运算符也有优先级和结合性,也可以用括号以用括号()()来改变优先级。来改变优先级。 6.4.1算术运算符算术运算符 8/13/202473748/13/2024自增、自减运算符的作用是使变量的值加自增、自减运算符的作用是使变量的值加1或减或减1。+i先使先使i的值加的值加1,然后再使用;,然后再使用;-i先使先使i的值减的值减1,然后再使用;,然后再使用;i+使用完使用完i的值以后,再使的值以后,再使i的值加的值加1;
73、i-使用完使用完i的值以后,再使的值以后,再使i的值减的值减1。6.4.1算术运算符算术运算符 8/13/202474758/13/2024例如:假设例如:假设i=8,则执行则执行j=+i时,时,i先加先加1变为变为9,然后把,然后把9赋给变量赋给变量j,所以执行结果为,所以执行结果为i=9,j=9。而执行而执行j=i+时,先将时,先将i的值的值8赋给赋给j,然后再使,然后再使i的值的值加加1,执行结果为,执行结果为i=9,j=8。 6.4.1算术运算符算术运算符 8/13/202475768/13/2024例:例:voidmain()inti=8;inta,b,c,d,e,f;a=+i;b=
74、-i;c=i+;d=i-;e=-i+;f=-i;while(1);6.4.1算术运算符算术运算符 8/13/202476778/13/2024“=”=”就是赋值运算符,其功能是将一个数据赋给一个变量,就是赋值运算符,其功能是将一个数据赋给一个变量,如如a=8;a=8;b=5;b=5;c=a/b;c=a/b;a=b=6;a=b=6;以上语句都是合法的。语句的执行过程是先计算出右边表达以上语句都是合法的。语句的执行过程是先计算出右边表达式的值,再将该值赋给左边的变量。式的值,再将该值赋给左边的变量。 6.4.2赋值运算符赋值运算符8/13/202477788/13/2024关系运算符的功能就是判断
75、两个数的关系。关系运算符的功能就是判断两个数的关系。C语言有以下六种关系运算符:语言有以下六种关系运算符:大于大于小于小于大于等于大于等于小于等于小于等于测试测试等于等于!测试测试不等于不等于关系运算符的优先级低于算术运算符,高于赋值运算符。关系运算符的优先级低于算术运算符,高于赋值运算符。六种关系运算符中前四种具有相同的优先级,后两种具有相六种关系运算符中前四种具有相同的优先级,后两种具有相同的优先级,而且前四种的优先级高于后两种。同的优先级,而且前四种的优先级高于后两种。注意赋值运算符注意赋值运算符“=”和和测试等于测试等于“=”关系运算符不一样。关系运算符不一样。6.4.3关系运算符关系
76、运算符8/13/202478798/13/2024两个表达式用关系运算符连接起来就构成了关系表达式。两个表达式用关系运算符连接起来就构成了关系表达式。关系表达式的值为逻辑值,即只有真(关系表达式的值为逻辑值,即只有真(true)和假()和假(false)两种状态,在两种状态,在C语言中用语言中用1表示真,用表示真,用0表示假。若关系表达表示假。若关系表达式的条件成立,则表达式的值为真(式的条件成立,则表达式的值为真(1),否则为假(),否则为假(0)。)。6.4.3关系运算符关系运算符8/13/202479808/13/2024例例观察关系运算符的用法和功能。观察关系运算符的用法和功能。voi
77、dmain()inta,b,c,d,e,f;a=(56);b=(3=10);d=(106)&(32);b=(36);c=(56)&(76);d=(106);e=(10=9)|(76);f=(10=9)|(76);g=!(32);i=(7=8)&(32)+(36)+!(56);while(1);6.4.4逻辑运算符逻辑运算符 8/13/202483848/13/20246.4.5位运算符位运算符 位运算符的功能是对变量按位进行运算,但并不改变运算变位运算符的功能是对变量按位进行运算,但并不改变运算变量的值。量的值。C语言有以下六种位运算符:语言有以下六种位运算符:&按位与按位与|按位或按位或按位
78、取反按位取反按位异或按位异或右移右移8/13/202484858/13/20246.4.5位运算符位运算符 六种位运算符的优先级由高到低的顺序为:按位取反、左六种位运算符的优先级由高到低的顺序为:按位取反、左移、右移、按位与、按位异或、按位或。下面以按位与为例移、右移、按位与、按位异或、按位或。下面以按位与为例了解位运算符的操作过程。假设有字符型变量了解位运算符的操作过程。假设有字符型变量a和和b,a=10111001,b=10000011,则表达式,则表达式a&b的值为:的值为:a: 1 0 1 1 1 0 0 1b:& 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1由此可见
79、,位运算就是将参与运算的两个变量的各个二由此可见,位运算就是将参与运算的两个变量的各个二进制位分别对应进行与、或、异或等操作。进制位分别对应进行与、或、异或等操作。 8/13/202485868/13/20246.4.5位运算符位运算符 左移运算符左移运算符用来将一个数的各个二进制位全部用来将一个数的各个二进制位全部左移若干左移若干位位,移出的数据位丢失,移入的数据位补,移出的数据位丢失,移入的数据位补“0”0”; 右移运算符右移运算符则用来将一个数的各个二进制位全部右移若则用来将一个数的各个二进制位全部右移若干位,此时有符号数和无符号数有区别。干位,此时有符号数和无符号数有区别。若为无符号数
80、若为无符号数,移,移出的数据位丢失,移入的数据位补出的数据位丢失,移入的数据位补“0”0”;若为有符号数若为有符号数,则移出的数据位丢失,移入的数据位用符号位填补。则移出的数据位丢失,移入的数据位用符号位填补。 8/13/202486878/13/20246.4.5位运算符位运算符 例例观察位运算符的用法和功能。观察位运算符的用法和功能。 voidmain()unsignedchari,j,a,b,c,d,e,f,g;charx=0xa6;i=0x36;j=0x98;a=i&j;b=i|j;c=ij;d=i;e=i3;g=x2;while(1);8/13/202487888/13/20246.
81、4.6复合赋值运算符复合赋值运算符 复合赋值运算符复合赋值运算符是是C语言的一种特色,它简化了代码的编写。语言的一种特色,它简化了代码的编写。该类运算符的功能是将某个变量先与表达式进行指定的运算,该类运算符的功能是将某个变量先与表达式进行指定的运算,再将运算结果赋予该变量。再将运算结果赋予该变量。C语言有以下十种复合赋值运算符:语言有以下十种复合赋值运算符:+=加并赋值运算符加并赋值运算符-=减并赋值运算符减并赋值运算符*=乘并赋值运算符乘并赋值运算符/=除并赋值运算符除并赋值运算符%=取余并赋值运算符取余并赋值运算符=右移并赋值运算符右移并赋值运算符&=按位与并赋值运算符按位与并赋值运算符|
82、=按位或并赋值运算符按位或并赋值运算符=按位异或并赋值运算符按位异或并赋值运算符8/13/202488898/13/20246.4.6复合赋值运算符复合赋值运算符 例例观察复合运算符的用法和功能。观察复合运算符的用法和功能。voidmain()unsignedchari,j,a,b,c;charx=0xa6;i=0x36,j=0x98;a=0x23,b=0x34;a&=i;b|=j;c=j;i=3;while(1);8/13/202489908/13/20246.4.7条件运算符条件运算符 条件运算符是三目运算符,条件运算符是三目运算符,格式如下:格式如下:判断结果判断结果=(判断式)?结果(
83、判断式)?结果1:结果:结果2其含义是先求判断式的值,若为真,则判断结果其含义是先求判断式的值,若为真,则判断结果=结果结果1;若;若为假,则判断结果为假,则判断结果=结果结果2。8/13/202490918/13/20246.4.7条件运算符条件运算符 例例4-8观察条件运算符的用法和功能。观察条件运算符的用法和功能。voidmain()chara,b,max;a=10;b=16;max=ab?a:b;while(1);执行结果:执行结果::max=16。8/13/202491928/13/20246.4.8指针和地址运算符指针和地址运算符 在前面在前面学习学习数据类型数据类型时,接触过时,
84、接触过指针类型数据指针类型数据,知道,知道它是一它是一种存放指向另一个数据的地址的变量类型。种存放指向另一个数据的地址的变量类型。C语言中提供了语言中提供了两个专门用于指针和地址的运算符:两个专门用于指针和地址的运算符:*指针运算符(取内容)指针运算符(取内容)&取地址运算符(取地址)取地址运算符(取地址)一般形式分别如下:一般形式分别如下:取内容:取内容:变量变量=*指针变量指针变量取地址:取地址:指针变量指针变量=&目标变量目标变量变量前面加变量前面加“*”说明该变量为指针,所以操作时取的不是变量的值,说明该变量为指针,所以操作时取的不是变量的值,而是将指针变量所指向的目标变量的值赋给左边
85、的变量;取地址运算是而是将指针变量所指向的目标变量的值赋给左边的变量;取地址运算是将目标变量的地址赋给左边的变量。将目标变量的地址赋给左边的变量。“*”和和“&”运算符均为单目运算运算符均为单目运算符。符。 8/13/202492938/13/20246.4.8指针和地址运算符指针和地址运算符 例例观察指针和地址运算符的用法和功能。观察指针和地址运算符的用法和功能。voidmain()chara,b,*m;a=10;m=&a;b=*m;while(1);8/13/202493948/13/2024作业:第六章作业:第六章1、2、3、4补充:补充:P1口的口的P1.2和和P1.3各接一开关各接一
86、开关S1、S2,.P1.4、P1.5、P1.6和和P1.7各接一个发光二极管,各接一个发光二极管,如图所示。由开关如图所示。由开关S1和和S2的不同状态,确定哪个发的不同状态,确定哪个发光二极管亮,真值表如下表所示:请编写程序实现上光二极管亮,真值表如下表所示:请编写程序实现上述功能。并用述功能。并用proteus仿真验证。仿真验证。8/13/202494958/13/2024C语语言言源源程程序序由由若若干干个个函函数数单单元元组组成成,每每一一个个函函数数都都是是完完成成某某个个特特殊殊任任务的子程序段。务的子程序段。一一个个C语语言言程程序序必必须须而而且且只只能能有有一一个个名名为为m
87、ain()的的函函数数。它它是是一一个个特特殊殊的的函函数数,也也称称为为该该程程序序的的主主函函数数,程程序序的的执执行行都都是是从从main()函函数数开开始的。始的。C语言程序一般具有如下结构:语言程序一般具有如下结构:预处理命令预处理命令#include函数定义函数定义charfun1();();floatfun2();();主函数主函数main()()函数体函数体功能函数功能函数1fun1()()功能函数功能函数2fun2()()6.5C51语言的程序设计语言的程序设计8/13/202495968/13/20246.5.151程序结构程序结构C语言程序有顺序结构、选择结构、循环结构三
88、种语言程序有顺序结构、选择结构、循环结构三种基本结构。基本结构。8/13/202496978/13/20246.5.151程序结构程序结构循环结构又分为循环结构又分为“while”型循环结构和型循环结构和“do-while”型循型循环结构,相应的流程图如下图所示。环结构,相应的流程图如下图所示。8/13/202497988/13/20246.5.2C51语言的语句语言的语句C51语言的语句是单片机执行的操作命令,每条语句都语言的语句是单片机执行的操作命令,每条语句都以分号结尾,需要注意的是,变量、函数的声明部分也以以分号结尾,需要注意的是,变量、函数的声明部分也以分号结尾,但不是语句。分号结尾
89、,但不是语句。C语言包括以下语句:语言包括以下语句:1.表达式语句表达式语句由一个表达式加上一个分号就构成了表达式语句。如:由一个表达式加上一个分号就构成了表达式语句。如:i=7;j=a=b;i+;8/13/202498998/13/20246.5.2C51语言的语句语言的语句2.复合语句复合语句用大括号用大括号“”将多条语句括起来就组成了复合语将多条语句括起来就组成了复合语句,也称为功能块。复合语句中的每一条语句都必须以句,也称为功能块。复合语句中的每一条语句都必须以“;”结束,而不允许将结束,而不允许将“;”写在写在“”外。复合语句外。复合语句不需要以不需要以“;”结束。结束。C语言中将复
90、合语句视为一条单语言中将复合语句视为一条单语句,也就是说在语法上等同于一条单语句。对于一个语句,也就是说在语法上等同于一条单语句。对于一个函数而言,函数体就是一个复合语句。如:函数而言,函数体就是一个复合语句。如:i=7;j=a=b;i+;8/13/2024991008/13/20246.5.2C51语言的语句语言的语句3.空语句空语句空语句是仅由一个分号空语句是仅由一个分号“;”组成的语句。空语句什么组成的语句。空语句什么也做,语句格式:也做,语句格式:; 8/13/20241001018/13/20246.5.2C51语言的语句语言的语句4.函数调用语句函数调用语句函数调用的一般形式加上分
91、号就构成了函数调用语句。函数调用的一般形式加上分号就构成了函数调用语句。语句格式:语句格式:函数名函数名(实际参数表实际参数表);执行函数调用语句就是调用函数体并把实际参数赋予函执行函数调用语句就是调用函数体并把实际参数赋予函数定义中的形式参数,然后执行被调函数体中的语句。数定义中的形式参数,然后执行被调函数体中的语句。8/13/20241011028/13/20246.5.2C51语言的语句语言的语句5.控制语句控制语句控制语句用于控制程序的流程,以实现程序的各种结构控制语句用于控制程序的流程,以实现程序的各种结构方式。方式。C51的控制语句有以下几类:的控制语句有以下几类:(1)选择语句选
92、择语句ifif语句是语句是C语言的一种基本的选择控制语句,它有以下三语言的一种基本的选择控制语句,它有以下三种形式:种形式:8/13/20241021038/13/20246.5.2C51语言的语句语言的语句if(表达式)(表达式)语句序列;语句序列;其它语句其它语句功能:如果表达式的值为真则执行语句,否则不执行语句。功能:如果表达式的值为真则执行语句,否则不执行语句。流程图如图所示。流程图如图所示。if分支结构示意图分支结构示意图8/13/20241031048/13/2024例例仿真电路如下图所示,试编程实现:当开关仿真电路如下图所示,试编程实现:当开关K闭合时上面闭合时上面四个发光二极管
93、先亮,下面四个二极管后亮,当开关四个发光二极管先亮,下面四个二极管后亮,当开关K打开时打开时仅下面四个发光二极管亮。仅下面四个发光二极管亮。程序如下:程序如下:#includesbitk=P34;voidmain()while(1)if(k=0)P1=0xf0;P1=0x0f;8/13/20241041058/13/2024例例仿真电路如下图所示,试编程实现:当开关仿真电路如下图所示,试编程实现:当开关K闭合时上面闭合时上面四个发光二极管先亮,下面四个二极管后亮,当开关四个发光二极管先亮,下面四个二极管后亮,当开关K打开时打开时仅下面四个发光二极管亮。仅下面四个发光二极管亮。#includes
94、bitk=P34;voidmain()while(1)if(k=0)P1=0xf0;P1=0x0f;8/13/20241051068/13/2024if(表达式)(表达式)语句序列语句序列1;else语句序列语句序列2;其它语句其它语句功能:如果表达式的值为真则执行语句序列功能:如果表达式的值为真则执行语句序列1,否则执行语句,否则执行语句序列序列2。 if-else分支结构示意图分支结构示意图 8/13/20241061078/13/2024例例 仿真电路如下图所示,试编程实现:当开关仿真电路如下图所示,试编程实现:当开关K K闭合时闭合时8 8个个发光二极管亮,发光二极管亮,K K断开时断
95、开时8 8个发光二极管灭。个发光二极管灭。 程序如下:程序如下:#includesbitk=P34;voidmain()while(1)if(k=0)P1=0x00;elseP1=0xff;8/13/20241071088/13/2024if(表达式(表达式1)语句序列语句序列1;elseif(表达式(表达式2)语句序列语句序列2;elseif(表达式(表达式3)语句序列语句序列3;elseif(表达式(表达式n)语句序列语句序列n;else语句序列语句序列n+1;其它语句其它语句 if-elseif分支结构示意图分支结构示意图 8/13/20241081098/13/2024例例4-124-
96、12假设从键盘输入数据假设从键盘输入数据x x,请编写一程序,判断,请编写一程序,判断x x大于大于0 0,等于等于0 0,还是小于,还是小于0 0;并输出其判断结果。;并输出其判断结果。解:程序如下:解:程序如下:#includevoidmain()charx,y;scanf(“%d”,&x);if(x0)y=1;elseif(x=0)y=0;elsey=-1;printf(x=%d,y=%dn,x,y);while(1);8/13/20241091108/13/2024(2).switch语句语句switch语句是多分支选择语句,也称开关语句。一般语句是多分支选择语句,也称开关语句。一般格
97、式如下:格式如下:switch(表达式表达式)case常量表达式常量表达式1:语句序列:语句序列1;case常量表达式常量表达式2:语句序列:语句序列2;case常量表达式常量表达式n:语句序列:语句序列n;default:语句序列:语句序列n+1;8/13/20241101118/13/2024每个每个case和和default出现的顺序不影响执行结果,但每个常量出现的顺序不影响执行结果,但每个常量表达式的值必须互不相同。该语句的执行过程如下:表达式的值必须互不相同。该语句的执行过程如下:求求switch后括号内的表达式的值,并将其值与各后括号内的表达式的值,并将其值与各case后的后的常量
98、表达式值进行比较;常量表达式值进行比较;当表达式的值与某个常量表达式相等时,则执行该常量当表达式的值与某个常量表达式相等时,则执行该常量表达式后边的语句序列;表达式后边的语句序列;接着执行下一个常量表达式后边的语句序列,直到后边接着执行下一个常量表达式后边的语句序列,直到后边所有的语句序列都执行完(即执行到语句序列所有的语句序列都执行完(即执行到语句序列n+1););如果表达式的值与所有如果表达式的值与所有case后的常量表达式都不相等,后的常量表达式都不相等,则执行则执行default后面的语句序列。后面的语句序列。8/13/20241111128/13/2024但是我们通常只是需要当某个常
99、量表达式的值与但是我们通常只是需要当某个常量表达式的值与switch后表后表达式的值相等时就执行该达式的值相等时就执行该case后的语句序列,并不希望程序一后的语句序列,并不希望程序一直执行下去,直到语句序列直执行下去,直到语句序列n+1。要达到这一目的,只需要在每。要达到这一目的,只需要在每个语句序列的后边加上个语句序列的后边加上“break”语句即可。格式如下:语句即可。格式如下:switch(表达式表达式)case常量表达式常量表达式1:语句序列:语句序列1;break;case常量表达式常量表达式2:语句序列:语句序列2;break;case常量表达式常量表达式n:语句序列:语句序列n
100、;break;default:语句序列:语句序列n+1;8/13/20241121148/13/2024例例 仿真电路如下图所示,试编程实现:当只有仿真电路如下图所示,试编程实现:当只有K1K1闭合时,闭合时,LED1LED1亮,只有亮,只有K2K2闭合时,闭合时,LED2LED2亮,依此类推。亮,依此类推。 #includevoidmain()unsignedchark;while(1)P1|=0xf0;/P1做做I/O口时为准双向口,口时为准双向口,/用作输入时应先写用作输入时应先写“1”k=P1;k=k&0xf0;/屏蔽低四位屏蔽低四位switch(k)case0xe0:P1=0xfe;
101、break;case0xd0:P1=0xfd;break;case0xb0:P1=0xfb;break;default:P1=0xf7;8/13/20241141158/13/20243.for语句语句for语句是一个很实用的计数循环语句。其格式如下:语句是一个很实用的计数循环语句。其格式如下:for(表达式(表达式1;表达式;表达式2;表达式;表达式3)语句序列;语句序列;/循环体循环体其中表达式其中表达式1通常为赋值表达式,用来确定循环结构中控制循通常为赋值表达式,用来确定循环结构中控制循环次数的变量的初始值,实现循环控制变量的初始化。环次数的变量的初始值,实现循环控制变量的初始化。表达式
102、表达式2通常为关系表达式或逻辑表达式,用来判断循环是否通常为关系表达式或逻辑表达式,用来判断循环是否继续进行。继续进行。表达式表达式3通常为表达式语句,用来描述循环控制变量的变化,最通常为表达式语句,用来描述循环控制变量的变化,最常见的是自增或自减表达式,实现对循环控制变量的修改。常见的是自增或自减表达式,实现对循环控制变量的修改。当循环条件满足时就执行循环体内的语句序列。语句序列可以当循环条件满足时就执行循环体内的语句序列。语句序列可以是简单语句,也可以是复合语句。若只有一条语句,则可以省略是简单语句,也可以是复合语句。若只有一条语句,则可以省略。 8/13/20241151168/13/2
103、024for语句的执行过程如下:语句的执行过程如下:1)计算表达式)计算表达式1的值,为循环控制变量赋初值。的值,为循环控制变量赋初值。2)计算表达式)计算表达式2的值,如果为的值,如果为真真则执行循环则执行循环体一次,否则退出循环,执行体一次,否则退出循环,执行for循环后的语句。循环后的语句。3)如果执行了循环体语句,则执行循环体后,)如果执行了循环体语句,则执行循环体后,要计算表达式要计算表达式3的值,调整循环控制变量。然后的值,调整循环控制变量。然后回到第回到第2步重复执行,直到表达式步重复执行,直到表达式2的值为的值为假假时,退出循环。时,退出循环。 for(表达式(表达式1;表达式
104、;表达式2;表达式;表达式3)语句序列;语句序列;/循环体循环体8/13/20241161178/13/2024例例仿真电路如下图所示,编程使图中的发光二极管仿真电路如下图所示,编程使图中的发光二极管D1闪亮。闪亮。 解:程序如下:解:程序如下:#include#defineucharunsignedcharsbitLED=P10;voidmain(void)uchari;while(1)LED=0;for(i=0;i250;i+);LED=1;for(i=0;i250;i+);8/13/20241171188/13/2024例例仿真电路如下图所示,编程使图中的发光二极管仿真电路如下图所示,编
105、程使图中的发光二极管D1闪亮。闪亮。 解:程序如下:解:程序如下:#include#defineucharunsignedcharsbitLED=P10;voidmain(void)uchari;while(1)LED=0;for(i=0;i250;i+);LED=1;for(i=0;i250;i+);8/13/20241181198/13/2024例例仿真电路如下图所示,编程使图中的发光二极管仿真电路如下图所示,编程使图中的发光二极管D1闪亮。闪亮。 解:程序如下:解:程序如下:#include#defineucharunsignedcharsbitLED=P10;voidmain(void
106、)uchari;while(1)LED=0;for(i=0;i250;i+)for(j=0;j80;j+);LED=1;for(i=0;i250;i+)for(j=0;j80;j+);8/13/20241191208/13/2024例例仿真电路如下图所示,编程仿真电路如下图所示,编程使图中的发光二极管使图中的发光二极管LED1闪闪烁烁10次次 。 解:程序如下:解:程序如下:#include#defineuintunsignedintsbitLED=P10;voidmain(void)uinti,j,k;for(k=10;k0;k-)LED=0;for(i=0;i100;i+)for(j=0;
107、j1000;j+);LED=1;for(i=0;i100;i+)for(j=0;j1000;j+);while(1);8/13/20241201218/13/2024注意:注意:for语句中的三个表达式都可以省略,但是分隔符语句中的三个表达式都可以省略,但是分隔符“;”不能省略。如不能省略。如for(;i=100,i+);for(;);/循环无限次循环无限次8/13/20241211228/13/2024(4).while语句语句while语句语句while语句是用来实现语句是用来实现“当型当型”循环的语句,格式为:循环的语句,格式为:while(条件表达式)(条件表达式)语句序列;语句序列;
108、/循环体循环体当型循环示意图当型循环示意图 条件表达式一般是关系表达式或逻辑表达式,条件表达式一般是关系表达式或逻辑表达式,也可以是其它表达式,执行时先计算表达式的值,也可以是其它表达式,执行时先计算表达式的值,当表达式的值为真(非当表达式的值为真(非0)时执行循环体内的语)时执行循环体内的语句序列,为假(句序列,为假(0)时则退出循环。循环体可以)时则退出循环。循环体可以是一条简单语句,也可以是由多条语句构成的复是一条简单语句,也可以是由多条语句构成的复合语句,此时要用括起来。如果没有合语句,此时要用括起来。如果没有,则,则while语句的范围只到语句的范围只到while后的第一个分号处。后
109、的第一个分号处。当型循环可概括为当型循环可概括为“先判断,后执行先判断,后执行”,当,当型循环示意图流程图如右图所示。循环次数需要型循环示意图流程图如右图所示。循环次数需要根据循环条件(表达式的值)来判定,如果开始根据循环条件(表达式的值)来判定,如果开始时循环条件就为假,则循环体一次也不执行。时循环条件就为假,则循环体一次也不执行。 8/13/20241221238/13/2024在在之之前前所所见见到到的的例例程程中中经经常常会会见见到到“while(1)”语语句句,该该语语句句因因为为表表达达式式为为常常数数1,即即永永远远为为真真,不不可可能能为为假假,所所以以该该语语句句将将循循环环
110、无无限限次次,除除非非在在循循环环体体中中有有退退出出语语句句(break)。)。8/13/20241231248/13/2024例例仿真电路如下图所示,编程使图中的发光二极管仿真电路如下图所示,编程使图中的发光二极管D1闪亮闪亮10次。次。用用while语句实现。语句实现。解:程序如下:解:程序如下:#include#defineuintunsignedintsbitLED=P10;voidmain(void)uinti,j,k;k=10;while(k0)LED=0;for(i=0;i100;i+)for(j=0;j1000;j+);LED=1;for(i=0;i100;i+)for(j=
111、0;j1000;j+);k-;while(1);8/13/20241241258/13/2024.do-while语句语句do-while语句是用来实现语句是用来实现“直到型直到型”循环的语句,格循环的语句,格式如下:式如下:do语句序列;语句序列;while(表达式);(表达式);直到型循环示意图直到型循环示意图 条件表达式一般是关系表达式或逻辑表达式,条件表达式一般是关系表达式或逻辑表达式,也可以是其它表达式,执行时先执行循环体一次,也可以是其它表达式,执行时先执行循环体一次,再计算表达式的值,当表达式的值为真(非再计算表达式的值,当表达式的值为真(非0)时执行循环体内的语句序列,为假(时
112、执行循环体内的语句序列,为假(0)时则退)时则退出循环。出循环。 直到型循环可概括为直到型循环可概括为“先执行,后判断先执行,后判断”,流程图如右图所示。无论循环条件是否满足,循流程图如右图所示。无论循环条件是否满足,循环体至少被执行一次。环体至少被执行一次。 8/13/20241251268/13/2024例例求自然数求自然数1200之和。之和。程序如下:程序如下:main()intcount=1,sum=0;/*初始化初始化*/dosum=sum+count;count+;while(count=200);while(1);程序执行结果:程序执行结果:sum=20100 8/13/2024
113、1261278/13/20246.5.3数组与指针数组与指针1数组数组数组是一个由同种类型的变量组成的集合,它保存在连数组是一个由同种类型的变量组成的集合,它保存在连续的存储区域中,第一个元素保存在最低地址中,最末一续的存储区域中,第一个元素保存在最低地址中,最末一个元素保存在最高地址中。个元素保存在最高地址中。数组的定义方式如下:数组的定义方式如下:数据类型数据类型存储器类型存储器类型数组名数组名常量表达式常量表达式;其中类型说明符用来说明数组中每个元素的数据类型;数组名的其中类型说明符用来说明数组中每个元素的数据类型;数组名的定名规则遵循标识符定名规则;方括号中的常量表达式表示该数组所定名
114、规则遵循标识符定名规则;方括号中的常量表达式表示该数组所包含的元素的个数。常量表达式中可以包括常量和符号常量,不能包包含的元素的个数。常量表达式中可以包括常量和符号常量,不能包含变量。也就是说,含变量。也就是说,C51不允许对数组的大小作动态定义,即数组的不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。大小不依赖于程序运行过程中变量的值。 8/13/20241271288/13/20246.5.3数组与指针数组与指针例如:例如:inta8;它表示定义了一个数组名为它表示定义了一个数组名为a,包含,包含8个元素的数组。这个元素的数组。这8个元素分别为个元素分别为a0,a
115、1,a2,a3,a4,a5,a6,a7,注意:下标从,注意:下标从0开始。开始。数组必须先定义,后使用。数组必须先定义,后使用。C51语言规定只能逐个引用数组元素而不语言规定只能逐个引用数组元素而不能一次引用整个数组。能一次引用整个数组。对数组元素的初始化可以用以下方法实现:对数组元素的初始化可以用以下方法实现:(1)在定义数组时对数组元素赋以初值。在定义数组时对数组元素赋以初值。例如例如:inta8=0,1,2,3,4,5,6,7;8/13/20241281298/13/20246.5.3数组与指针数组与指针(2)可以只给一部分元素赋值。可以只给一部分元素赋值。例例:inta8=0,1,2,
116、3,4;定义定义a数组有数组有8个元素,但花括弧内只提供个元素,但花括弧内只提供5个初值,这表个初值,这表示只给前面示只给前面5个元素赋初值,后个元素赋初值,后3个元素值为个元素值为0。(3)如果想使一个数组中全部元素值为如果想使一个数组中全部元素值为0,可以写成,可以写成inta8=0,0,0,0,0,0,0,0;不能写成不能写成inta8=0*8;(4)在对全部数组元素赋初值时,可以不指定数组长度。在对全部数组元素赋初值时,可以不指定数组长度。例例如如:inta5=1,2,3,4,5;可以写成可以写成inta=1,2,3,4,5(5)可以对数组的某个元素赋值,)可以对数组的某个元素赋值,例
117、如:例如:a1=1;a3=3;8/13/20241291308/13/20246.5.3数组与指针数组与指针2指针指针每个存储单元都有一个地址,假设有一个变量每个存储单元都有一个地址,假设有一个变量a,其地,其地址为址为2000H,如果要访问这个单元,可以采用直接按变量,如果要访问这个单元,可以采用直接按变量名名a来存取变量的内容的访问方式,也可以把变量的地址来存取变量的内容的访问方式,也可以把变量的地址2000H放到另外一个变量放到另外一个变量p中,那么为了访问变量中,那么为了访问变量a,可以通可以通过变量过变量p得到得到a的地址的地址2000H,再到该地址中访问变量,再到该地址中访问变量a
118、。由由于通过变量于通过变量p能够间接地存取它所指向的变量能够间接地存取它所指向的变量a,所以把,所以把p称为指针变量。称为指针变量。8/13/20241301318/13/20246.5.3数组与指针数组与指针指针变量的定义方式:指针变量的定义方式:数据类型数据类型*指针变量名;指针变量名;数据类型是指该指针变量可以指向的变量的类型,在上例数据类型是指该指针变量可以指向的变量的类型,在上例中就是变量中就是变量a的类型;的类型;“*”表示该变量的类型为指针型。表示该变量的类型为指针型。例如:例如:int*p_1;char*p_2;float*p_3;8/13/20241311328/13/202
119、46.5.3数组与指针数组与指针定义了指针变量以后,可以通过以下方法使指针变量指向定义了指针变量以后,可以通过以下方法使指针变量指向另一个变量:另一个变量:inta;charb;floatc;p_1=&a;p_2=&b;p_3=&c;这样就把变量这样就把变量a,b,c的地址分别存放到了指针变量的地址分别存放到了指针变量p_1,p_2,p_3中,三个指针就分别指向三个变量了。中,三个指针就分别指向三个变量了。8/13/20241321338/13/20243结构结构结构变量是将互相关联的、多个不同类型的变量结合结构变量是将互相关联的、多个不同类型的变量结合在一起形成的一个组合形变量,简称结构。构
120、成结构的在一起形成的一个组合形变量,简称结构。构成结构的各个不同类型的变量称为结构元素(或成员),其定义各个不同类型的变量称为结构元素(或成员),其定义规则与变量的定义相同。规则与变量的定义相同。一般先声明结构类型,再定义结构变量。一般先声明结构类型,再定义结构变量。6.5.3数组与指针数组与指针8/13/20241331348/13/2024定义一个结构类型的格式为:定义一个结构类型的格式为:Struct结构名结构名结构成员说明结构成员说明;结构成员还可以是其他已定义的结果。结构成员还可以是其他已定义的结果。结构成员说明的格式为:结构成员说明的格式为:类型标识符类型标识符成员名;成员名;C5
121、1结构定义的格式为:结构定义的格式为:struct结构名结构名变量表;变量表;6.5.3数组与指针数组与指针8/13/20241341358/13/2024例例:结构与结构变量的定义结构与结构变量的定义structdate/定义名称为定义名称为date的结构类型的结构类型unsignedcharmonth;unsignedcharday;unsignedcharyear;structdatedate1,date2;/定义结构变量定义结构变量date1和和date2对结构变量中成员的访问使用对结构变量中成员的访问使用“.”运算符,例如:运算符,例如:date1.year=07;date1.mon
122、th=1;date1.day=25;8/13/20241351368/13/20246.5.4C51语言的函数语言的函数C程序由一个主函数程序由一个主函数main()和若干个其他函数组成。由主和若干个其他函数组成。由主函数调用其他函数,其他函数也可以互相调用,同一个函函数调用其他函数,其他函数也可以互相调用,同一个函数可以被调用多次。数可以被调用多次。1函数定义函数定义函数定义的一般格式为:函数定义的一般格式为:函数类型函数类型函数名函数名(形式参数列表形式参数列表)局部变量声明部分局部变量声明部分语句语句(有返回值的要有有返回值的要有return语句语句)8/13/20241361378/1
123、3/20242函数返回值函数返回值返返回回语语句句return用用来来回回送送一一个个数数值值给给定定义义的的函函数数,从从函函数数中中退退出出。返返回回值值是是通通过过return语语句句返返回回的的。如如果果函函数数无无须须返返回回值值,可可以以用用void类类型型说说明明符符指指明明函函数数无无返返回值。回值。3形式参数与实际参数形式参数与实际参数与与使使用用变变量量一一样样,在在调调用用一一个个函函数数之之前前,必必须须对对该该函函数进行声明。函数声明的一般格式为:数进行声明。函数声明的一般格式为:函数类型函数类型函数名函数名(形式参数列表形式参数列表)函函数数定定义义时时参参数数列列
124、表表中中的的参参数数称称为为形形式式参参数数,简简称称形形参参。函函数数调调用用时时所所使使用用的的替替换换参参数数,是是实实际际参参数数,简简称称实实参参。定定义义的的形形参参与与函函数数调调用用的的实实参参类类型型应应该该一一致,书写顺序应该相同。致,书写顺序应该相同。8/13/20241371388/13/2024 在在下下图图所所示示的的仿仿真真电电路路中中,AT89C51AT89C51单单片片机机的的P1.0P1.0引引脚脚连连接接LEDLED发发光光二二极极管管,设设计计程程序序使使LEDLED按按固固定定的的时时间间间间隔隔持持续闪烁。续闪烁。 8/13/20241381398/
125、13/2024#includesbitLED=P10;voidDelayMS(unsignedintx);voidmain()while(1)LED=0;DelayMS(150);LED=1;DelayMS(150);voidDelayMS(unsignedintx)unsignedchari;while(x-)for(i=120;i0;i-);8/13/20241391408/13/20244调用函数的方式调用函数的方式被调用的函数必须是已经存在的函数。被调用的函数必须是已经存在的函数。(1)函函数数作作为为语语句句。把把函函数数调调用用作作为为一一个个语语句句,不不使使用用函数返回值,只是
126、完成函数所定义的操作。例如:函数返回值,只是完成函数所定义的操作。例如:DelayMS(150);(2)函函数数作作为为表表达达式式。函函数数调调用用出出现现在在一一个个表表达达式式中中,使用函数的返回值。使用函数的返回值。intk;k=sum(a,b);(3)函函数数作作为为一一个个参参数数。函函数数调调用用作作为为另另一一个个函函数数的的实实参。参。intk;k=sum(sum(a,b),c);8/13/20241401418/13/20245中断服务程序中断服务程序中中断断服服务务程程序序是是一一种种特特殊殊的的函函数数,又又称称为为中中断断函函数数。使使用用interrupt关键字来实
127、现。关键字来实现。定义中断服务程序的一般格式如下:定义中断服务程序的一般格式如下:void函数名(函数名()interruptnusingm关关键键字字interrupt后后面面的的n是是中中断断号号,理理论论上上可可以以是是031的的整整型型参参数数,用用来来表表示示中中断断处处理理函函数数所所对对应应的的中中断断号号,该该参参数数不不能能是是带带运运算算符符的的表表达达式式。对对于于AT89C51单单片片机机n的取值范围是的取值范围是04。usingm属属性性使使用用一一个个03的的整整型型参参数数,这这个个参参数数表表示示使用的寄存器组的编号。使用的寄存器组的编号。8/13/202414
128、11428/13/2024表表6-4中断源与中断号对应关系中断源与中断号对应关系中断号中断号中断源中断源中断向量中断向量0外部中断外部中断00003H1定时定时/计数器计数器0000BH2外部中断外部中断10013H3定时定时/计数器计数器1001BH4串行口串行口0023H8/13/20241421438/13/20246.5.5C51的预处理的预处理 预处理功能包括宏定义、文件包含和条件编译预处理功能包括宏定义、文件包含和条件编译 3 3个个主要部分。预处理命令不同于主要部分。预处理命令不同于C C语言语句,具有以下特语言语句,具有以下特点:点:预处理命令以预处理命令以“#”#”开头,后面
129、不加分号;开头,后面不加分号;预处理命令在编译前执行;预处理命令在编译前执行;多数预处理命令习惯放在文件的开头。多数预处理命令习惯放在文件的开头。1宏定义宏定义2包含文件包含文件3条件编译命令条件编译命令8/13/20241431448/13/20241宏定义宏定义不带参数的宏定义的格式为:不带参数的宏定义的格式为:#define新名称新名称原内容原内容例:有如右所示的程序,其中例:有如右所示的程序,其中的的#defineuintunsignedint就是一条宏定义。就是一条宏定义。该指令的作用是用该指令的作用是用#define后面后面的第一个字母组合代替该字母的第一个字母组合代替该字母后面的
130、所有内容,即给原内后面的所有内容,即给原内容重新起一个比较简单的新名容重新起一个比较简单的新名称,以后在程序中就可以直接称,以后在程序中就可以直接写简短的新名称,而不必每次写简短的新名称,而不必每次都写繁琐的原内容。都写繁琐的原内容。#include#defineuintunsignedintsbitLED=P10;voidmain(void)uinti,j,k;k=10;while(k0)LED=0;for(i=0;i100;i+)for(j=0;j1000;j+);LED=1;for(i=0;i100;i+)for(j=0;j1000;j+);k-;while(1);8/13/202414
131、41458/13/2024又例:又例:#definePI3.14以后在程序中用以后在程序中用PI代替代替3.14。2包含文件包含文件包包含含文文件件的的含含义义是是在在一一个个程程序序文文件件中中包包含含其其他他文文件件的的内内容容。用文件包含命令可以实现文件包含功能,命令格式为:用文件包含命令可以实现文件包含功能,命令格式为:#include或或#include“文件名文件名”例如,在文件中第一句经常为:例如,在文件中第一句经常为:#includemain()在在编编译译预预处处理理时时,对对#include命命令令进进行行文文件件包包含含处处理理。实实际际上上就就是是将将文文件件reg51
132、.h中中的的全全部部内内容容复复制制插插入入到到#include的命令处。的命令处。8/13/20241451468/13/20243条件编译命令条件编译命令提提供供一一种种在在编编译译过过程程中中根根据据所所求求条条件件的的值值有有选选择择地地包包含含不不同同代代码码的的手手段段,实实现现对对程程序序源源代代码码的的各各部部分分有有选选择择的的进进行行编编译,称为条件编译。译,称为条件编译。#if语语句句中中包包含含一一个个常常量量表表达达式式,若若该该表表达达式式的的求求值值结结果果不不等等于于0时时,则则执执行行其其后后的的各各行行,直直到到遇遇到到#endif、#elif或或#else
133、语语句句为为止止(预预处处理理elif相相当当于于elseif)。在在#if语语句句中中可可以以使使用用一一个个特特殊殊的的表表达达式式defined(标标识识符符):当当标标识识符符已已经定义时,其值经定义时,其值1;否则,其值为;否则,其值为0。8/13/20241461478/13/2024例如,为了保证例如,为了保证hdr.h文件的内容只被包含一次,可以像文件的内容只被包含一次,可以像下面这样用条件语句把该文件的内容包含起来:下面这样用条件语句把该文件的内容包含起来:#ifndef(hdr)#definehdr#include(hdr.h)#endif8/13/20241471488/
134、13/2024所定义的变量经过编译之后会具有所定义的变量经过编译之后会具有浮动地址浮动地址,其,其绝对地址绝对地址必须经过必须经过BL51连接定位连接定位后才能确定。但是我后才能确定。但是我们在设计单片机系统时,有时需要对系统中的某个确们在设计单片机系统时,有时需要对系统中的某个确定的定的具体地址空间具体地址空间进行访问,特别是对外设的操作,进行访问,特别是对外设的操作,必须对绝对地址进行访问。必须对绝对地址进行访问。C51提供了三种访问绝对地提供了三种访问绝对地址的方法。址的方法。6.5.6C51绝对地址的访问绝对地址的访问1使用指针使用指针2使用使用C51扩展关键字扩展关键字_at_3.采
135、用预定义宏采用预定义宏8/13/20241481498/13/20241使用指针使用指针定定义义一一个个指指针针变变量量,然然后后把把地地址址常常数数赋赋予予该该变变量量,就就可以通过该指针变量对该绝对地址进行访问了。例可以通过该指针变量对该绝对地址进行访问了。例:6.5.6C51绝对地址的访问绝对地址的访问#defineucharunsignedcharvoidmain(void)ucharxdata*xdp;uchardata*dp;xdp=0x1000;*xdp=0x66;dp=0x30;*dp=0x77;8/13/20241491508/13/20242使用使用C51扩展关键字扩展关键
136、字_at_对确定地址进行访问对确定地址进行访问使用使用_at_对指定的存储器空间的绝对地址进行定位。格对指定的存储器空间的绝对地址进行定位。格式如下:式如下:存储器类型存储器类型数据类型数据类型标识符标识符_at_常数常数例如:例如:intidatai_at_0x40;/变量变量i定位于定位于idata空间,地址为空间,地址为40Hcharxdataname120_at_0x7000;/字符型数组字符型数组name定位于定位于xdata空间,地址从空间,地址从7000H开始开始注意:注意:(1)用用_at_定义的绝对变量不能初始化;定义的绝对变量不能初始化;(2)bit类型的函数及变量不能定位
137、到一个绝对地址;类型的函数及变量不能定位到一个绝对地址;(3)用用_at_定义的变量必须是全局变量。定义的变量必须是全局变量。8/13/20241501518/13/2024例例将片外将片外RAM1000H开始的开始的12个字节的内容传送到片内个字节的内容传送到片内RAM60H开始的单元。开始的单元。#include#defineucharunsignedcharucharxdatatext112_at_0x1000;uchardatatext212_at_0x60;voidmain(void)uchari;for(i=0;i12;i+)text2i=text1i;while(1);8/13/
138、20241511528/13/20243.采用预定义宏采用预定义宏C51编译器提供了一组编译器提供了一组宏定义来对单片机的宏定义来对单片机的code区、区、data区、区、pdata区和区和xdata区等不同存储区域进行绝对地址区等不同存储区域进行绝对地址的访问。的访问。CBYTE表示以字节方式寻址表示以字节方式寻址code区,区,CWORD表示以字方式寻址表示以字方式寻址code区,区,DBYTE表示以字节方式寻址表示以字节方式寻址data区,区,DWORD表示以字方式寻址表示以字方式寻址data区,区,PBYTE表表示以字节方式寻址示以字节方式寻址pdata区,区,PWORD表示以字方式寻
139、址表示以字方式寻址pdata区,区,XBYTE表示以字节方式寻址表示以字节方式寻址xdata区,区,XWORD表示以字方式寻址表示以字方式寻址xdata区。这些宏定义包含在区。这些宏定义包含在ABSACC.H文件中。文件中。 8/13/20241521538/13/2024例:例:#include#include#defineucharunsignedchar#defineuintunsignedintvoidmain(void)uchara;uintb;DBYTE0x16=a=3;b=XWORD0x2000=8;while(1);例中例中DBYTE0x16=a=3表示把无符号字符型变量表示把
140、无符号字符型变量a(其值为(其值为3)传送给片内)传送给片内数据存储器中地址为数据存储器中地址为16H的单元;的单元;XWORD是以字是以字方式寻址方式寻址xdata区,即每区,即每次寻址两个字节,所以次寻址两个字节,所以b=XWORD0x2000=8表表示对片外数据存储器地址示对片外数据存储器地址为为2000H*2的单元(其值的单元(其值为为8)进行操作,也就是)进行操作,也就是把把4000H和和4001H两个单两个单元内的数据传送给无符号元内的数据传送给无符号整型变量整型变量b。8/13/20241531548/13/20246.5.8C51的库函数的库函数本征库函数:本征库函数:C51提
141、供的本征函数在编译时直接将固定的代码插入当前提供的本征函数在编译时直接将固定的代码插入当前行,而不是用行,而不是用ACALL和和LCALL语句实现的,这样就大大提供了函数访语句实现的,这样就大大提供了函数访问的效率,而非本征函数则必须由问的效率,而非本征函数则必须由ACALL及及LCALL调用。例如:调用。例如:_crol_,_cror_:将:将char型变量循环向左(右)移动指定位数后返回。型变量循环向左(右)移动指定位数后返回。_iror_,_irol_:将:将int型变量循环向左(右)移动指定位数后返回。型变量循环向左(右)移动指定位数后返回。_lrol_,_lror_:将:将long型
142、变量循环向左(右)移动指定位数后返回。型变量循环向左(右)移动指定位数后返回。_nop_:相当于插入汇编指令:相当于插入汇编指令NOP。_testbit_:相当于:相当于JBCbitvar测试该位变量并跳转同时清除。测试该位变量并跳转同时清除。使用上述函数时,源程序开头必须包含使用上述函数时,源程序开头必须包含#include头文件。头文件。8/13/20241541558/13/20246.5.8C51的库函数的库函数例:例:#include#includeunsignedinti,j;unsignedchark,ab;voidmain(void)ab=0xfe;while(1)for(k=
143、0;k0;i-)for(j=110;j0;j-);8/13/20241551568/13/2024例例:对:对AT89C51单片机的片外数据存储器进行读写,首先将单片机的片外数据存储器进行读写,首先将数据数据00H0FH写入到片外数据存储器的写入到片外数据存储器的3000H300FH,然后将数据依次读出来,存储到片内然后将数据依次读出来,存储到片内60H6FH。 #includevoidmain()unsignedintaddr;charaddr1,i;addr=0x3000,addr1=0x60;/片内、外存储区首地址分别为片内、外存储区首地址分别为60H、3000Hfor(i=0;i16;
144、i+)*(charxdata*)addr+)=i;/给片外存储地址赋初值给片外存储地址赋初值addr=0x3000;for(i=0;i16;i+)/从片外存储区读出数据并从片外存储区读出数据并/存储到片内的数据存储区存储到片内的数据存储区*(charidata*)addr1+)=*(charxdata*)addr+);while(1);8/13/20241561578/13/2024例:首先将例:首先将30H30H为首地址的为首地址的1616个单元送数据个单元送数据0FH0FH00H00H,然后再,然后再将这些数据按照从小到大的顺序重新排列。将这些数据按照从小到大的顺序重新排列。#includ
145、evoidmain()charaddr,i,j,t;addr=0x30;/数据块的首地址数据块的首地址for(i=0;i16;i+)*(charidata*)(addr+i)=15-i;/初始化数据块初始化数据块for(i=0;i15;i+)/采用冒泡法排序采用冒泡法排序for(j=i+1;j*(charidata*)(addr+j)t=*(charidata*)(addr+i);*(charidata*)(addr+i)=*(charidata*)(addr+j);*(charidata*)(addr+j)=t;8/13/20241571588/13/2024作业:作业:1.编写程序,在编写
146、程序,在P1.0端口上接一个发光二极管端口上接一个发光二极管L1,使,使L1在不停地一亮一灭,一亮一灭的时间间隔为在不停地一亮一灭,一亮一灭的时间间隔为0.2秒(假秒(假设设P1端口输出高电平,发光二极管灭)。要求用端口输出高电平,发光二极管灭)。要求用proteus仿真验证。仿真验证。2.编写程序监视开关编写程序监视开关K1(接在(接在P3.0端口上),用发光二端口上),用发光二极管极管L1(接在单片机(接在单片机P1.0端口上)显示开关状态,如端口上)显示开关状态,如果开关合上,果开关合上,L1亮,开关打开,亮,开关打开,L1熄灭(假设熄灭(假设P1端口端口输出高电平,发光二极管灭)。要求
147、用输出高电平,发光二极管灭)。要求用proteus仿真验仿真验证。证。3.编写程序,利用单片机的编写程序,利用单片机的P0.0P0.3接四个发光二极管接四个发光二极管L1L4,P0.4P0.7接了四个开关接了四个开关K1K4,编程将开,编程将开关的状态反映到发光二极管上。(开关闭合,对应的关的状态反映到发光二极管上。(开关闭合,对应的灯亮,开关断开,对应的灯灭)。要求用灯亮,开关断开,对应的灯灭)。要求用proteus仿真仿真验证。验证。8/13/20241581598/13/2024作业:作业:1.分析以下程序,写出运行结果。分析以下程序,写出运行结果。inta=3,b=5;intmax(inta,intb)intc;c=ab?a:b;returnc;main()inta=8;printf(“%d”,max(a,b); 8/13/20241591608/13/2024作业:作业:2.设设X、Y为变量,试按下式要求编程。为变量,试按下式要求编程。 3.用用AT89C51的的P1口控制口控制8个发光二极管个发光二极管LED。相邻的两个。相邻的两个LED为一组,使每组每隔一段时间发亮一次,周而复始,编为一组,使每组每隔一段时间发亮一次,周而复始,编写程序实现上述要求写程序实现上述要求(设设P1口所接发光二极管为共阳极口所接发光二极管为共阳极)。 8/13/2024160