第8章-IO口的C语言编程_第1页
第8章-IO口的C语言编程_第2页
第8章-IO口的C语言编程_第3页
第8章-IO口的C语言编程_第4页
第8章-IO口的C语言编程_第5页
已阅读5页,还剩78页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、23MCS-51单片机的输出口有4个,分别为P0、P1、P2、P3,其中,P1,P2和P3口是准双向口,P0口为双向三态口。 。4 1P0口 P0口一个引脚的内部结构如图8-1所示。从图8-1中可以看出,电路中包含一个数据输出锁存器、两个三态数据输入缓冲器和一个数据输出的驱动电路。P0.x可以是P0.0到P0.7中的任何一位,即P0口是由8个与图8-1相同的电路构成。多路开关MUX与 相连接时,P0口作为普通的I/O口使用;多路开关MUX和与门相连接时,P0口作为数据/地址总线使用。P0口作为I/O口使用时,由于其内部没有上拉电阻,因而需要外接上拉电阻。5图8-1 P0口内部结构 2P1口 P

2、1口为8位准双向口,这8位均可单独定义为输入或输出口,每一位的内部电路结构如图8-2所示。 P1.x输出数据时,把1写入锁存器时, =0,T2截止,内上拉电阻将电位拉至1,此时该口输出为1;把0写入锁存器时, =1,T2导通,输出为0。 准双向口P1作为输入口时,应先将锁存器置1,这样 =0,T2截止,此时该位既可以由外部电路拉成低电平,也可由内部上拉电阻拉成高电平。6图8-2 P1口内部结构双向口与准双向口的区别是准双向I/O口用于数据输入时需要先对其置1,否则,若前一位输入低电平,后一位输入高电平时将导致数据出错;而双向口则不需要提前置1操作,因为双向口有悬浮态。 7需要说明的是,P1作为

3、输入口使用时,输入方式有两种情况: (1)先读锁存器的内容,处理后再写入到锁存器,这种操作即“读修改写”操作,JBC(逻辑判断)、CPL(取反)、INC(递增)、DEC(递减)、ANL(与逻辑)和ORL(逻辑或)指令均属于这类操作。 (2)打开三态门G2,将P1口的外部状态读入CPU。 3P2口 P2口不仅可以用作输入/输出口,也可以和P0口一起用作外部存储器的地址总线。8由于单片机没有专用的地址总线和数据总线,在向外扩展存储器和接口时,P2口和P0口充当地址总线和数据总线,P2口输出地址的高8位(A8A15),P0口输出地址的低8位(A0A7)。P2口结构如图8-3所示。图8-3 P2口内部

4、结构 4P3口9 P3口的第一功能和P1口一样,既可作为输入/输出端口,又能够进行字节操作和位操作。在位操作模式下,每位引脚可以单独定义为输入或输出引脚。 在实际应用中,P3口第二功能的作用更为突出。为适应第二功能的需要,每位引脚内部都增加了第二功能控制逻辑,其内部结构如图8-4所示。图8-4 P3口内部结构 下面着重讨论P3口的第二功能,P3口用于第二功能的各引脚定义如下:10 P3.0:串行输入口(RXD)。 P3.1:串行输出口(TXD)。 P3.2:外部中断0(INT0)。 P3.3:外部中断1(INT1)。 P3.4:定时/计数器0的外部输入口(T0)。 P3.5:定时/计数器1的外

5、部输入口(T1)。 P3.6:外部数据存储器写选通(WR)。 P3.7:外部数据存储器读选通(RD)。 P3作为输出端口使用时,第二功能信号线保持高电平,与非门开通,从锁存器到输出口的通路畅通无阻,数据能够正常输出。P3口使用第二功能输出时,锁存器置为高电平,与非门对第二功能信号的输出是畅通的,从而实现第二功能信号的输出。 使用第二功能输入时,引脚的第二功能控制逻辑在输入通路上增设了一个缓冲器,输入的第二功能信号可从这个缓冲器的输出端取得。而作为I/O口时,输入信号取自三态缓冲器的输出端。不管是作为第一功能的输入端口使用还是第二功能信号输入,输出电路中的锁存器输出和第二功能输出信号线均应置1。

