c51单片机P1.0-P1.7控制列,P2.0-P2.3控制行,8*4的矩阵键盘扫描,程序思路都好,求大虾帮忙!!!!c语言

作者&投稿:皇伦 (若有异议请与网页底部的电邮联系)
51单片机矩阵键盘扫描程序分析?~

我给你一个我自己写的吧 有注释

假设按下的是S1键进行如下检测(4*4键盘)

先在P3口输出
p3 00001111

低四位 行会有变化
cord_h =00001111&00001110 =00001110
if !=00001111

延时0.1us

cord_h=00001110&00001111=00001110
if !=00001111

P3再输出11111110

P3 =00001110|11110000=11111110

输出高四位
cord_l=P3&0xf0 //此时P3口就是输入值01111110 而不是上面的11111110
cord_l=01111110&11110000=01110000

cord_h+cord_l=00001110+01110000=01111110=0x7e //此编码即为S1的编码


#include //包含头文件
#define uchar unsigned char
#define uint unsigned int



unsigned char const table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F

uchar keyscan(void);
void delay(uint i);

void main()
{
uchar key;
P2=0x00;//1数码管亮 按相应的按键,会显示按键上的字符
while(1)
{
key=keyscan();//调用键盘扫描,
switch(key)
{
case 0x7e:P0=table[0];break;//0 按下相应的键显示相对应的码值
case 0x7d:P0=table[1];break;//1
case 0x7b:P0=table[2];break;//2
case 0x77:P0=table[3];break;//3
case 0xbe:P0=table[4];break;//4
case 0xbd:P0=table[5];break;//5
case 0xbb:P0=table[6];break;//6
case 0xb7:P0=table[7];break;//7
case 0xde:P0=table[8];break;//8
case 0xdd:P0=table[9];break;//9
case 0xdb:P0=table[10];break;//a
case 0xd7:P0=table[11];break;//b
case 0xee:P0=table[12];break;//c
case 0xed:P0=table[13];break;//d
case 0xeb:P0=table[14];break;//e
case 0xe7:P0=table[15];break;//f
}
}
}
uchar keyscan(void)//键盘扫描函数,使用行列反转扫描法
{
uchar cord_h,cord_l;//行列值
P3=0x0f; //行线输出全为0
cord_h=P3&0x0f; //读入列线值
if(cord_h!=0x0f) //先检测有无按键按下
{
delay(100); //去抖
cord_h=P3&0x0f; //读入列线值
if(cord_h!=0x0f)
{

P3=cord_h|0xf0; //输出当前列线值
cord_l=P3&0xf0; //读入行线值
return(cord_h+cord_l);//键盘最后组合码值
}
}return(0xff); //返回该值
}

void delay(uint i)//延时函数
{
while(i--);
}


在P3口做的键盘
你的去抖检测没有做好

2*3的键盘,太简单了,不值得用循环,特别是双重循环。

最简明、高效的程序如下:

sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P12 = P1^2;
sbit P13 = P1^3;
sbit P14 = P1^4;

char scan_key(void)
{
P13 = 0;
if (!P10) return 0;
if (!P11) return 1;
if (!P12) return 2;
P13 = 1;

P14 = 0;
if (!P10) return 3;
if (!P11) return 4;
if (!P12) return 5;
}

本程序,使用的变量最少,也不涉及其它接口。
代码最少,执行效率最高。

我随便写了下,配着注释,你理解下意思,然后弄个适合你的
void key_scan()
{ unsigned char key1,key2;unsigned int key;
P1 = 0XFF; //P1拉高
P2 &= 0XF0; //P2.0 -P2.3 拉低
if(P1 != 0XFF) // 如果有按键按下,P1就有引脚被拉低,
{
delay_ms(10); //延时10ms, 防抖
if(P1 != 0XFF)
{ key1 = P1; //记下P1口的值
P1 = 0X00; P2 |= 0X0F; //P1拉低,P2拉高
if((P2&0X0F)!=0X0F) //P2口有引脚被拉低了,说明有按键按下
key2 = P2 & 0x0F; //记下P2后4位的值
//现在通过key1和key2就可以区分每个按键了
key = (key2<<8) + key1; //把key1 和key2组合在一起
switch (key) //每个key值都对应着一个按键 ,用case 语句执行就行了
{ case 0X077F : 按键1按下的子程序;break;
.....................
}
}
}
}
大致就这个意思 是按键扫描的 行列翻转法 ,

