C51单片机用IO口做为几个按键的控制,现在想用4X4键盘控制,请问下面显示程序应该怎么改啊?折磨死了 用C51单片机 设计一个整数计算器 C语言编程(用到4x4矩...

51\u5355\u7247\u673a c\u8bed\u8a00 \u5c31\u662f\u6211\u73b0\u5728\u5728\u75284x4\u77e9\u9635\u952e\u76d8 \u7136\u540e\u6211\u4e00\u4e2a\u6309\u952e\u662f\u63a7\u5236\u6d41\u6c34\u706f\u5f00\u59cb

\u8fd9\u4e2a\u8981\u4f7f\u7528\u5916\u90e8\u4e2d\u65ad\uff0c\u4f60\u5728\u7a0b\u5e8f\u91cc\u9762\u6539\u4e00\u4e0b\uff0c\u52a0\u5165\u4e2d\u65ad\uff0c\u53ef\u4ee5\u7528\u4f60\u7684\u8fde\u63a5\u77e9\u9635\u952e\u76d8\u7684io\u53e3\u7684\u6700\u9ad8\u4f4d\u4e0e\u6700\u4f4e\u4f4d\u505a\u4e00\u4e2a\u4e0e\u975e\u95e8\u4f5c\u4e3a\u4e2d\u65ad\u4fe1\u53f7\u5c31\u53ef\u4ee5\u4e86\u3002\u9644\u4e0a\u4e00\u6bb5\u4ee5\u524d\u5199\u7684\uff0c\u4f60\u770b\u770b\uff0c\u4e0d\u8fc7\u7531\u4e8e\u6211\u6ca1\u6709\u4e0e\u975e\u95e8\uff0c\u6240\u4ee5\u6211\u7528\u6309\u952e\u4ee3\u66ff\u4e86\u4e2d\u65ad\u4fe1\u53f7\u3002

\u6570\u7801\u7ba1\uff0c\u663e\u793a\u80fd\u529b\u592a\u5dee\u3002
\u5236\u4f5c\u8ba1\u7b97\u5668\uff0c\u5e94\u8be5\u7528\u6db2\u6676\u5c4f\uff0c\u624d\u5bf9\u8def\u3002

4X4太浪费单片机IO了,我为你介绍5个IO控制25按键的电路,如下文:

本文以循序渐进的思路,引导大家思考如何用最少的IO驱动更多的按键,并依次给出5种方案原理图提供参考。在实际项目中我们经常会遇到有按键输入的需求,但有的时候为了节省资源成本,我们都会选择在不增加硬件的情况下使用最少的控制器IO驱动更多的按键,那么具体是怎么做的呢,下面我们就以用5个IO引脚为例,讲下怎么设计可以实现更多的按键?共有5种设计思路,下面依次介绍。

思路一

首先通常想到的可能是下面这样的设计:

上图形式的按键就是我们通常说的行列式按键,它的驱动思路是这样的:

1. 对IO1、2、3配置为推挽输出,依次只让其中一个输出为0其他输出为1。

2. 对IO4、5进行读操作,根据读出的结果判断哪个按键按下。

例如:配置IO1、2、3为011,读IO4、5,若IO4为0则SW14按下,若IO5为0则SW15按下;

依次的配置IO1、2、3为101,读IO4、5,若IO4为0则SW24按下,若IO5为0则SW25按下;

依次的配置IO1、2、3为110,读IO4、5,若IO4为0则SW34按下,若IO5为0则SW35按下;

思路二

但是我们在不知道行列式按键之前我们肯定是依次将IO口接一个按键到GND或者到VCC,然后去读IO口去判断哪个按键按下,这也是最简单的方法,但是很浪费IO口,下面这种就结合了这种简单方法和行列式的思路,实现了又多增加3个按键,如下图:

这里我们的思路是先依次读IO1、2、3的电平来识别S1、2、3,哪个按键按下,其后的流程和思路一是一样的,这样就可以识别11个按键了。

思路三

按照扫描的思想,某一时刻设置一个IO口为0,其他IO口读,如果有IO口读到0,则有对应按键按下。比如IO1为0,然后读到IO5也为0,那么K15就是按下的。对照这样的思路,我们可以有下面的设计:

这个电路按键识别思路是这样的:

1. 只配置IO1为0,其他IO读,若IO5读到0,则K15按下,若IO4读到0,则K14按下,依次识别K13,K12;

2. 只配置IO2为0,其他IO读,若IO5读到0,则K25按下,若IO4读到0,则K24按下,依次识别K23;

3. 只配置IO3为0,其他IO读,若IO5读到0,则K35按下,若IO4读到0,则K34按下;

4. 只配置IO4为0,其他IO读,若IO5读到0,则K45按下;

思路四

对于思路3我们发现,如果只配置IO5为0,其他IO读,若IO1读到0,则K15按下,若IO2读到0,则K25按下,依次可识别K35和K45。这样就存在重复,那么有么有好的方法,解决这样的重复呢?我们发现,若配置IO1为0,K15按下,电流流向IO1的,若配置IO5为0,同样K15按下,电流是流向IO5的。这样我们就可以通过区分电流的流向来避免重复。于是就有了下图的设计:

这样就可以避免重复,IO5为0时,按K15,IO1是读不到0的。那么怎样设计,IO5为0时对应一个按键按下IO1为0呢?如是就有人想到下面的设计:

这个电路按键识别思路是这样的:

1. 只配置IO1为0,其他IO读,若IO5读到0,则K51按下,若IO4读到0,则K41按下,依次识别K31,K21;

2. 只配置IO2为0,其他IO读,若IO5读到0,则K52按下,若IO4读到0,则K42按下,依次识别K32,K21';

3. 只配置IO3为0,其他IO读,若IO5读到0,则K53按下,若IO4读到0,则K43按下,依次识别K32’,K31';

4. 只配置IO4为0,其他IO读,若IO5读到0,则K54按下,若IO4读到0,则K43’按下,依次识别K42’,K41';

5. 只配置IO5为0,其他IO读,若IO4读到0,则K54’按下,若IO3读到0,则K53’按下,依次识别K52’,K51'。

思路五

很多人可能认为思路四已经识别20个按键了,但是真的就没有其他方法了吗?不要忘了,我们还没有将思路二你介绍的那种最简单的方法结合进去,于是又可以多5个按键,如下图:

这样我们可以先识别K01、K02、K03、K04、K05,若没有按键按下然后再和思路四的设计一样去识别其他按键。但这样存在一个问题,如果IO1配置为0,IO5读到0,那么怎么知道是K51按下还是K05按下呢,这里只需要在程序里做下判断,先判断下是不是K05按下,若不是就是K51,因为按键K01、K02、K03、K04、K05在5个IO口都为读取的情况下,就可以识别,不需要扫描识别处理,相当于这5个按键优先级高与其他按键。

总结

综合上述,5个IO口最多可以识别25个按键,思路五程序上处理比较麻烦,若实际中只按思路四设计,也可识别20个按键,那么如果有N个IO口可识别多少按键呢?这里给出如下公式:

假设有N个IO口按照思路三可以识别N*(N-1)/2个;

按照思路四可识别N*(N-1)个;

按照思路5可以识别N*(N-1)+N个。

最后再说下,如果实际设计时,还是按思路四设计好,软件也没那么麻烦。如果是你的话你会选择哪种方法呢?你还有没有其他的设计方法呢?



// 4*4矩阵键盘
/********************************************************
连接:
------------------------------------
P1.0 P1.1 P1.2 P1.3
p1.4 S1 S5 S9 S13
P1.5 S2 S6 S10 S14
P1.6 S3 S7 S11 S15
P1.7 S4 S8 S12 S16
------------------------------------
实现原理:
当高电平端口与低电平端口短接时,高电平端口会被拉成低电平
------------------------
算法分析:
1,检查是否有键按下:
P1=f0h (即0-3置1,4-7置0)
检查P1口是否是0F0H
是,则无键按下
否,则有键按下
2,扫描按下的键值:
循环(依次将4至7口单独置0)
检查0-3口是否有低电平端
确定被按下的键
返回键值
3,键盘防抖:
抖动原因:键按下时,会产生电压的波动,持续约10MS
去抖方法:10MS扫描一次,使前后两次均有键按下
********************************************************/
#include<ytc51.h>
uchar jps,ks; //键盘缓存
/*键盘扫描程序1,检查是否有按键*/
uchar keyfun()
{
uchar key_c;
P2 = P2 & 0x03;
P2 = P2 | 0x3c;
key_c = P2;
if((key_c & 0xfc) == 0x3c) return (0);
else return(1);
}
/*键盘扫描程序2,确定按键数值*/
uchar keyscan()
{
uchar i,k;
P2 = P2 & 0x03;
P2 = P2 | 0xbc;
if((P2 & 0x3c) != 0x3c)
{
i = 0;
k = (~P2) & 0x3c;
}
else
{
P2 = P2 & 0x03;
P2 = P2 | 0x7c;
if((P2 & 0x3c) != 0x3c)
{
i = 1;
k = (~P2) & 0x3c;
}
}
k = k>>3;
if( k==4 ) k=3;
k=i*4+k+1;
return(k);
}
/**********************************************************************
函数功能: 定时器中断函数(扫描键盘)(10ms 16位定时)
入口参数: 无
出口参数: 无
***********************************************************************/
void Time0_Func() interrupt 3 /*当定时器中断时执行此函数*/
{
TH1=(0xffff-9259)/256; /*T0初始化*/
TL1=(0xffff-9259)%256;
WR = 1;
if((ks == 0) && ( keyfun() ))
{
jps = keyscan();
}
ks = keyfun();
}

/**********************************************************************
函数功能: 上电初始化函数
入口参数: 无
出口参数: 无
***********************************************************************/
void Power_Up(void)
{
TMOD = 0x10;/*Time0/1为16计数器*/
TH1=(0xffff-9216)/256;/*10ms*/
TL1=(0xffff-9216)%256;/*10ms*/
TR1=1;
SCON = 0x00;//串口工作模式设置
IE=0x88; /*EA=1 ET1=1*/
P0=0xff;
P2=0xff;
}

  • 51鍗曠墖鏈虹殑4涓IO绔彛鐨勪綔鐢ㄦ槸浠涔?
    绛旓細鍙互褰撳仛鏅鐨処O鍙鐢紝P3鍙f湁澶嶇敤鍔熻兘锛屼覆琛屼紶杈擄紝澶栭儴涓柇锛屽畾鏃跺櫒绛夌瓑锛孭2鍜孭0鍙互浣滀负鍦板潃鍙g敤锛孭1灏辨槸鏅氱殑IO鍙
  • 89c51鍗曠墖鏈鏈夊嚑缁処/O鍙,璇风畝鍗曚粙缁嶅叾涓昏鍔熻兘
    绛旓細P3鍙i櫎浣滀负涓鑸IO鍙杩樹负绗簩杈撳叆/杈撳嚭鍔熻兘(P3.0 涓茶鏁版嵁鎺ュ叆绔;P3.1 涓茶鏁版嵁鍙戦佺;P3.2 澶栦腑鏂0杈撳叆绔 ;P3.3 澶栦腑鏂1杈撳叆绔;P3.4 瀹氭椂鎴栬鏁板櫒TO 鐨勫閮ㄨ緭鍏ョ;P3.5 瀹氭椂鎴栬鏁板櫒T1鐨勫閮ㄨ緭鍏ョ;P3.6 澶栭儴鏁版嵁瀛樺偍鍣ㄥ啓閫夐氫俊鍙;P3.7 澶栭儴鏁版嵁瀛樺偍鍣ㄨ閫夐氫俊鍙;)...
  • 51鍗曠墖鏈虹殑鍥涗釜骞惰I/o鍙e湪浣跨敤涓婂浣曞垎宸
    绛旓細51鍗曠墖鏈虹殑鍥涗釜骞惰I/o鍙i兘鏄弻鍚戦氱敤IO鍙锛孭3鏄鍚堝姛鑳藉紩鑴氾紝涓鑸笉鐢ㄥ畠銆侾0鍙h鎺ヤ笂鎷夌數闃汇傛讳箣锛岄櫎浜哖3鍙o紝鍏朵粬鍙e彲浠ラ殢鎰忎娇鐢紝褰撶劧锛孭3鍙d篃鍙互浣滀负閫氱敤IO鍙
  • 51鍗曠墖鏈虹殑P0, P1, P2, P3, P4鍙e悇鏄粈涔堟剰鎬?
    绛旓細涓銆丳0鍙o細鐪熸鐨勫弻鍚戝彛锛岃緭鍑洪攣瀛橈紝杈撳叆缂撳啿锛岃緭鍏ュ墠瑕佸厛缃1锛圞EIL鍖呭惈鐨勫ご鏂囦欢宸茬粡鏈夊姩浣滀簡锛屽鏋滅敤姹囩紪锛岃浜哄伐缃1锛夛紝杈撳嚭涓烘紡鏋佸紑璺紝杈撳嚭涓鑸兘瑕佷笂鎷夌數闃汇傝緭鍏ヤ负楂橀樆鎬侊紝鑳介┍鍔8涓猅TL璐熻浇銆傚綋鏈夌墖澶栧瓨鍌ㄥ櫒鏃讹紝浣滄暟鎹嚎浣跨敤銆備簩銆丳1鍙o細鏈绠鍗鐨勫彛锛岃緭鍏ヤ篃瑕佸厛缃1锛屾棤楂橀樆鎬侊紝鍙兘鏄緭鍑...
  • 鍏充簬c51鍗曠墖鏈虹殑闂
    绛旓細涓嶇敤鐨勫紩鑴氬彲浠ユ偓绌猴紝瀹炵幇LED鐐逛寒锛屽彲浠ョ敤涓涓IO鍙灏卞彲浠ヤ簡锛屾瘮濡侾1.0鎺ED鎺ヤ竴涓檺娴佺數闃诲啀鎺ョ數婧愭灏卞彲浠ャ
  • 姹備竴涓c51鍗曠墖鏈虹殑绋嬪簭
    绛旓細寰堢畝鍗曪紝鏌24涓猯ed鎺0锛孭2锛孭3锛屼笁涓彛锛屽崰24涓io鍙锛屼笂闈5涓姳鐘跺洜涓哄悓涓鍦嗗湀led鍚屾椂浜 鍙互骞跺湪涓璧凤紝鍗8涓猧o鍙o紝鍒氬ソ32涓猧o鍙c傛垜浠粠涓嬪埌涓婂皢led瀹氫箟涓1~24鍙凤紝鎵╂暎浠庝腑蹇冨線澶栧畾涔変负25~32鍙穕ed銆1~32鍙穕de锛屽垎鍒帴鍒癙0锛孭2锛孭3锛孭1鐨凱0_0~P0_7鍙疯剼锛孭2_0~P2_7鍙疯剼锛孭3_0~P3...
  • 鍏充簬51鍗曠墖鏈虹殑鍑犱釜闂: 缁忚繃涓娈垫椂闂寸殑瀛︿範,瀵瑰崟鐗囨満鏈変簡鍒濇鐨勮...
    绛旓細浣滀负绗簩鍔熻兘浣跨敤鏃讹紝鍚勫紩鑴氱殑瀹氫箟濡傝〃鎵绀恒傚煎緱寮鸿皟鐨勬槸锛孭3鍙g殑姣忎竴鏉″紩鑴氬潎鍙嫭绔嬪畾涔変负绗竴鍔熻兘鐨勮緭鍏ヨ緭鍑烘垨绗簩鍔熻兘銆傚叿浣撶殑瑕佸湪鐢ㄦ槸鏃跺欐墠浼氭洿鍔犳繁鍒荤殑浜嗚В锛丄T89C52鍜孲TC89C52rc闄や簡鍘傚晢浠ュ鍦ㄧ紪绋嬫椂閮芥槸涓鏍风殑锛屼笉鐢ㄧ壒鍒殑鍦ㄦ剰锛屽氨鏄儳鍐欑▼搴忕殑鏂瑰紡涓嶅悓锛焥tc89c52rc鐨剅c濂藉儚鏄创鐗鍗曠墖鏈鍚э紒鍏跺疄...
  • 51鍗曠墖鏈澶栭儴涓柇鏄摢鍑犱釜绠¤剼?
    绛旓細浜斾釜涓柇鏈夋寚瀹鐨処O鍙锛屼竴鑸51鍗曠墖鏈鏄疨3.2鏄疘NT0锛孭3.3鏄疘NT1锛孭3.4鏄疶0锛孭3.5鏄疶1锛孖NT0鍜孖NT1鏄閮ㄤ腑鏂紝T0鍜孴1鏄畾鏃跺櫒锛孍S鏄覆琛屽彛涓柇鍏佽浣嶏紝ET1鏄畾鏃跺櫒1涓柇鍏佽浣嶏紝EX1鏄閮ㄤ腑鏂厑璁镐綅锛孍T0鍜孍X0绫讳技銆傝浜х敓涓柇锛屽繀椤诲厛閰嶇疆濂藉苟浣胯兘涓柇绾裤傛牴鎹渶瑕佺殑杈规部妫娴嬭缃袱涓Е鍙...
  • 51鍗曠墖鏈鎬庝箞鐢10涓IO鍙鎵╁睍鎴40涓緭鍏ュ彛
    绛旓細鍏跺疄涓嶇敤鍗佷釜锛屽彧鐢ㄤ袱涓氨鍙互銆傜敤TXD/RXD涓や釜寮曡剼閫氳繃鍗曠墖鏈涓插彛宸ヤ綔鏂瑰紡0锛屽閮ㄨ繛鎺5涓74LS165锛堝苟鍏ヤ覆鍑虹Щ浣嶅瘎瀛樺櫒锛夈傝繖鏍峰氨鎵╁睍鍑烘潵5*8=40涓閮ㄨ緭鍏ュ彛銆備紭鐐癸細鍗犵敤鍗曠墖鏈篒/O鍙e皯锛岀紪绋嬬畝鍗曘傜己鐐癸細鍝嶅簲閫熷害鎱
  • 涓涓搷浣51鍗曠墖鏈鏌鍑犱釜IO鍙g殑鏂规硶
    绛旓細瀵逛簬51鍗曠墖鏈虹殑P鍙f潵璇达紝鎴戜滑涔犳儻涓婄殑璧嬪兼槸P1 = 0xXX銆備絾鏄繖鏍锋搷浣滄槸涓娆℃ф搷浣滀簡8涓IO鍙銆傝屾湁浜涙儏鍐典笅锛屾垜浠彧闇瑕佹搷浣滃叾涓殑鍑犱釜鑰屼笉鏄叏閮ㄧ殑鏃跺欙紝鎴戜滑濡備綍鎿嶄綔鍛紵濡備笅鍥炬敞閲婁笂杈圭殑閮ㄥ垎锛屾槸鎴戝啓鐨勭▼搴忎唬鐮併傝繖涓槸鎿嶄綔51鍗曠墖鏈篜1鍙g殑浣4浣嶅姝ヨ繘鐢垫満杩涜鎿嶄綔鐨勭▼搴忥紝鍦ㄨ繖涓搷浣滆繃绋嬩腑锛屾垜浠彧...
  • 扩展阅读:单片机入门基础知识 ... 单片机io口四种模式 ... 51单片机常见型号 ... 51单片机通用io口 ... c++编程 ... 51单片机的io口一共有 ... 89c51单片机有几个io口 ... c51单片机io口是哪个 ... mcs-51单片机有几个中断源 ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网