6、 新型的51系列单片机,除了有传统的P0P3口之外,还有P4口,各端口地址及数据位如表8-1所示。11表8-1 新型51单片机I/O端口助记符地址名字76543210复位值P080H8位P0P0.7P0.6P0.5P0.4P0.3P0.2P0.1P0.011111111P190H8位P1P1.7P1.6P1.5P1.4P1.3P1.2P1.1P1.011111111P2A0H8位P2P2.7P2.6P2.5P2.4P2.3P2.2P2.1P2.011111111P3B0H8位P3P3.7P3.6P3.5P3.4P3.3P3.2P3.1P3.011111111P4E8H4位P4-P4.3P4.2

7、P4.1P4.0*1111 P4口可以像普通的P1,P2,P3口一样进行操作,在使用C语言编程时,需要在程序的开头进行声明。 sfr P4 = 0 xe8;/C语言中声明P4口特殊功能寄存器地址 在汇编语言编程时,可以进行如下操作。 P4 DATA 0E8H;或P4 EQU 0E8H MOV A, P4;读取P4口的状态到累加器中 MOV P4, #0AH;向P4口输出数据“#0AH” SETB P4.0;P4.0=1 CLR P4.0 ;P4.0=01213148.2.1驱动发光二极管8.2.2驱动蜂鸣器8.2.3驱动继电器8.2.4驱动7段LED数码管15【例8-1】如图8-5所示,P2驱

8、动8个LED灯。当每位引脚输出为0时,LED灯被点亮;引脚输出为1时,LED灯不亮。在此结构图基础上设计一个霹雳灯程序,使得任何时候只有一个LED灯亮。图8-5 霹雳灯电路连接16 每次只点亮一个LED,即P2端口在输出时只能有一位为0,其他位为1。设计程序时,可以先使P2端口的值左移7次,左移可采用“LED=1;”实现右移1位,移动后在最高位补1;如此循环即可实现其功能。霹雳灯程序流程如图8-6所示。【例8-1】如图8-5所示,P2驱动8个LED灯。当每位引脚输出为0时,LED灯被点亮;引脚输出为1时,LED灯不亮。在此结构图基础上设计一个霹雳灯程序,使得任何时候只有一个LED灯亮。图8-6

9、 霹雳灯程序流程图17 【参考代码】/*/此程序实现LED灯先向左移动,后向右移动,即为霹雳灯/*#include/*程序声明*#define LED P2/将P2口定义为LEDvoid delay(int);/*主程序*main()【例8-1】如图8-5所示,P2驱动8个LED灯。当每位引脚输出为0时,LED灯被点亮;引脚输出为1时,LED灯不亮。在此结构图基础上设计一个霹雳灯程序,使得任何时候只有一个LED灯亮。18 unsigned char i; LED=0 xfe; while(1) for(i=0;i7;i+)/向左移动7次 delay(100); LED=(LED1)|0 x01

10、;/向左移动,每移动1次在最低位补1for(i=0;i1)|0 x80;/向右移动,每移动1次在最高位补1 /*延时x0.5ms子函数*void delay(int x) int i,j; for(i=0;ix;i+)for(j=0;j=60;j+);【例8-1】如图8-5所示,P2驱动8个LED灯。当每位引脚输出为0时,LED灯被点亮;引脚输出为1时,LED灯不亮。在此结构图基础上设计一个霹雳灯程序,使得任何时候只有一个LED灯亮。蜂鸣器(buzzer)是一种发声装置,可分为无源蜂鸣器与有源蜂鸣器,如图8-7所示。20图8-7 有源(左)与无源(右)蜂鸣器 蜂鸣器的“源”不是指电源,而是指震

11、荡源。有源蜂鸣器内部带有震荡源,只要通电就可以鸣叫,所以通常用作报警提示,其优点是程序控制方便。 无源蜂鸣器内部不带震荡源,所以直流信号无法令其鸣叫,必须使用1K5K的方波才能驱动它。无源蜂鸣器的优点是声音频率可控,并可做出类似“哆来咪发嗦拉西”的效果。在一些特例中,无源蜂鸣器可以和LED复用一个控制口。 蜂鸣器的驱动电路如图8-8所示,该电路中三极管基极直接与P1,P2,P3相连,P0与三极管的基极相连时可以在基极接上上拉电阻。21 蜂鸣器本质上是一个感性元件,其电流不能瞬变,因此必须有一个续流二极管提供续流,否则在蜂鸣器两端会产生几十伏的尖峰电压,可能损坏三极管,并干扰整个电路系统的其他部

12、分。 图8-8 蜂鸣器驱动电路22 使无源蜂鸣器鸣叫的关键是设置合适的方波。方波即先设置一定时间的高电平,再设置同样时长的低电平,这里通过pulse_BZ()函数来实现。 【参考代码】/*/此实验用的蜂鸣器为可编程控制的无源蜂鸣器,应要考虑蜂鸣器的工作频率/频率不能过低,过低不会蜂鸣,过高即表现为噪音,频率不同声音效果不同/*声明*#includesbit buzzer=P10;void delay(int);void pulse_BZ(int,int,int);【例8-2】编程实现无源蜂鸣器的鸣叫。23 /*主程序*main() while(1) pulse_BZ(100,10,10);/蜂

13、鸣器发声100(5+5)ms=0.5Sdelay(10000);/延时100000.5ms=5S 【例8-2】编程实现无源蜂鸣器的鸣叫。24/*延时子函数*/*延时函数开始,延时x0.05ms */void delay(int x) int i,j; for(i=0;ix;i+) for(j=1;j=6;j+);【例8-2】编程实现无源蜂鸣器的鸣叫。25/*蜂鸣器蜂鸣子函数*/*蜂鸣器发声函数,count=计数次数,TH=高电平时间,TL=低电平时间 */void pulse_BZ(int count,int TH,int TL) int i; for(i=0;icount;i+) buzze

