标题: 关于51单片机矩阵键盘程序调试的问题 [打印本页]

作者: vo1t    时间: 2023-3-21 21:50
标题: 关于51单片机矩阵键盘程序调试的问题
rt,在跟着郭天祥老师的视频学习中,自己写了代码和老师的不一样,但可以成功运行。可是之后怎么都想不通是如何运行成功的,

我疑问的点在于当我按下一个按键时,P3口的值就发生了变化,但是如果我是在一次循环的末尾按下的按键,那么进入下一次循环的时候,P3的值不是就又被代码重新赋值了吗?那么是怎么检测到是哪一行的呢?越想越想不通了,但是下载到开发板上是可以完美运行的。好晕

单片机代码如下:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int


sbit wela=P2^7;
sbit dula=P2^6;

uchar code tabledu[]=
{0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};

uchar i,num,temp,key;

void delay(uint i)
{
        uint x,y;
        for(x=i;x>0;x--)
                for(y=110;y>0;y--);
}

void main()
{
        num=0;
        temp=0xfe;
        wela=1;
        P0=0xc0;
        wela=0;
        dula=1;        
        P0=0x00;
        dula=0;
        while(1)
        {
                for(i=0;i<4;i++)
                {
                        P3=_crol_(temp,i);
                        key=P3;
                        key=key&0xf0;
                        while(key!=0xf0)
                        {
                                delay(10);
                                key=P3;
                                key=key&0xf0;
                                while(key!=0xf0)
                                {
                                        switch(key)
                                        {
                                                case 0xe0:num=1+(i*4);        
                                                        break;
                                                case 0xd0:num=2+(i*4);        
                                                        break;
                                                case 0xb0:num=3+(i*4);        
                                                        break;
                                                case 0x70:num=4+(i*4);        
                                                        break;
                                        }
                                        break;        
                                }
                                dula=1;        
                                P0=tabledu[num-1];
                                dula=0;        
                                break;        
                        }
                }
        }
}




作者: vo1t    时间: 2023-3-21 21:52
我的代码里并没有对P3的低位(也就是行数)进行验证是多少,但是却可以完美的运行出来,真的没搞懂
作者: vo1t    时间: 2023-3-21 21:52
感觉自己表达的也不是很清楚,不知道有没有大佬能懂我意思
作者: vo1t    时间: 2023-3-21 22:06
我尝试把for循环中第一条给P3口赋值的语句删除掉,程序就无法运行了,按任何按键都没有反应。所以我想问一下,给P3赋一个值的意义是什么呢?我反复看了几遍老师的视频,没有理解得很透彻。视频里的意思是先给低位赋值,先确定行后确定列,可是用代码这样赋值不就是和实际使用当中矛盾了嘛希望有大佬帮我解答一下,或者有讲得比较清楚的视频或帖子可以推荐一下,我自己去看,感谢各位
作者: lkc8210    时间: 2023-3-21 23:34
传统51单片机的准双向IO结构
准双向IO置1时是弱上拉,只能输出很小的电流(150~270uA)
准双向IO置0时是开漏,能接受比较大的电流(6~20mA)
所以当IO(P30)置0时(i=0),而其它IO置1时(P3 => 0xFE)
如果他们之间的按键被按下(短路P34)
P34就会被拉低(P3 => 0xEE)
P3 & 0xF0 => 0xE0
结合i就得出键值

给P3赋一个值就是为了拉低一位
不赋值P3=> 0xFF
按啥键都没有电平变化
自然不符合 switch(key)中的任一个case
作者: vo1t    时间: 2023-3-21 23:39
lkc8210 发表于 2023-3-21 23:34
传统51单片机的准双向IO结构
准双向IO置1时是弱上拉,只能输出很小的电流(150~270uA)
准双向IO置0时是开 ...

懂了懂了,太感谢了!!!!谢谢大神!
作者: vo1t    时间: 2023-3-22 01:00
lkc8210 发表于 2023-3-21 23:34
传统51单片机的准双向IO结构
准双向IO置1时是弱上拉,只能输出很小的电流(150~270uA)
准双向IO置0时是开 ...

在感谢一下大神,又仔细想了想完全懂了,谢谢你!
作者: a185980800    时间: 2023-3-22 02:15
#include<reg52.h> // 导入 8052 单片机头文件 #include<intrins.h> // 导入 _crol_ 函数所需的头文件  #define uchar unsigned char // 定义无符号字符类型 #define uint unsigned int // 定义无符号整数类型  sbit wela=P2^7; // 定义 WELA 引脚 sbit dula=P2^6; // 定义 DULA 引脚  uchar code tabledu[]= {0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; // 定义显示表格  uchar i,num,temp,key; // 定义变量  void delay(uint i) { // 延时函数     uint x,y;     for(x=i;x>0;x--)         for(y=110;y>0;y--); }  void main() {     num=0; // 初始化 num 变量     temp=0xfe; // 初始化 temp 变量     wela=1; // 置位 WELA 引脚     P0=0xc0; // 将 "1100 0000"(第一位和第二位为 1)写入 P0 寄存器中,用于控制数码管     wela=0; // 复位 WELA 引脚     dula=1; // 置位 DULA 引脚     P0=0x00; // 将 "0000 0000" 写入 P0 寄存器,用于清除数码管上次显示的内容     dula=0; // 复位 DULA 引脚     while(1) {         for(i=0;i<4;i++) { // 遍历四个数码管             P3=_crol_(temp,i); // 将 temp 变量左移 i 位后的值赋给 P3 寄存器             key=P3; // 将 P3 寄存器中的值赋给 key 变量             key=key&0xf0; // 将 key 变量的低四位清零             while(key!=0xf0) { // 如果按键没有被按下,则等待                 delay(10); // 延时 10ms                 key=P3; // 将 P3 寄存器中的值赋给 key 变量                 key=key&0xf0; // 将 key 变量的低四位清零                 while(key!=0xf0) {                     switch(key) { // 根据按键的不同,将对应的数字显示在数码管上                         case 0xe0:num=1+(i*4); break; // 按下第一行第一个按键                         case 0xd0:num=2+(i*4); break; // 按下第二行第一个按键                         case 0xb0:num=3+(i*4); break; // 按下第三行第一个按键                         case 0x70:num=4+(i*4); break; // 按下第四行第一个按键                     }                     break;                 }                 dula=1; // 置位 DULA 引脚                 P0=tabledu[num-1]; // 在数码管上显示 num 变量对应的数字                 dula=0; // 复位 DULA 引脚                 break;             }         }     } }
作者: glinfei    时间: 2023-3-22 10:24
a185980800 发表于 2023-3-22 02:15
#include // 导入 8052 单片机头文件 #include // 导入 _crol_ 函数所需的头文件  #define uchar unsigned  ...

这个是不是ChatGPT给的答复啊?
作者: a185980800    时间: 2023-3-22 14:57
Gpt不就是这么用的吗叫他帮我写个注释了我才看得懂啊
作者: glinfei    时间: 2023-3-22 15:08
本帖最后由 glinfei 于 2023-3-22 15:16 编辑
a185980800 发表于 2023-3-22 14:57
Gpt不就是这么用的吗叫他帮我写个注释了我才看得懂啊

就算有点错,总体写的还行,我觉得如果变量名称起的规范,以后写程序都不用写注释了,可惜我没注册上。有没试过,让它写个矩阵键盘程序?




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1