本欲实现,基于stc15w4k32s4的简单密码锁,目前只能实现数字锁存,后续完整部分,等待整个项目完全实现在上传,希望对大家有所帮助。
下面是Proteus的仿真图
下面是实现功能
下面是代码
main.c
#include <stc15.h>
#include <intrins.h>
#include "delay.h"
#define uchar unsigned char
//#include "keyvalue8.h"
sbit DS=P1^5;//
sbit ST=P1^6;//
sbit SH=P1^7;//
sbit D_port=P1^0;
sbit C_port=P1^1;
sbit B_port=P1^2;
sbit A_port=P1^3;
sbit G_port=P1^4;
void HC595SendData(unsigned char n)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(n&0x80)DS=1;
else DS=0;
n<<=1;
SH=0;
SH=1;
}
ST=0;
ST=1;
}
/*-------------------------------------------------------
其中date为595发送的数据,wei是138发送的
--------------------------------------------------------*/
void HC595_Data_Send(uchar date,wei)
{
HC595SendData(date);
G_port = 1; /*关屏显示,原理为使HC138输出全为1,从而三极管截止,不显示*/
switch (wei){
case 0:
A_port = 0; B_port = 0; C_port = 0; D_port = 0;
break;
case 1:
A_port = 1; B_port = 0; C_port = 0; D_port = 0;
break;
case 2:
A_port = 0; B_port = 1; C_port = 0; D_port = 0;
break;
case 3:
A_port = 1; B_port = 1; C_port = 0; D_port = 0;
break;
case 4:
A_port = 0; B_port = 0; C_port = 1; D_port = 0;
break;
case 5:
A_port = 1; B_port = 0; C_port = 1; D_port = 0;
break;
case 6:
A_port = 0; B_port = 1; C_port = 1; D_port = 0;
break;
case 7:
A_port = 1; B_port = 1; C_port = 1; D_port = 0;
break;
}
ST = 1; /*允许HC595数据输出到Q1-Q8端口*/
G_port = 0; /*HC138输出有效,打开显示*/
ST = 0; /*锁定HC595数据输出*/
}
unsigned char times;
unsigned char idata value[8]={16,16,16,16,16,16,16,16};//接收按键值数组,<8个
unsigned char table[]={ //阳码
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0x1A,0x86,0x8E,0xFF};
/*0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15*/
/*A ,b ,C ,d ,E ,F*/
unsigned char seg[8]={
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
/*空,空,空 ,空 ,空 ,空 ,空 ,空*/
//临时存放数组内部有八个,初始时为全空
};
unsigned char keynum;
unsigned char keyscan() //键盘输入扫描函数,低4列,高4行
{
unsigned char hang,lie,key,buff;
P3=0xf0;//列送入低电平
if((P3&0xf0)!=0xf0) //取出高四位,用于行的控制
{
Delay10ms();//延时消抖
if((P3&0xf0)!=0xf0) //判断此时行有键按下
{
lie=0xfe; //逐列扫描,列用低四位控制
times++; //统计按键次数
if(times==9) //统计按键次数
times=1;
while((lie&0x10)!=0) //扫描完4列后跳出
{
P3=lie;
if((P3&0xf0)!=0xf0) //再一次判断高四位,判断行是否有按下
{
hang=P3&0xf0;
buff=lie&0x0f+hang;
switch(buff)
{
case 0xee: key=0;break; //1110 1110
case 0xed: key=1;break; //1110 1101
case 0xeb: key=2;break; //1110 1011
case 0xe7: key=3;break; //1110 0111
case 0xde: key=4;break; //1101 1110
case 0xdd: key=5;break; //1101 1101
case 0xdb: key=6;break; //1101 1011
case 0xd7: key=7;break; //1101 0111
case 0xbe: key=8;break; //1011 1110
case 0xbd: key=9;break; //1011 1101
case 0xbb: key=10;break; //1011 1011
case 0xb7: key=11;break; //1011 0111
case 0x7e: key=12;break; //0111 1110
case 0x7d: key=13;break; //0111 1101
case 0x7b: key=14;break; //0111 1011
case 0x77: key=15;break; //0111 0111
}
value[times-1]=key; //按下的键值保存到数组
}
else lie=_crol_(lie,1);//下一列扫描
} } }
if(times!=0) return key;
else return 0xff;
}
void main(){
while(1){
unsigned char i;
unsigned char wei=0;
keynum=keyscan();//获取键值
if(keynum!=0xff){
seg[0]=table[value[0]];
seg[1]=table[value[1]];
seg[2]=table[value[2]];
seg[3]=table[value[3]];
seg[4]=table[value[4]];
seg[5]=table[value[5]];
seg[6]=table[value[6]];
seg[7]=table[value[7]];
for(i=0;i<8;i++){//循环显示部分
HC595_Data_Send(seg[i],wei);//通过595和139发送数据
Delay10ms();
HC595_Data_Send(0xFF,0);
wei++;
if(wei==8) wei=0;//位选线是从0~7
} } } }
上面的功能,主要是基于stc15w3k32s4,分别运用74LS138和74HC595两个译码器,实现的也是一个比较简单的功能。
在我原本的设想中,我添加功能还有确认按键,删除按键,以及输入错误6次自动锁定功能,其中,最后一个自动锁定功能在设想中有点难搞,但是呢这边由于时间原因就只能先将部分东嗯那个做出来,后续,我在抽点时间,将这个项目车企完成。