14、r=1;/输出高电平delay(TH);/延迟TH0.05msbuzzer=0;/输出低电平delay(TL);/延迟TL0.05ms 【例8-2】编程实现无源蜂鸣器的鸣叫。26【例8-3】使用单片机控制继电器,P1.1控制所连接的继电器,每1S开关一次,开关8次后,蜂鸣器发出两声鸣叫“哔哔”,然后再从头开始执行上述操作。电路连线如图8-9所示。图8-9 继电器与蜂鸣器实验电路27【例8-3】使用单片机控制继电器,P1.1控制所连接的继电器,每1S开关一次,开关8次后,蜂鸣器发出两声鸣叫“哔哔”,然后再从头开始执行上述操作。 程序流程如图8-10所示。声明变量和函数后,先给P1.1引脚高电平0

15、.5秒,使继电器闭合从而形成通路点亮灯泡;然后给P1.1引脚低电平,熄灭灯泡,持续时间也是0.5秒。如此点亮灯泡8次后,使蜂鸣器鸣叫2次。以上操作不断重复执行即可实现指定的功能。图8-10 继电器程序执行流程28【例8-3】使用单片机控制继电器,P1.1控制所连接的继电器,每1S开关一次,开关8次后,蜂鸣器发出两声鸣叫“哔哔”,然后再从头开始执行上述操作。 【参考代码】/*/继电器驱动实验/*#includesbit buzzer=P10;/声明蜂鸣器接到P1.0引脚sbit relay=P11;/声明继电器接到P1.1引脚void delay(int);/声明延时函数void pulse_B

16、Z(int,int,int);/声明蜂鸣器函数void pulse_RL(int,int,int);/声明继电器函数29【例8-3】使用单片机控制继电器,P1.1控制所连接的继电器,每1S开关一次,开关8次后,蜂鸣器发出两声鸣叫“哔哔”,然后再从头开始执行上述操作。main() while(1) pulse_RL(8,1000,1000);/继电器使灯亮灭各8次,每次10000.5ms=0.5spulse_BZ(100,1,1);/蜂鸣器发第1声delay(200); /延时2000.5ms=100mspulse_BZ(100,1,1);/蜂鸣器发第2声delay(200); 30【例8-3】

17、使用单片机控制继电器,P1.1控制所连接的继电器,每1S开关一次,开关8次后,蜂鸣器发出两声鸣叫“哔哔”,然后再从头开始执行上述操作。/*延时0.5ms子函数*void delay(int x) int i,j; for(i=0;ix;i+) for(j=1;j=60;j+);31【例8-3】使用单片机控制继电器,P1.1控制所连接的继电器,每1S开关一次,开关8次后,蜂鸣器发出两声鸣叫“哔哔”,然后再从头开始执行上述操作。/*蜂鸣器发声函数*void pulse_BZ(int count ,int TH,int TL) int i; for(i=0;icount;i+) buzzer=1;/

18、输出高电平 delay(TH);/延时TH时间buzzer=0;/输出低电平delay(TL);/延时TL时间 32【例8-3】使用单片机控制继电器,P1.1控制所连接的继电器,每1S开关一次,开关8次后,蜂鸣器发出两声鸣叫“哔哔”,然后再从头开始执行上述操作。/*继电器子函数*void pulse_RL(int count ,int TH,int TL) int i; for(i=0;i=count;i+) relay=1;/输出高电平,继电器励磁(灯亮) delay(TH);relay=0;/输出低电平,继电器消磁(灯灭)delay(TL); 33【例8-4】编写程序,驱动共阳极7段数码管

19、依次显示数字09。 这里使用单片机的P0口驱动数码管,数码管与单片机的连接见图8-11,程序流程如图8-12所示。图8-11 7段数码管实验图 图8-12 程序流程图34【例8-4】编写程序,驱动共阳极7段数码管依次显示数字09。 将数码管的驱动信号放置在数组TAB10中,每取出一个数据,就通过P0口进行输出,这样就能在数码管显示出对应的数字了。 【参考代码】/*/驱动7段数码管依次显示数字09/*#include#define SEG P0/*声明7段数码管09驱动信号(共阳)*char TAB10=0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,0 x83,0 xf

20、8,0 x80,0 x98;void delay(int);35【例8-4】编写程序,驱动共阳极7段数码管依次显示数字09。/*主函数*main() unsigned char i; while(1) for(i=0;i10;i+) SEG=TABi; delay(500); 36【例8-4】编写程序,驱动共阳极7段数码管依次显示数字09。/*延时函数*void delay(int x) int i,j; for(i=0;ix;i+)for(j=1;j=150;j+);378.3.1输入设备8.3.2输入电路设计8.3.3抖动与防抖动8.3.4输入设备编程应用38单片机的I/O口既可以输出数据

21、,也可以输入数据。P0口用于输出时,需要外接10K的上拉电阻,以确保输出数据的可靠性;若用于输入,则使用时需要先向该口赋值1。39对于数字电子电路而言,最基本的输入设备是开关。开关按其结构可以分为按钮开关和闸刀开关两类。按钮开关通常用于产生边缘触发的场合,每按一次产生一个脉冲;而闸刀开关主要用于电平触发的场合。 。 1按钮开关(Button) 按钮开关的特点是具有自动恢复(回弹)功能。常见的按钮开关是轻触开关,如图8-13(a)所示。按下按钮时开关接通,放开按钮时开关断开,其内部结构如图8-13(b)所示。40 如图8-13所示,按钮开关有4个引脚,引脚1与引脚4连通、引脚2与引脚3连通。按钮

22、按下时,内部开关a接通;松开按钮,a自动弹起,开关断开。电子电路或微型计算机所使用的按钮开关有6mm,8mm,10mm,12mm等尺寸。(a)轻触开关实物(b)轻触开关内部电路结构图8-13 轻触开关实物及其内部电路结构 2闸刀开关(Knife Switch) 这类开关具有保持功能,将开关拨动到ON时,内部的开关接通形成通路,若要断开通路,则需要再次拨动开关。比较典型的闸刀开关是指拨开关(DIP switch),如图8-14所示。指拨开关内部相当于含有若干个独立的开关。 当电路板上不需要经常切换状态时可以利用短路帽进行替代。说 明41(a)指拨开关实物 (b)指拨/闸刀开关电路符号图8-14

23、指拨开关实物与电路符号设计数字电路或含有微控制器的输入电路时,输入端不能含有不确定的状态,即输入端不可留空,否则除了会产生不确定的状态外,还可能感染噪声,使电路产生误动作。 1按钮开关的输入电路设计将按钮开关接入输入端时,需要连接一个电阻再接到VCC或GND上,如图8-15所示。42图8-15 按钮开关作为输入元件 P0.7引脚连接的按钮开关初始状态为开路状态,该开关与一个10KW的电阻串联后连接到VCC上,此时输入引脚保持为高电平。按下按钮开关时,输入引脚变为低电平;放开开关时,输入引脚恢复为高电平,这样就产生了一个负脉冲。设计数字电路或含有微控制器的输入电路时,输入端不能含有不确定的状态,

24、即输入端不可留空,否则除了会产生不确定的状态外,还可能感染噪声,使电路产生误动作。 1按钮开关的输入电路设计将按钮开关接入输入端时,需要连接一个电阻再接到VCC或GND上,如图8-15所示。43图8-15 按钮开关作为输入元件 P0.5引脚连接的按钮开关初始状态为开路状态,开关与一个470W的电阻相接后接地,此时输入引脚为低电平。按下按钮开关时,引脚经开关连接上VCC,输入引脚变为高电平;放开开关时,输入引脚将恢复为低电平,这样就产生了一个正脉冲。 2闸刀开关的输入电路设计 将闸刀开关接到输入端时,通常也会接一个上拉电阻到VCC或接一个下拉电阻到GND,如图8-16所示。 闸刀开关作为输入设备

25、使用时,其工作原理类似于按钮开关。但闸刀开关两种状态的切换需要手动完成,即拨动开关一次能够完成一次切换,再次拨动才能恢复开关原状。44图8-16 闸刀开关作为输入元件不管是按钮开关还是闸刀开关,在操作时,信号的高低电平切换并不如想象中的理想。实际应用中,开关操作在很多情况下会产生不确定状态,这种状态将产生噪声信号,因而需要及时进行去干扰处理。 1抖动现象如图8-17所示,图的上半部分为开关按下和松开时的实际状态,下半部分为理想状态。在实际应用中,按键按下和松开都将产生抖动,同时也会产生干扰信号,这种干扰信号对数字电路的影响很大,往往会导致计数的错误。451020ms抖动1020ms抖动理想状态

26、实际状态图8-17 开关的实际状态与理想状态 2硬件防抖动要避免按键抖动,可以用一个切换开关及互锁电路组成一个防抖动电路(debouncer),如图8-18所示。这个电路虽然可以降低抖动所产生的噪声,但它所需要的元件较多,且将占用电路的PCB板空间,这样就增加了成本与电路的复杂程度。46图8-18 互锁防抖动电路 除了上述电路外,也可以利用RC元件来设计一个防抖动的滤波电路,如图8-19所示。放开按钮开关时,开关通路被断开,电容开始充电;而开关被按下时,电容被短路,此时电容开始放电。电容在开关抖动期间处于充电或放电状态,这期间电容始终保持为低电平,并不随抖动而发生变化;抖动过后,电容两端的电压

27、才稳定上升,这样就避开了抖动的时间段。这种电路结构简单,是一种常用的防抖动电路。47图8-19 RC防抖动电路 3软件防抖动 利用硬件防抖动电路会增加硬件设计的成本与复杂度,故有时也利用软件来防抖动。只要避开按键按下时产生抖动的20ms,即可达到防抖动的目的。 因而在按下按钮开关的瞬间,立刻执行debouncer()防抖动函数,这样就避开了产生抖动的时间段。而debouncer()防抖动函数只是一个延时函数(总延时为20ms),其代码如下所示。 void debouncer(void) int i;/声明变量 for(i=0;i2400;i+);/计数2400次来达到延时目的 48【例8-5】

28、如图8-20所示,编程实现以下功能:若P0.0所连接的LED不亮,按一下PB1,则LED亮;再按一下PB1,则LED不亮,如此循环。49图8-20 按钮切换式控制实验 实现该功能的程序流程如图8-21所示。初始化时先关闭LED,然后判断PB1是否按下,如果按下,则先调用防抖动函数,再切换LED的状态。【例8-5】如图8-20所示,编程实现以下功能:若P0.0所连接的LED不亮,按一下PB1,则LED亮;再按一下PB1,则LED不亮,如此循环。50图8-21 按钮切换式控制程序流程 【参考代码】/*/按钮切换式控制实验:若原本P0.0所连接的LED不亮,按一下PB1/则LED灯亮,再按一下PB1

