我也在做这个题的实训,总是出现问题,开始我又找不到哪里有问题 |
xdn 发表于 2017-12-28 09:09 用STC12系列芯片P0~P4加电复位后都是高电平准双向口,不必设置,给你这个例程主要是介绍不同组别端口组成的4*4矩阵键盘读写方法。 |
wulin 发表于 2017-12-27 20:43 //新一代 1T 8051系列,单片机i/o口的特殊功能寄存器 // 7 6 5 4 3 2 1 0 Reset Value sfr P0 = 0x80; //8 bitPort0 P0.7 P0.6 P0.5 P0.4 P0.3 P0.2 P0.1 P0.0 1111,1111 sfr P0M0 = 0x94; // 0000,0000 sfr P0M1 = 0x93; // 0000,0000 sfr P1 = 0x90; //8 bitPort1 P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0 1111,1111 sfr P1M0 = 0x92; // 0000,0000 sfr P1M1 = 0x91; // 0000,0000 sfr P1ASF = 0x9D; //P1 analog special function sfr P2 = 0xA0; //8 bitPort2 P2.7 P2.6 P2.5 P2.4 P2.3 P2.2 P2.1 P2.0 1111,1111 sfr P2M0 = 0x96; // 0000,0000 sfr P2M1 = 0x95; // 0000,0000 sfr P3 = 0xB0; //8 bitPort3 P3.7 P3.6 P3.5 P3.4 P3.3 P3.2 P3.1 P3.0 1111,1111 sfr P3M0 = 0xB2; // 0000,0000 sfr P3M1 = 0xB1; // 0000,0000 sfr P4 = 0xC0; //8 bitPort4 P4.7 P4.6 P4.5 P4.4 P4.3 P4.2 P4.1 P4.0 1111,1111 sfr P4M0 = 0xB4; // 0000,0000 sfr P4M1 = 0xB3; // 0000,0000 // 7 6 5 4 3 2 1 0 Reset Value sfr P4SW = 0xBB; //Port-4 switch - LVD_P4.6 ALE_P4.5 NA_P4.4 - - - - x000,xxxx sfr P5 = 0xC8; //8 bitPort5 - - - - P5.3 P5.2 P5.1 P5.0 xxxx,1111 sfr P5M0 = 0xCA; // 0000,0000 sfr P5M1 = 0xC9; // 0000,0000 这是STC12C5A60S2头文件里面的定义,你的main函数所指的初始化为标准的双向端口是要修改这个地方吗?还是直接在主程序中重新定义修改? |
xdn 发表于 2017-12-27 19:06 main函数里面很简单,所有端口初始化为准双向口是因为使用可以仿真的IAP15W4K58S4单片机,其很多端口默认状态是强推挽或高阻,需要改为准双向口。主循环里就是调用键盘扫描程序和用LED显示键值语句。 |
wulin 发表于 2017-12-27 17:47 没能理解你的main函数里面的意思?能解释一下吗? |
异组端口组成的4*4矩阵键盘读写方法 #include <STC15F2K60S2.H> #define uint unsigned int //宏定义数据类型uint #define uchar unsigned char //宏定义数据类型uchar sbit code0=P3^0; //定义4*4键盘端口 sbit code1=P3^1; sbit code2=P3^2; sbit code3=P3^3; sbit code4=P3^4; sbit code5=P3^5; sbit code6=P4^2; sbit code7=P4^4; uchar key=0xff; //键值变量初始值 void PX(uchar i) //写入8位数据 { code0=i&0x01;i>>=1; code1=i&0x01;i>>=1; code2=i&0x01;i>>=1; code3=i&0x01;i>>=1; code4=i&0x01;i>>=1; code5=i&0x01;i>>=1; code6=i&0x01;i>>=1; code7=i&0x01; } uchar PD() //读取8位数据 { uchar i; i=code7; i=(i<<1)|code6; i=(i<<1)|code5; i=(i<<1)|code4; i=(i<<1)|code3; i=(i<<1)|code2; i=(i<<1)|code1; i=(i<<1)|code0; return i; } void key_scan() //矩阵键盘扫描函数 { uchar temp1,temp2,temp3; //临时变量 static bit sign=0; //按键自锁标志 static uint count=0; //消抖计数变量 PX(0xf0); //先给矩阵端口赋一个初值0xf0 if(PD()!=0xf0) //判断矩阵端口不等于所赋初值,说明有健按下 { if(sign==0) //如果按键自锁标志为0 { count++; //消抖计数 if(count>=1000) //消抖计数>=1000,估算主循环周期调整 { //摒弃Delay延时方式, count=1000; //防止溢出 sign=1; //按键自锁标志置1,键不抬起,按其他键无效 temp1=PD(); //temp1保存矩阵端口高4位变化 PX(0x0f); //再给矩阵端口赋值0x0f temp2=PD(); //temp2保存矩阵端口低4位变化 temp3=temp2|temp1; //temp3=高4位+低4位 key=temp3; //保存键值 } } } else //按键抬起 { sign=0; //按键自锁标志清0 count=0; //消抖计数清0 } } void main() { P0M0 = 0x00; //初始化端口准双向 P0M1 = 0x00; P1M0 = 0x00; P1M1 = 0x00; P2M0 = 0x00; P2M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P4M0 = 0x00; P4M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; P6M0 = 0x00; P6M1 = 0x00; P7M0 = 0x00; P7M1 = 0x00; while(1) { key_scan(); //键盘扫描 P1=key; //LED低电平亮显示键值 } } |
zzzxxxccc 发表于 2017-12-27 17:36 这两句已经单独测试过了,LCD_PutString(0+i,1+j,TAB[num])不能显示TAB[num]的具体值。这个问题我改怎么改呢? 还有按键扫描的函数不正确吗?按下按键它会弹出乱码,而且是一直循环着,按下复位键也没反应,这是为什么呢? |
检查 修改 显示的计算 一定要 让显示的参数 和 函数能够对应 比如0-f 是否是 你想要的 0-15 unsigned char code TAB[]={1,2,3,15,4,5,6,14,7,8,9,13,10,0,11,12}; LCD_PutString(0+i,1+j,TAB[num]); 这俩个好好检查 扫描的 按键 先单个测试 多个的话 你的代码暂时不能实现 |
求大神帮帮忙, |