用一条IO口实现两个按键功能
- 格式:doc
- 大小:23.50 KB
- 文档页数:4
北京科技大学微型计算机原理实验报告学院:____自动化学院________________专业、年级:_自动化1101_ ______________ 姓名:__廖文骏_ ________________学号:_ 20111002124 ____________ 指导教师:___ _____王粉花____________2013年12 月综合实验一按键控制流水灯实验(查询方式)实验学时:2学时一、实验目的1.掌握ATmega16 I/O口操作相关寄存器2.掌握CodeVision AVR软件的使用3. 复习C语言,总结单片机C语言的特点二、实验内容1. 设计一个简单控制程序,功能是8个LED逐一循环发光0.5s,构成“流水灯”。
2. 用两个按键K1和K2控制流水灯(中断方式):(1)当按下K1时,流水灯从左向右流动;(2)当按下K2时,流水灯从右向左流动。
三、实验所用仪表及设备硬件:PC机一台、AVR_StudyV1.1实验板软件:CodeVision AVR集成开发软件、SLISP下载软件四、实验原理ATmega16芯片有PORTA、PORTB、PORTC、PORTD(简称PA、PB、PC、PD)4组8位,共32路通用I/O接口,分别对应于芯片上32根I/O引脚。
所有这些I/O口都是双(有的为3)功能复用的。
其中第一功能均作为数字通用I/O接口使用,而复用功能则分别用于中断、时钟/计数器、USRAT、I2C和SPI串行通信、模拟比较、捕捉等应用。
这些I/O口同外围电路的有机组合,构成各式各样的单片机嵌入式系统的前向、后向通道接口,人机交互接口和数据通信接口,形成和实现了千变万化的应用。
每组I/O口配备三个8位寄存器,它们分别是方向控制寄存器DDRx,数据寄存器PORTx,和输入引脚寄存器PINx(x=A\B\C\D)。
I/O口的工作方式和表现特征由这3个I/O口寄存器控制。
AVR通用I/O端口的引脚配置情况:I/O口引脚配置表表中的PUD为寄存器SFIOR中的一位,它的作用相当AVR全部I/O口内部上拉电阻的总开关。
用一条IO口实现两个按键功能发布时间:2011-02-27 14:11:36 年前去到一个朋友那里,提到现在客户对成本要求非常之高,尤其是玩具行业,已经是一分一厘的去计算产品成本。
朋友感慨为了省成本,方案商是绞尽脑汁地去想各种实现方法,说遇到过为了节省成本,硬是用单片机一条IO实现了两个按键的功能,让他颇为诧异,好久都没想明白原理。
一条IO实现两个按键,听上去确实挺新奇,既然别人能够实现,我想我也应该可以做到,看来得找找实现的方法。
我有一个习惯,遇到某些问题的时候,会在睡觉前想解决方法,想着想着就会睡着了,问题的答案有没有找到则不一定。
我知道有用一条IO实现多个按键的方法,这样的方法大多是选用的IO支持ADC功能,用电阻分压后通过读电压判断键值。
如果IO不支持ADC功能,也不是不行,可以用电容充放电的方法实现ADC,从而用普通IO间接进行测量。
(参见我之前关于键盘扫描的文章)这样用一条IO实现两个按键给我的第一感觉是可能需要利用到电容充放电原理,于是在半梦半醒之中找到了实现的方法。
先看上图左边部分,如果MCU_IO1为双向IO口,假设单片机程序按以下流程处理,看看会得到什么样的结果?1.MCU_IO1设定为输出,输出高电平一段时间,此时电容C1会充电,最后C1上的电压接近电源电压。
2.MCU_IO1设定为输入,如果J1、J2均不按下,此时MCU_IO1可以理解成一个阻值很大的电阻接地,电容C1上的电荷会通过这个电阻逐渐释放掉,这样C1上的电压会逐渐降低到零。
因为C1上的电压下降需要一个过程,当MCU_IO1设为输入后马上读一下MCU_IO1的状态,此时会读到什么结果?显然是高电平状态1。
3.再将MCU_IO1设定为输出,输出低电平一段时间,显然不管电容C1处于什么状态,只要MCU_IO1输出低电平时间足够长,最后C1上的电压应该接近零。
4.再将MCU_IO1设定为输入,如果J1、J2同样不按下,MCU_IO1读到的是低电平状态0。
51单片机并行io口工作原理51单片机是一种常用的嵌入式系统开发平台,具有强大的并行IO 口功能。
本文将介绍并行IO口的工作原理及其在51单片机中的应用。
我们来了解一下什么是并行IO口。
并行IO口是指可以同时进行多个输入输出操作的接口。
在51单片机中,通过并行IO口可以实现与外部设备的数据交互,如控制LED灯、读取按键状态等。
在51单片机中,有两种类型的IO口:通用IO口和特殊功能IO口。
通用IO口可以进行输入输出操作,而特殊功能IO口则有特定的功能,如串口通信、定时器等。
并行IO口的工作原理是通过对寄存器的写入和读取来控制IO口的状态。
在51单片机中,有4个8位寄存器,分别是P0、P1、P2、P3。
P0口的每一位对应一个IO口,P1、P2、P3口则是通过外部扩展芯片来实现更多的IO口。
通过向寄存器中写入数据,可以控制IO口的输出状态。
例如,向P0寄存器写入0x55,即二进制01010101,可以控制P0口的1、3、5、7位输出高电平,2、4、6、8位输出低电平。
通过读取寄存器中的数据,可以获取IO口当前的输入状态。
例如,读取P1寄存器的值,可以获取P1口每一位的输入状态。
在51单片机中,可以通过对寄存器的位操作来实现对单个IO口的控制。
例如,通过设置P2口的某一位为1,可以将对应的IO口设置为输出模式;通过设置P2口的某一位为0,可以将对应的IO口设置为输入模式。
通过对寄存器的位操作,可以实现对多个IO口的同时控制。
除了通过编程对寄存器进行操作外,51单片机还提供了一些特殊功能IO口,可以直接使用这些IO口来实现一些常见的功能。
例如,P3.0和P3.1口可以作为外部中断输入口,P3.3和P3.4口可以作为定时器输入口,P3.5和P3.6口可以作为串口通信口。
在实际应用中,我们可以根据需要将不同的外部设备连接到51单片机的IO口上,通过对寄存器的编程,控制外部设备的状态。
例如,我们可以将LED灯连接到P0口的某一位上,通过对P0寄存器的位操作,控制LED灯的亮灭;我们也可以将按键连接到P1口的某一位上,通过读取P1寄存器的值,获取按键的状态。
用一条IO口实现两个按键功能年前去到一个朋友那里,提到现在客户对成本要求非常之高,尤其是玩具行业,已经是一分一厘的去计算产品成本。
朋友感慨为了省成本,方案商是绞尽脑汁地去想各种实现方法,说遇到过为了节省成本,硬是用单片机一条IO实现了两个按键的功能,让他颇为诧异,好久都没想明白原理。
一条IO实现两个按键,听上去确实挺新奇,既然别人能够实现,我想我也应该可以做到,看来得找找实现的方法。
我有一个习惯,遇到某些问题的时候,会在睡觉前想解决方法,想着想着就会睡着了,问题的答案有没有找到则不一定。
我知道有用一条IO实现多个按键的方法,这样的方法大多是选用的IO支持ADC功能,用电阻分压后通过读电压判断键值。
如果IO不支持ADC功能,也不是不行,可以用电容充放电的方法实现ADC,从而用普通IO间接进行测量。
(参见我之前关于键盘扫描的文章)这样用一条IO实现两个按键给我的第一感觉是可能需要利用到电容充放电原理,于是在半梦半醒之中找到了实现的方法。
先看上图左边部分,如果MCU_IO1为双向IO口,假设单片机程序按以下流程处理,看看会得到什么样的结果?1.MCU_IO1设定为输出,输出高电平一段时间,此时电容C1会充电,最后C1上的电压接近电源电压。
2.MCU_IO1设定为输入,如果J1、J2均不按下,此时MCU_IO1可以理解成一个阻值很大的电阻接地,电容C1上的电荷会通过这个电阻逐渐释放掉,这样C1上的电压会逐渐降低到零。
因为C1上的电压下降需要一个过程,当MCU_IO1设为输入后马上读一下MCU_IO1的状态,此时会读到什么结果?显然是高电平状态1。
3.再将MCU_IO1设定为输出,输出低电平一段时间,显然不管电容C1处于什么状态,只要MCU_IO1输出低电平时间足够长,最后C1上的电压应该接近零。
4.再将MCU_IO1设定为输入,如果J1、J2同样不按下,MCU_IO1读到的是低电平状态0。
如果J1按下,再来看看这四步,此时电容C1已经被强制接到电源上,MCU_IO1对其的充放电已经不起作用,在步骤2中MCU_IO1读到的状态依然是1,但在步骤4中MCU_IO1读到的状态就不再是0,而是变为1。
交换两个按键的功能交换两个按键的功能改变按键的功能最简单的方法就是交换俩个按键的功能。
在做这项测试之前,先分析一下键盘布局文件和按键的原理。
在明白这些之后,你就会发现只是如此的简单。
从键盘布局文件截取一部分类容:Key 2 1Key 158 BACK WAKE_DROPPED其中,第二列是一个整数值,表示驱动程序中Event事件的名称。
我们可以这么理解,2表示Event事件2。
即当我们按下一个键时,就会有相应的中断产生,并且这个中断号是已知的。
在input.c中定义了输入设备的数据结构:其中struct event_dev {struct input_dev *input;int irq;unsigned addr;char name[0];};#define KEY_BACK 158在这个结构体中保存着中断号的信息以及另外一个非常的结构体:struct input_dev *input;。
struct input_dev *input;这个结构体的数据结构很庞大,包含的信息量很多。
其中有:struct input_id id;unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; //区分哪中输入设备unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; //按键与按钮unsigned int keycodemax;unsigned int keycodesize;void *keycode;int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);//以上是几个与键盘关系较密切的几个成员。
,#define KEY_BACK 158表示的意思是事件码158(scancode)对应的字符串为KEY_BACK。
本文介绍两种方法解决"如何占用较少的单片机I/O口就能够实现较多的按键功能?"
方法一:二进制编码法
这个方法我在好几个产品上都用过,适合需要的按键不是太多的情况下使用.如果单片机有n 个I/O口,那么在理论上就可以实现2n—1个按键, 下面的电路图是利用3个I/O口实现6个按键的功能,每个按键代表1个二进制编码,如[ENT]键的编码是[0 0 1],其他按键以此类推。
方法二:A/D值判断法
这个方法只占用单片机的1个A/D输入口,就可以实现较多的按键功能.通过采样A/D值的大小就可以判断是哪个按键被按下,缺点是当多个按键同时按下时,容易判断出错.
本文简单介绍“低边与高边电流检测”的主要区别。
图B低边电流检测方案简单而且便宜,一般的运放器都可以实现此功能。
但是很多应用无法接受检测电阻Rs引入的地线干扰问题,负载电流较大时更会加剧这个问题,因为系统中一部分电路的地电位由于低边检流电阻而产生偏移,而这部分电路可能与另一部分地电位没有改变的电路相互联系。
所以当需要大电流检测时,必须重视这个问题。
图A在负载的高端进行电流检测的简易电路,不仅消除了地线干扰,而且能够检测到短路故障,需要注意的是高边检测要求放大器能够处理接近电源电压的共模电压。
本文介绍无源滤波电路的频率计算公式
1. 常用的RC滤波电路
f 0 = 1/(2πRC)
例:R = 16K ,C =10nF
f 0 = 1/(2πRC) = 1/(2π×16×103×10×10-9 ) =1000Hz
2. LC滤波电路
下期介绍。
用一个IO口引脚控制几个按键的方法
这个方法是利用电阻的分压和ADC的电压采集。
使用方法:
用ADC采集电压,根据电压分析哪个键被按下:
没按键按下:ADC = 0V
K1被按下:ADC = DVCC * R26 / (R26 + R29)
K2被按下:ADC = DVCC * R32 / (R32 + R29)
……
使用注意:
ADC测到的电压值只是大约的范围,例如假如上面K1算得1.0V,那么实际可能是在0.9V~1.1V之间波动;
电路中的电阻应合理计算,使各按键对应的电压值均匀分布在 0~DVCC之间;
矛盾是普遍存在的,节省IO口的同时会带来其它的付出:要进行AD转换占用CPU资源,电路上多了些电阻复杂点了。
这个方法在网上偶然发现想到的,分享一下
--------QinZhengye。
一种节省单片机I /O 口的双矩阵键盘※—■大连理工大学 邹久朋 张礼鸣 林瑶瑶图1 交互式与双交互式键盘电路引 言单片机系统通常使用键盘输入各种数据和命令,实现人机对话。
当单片机的I/O 口够用时,可以首选并行输出扫描码的矩阵键盘,能够连接M ×N 个按键,不需要外围器件,只用几只上拉电阻即可。
在I/O 口紧缺的情况下,可以使用串行转并行的器件(如74HC164等),只需2个口输出串行扫描码和移位脉冲,用1片74HC164就能转换成8位并行输出,能节省单片机的6个输出口。
但如果I/O 口缺得不多,那么使用串转并器件,I/O 口会过剩,而不用又确实不够。
当使用引脚少、功能却很强大的单片机(如P89L PC93x 、STC12C54xxAD 、A Tmega8等)时,常会遇到这种尴尬的情况。
在现有各种形式的非编码扫描查询键盘当中,只有称为“交互式”和“双交互式”的键盘,在相同I/O 口的数量下,可以连接比并行输出矩阵键盘还要多的按键(如图1所示)。
但是,这类键盘不能实现中断,而且查询速度也比矩阵键盘要慢得多。
这是因为它不能快速查询到有无按键被按下,而只能逐个地将所有的按键都查询完,才能确定有没有按键按下。
为使按键及时得到响应,程序中查询键盘的操作是很频繁的,因此会耗费CPU 较多的时间。
单片机对任何形式的键盘都是以输出0,再检查输入是否为0来获得按键信息的。
对于普通矩阵键盘在二次查询时,单片机依次输出只有1位为0的扫描码,因此每列所能连接的按键数量就只能等于M 个输入查询口的数量,总的按键数量只能是行数乘以列数(即M ×N )。
众所周知,只有向矩阵键盘列线输出的扫描码为0时,才能查询到接通行、列节点的按键。
因此决定了扫描码的固定格式为:一次扫描码全都是0,二次扫描码则轮流只有一位为0。
这对单片机的N 条输出口线来说,只输出如此简单、限量的编码,其利用率不高。
1 双矩阵键盘电路原理如果列线为1时也能查询到键按下,就可以输出常规扫描码的反码来进行查询,从而使每一条列线(连到单片机的输出口)上连接2M 个按键,总体上组成双M ×N 的矩阵键盘。
我知道有用一条IO实现多个按键的方法,这样的方法大多是选用的IO支持ADC功能,用电阻分压后通过读电压判断键值。
如果IO不支持ADC功能,也不是不行,可以用电容充放电的方法实现ADC,从而用普通IO间接进行测量。
这样用一条IO实现两个按键给我的第一感觉是可能需要利用到电容充放电原理,于是在半梦半醒之中找到了实现的方法。
先看上图左边部分,如果MCU_IO1为双向IO口,假设单片机程序按以下流程处理,看看会得到什么样的结果?1.MCU_IO1设定为输出,输出高电平一段时间,此时电容C1会充电,最后C1上的电压接近电源电压。
2.MCU_IO1设定为输入,如果J1、J2均不按下,此时MCU_IO1可以理解成一个阻值很大的电阻接地,电容C1上的电荷会通过这个电阻逐渐释放掉,这样C1上的电压会逐渐降低到零。
因为C1上的电压下降需要一个过程,当MCU_IO1设为输入后马上读一下MCU_IO1的状态,此时会读到什么结果?显然是高电平状态1。
3.再将MCU_IO1设定为输出,输出低电平一段时间,显然不管电容C1处于什么状态,只要MCU_IO1输出低电平时间足够长,最后C1上的电压应该接近零。
4.再将MCU_IO1设定为输入,如果J1、J2同样不按下,MCU_IO1读到的是低电平状态0。
如果J1按下,再来看看这四步,此时电容C1已经被强制接到电源上,MCU_IO1对其的充放电已经不起作用,在步骤2中MCU_IO1读到的状态依然是1,但在步骤4中MCU_IO1读到的状态就不再是0,而是变为1。
如果J2按下,同样看这四步,此时电容C1被强制接到地,MCU_IO1对其充放电也失去作用,在步骤2中MCU_IO1读到的状态变为0,但在步骤4中MCU_IO1读到的状态保持为0。
到这里我想大家应该已经明白了实现方法,根据此四步中读到的MCU_IO1状态,就可以判断出J1、J2是否按下。
既然已经找到方法,是不是就万事大吉了呢?不然,我们还得回过头去看看此方法是不是足够可靠。
用一条IO口实现两个按键功能发布时间:2011-02-27 14:11:36 年前去到一个朋友那里,提到现在客户对成本要求非常之高,尤其是玩具行业,已经是一分一厘的去计算产品成本。
朋友感慨为了省成本,方案商是绞尽脑汁地去想各种实现方法,说遇到过为了节省成本,硬是用单片机一条IO实现了两个按键的功能,让他颇为诧异,好久都没想明白原理。
一条IO实现两个按键,听上去确实挺新奇,既然别人能够实现,我想我也应该可以做到,看来得找找实现的方法。
我有一个习惯,遇到某些问题的时候,会在睡觉前想解决方法,想着想着就会睡着了,问题的答案有没有找到则不一定。
我知道有用一条IO实现多个按键的方法,这样的方法大多是选用的IO支持ADC功能,用电阻分压后通过读电压判断键值。
如果IO不支持ADC功能,也不是不行,可以用电容充放电的方法实现ADC,从而用普通IO间接进行测量。
(参见我之前关于键盘扫描的文章)
这样用一条IO实现两个按键给我的第一感觉是可能需要利用到电容充放电原理,于是在半梦半醒之中找到了实现的方法。
先看上图左边部分,如果MCU_IO1为双向IO口,假设单片机程序按以下流程处理,看看会得到什么样的结果?
1.MCU_IO1设定为输出,输出高电平一段时间,此时电容C1会充电,最后C1上的电压接近电源电压。
2.MCU_IO1设定为输入,如果J1、J2均不按下,此时MCU_IO1可以理解成一个阻值很大的电阻接地,电容C1上的电荷会通过这个电阻逐渐释放掉,这样C1上的电压会逐渐降低到零。
因为C1上的电压下降需要一个过程,当MCU_IO1设为输入后马上读一下
MCU_IO1的状态,此时会读到什么结果?显然是高电平状态1。
3.再将MCU_IO1设定为输出,输出低电平一段时间,显然不管电容C1处于什么状态,只要MCU_IO1输出低电平时间足够长,最后C1上的电压应该接近零。
4.再将MCU_IO1设定为输入,如果J1、J2同样不按下,MCU_IO1
读到的是低电平状态0。
如果J1按下,再来看看这四步,此时电容C1已经被强制接到电源上,MCU_IO1对其的充放电已经不起作用,在步骤2中MCU_IO1读到的状态依然是1,但在步骤4中MCU_IO1读到的状态就不再是0,而是变为1。
如果J2按下,同样看这四步,此时电容C1被强制接到地,MCU_IO1对其充放电也失去作用,在步骤2中MCU_IO1读到的状态变为0,但在步骤4中MCU_IO1读到的状态保持为1。
到这里我想大家应该已经明白了实现方法,根据此四步中读到的MCU_IO1状态,就可以判断出J1、J2是否按下。
既然已经找到方法,是不是就万事大吉了呢?不然,我们还得回过头去看看此方法是不是足够可靠。
如果J1按下,电容C1直接接到电源上,当MCU_IO1输出低时,MCU_IO1输出的低电平直接与电源短路,弄不好就会烧坏MCU_IO1,同理当J2按下时MCU_IO1输出高也存在同样的问题。
还有比这更严重的问题,如果用户同时按下J1和J2,哈!居然是电源和地直接短路,这样的后果很可能就是整个产品的电源部分一股青烟了事,就别想产品还能不能工作了。
不用担心,看一看前面电路图中的右半部分,在开关J3和J4上分别串联了一个220欧的电阻,这个电路不管J3和J4如何按,都不会出现短路的情况,按前面的四个步骤即可判断出J3和J4有没有按下,不过如果J3和J4同时按下并不能进行识别判断。