29、,则LED不亮,依次循环工作/*#includesbit PB1=P20; /声明PB1接到P2.0引脚sbit LED=P00; /声明LED接到P0.0引脚void debouncer(void);/声明防抖动函数/=主程序=【例8-5】如图8-20所示,编程实现以下功能:若P0.0所连接的LED不亮,按一下PB1,则LED亮;再按一下PB1,则LED不亮,如此循环。51main() LED=1;/关闭LED P2=0 xff;/将P2口设置为输入口 while(1) if(PB1=0)/判断按键是否按下 debouncer();/进行按键防抖动 LED=!LED;/切换LED为反相 【例

30、8-5】如图8-20所示,编程实现以下功能:若P0.0所连接的LED不亮,按一下PB1,则LED亮;再按一下PB1,则LED不亮,如此循环。52/=延时20ms防抖动子程序=/*防抖动函数,延时约20ms */void debouncer(void) int i;/声明整数变量i for(i=0;i2400;i+);【例8-5】如图8-20所示,编程实现以下功能:若P0.0所连接的LED不亮,按一下PB1,则LED亮;再按一下PB1,则LED不亮,如此循环。53Q【思考题】 在上述过程中,改变debouncer()函数的时间长短会有什么影响?若按住PB1不放会怎么样?如何改善?54 如图8-2