以下是4*3矩阵键盘的扫描程序,一些该修改的地方自己修改一下。仿照一下就行了
void matrixkeyscan()
{
uchar temp;
P1=0xfd;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xed:
key=0;
break;
case 0xdd:
key=1;
break;
case 0xbd:
key=2;
break;
case 0x7d:
key=3;
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
display(key);
}
}
P1=0xfb;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xeb:
key=4;
break;
case 0xdb:
key=5;
break;
case 0xbb:
key=6;
break;
case 0x7b:
key=7;
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
display(key);
}
}
P1=0xf7;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xe7:
key=8;
break;
case 0xd7:
key=9;
break;
case 0xb7:
key=10;
break;
case 0x77:
key=11;
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
display(key);
}
}
}

键盘矩阵

高人啊,楼上说的对


51单片机sbit led=P1^0是什么意思?语句里面起什么作用,怎么看的?和...
sbit 这个是说明你定义的类型为位。led=P1^0; 这里表示 定义单片机I\/O口 P1.0的伪名称叫led 这样你要对P1.0控制时直接写 led=1; 或者=0 让灯亮或者灭。和sbit CY=psw^7; 是一样的定义模式,都是定义一个字符内的其中一位!

单片机P1=0x02的含义是什么?
单片机程序中P1=0x02的意思是P1.1赋值为1,其余赋值为0。51单片机的P1口是一个准双向I\/O口,但是它没有多路开关和控制电路部分。其输出驱动电路部分只有一个FET场效应管,同时带内部上拉电阻,该电阻与电源相连。当P1口输出高电平时,可以向外部提供拉电流负载,无需上拉电阻。当用作输入口时,...

51单片机P1.0 P1.1接两个按键,这两个电阻值大概设为多少?为什么?_百度...
这两个电阻的选择依据是:1)电阻值不能过小,否则键按下后流过的电流值过大,增加功耗;2)又不能太大,否则影响上拉效果。因此,一般选择2K-20K左右。注:如果你使用AT89系列的单片机,这两个键可以去除。

51单片机时针频率12MHz,要求从p1.0引脚输出一个频率为100KHz占空比为1...
周期是 10us。50% 的占空比?那就是 5us 高电平、5us 低电平。程序如下:LOOP:SETB P1.0 NOP NOP NOP NOP CLR P1.0 NOP NOP SJMP LOOP END

51单片机输出电压只有0V和5V吗??还是要根据负载来判断。麻烦请具体...
是的,常规情况下就是这两种情况,如:P1.0=1, 则P1.0管脚输出5V; P1.0=0 则P1.0管脚输出0V。也有特殊情况,如51系列的STC单片机有PWM功能,改变占空比就可在管脚得到0~5V内的任意电压 希望能帮到你

