经过查找源程序,发现按钮按下,应该是==0!
其实还有个地方,行和列要恢复一下初值:
if(( ROW1 == 0 ) || ( ROW2 == 0 )) //如果行按键有按下
{
if(( ROW1 ==0 ) && ( ROW2 ==0 )) //如果两行都有按键按下,不处理
{
}
else if((( ROW1 ==1 )&&( ROW2 ==0 )) || (( ROW1 ==0 )&&( ROW2 ==1 ))) //如果有按键按下,而且只有一颗
{
if( ROW1 ==0 ) //判断哪一行,输出行开始的序号
key_num = 0;
else if( ROW2 ==0 )
key_num = 4;
//②第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。
COL1 = 1;
COL2 = 1;
COL3 = 1;
COL4 = 1;
ROW1 = 0;
ROW2 = 0;
if( COL1 ==0 ) //判断哪一列,叠加按键的序号
{
// key_num = key_num +0 ; //③第三步:行列组合一下就可以判断出是哪个按键按下了。
}
else if( COL2 ==0 )
{
key_num = key_num + 1;
}
else if( COL3 ==0 )
{
key_num = key_num + 2;
}
else if( COL4 ==0 )
{
key_num = key_num + 3;
}
}
COL1 = 0; //以下6行如果不写的话,会有点小问题,就是上次检测完按键后
COL2 = 0;//没有把初始值恢复,数码管会闪一下,感觉很不稳定
COL3 = 0;//所以这样要把行和列都重新设置回初值
COL4 = 0;
ROW1 = 1;
ROW2 = 1;
}
else
{
key_num = 0xff;
}
其实主要是端口的电平还是要恢复为初始状态
任务二:做一把密码锁:
矩阵按键的程序实现
密码锁.
1.没有输入时,显示
2.有输入时,按下一个按键,开始按顺序写入例如,第一个按下1,显示“1例如,第二个按下3,显示“1 3.-
3.当按下的密码为“12345670”时,数码管显示“88888888”的字符,否则,还是显示 “EEEEEEEE”
程序怎么写?
我们先把冲哥的程序代码贴上来:
/*下面是任务二密码锁代码
u8 passward = { 16,16,16,16,16,16,16,16 };
u8 Seg_no = 0;
void SEG_Task(void)
{
u8 num = 0;
if( Seg_no ==0 ) //小时十位
{
Display_Seg( SEG_NUM] , ~T_NUM); //数码管刷段码和位码
}
else if( Seg_no ==1 ) //小时的个位
{
Display_Seg( SEG_NUM] , ~T_NUM); //数码管刷段码和位码
}
else if( Seg_no ==2 ) //第一个横杠
{
Display_Seg( SEG_NUM] , ~T_NUM); //数码管刷段码和位码
}
else if( Seg_no ==3 ) //分钟的十位
{
Display_Seg( SEG_NUM] , ~T_NUM); //数码管刷段码和位码
}
else if( Seg_no ==4 )
{
Display_Seg( SEG_NUM] , ~T_NUM); //数码管刷段码和位码
}
else if( Seg_no ==5 )
{
Display_Seg( SEG_NUM] , ~T_NUM); //数码管刷段码和位码
}
else if( Seg_no ==6 )
{
Display_Seg( SEG_NUM] , ~T_NUM); //数码管刷段码和位码
}
else if( Seg_no ==7 )
{
Display_Seg( SEG_NUM] , ~T_NUM); //数码管刷段码和位码
}
else
{
}
Seg_no ++;
if( Seg_no>7 )
Seg_no=0;
}
u8 Key_Vol3 = 0;
u8 key_no =0 ;
void PW_write_Task(void)
{
if( key_num <0xff )
{
Key_Vol3 ++;
if( Key_Vol3 == 5 )
{
if( key_no == 0 )
{
passward = 16;
passward = 16;
passward = 16;
passward = 16;
passward = 16;
passward = 16;
passward = 16;
passward = 16;
}
passward[ key_no] = key_num ;
key_no ++;
// passward = 17;
if( key_no == 8 ) //密码输入到了八位
{
if((passward==1) && (passward==2) && (passward==3) && (passward==4) && (passward==5) && (passward==6) && (passward==7) &&(passward==0) )
{
passward = 17;
passward = 17;
passward = 17;
passward = 17;
passward = 17;
passward = 17;
passward = 17;
passward = 1; }
else
{
Key_Vol3 = 0;
}
}
第一个函数void SEG_Task(void)其实就是负责显示
不过这里有8位,就要考虑闪烁问题:
执行扫描的间隔不能太长
static TASK_COMPONENTS Task_Comps[]=
{
//状态计数周期函数
{0, 10,10, Task_1}, /* task 1 Period: 300ms */
{0,1, 1, SEG_Task}, /* task 1 Period: 300ms */
{0, 10,10, PW_write_Task},
};
1ms就扫描一次
PW_write_Task()
函数是按键输入函数:
void PW_write_Task(void)
{
if( key_num <0xff )
{
Key_Vol3 ++;
if( Key_Vol3 == 5 )
{
if( key_no == 0 )
{
passward = 16;
passward = 16;
passward = 16;
passward = 16;
passward = 16;
passward = 16;
passward = 16;
passward = 16;
}
passward[ key_no] = key_num ;
key_no ++;
// passward = 17; //把显示1的位置清空
if( key_no == 8 ) //密码输入到了八位
{
if((passward==1) && (passward==2) && (passward==3) && (passward==4) && (passward==5) && (passward==6) && (passward==7) &&(passward==8) )
{
passward = 17;//清空密码
passward = 17;//清空密码
passward = 17;//清空密码
passward = 17;//清空密码
passward = 17;//清空密码
passward = 17;//清空密码
passward = 17;//清空密码
passward = 1;//清空密码,显示个1
}
else
{
Key_Vol3 = 0;
}
}
这个逻辑还是有点复杂,慢慢理解才行,首先这个键盘是矩阵按键
要和上面的实验连续起来才行,void Task_1(void)是每10ms执行一次
所以key_num会随时反应你按下的键值,这样联合思考,才能读懂上面的
void PW_write_Task(void)函数,我其实没有写过自己的体会,主要是觉得
现阶段只是看懂冲哥的程序,理解冲哥的意图........能完成这2个任务,都很
吃力。
出现一个小问题:
键盘上没有8
我们把密码中的8改为0:
经过以上修改,程序可以稳定运行
实验成功!
第十一课矩阵键盘到此结束
神农鼎 发表于 2025-11-30 21:33
要 做到 USB不停电下载;
要 尝试 图形化配置外设;
推荐优先看的 printf_usb("Hello World !\r\n")及usb不 ...
今天我们复习AiCube
先跟着李工看一遍她的操作:
如何利用这个智能配置开发工具来实验,自动辅助开发,程序自动生成的工具,快速的让单片机发送字符串到PC机 ?
当然上位机PC的程序STC也直接开发了串口助手,并且集中在ISP软件中:在李工带领下
我们要完成三个超简单的USB通信实验,及USB不停电下载:
当然是对李工来讲超简单:
实验一:直接输出,printf_usb("Hello World!\r\n")
实验二:查询方式,查询到电脑命令后,printf_usb("Hello World!\r\n")或其他
实验三:中断方式,单片机USB中断接收服务函数收到命令后,printf_usb("Hello World!\r\n")或其他