31、2(下页)所示,P0口通过限流电阻连接至共阳极7段LED数码管,P2.0连接按钮开关PB1,PB2.1连接PB2,其中PB1具有增数功能,PB2具有减数功能。编程实现如下功能:7段LED数码管最初显示为0,按一下PB1后,数码管显示1;再按一下PB1,数码管显示2数码管显示9时,再按下PB1,重新显示数字0。若7段LED数码管显示数字n(n9),按一下PB2,数码管显示n1;再按一次PB2,数码管显示n2依此类推。 先将09这10个数字的驱动信号放入字符数组中,然后判断PB1是否为0,若PB1被按下,则显示下一个数字,若显示数字9,按下PB1则重新显示数字0;如果按下PB2,则显示上一个数字,

32、若当前显示的是数字0,按下PB2后重新显示数字9。程序流程如图8-23(下下页)所示。【例8-6】55【例8-6】56图8-22 按键控制7段LED数码显示【例8-6】57图8-23 按钮开关控制7段LED数码管 【参考代码】/*/ 两个按钮开关控制7段LED数码管进行加减数显示/ 功能:P2.0连接PB1,P2.1连接PB2,PB1具有增数功能,PB2具有减数功能/*#include#define SEG P0/将P0口连接至7段LED数码管/* 声明7段LED数码管驱动信号数组(共阳极)*/char TAB10=0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,0 x