51单片机晶振频率为12MHz,用定时器T1在P1.0引脚上输出周期为2秒,占 ...
include<reg51.h> define uchar unsigned char uchar cnt;sbit p10=P1^0;void t0isr(void) interrupt 3 { TH1=(65536-50000)\/256;TL1=(65536-50000)%256;cnt++;if(cnt>=20){ cnt=0;p10=~p10;} } main(){ TMOD=0x10;TH1=(65536-50000)\/256;TL1=(65536-50000)%256;TR1=1;ET1=1;E...

如何用单片机c语言点亮p1.0
P1^0=1; P1.0 输出高电平,可点亮阴极接地的LED P1^0=0; P1.0输出低电平,可点亮阳极接电源的LED

51单片机时钟频率6MHz,要求从P1.0处产生一个频率100Hz,占空比为1:2...
include"reg51.h"define TRUE 1 define FALSE 0 define uchar unsigned char define uint unsigned int define th0 0xf6 define tl0 0x3c sbit WaveOut=P1^0;void Timer0() interrupt 1 { TL0=tl0;TH0=th0;WaveOut=~WaveOut;} void TimerInit(){ TMOD=0x01;TH0=th0;TL0=tl0;TR0=1;...

51单片机c语言编程:编写一段程序,P1.0控制LED,P1.1控制LED的亮和灭...
P1.0、P1.1,都是控制 LED 的?试试下面的程序:include <reg51.h> sbit led = P1^0;sbit key = P1^7;void main(){ while(1) led = key;} P1.1,不知道怎么用。

为什么51单片机编程中P1^0 表示 P1I\/O口里面的0号引脚
去看一下 #include<reg51.h>或者是类似的头文件你就会发现有 例:sfr P1 = 0x90;这样的一行即定义P1 与地址0x90 对应,P1 口的地址就是0x90.SFR的定义在头文件reg51.h或reg52.h中。在C51里,利用sbit可访问RAM中可寻址位或SFR中可寻址位。如果直接写P1.0,C 编译器并不能识别,而且P1...

临川区13025688735: 单片机中假如知道p1.0到p1.7的数据 -
诸进复方: 最高为是P1.7,最低为是P1.0,A是1001,进行移位的话,RR A那么结果是: 00010010,A是八位累加器,如果是10000001,移位的话 RR A,结果是00000011

临川区13025688735: 在C51编程中P1到底是什么,又控制灯亮,又控制蜂鸣器
诸进复方: P1口的P1.0和P1.1是多功能复用口,P1.2-P1.7是准双向口,可做输入或输出口使用,用做输入口时需先置1锁存器,P1.0的第二功能是定时器T2的外部计数脉冲输入口,P1.1口的第二功能是定时器T2的EX(额外)输入端,T2捕捉方式时为触发输入线,加减计数方式时控制加减. P1,P2,P3都可以驱动4个LSTTL P0可以驱动8个LSTTL电路 由于其驱动能力较强,可以直接驱动LED,和小型蜂鸣器. 其中P1有八位(P1.0-P1.7),每位都可以直接驱动LED和蜂鸣器,可以同时控制灯和蜂鸣器,只要设置相应的数据位就可以.具体的高低电平,还要看实际的电路.

临川区13025688735: 用单片机P1.0和P1.7作输出,分别接小喇叭和发光二极管.P3.0和P3.1作输入,分别接开关K0和K1. -
诸进复方: 嘿嘿 俺先给你提供一个实现上述要求的算法: 1 2个按键的判别顺序是先判断K1再判断K2,即当K1接低电平时,小喇叭发声报警 (报警优先) 2 只有当没有预警时,才能去查询K0的状态,当K0为高电平,表示系统没工作(不显示)当K0为低电平,表示系统工作了(发光二极管交替亮、灭 即闪亮) 3 不断地重复执行1和2的步骤,就可以实现你的要求了. 发光二极管交替亮、灭 即闪亮的方法:每隔一定的时间 对P1.7求反,既可以实现发光二极管交替亮、灭. 呵呵 ,满意就选满意回答

临川区13025688735: C51程序中P1.0 - P1.7端口输入0x0F,是P1.0在前面还是P1.7在前面? -
诸进复方: 高位在前,也就是说P1.7在前面!P1.7-P1.0 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01

临川区13025688735: 单片机程序中P1==0是什么意思?是P1.0~P1.7均为0还是某一位为零?while(P1==0) while(P1=0X00)区别. -
诸进复方: P1==0 这个事一个判断语句 用在 if()里 比如 if (P1==0) {//动作 这里就是判断 P1.0-P1.7是否均为0 如果是 就执行动作... } while(P1==0) while(P1=0X00)区别. 前者区别在于 P1==0则跳出while循环 而 第二个 是错误语句 P1会被赋值与0 起不到什么判断作用{0,10} 数组中 10是你所定义或在程序中改变的值...引索为 1 比如 unsigned char number[]={0,10}; 这里 数组number[1]的值就为10

临川区13025688735: 51单片机,例如P1.0~P1.7,P1.0是高位还是P1.7是高位啊 -
诸进复方: 在端口操作中,以并行数据读写一个端口的数据时,那么 PIO.0 对应为最低位,PIO.7 对应为最高位;

临川区13025688735: 我是初学c51的,有个问题不解请高手指点! -
诸进复方: b是一个8位的2进制如10101010控制p1.0--p1.7引脚的高低电平

临川区13025688735: 利用单片机中的定时器实现在P1.0和P1.7引脚上分别输出100Hz和50Hz的方波信号 用c语言 -
诸进复方: #include<reg51.h> sbit p10=P1^0; sbit p17=P1^7; unsigned char tt=0; void t0isr() interrupt 1 { tt++; if(tt==20)p10=~p10; if(tt>=40){p17=~p17;tt=0;} } main() { TMOD=0x02; TH0=6; TL0=6; ET0=1; TR0=1; EA=1; while(1); }

临川区13025688735: 单片机C语言程序设计(开关控制二极管) -
诸进复方: int0_init(); //外部中断初始化,设置成上升沿中断或下降沿中断 int0() interrupt X //中断函数,中断号我忘记了 {P1|=0X01;delay();P1|=0X02;delay();P1|=0X04;delay();P1|=0X08;delay();P1|=0X10;delay();P1|=0X20;delay();P1|=0X40;delay();P1=0X00;delay();P1=0, }

临川区13025688735: 单片机c51程序如何根据p1.7引脚电压实现功能选择 -
诸进复方: a=1000+cWeightVerifyVal; a=nWeight*a/1000; /*软件放大 调整范围:当前值的25%;调整精度: 当前值的1/1000*/ a=a*2000/1622; /* 大约80个刻度=1kg */ if(P1^7)a=a*1000/6350; /* 转换为市斤ST 1KG=6.35*/ else a=a*1/10; /* 转换为公斤KG*/ a=(a+5)/10;

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网