I/O口是单片机最重要的系统资源之一,也是单片机连接外围设备的通道。下面以发光二极管、开关、数码管等典型I/O设备为例介绍单片机I/O口的基本应用。这样一方面可使读者在学习单片机部分原理之后能及早了解单片机的相关应用;另一方面可使读者在具体实例分析过程中能逐渐熟悉并掌握C51语言编程方法。
1.基本输入/输出单元介绍
(1)发光二极管(简称LED)具有电路简单、寿命长、响应快等特点,它是单片机应用系统最为常用的输出设备之一。发光二极管与单片机接口可以采用低电平驱动和高电平驱动两种方式。图4.2为低电平驱动,I/O端口输出“0”电平可使其点亮,反之输出“1”电平可使其关断。图4.3为高电平驱动,点亮电平和关断电平分别为“1”和“0”。最简单的发光二极管接口形式是通过将限流电阻R直接挂在I/O口线上实现的,限流电阻通常取100Ω~1KΩ。
大部分人习惯采用图4.2电路的原因有两个:
一是单片机复位后,P0~P3口均输出高电平(复位后P0~P3默认为FFH),在图4.3电路中,系统上电或没有执行对P1口操作的指令,则LED将全部被点亮。
二是采用图4.2电路,二极管导通时,电流流入单片机,此时称灌电流;而采用图4.3电路,二极管导通时,电流流出单片机,此时称拉电流。单片机灌电流的能力远远大于拉电流的能力,所以在图4.3电路中必须加上驱动电路,才能保证LED的亮度。
图4.2 低电平驱动LED
图4.3 高电平驱动LED
(2)LED数码管是由发光二极管组成的显示器件,它是单片机应用系统最为常用的输出设备之一。最常用的是七段LED显示器,这种显示器由8个发光二极管(7个笔画段+1个小数点)组成,简称数码管。当数码管的某个发光二极管导通时,相应的笔画(长称为段)就发光。控制不同的发光二极管的导通就能显示出所要求的字符如图4.4所示。
图4.4 LED数码管
在数码管内部,通常将8个发光二极管的阴极或阳极连在一起作为公共端,这样可以使驱动电路简单,将阴极连在一起的称为共阴极数码管,用高电平驱动数码管各段的阳极,其com端接地;将阳极连在一起的称为共阳极数码管,用低电平驱动数码管各段的阴极,其com端接+5V。
要想显示某字形就要使此字形的相应笔画段点亮,即要送一个用不同电平组合的数据至数码管,这种装入数码管的数据编码简称为字形码。共阴极显示器与共阳极显示器的字形码是逻辑非的关系。常用字符字形码如表4.7所示。
表4.7 8段LED数码管字形码
(3)按键或开关是最基本的输入设备,通常直接与单片机I/O口线连接,见图4.5。当按键或开关闭合时,对应的口线的电平就会发生反转,CPU通过读端口电平即可识别是哪个按键或开关闭合。需要注意的是,P0口工作在I/O口方式时,其内部结构为漏极开路状态,因此与按键或开关接口时需要有上拉电阻,而P1~P3口均不存在这一问题,故不需要上拉电阻(如图4.15PX.N端口)。
图4.5 按键或开关与单片机的简单接口
上面介绍了一些常用的输入输出设备,下面将按由易到难的顺序介绍几个典型实例,使我们对C51编程进一步熟悉。
【实例一】闪烁的LED
单片机P2.0引脚连接LED,程序按设定的时间间隔取反P2.0,使LED按固定的时间间隔持续闪烁,电路如图4.6所示
图4.6 闪烁的LED电路
参考源程序代码如下:
程序设计与调试。
(1)关于头文件reg51.h。
源程序中包含的头文件reg51.h不能省略,因为Keil C认为P2是未定义的标识符,将导致编译时出错。
(2)延时函数设计。
本例中的延时函数代码为:
void delay_ms(INT16U x) {INT8U t;while(x--) for(t=0;t<120;t++);}
要改变LED的闪烁频率,可修改延时函数参数,参数类型为INT16U,其取值范围为0~65535,如果参数类型为INT8U,则取值范围仅为0~255。
(3)延时函数设计。
仿真运行实例过程中,观察到的引脚状态颜色可能有以下4种:
红色:表示高电平(1);
蓝色:表示低电平(0);
灰色:表示高阻状态;
黄色:表示出现逻辑冲突;
【实例二】流水灯
单片机P2端按共阴方式连接8只LED,程序运行时LED上下双向循环滚动点亮,产生走马灯效果。电路如图4.7所示。
图4.7 流水灯电路
参考源程序代码如下:
(1)程序设计与调试。(www.xing528.com)
8只LED连接在P2端口,LED阳极连接P2,阴极通过限流电阻接地,程序将P2端口初值设为0x01(00000001),由于电路中LED是共阴连接的,初值会使最上面的第0只LED被点亮。当00000001向左循环移位时,可使8只LED形成循环走马灯效果。循环左移由函数_crol_完成,要注意添加头文件intrins.h。
(2)拓展提高。
①改用共阳接法,仍实现走马灯效果。
②将8只LED改接到其它端口,重新设计程序实现同样的功能。
【实例三】数码管循环显示0~9
80C51单片机P0口的P0.0~P0.7引脚连接到共阴极数码管上,使之循环显示0~9。电路如图4.8所示。
图4.8 数码管循环显示0~9电路图
【分析】编程原理分析:
数码管的显示字模与显示数值之间没有规律可循,常用做法是:将字模按显示值大小顺序存入一组数组中,例如,数值0~9的共阴极字模数组为led_mod[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}。使用时,只需将待显示值作为该数组的下标变量即可取得相应的字模。顺序提取0~9的字模并送P0口输出,便可实现题意要求的功能。参考源程序代码如下:
(1)程序设计与调试。
仿真电路中共阴极数码管器件的名称为7SEG-COM-CAT-GREEN,其中7SEG表示七段(7 Segments),COM-CAT表示共阴(Common-Cathode),GREEN表示显示颜色为绿色。如果选择共阳极数码管则为7SEG-COM-AN-GREEN,其中COM-AN表示共阳(Common-Anode)。仿真电路中给出了数码管的外部引脚,共阴数码管的COM引脚接GND,共阳数码管的COM引脚接VCC。
(2)拓展提高。
①仍使用源程序中的共阴段码表,在单只共阳数码管上滚动显示0~9。
②将段码表改为共阳数码管段码表,改写程序仍实现相同功能。
【实例四】0~99计数显示器
对按键动作次数进行统计,并将次数通过数码管显示出来,电路原理图如4.9所示。计数范围为0~99,增量为1,超过计量限制后自动循环显示。
图4.9 计数显示器电路图
【分析】编程原理分析:
(1)计数统计原理。
循环读取P3.7口电平。若输出为0,计数器变量count加1;若判断计满100,则count清0。为了避免按键在压下期间连续计数,每次计数处理后都需查询P3.7口电平,直到P3.7为1(按键释放)时才能结束此次统计。为防止按键抖动产生的误判,本例中采用了软件去抖措施。
(2)拆字显示原理。
为使count的两位数值分别显示在两只数码管上,可将count用取模运算(count%10)拆出个位值,整除10运算(count/10)拆出十位值,提取字模后分别送相应的显示端口即可。参考程序如下:
【实例五】数码管显示4×4键盘矩阵按键
当按键较多时会占用更多的控制器端口,为减少对端口的占用,图4.10所示电路中使用了4×4键盘矩阵,大大减少了单片机端口的占用,但识别按键的代码比独立按键的代码要复杂一些。
程序运行过程中按下不同按键时,其键值将显示在数码管上。
程序设计与调试。
图中键盘矩阵行线R0~R3连接P1.4~P1.7,列线C0~C3连接P1.0~P1.3,扫描过程如下:
图4.10 数码管显示4×4键盘矩阵按键电路
程序首先判断是否有键按下。为判断16个按键中是否有键按下,程序首先在4条行线输出0000,4条列线输出1111,即P1端口输出0x0F。如果有任意键按下,则4条列线上的1111中必有一位变为0,P1端口读取值将由0x0F,即00001111变成0000XXXX,X中有1个为0,3个仍为1,所有4种可能的值为0x0E、0x0D、0x0B、0x07,由这4个不同的值可知按键分别发生的0~3列。
得到列号后,再执行相反的操作,在4条列线输出0000,4条行线输出1111,即P1端口输出0xF0。如果有任意键按下,则4条行线上的1111中必有一位变为0,P1端口读取值将由0xF0,即11110000变成XXXX0000,X中有1个为0,3个仍为1,所有4种可能的值为0xE0、0xD0、0xB0、0x70,由这4个不同的值可知按键分别发生的0~3行。
根据当前按键操作所在的列号及行号就可得到按键值0~F。
参考源程序如下:
1.C语言有哪些特点?C程序的主要结构特点是什么?
2.C51特有的数据类型有哪些?
3.在C51中,bit位与sbit位有什么区别?
4.C51支持的存储器类型有哪些?与单片机存储器有何对应关系?
5.C51有哪几种编译模式?每种编译模式的特点是什么?
6.用P0口接8个开关,P1口接8个发光二极管,要求每个开关与一个发光二极管对应,画图并写出发光二极管跟随开关状态变化的程序。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。