33、83,0 xf8,0 x80,0 x98 ;/ 0 1 2 3 4 5 6 7 8 9void debouncer(void);/声明防抖动函数sbit PB1=P20;/声明按钮1与P2.0相连sbit PB2=P21;/声明按钮2与P2.1相连【例8-6】58 /=主程序=main() unsigned char i=0; PB1=PB2=1; /设置为输入口 while(1) SEG=TABi;/输出数字到7段LED数码管if(PB1=0)/判断PB1是否按下 debouncer();/调用防抖动函数 i=(i9)?i+1:0;/若i=9清除为0 【例8-6】59 if(PB2=0)/判

34、断PB2是否按下 debouncer();/调用防抖动函数 i=(i0)?i-1:9;/若i0则i=i-1,i=0则从9开始继续显示 /=延时防抖动子程序=void debouncer(void) int i; for(i=0;i2400;i+);/单片机晶振12MHz,计数2400次,延时20ms【例8-6】60 如图8-24所示,P0口经限流电阻连接8个LED灯,P2口的低四位各连接一个开关,每个输入/输出端口上都连接了一个10K的上拉电阻使其保持高电平。【例8-7】61图8-24 多重按钮开关实验电路按一下PB1按钮,前4个LED(D1D4)和后4个LED(D5D8)交互点亮3次(即前4

35、个LED亮、后4个LED不亮;0.5s后,切换为前4个LED不亮、后4个LED亮;如此循环3次),然后8个LED闪烁3次(每闪烁一次为全亮0.5s、全暗0.5s)。按一下PB2按钮,单灯左移(先点亮最右侧LED,点亮的LED逐步向左移动一位,直至点亮最左侧的LED,这个过程为1圈)3圈,然后8个LED闪烁3次。按一下PB3按钮,单灯右移(先点亮最左侧LED,点亮的LED逐步向右移动一位,直至点亮最右侧的LED,这个过程为1圈)3圈,然后8个LED闪烁3次。按一下PB4按钮,点亮霹雳灯(单灯先左移1圈,再右移1圈)3圈,然后8个LED闪烁3次。【例8-7】编程实现如下功能:62 根据功能需求,对

