我博客有相关程序,包含两个单片机的通信,一个为呼叫,另一单片机为应答,当然,如果知道密码也不需要呼叫的密码锁。
说明:
1.基本部分为单片机的串口通信,包含串口通信,键盘扫描
2.程序部分有详细的注释。
/*-------------------------------------------
Project: mimasuo program (V0.1)
Filename: mimasuo.c
Prozessor: 80C51 family
Compiler: Keil Version 6.14
Autor: ********
Copyrigth: 041151**
date: 2008.3.17
------------------------------------------ */
#include
#define uchar unsigned char
sbit ADCS =P3^6;
sbit ADC =P3^7;
sbit AD =P1^0;
int fafu=0;
uchar key,key1,i,count1=1,yidong=256;
uchar jgh[9]=;//输出指示
uchar jgh1[9]; //输入键盘缓存
uchar mima[9]=;//初始8位密码 : 12345678 第0位未用
uchar fangjian[4]=; //初始门牌号 252 第0位未用
char count=0;
void init_serialcomm(void) //串口波特率设置
{
SCON=0x50;
TMOD=0x20;
PCON=0x80;
TH1=0x40;
TL1=0x40;//300
TR1=1;
EA=1;
TI=0;
RI=0;
}
void delay10ms(void) //10毫秒延时程序
{
unsigned char i,j,k;
for(i=5;i>0;i--)
for(j=4;j>0;j--)
for(k=248;k>0;k--);
}
uchar kbscan(void) // 键盘扫描程序
{
uchar sccode,recode;
P1=0xf0; //置所有行为低电平,行扫描,列线输入(此时)
if((P1&0xf0)!=0xf0) //判断是否有有键按下(读取列的真实状态,若第4列有键按下则P1的值会变成0111 0000),有往下执行
{
delays(); //延时去抖动(10ms)
if((P1&0xf0)!=0xf0) //再次判断列中是否是干扰信号,不是则向下执行
{
sccode=0xFE; //逐行扫描初值(即先扫描第1行)
while((sccode&0x10)!=0)//行扫描完成时(即4行已经全部扫描完成)sccode为1110 1111 停止while程序
{
P1=sccode; //输出行扫描码
if ((P1&0xf0)!=0xf0) //本行有键按下(即P1(真实的状态)的高四位不全为1)
{
recode=(P1&0xf0)|0x0f; //列
return(sccode&recode); //返回行和列
}
else //所扫描的行没有键按下,则扫描下一行,直到4行都扫描
{
sccode=(sccode<<1)|0x01;//行扫描码左移一位
}
}
}
}
else
{
return 0; //无键按下,返回0
}
}
uchar readnumber(uchar tmp) //按键扫描的结果,转换为数字,便于程序对按键数据处理
{
switch(tmp)
{
case 0x28:return 0 ;break;
case 0x14:return 1 ;break;
case 0x24:return 2 ;break;
case 0x44:return 3 ;break;
case 0x12:return 4 ;break;
case 0x22:return 5 ;break;
case 0x42:return 6 ;break;
case 0x11:return 7 ;break;
case 0x21:return 8 ;break;
case 0x41:return 9 ;break;
case 0x88:return 10 ;break;
case 0x82:return 11 ;break;
default:break;
}
}
void main(void) //主程序
{
P2=0xff;
init_serialcomm();
while(1)
{
key=kbscan();
// P2=key;
fafu++;
if(fafu==10000){
fafu=0;
ADCS = 1;
ADC = 1;}
if(RI) //呼叫应答
{
RI=0;
ADCS = 0;
// P2=~P2;
}
if(key!=0){
do{
key1=kbscan();
AD = 0;
}while(key1!=0);//等待按键释放
AD = 1;
if(readnumber(key)==10) // 密码比较
{ count1=1;
for(i=1;i<=8;i++)
{
if(mima[i]==jgh1[i])
count1++;
}
if(count1==9)
{
// P2=~P2;
ADCS = 0;
}
else ADC=0;
}
if(readnumber(key)==11) // 呼叫房间
{ count1=1;
for(i=1;i<=3;i++)
{
if(fangjian[i]==jgh1[i])
count1++;
}
if(count1==4) //发送传送码
{
SBUF=0xf0;
while(TI==0);
TI=0;
P2=~P2;
}
}
if((key!=0x88)&&(key!=0x84)&&(key!=0x82)) //数字键输入,并把输入的数据存到数组中
{ count++;
P2=jgh[count];
jgh1[count]=readnumber(key);
if(count==8)
count=0;
}
if(key==0x84)
{ //取消功能键
count--;
if(count<=0)count=0;
P2=jgh[count];
}
}
}
}
详细代码可以到我博客下载:
不要用传感器啦,开门时,门转动的方向是不一样的,可以用铁片接触(从里往外门开),有信号(信号可以直接进单片机),从外往里开(不接触)无信号;直接检测I/O就可以啦!
可以用震动传感器,检测震动,或者你在转轴的地方,弄个角度传感器。都可以实现。
记得选最佳答案。呵呵。为人民服务才有动力。
最简单用2个红外管 检测2个红外管的电平变化