36、不同的功能编写不同的函数,如防抖动函数、交互闪烁函数、单灯左移函数、单灯右移函数、霹雳灯函数、闪烁函数及延迟函数等。利用条件判断语句来判断PB1,PB2,PB3,PB4按钮是否被按下,再根据按钮的不同状态,调用不同的函数,以实现相应的功能。由于函数较多,且大都在前面的操作过程中使用过,在此将所有函数放在头文件myio.h中,这样整个程序的结构比较清楚。 本例将分别用if-else结构和switch结构来说明按钮的优先等级问题。【例8-7】63 (1)采用if-else结构,程序流程如图8-25所示。依次判断各开关的状态,选择执行不同的操作。【例8-7】64图8-25 if-else结构实现多重

37、按钮开关流程 【参考代码】 myio.h头文件。/*/此头文件包含:防抖动函数、交互闪烁函数、单灯左移函数、单灯右移函数/霹雳函数、闪烁函数、延时函数/*#define LED P0 /将LED连接到P0口void debouncer(void);/声明防抖动函数void delay10ms(int); /声明10ms延迟函数void alter(int);/声明交互闪烁函数void left(int);/声明单灯左移函数void right(int);/声明单灯右移函数void pili(int);/声明霹雳灯函数void flash(int);/声明闪烁函数【例8-7】 (1)采用if-e

38、lse结构65 /=防抖动函数,延迟约20ms =void debouncer(void) int i; for(i=0;i2400;i+);/计数2400次,延迟约20ms/=延迟10*x ms函数=void delay10ms(int x) int i,j; for(i=0;ix;i+) for(j=1;j=1200;j+);/计数1200次,延迟约10ms【例8-7】 (1)采用if-else结构66 /=高低位交互闪烁函数,执行x次=void alter(int x) int i; LED=0 x0f;/初始化状态(高位亮,低位灭) for(i=0;i2*x-1;i+)/i变量for循

39、环执行2x-1次 delay10ms(50);/延迟5010ms=0.5s LED=LED;/LED反相输出 delay10ms(50);【例8-7】 (1)采用if-else结构67/=全灯闪烁函数,执行x次=void flash(int x) int i;/声明变量i LED=0 x00;/初始化状态(全亮) for(i=0;i2*x-1;i+)/i变量for循环执行2x-1次 delay10ms(50); LED=LED;/P0口反相输出 delay10ms(50);【例8-7】 (1)采用if-else结构68/=单灯左移函数,执行x圈=void left(int x) int i,j

40、; for(i=0;ix;i+)/i循环,执行x圈 LED=0 xfe;/初始化状态=1111 1110 for(j=0;j7;j+)/j循环,左移7次 delay10ms(25);/延迟2510ms=0.25sLED=(LED1)|0 x01; /左移1位后,LSB设为1 delay10ms(25);/延迟0.25s 【例8-7】 (1)采用if-else结构69/=单灯右移函数,执行x圈=void right(int x) int i,j;/声明变量i,j for(i=0;ix;i+)/i循环,执行x圈 LED=0 x7f;/初始化状态=0111 1111 for(j=0;j1)|0 x80;/左移1位后,MSB设为1 delay10ms(25);/延迟2510ms=0.25ms 【例8-7】 (1)采用if-else结构70/=霹雳灯函数,执行x圈=void pili(int x)/霹雳灯函数开始 int i;/声明变量i for(i=0;ix;i+)/i循环,执行x圈 left(1);/单灯左移一圈 right(1);/单灯右移一圈 【例8-7】 (1)采用if-else结构71 主程序main.c文件。/=声明=#include#include myio.hsbit PB1=P20 ; /声

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论