C51单片机银行取款机
要求:
1. 原始密码为6个0,存放在RAM中,可以用passwordbuf[ ]数组存储原始密码;
2.开机后液晶屏第一行显示为:Inputpassword:通过矩阵键盘在第二行输入6位
密码(******),不显示其数值,都以*来显示密码,你需要重新用一个数组保存
键盘输入的密码;
3.11号键修改密码,按下后液晶屏第一行会显示:Newpassword:然后输入新密
码,在第二行上显示为******;
4.12键按下后保存密码到24c02及passwordwordbuf[ ]中,然后液晶屏第一行显示
为:success:
5.13键确认密码(进行密码对比),密码不正确则液晶屏第一行显示:Flase 第
二行显示:Re-input;密码正确:第一行显示OK;
6.14号键重新输入密码,按下后液晶屏显示第一行显示InputPassword:然后输
入密码会在第二行会显示你输入的密码(******),不显示其数值,都以*来显示密码;
7.15号键删除密码,如果密码输入错误,按15号按键删除当前一个密码;
8.注意24c02掉电后密码不会丢失,而ram中的passwordbuf[ ]数据会丢失,变为
初试密码6个0,所以我们测试的时候,分为两个部分:
(1)不掉电的情况下,输入原始密码,比较正确;然后修改密码后,再次输入
新密码,输入正确密码,显示ok;然后再输入错误密码,显示错误,再进行正确
密码输入,显示ok即可。
(2)开发板关掉电源,然后再上电,输入新修改的密码,对比显示正确即可
(我们在向24c02写入新密码时,可以多写一个数值,比如说我们将密码存放在
01H-06H地址,而00H地址默认的数据是0,当修改完密码后,我们可以将00H内容修改为0x55,
然后01H-06H为新密码数据,断电再上电后,我们程序应该先读取00H地址的内容,判断是否为0x55,
是0x55则说明新密码已经存放在01H-06H处,然后从24c02的01H-06H地址中读出密码送到passwordbuf
数组中保存,如果不是0x55,就直接使用passwordbuf数组的值进行密码比较,每次密码对比都是和
passwordbuf的数值进行比较)
###主程序
#include<reg51.h>
#include<1602_led.h>
#include<ic.h>
#include<16key.h>
unsigned tem1,tem2,key;
char m=0 ,i=0,flag=1;
unsigned char passwordbuf[6]={0},buf[7]={0},xing[7]={0};
void mima();
void At24c02Write(unsigned char addr,unsigned char dat);
unsigned char At24c02Read(unsigned char addr);
void main()
{
lcdcom(0x01);
lcdcom(0x06);
lcdcom(0x0e);
lcdcom(0x38);
if(At24c02Read(7)==0xaa)
{
for(i=0;i<6;i++)
passwordbuf[i]=At24c02Read(i+1);
}
lcdcom(0x80);
lcddat('I');lcddat('n');lcddat('p');lcddat('u');lcddat('t');
lcddat('p');lcddat('a');lcddat('s');lcddat('s');lcddat('w');
lcddat('o');lcddat('r');lcddat('d'); lcddat(':');
while(1)
{
key=getkey();
mima();
switch(key)
{
case 10:
{
lcdcom(0x01);
lcdcom(0x80);
lcddat('N');lcddat('e');lcddat('w');
lcddat('p');lcddat('a');lcddat('s');lcddat('s');lcddat('w');
lcddat('o');lcddat('r');lcddat('d');lcddat(':');
m=0;
mima();
};break;
case 11:
{
At24c02Write(1,buf[0]);delayms(10);
At24c02Write(2,buf[1]);delayms(10);
At24c02Write(3,buf[2]);delayms(10);
At24c02Write(4,buf[3]);delayms(10);
At24c02Write(5,buf[4]);delayms(10);
At24c02Write(6,buf[5]);delayms(10);
At24c02Write(7,0xaa);delayms(10);
lcdcom(0x01);
lcdcom(0x80);
lcddat('s');lcddat('u');lcddat('c');lcddat('c');lcddat('e');lcddat('s');lcddat('s');
};break;
case 12:
{
lcdcom(0x01);
if(buf[0] == passwordbuf[0]&&buf[1] == passwordbuf[1]&&buf[2] == passwordbuf[2]
&&buf[3] == passwordbuf[3]&&buf[4] == passwordbuf[4]&&buf[5] == passwordbuf[5])
flag=1;
else
flag =0;
if(flag == 0)
{
lcdcom(0x01);
lcdcom(0x80);lcddat('F');lcddat('l');lcddat('a');lcddat('s');lcddat('e');
lcdcom(0xc0);lcddat('R');lcddat('e');lcddat('-');lcddat('i');lcddat('n');
lcddat('p');lcddat('u');lcddat('t');
}
else
{
lcdcom(0x01);lcdcom(0x80);
lcddat('o');lcddat('k');
}
};break;
case 13:
{
lcdcom(0x01);
lcdcom(0x80);
lcddat('I');lcddat('n');lcddat('p');lcddat('u');lcddat('t');
lcddat('p');lcddat('a');lcddat('s');lcddat('s');lcddat('w');
lcddat('o');lcddat('r');lcddat('d'); lcddat(':');
m=0;
mima();
};break;
case 14:
{
lcdcom(0xc0+m-1);
lcddat(0x20);
buf[m]='\0';
m=m-1;
};break;
}
}
}
void mima()
{
if(key!=-1)
{
if(key<10&&m<6)
{
buf[m]=key;
lcdcom(0xc0+m);
lcddat('*');
m++;
}
}
}
void At24c02Write(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_WritByte(0xA0);
while(check_Ack());
IIC_WritByte(addr);
while(check_Ack());
IIC_WritByte(dat);
while(check_Ack());
IIC_Stop();
}
unsigned char At24c02Read(unsigned char addr)
{
unsigned char tem;
IIC_Start();
IIC_WritByte(0xA0);
while(check_Ack());
IIC_WritByte(addr);
while(check_Ack());
IIC_Start();
IIC_WritByte(0xA1);
while(check_Ack());
tem=IIC_ReadByte();
noack();
IIC_Stop();
return tem;
}
显示屏1602
#include "1602_led.h"
void delayms(int ms)
{
int i,j=0;
for(i=0;i<ms;i++)
for(j=0;j<180;j++); //不同的单片机不同的延迟函数
}
bit check_busy() //有返回值属性,就要首先定义一个相关的名
{
bit busy;
rs = 0; wr = 1; e = 0;//读状态,读有效
delayms(1);
e=1;
delayms(1);//读为高电平,但是写:由高到低,进行拉低
busy = P0&0x80;
e=0; delayms(1);
return busy;
}
void lcdcom(unsigned char com)
{
while(check_busy());//返回1时一直循环 1代表忙,0往下
rs = 0; wr = 0; e =0;//写指令,写有效 ,与之前的一样
delayms(1);
P0 =com;//写指令(写数据),此时1602并不接收
e=1;delayms(1);e=0;delayms(1);//产生下降沿,1602接收指令(P0口数据) 写:由高到低,进行拉低
}
void lcddat(unsigned char date)
{
while(check_busy());//返回1时一直循环 1代表忙,0往下
rs = 1; wr = 0; e =0;//写数据,写有效 ,与之前的一样
delayms(1);
P0 =date;//(写数据),此时1602并不接收
e=1;delayms(1);e=0;delayms(1);//产生下降沿,1602接收数据(P0口数据) 写:由高到低,进行拉低
}
1602.h
#ifndef __1602_LED_H__
#define ___1602_LED_H__
#include<reg51.h>
sbit rs = P2^6;
sbit wr= P2^5;
sbit e = P2^7;
void delayms(int ms);
bit check_busy();
void lcdcom(unsigned char com);
void lcddat(unsigned char date);
#endif
IC2
#include "ic.h"
void delay10us()
{
char x ;
for(x=0;x<3;x++);
}
//启动函数
void IIC_Start()
{
sda=1;//先让他为高电平:之前我们不知道是什么电平
scl=1;//先定义时钟线
delay10us();
sda=0; //产生启动信号
delay10us();
scl=0;//时钟线拉低,产生脉冲
}
//停止函数
void IIC_Stop()
{
sda=0;//先让他为高电平:之前我们不知道是什么电平
scl=1;//先定义时钟线
delay10us();
sda=1; //产生启动信号
delay10us();
scl=0;//时钟线拉低,产生脉冲
}
void IIC_WritByte(unsigned char dat)
{ char n;
for( n =0;n<8;n++)
{
if((dat&0x80)==0x80)//发送dat的最高位 (1/0)
sda=1;
else sda=0;
scl=1;
delay10us();
//最后一步必须有脉冲
scl=0;//时钟是由脉冲形成的
dat=dat<<1;//左一位
}
}
unsigned char IIC_ReadByte()
{
unsigned char tem=0;//返回值初始化为0
char m;
sda=1;//(mos管)引脚内部的场效应管不导通
for( m =0;m<8;m++)
{
scl=1;//时钟线有效
delay10us();
tem=tem<<1;//防止最后一位是0
tem=tem|sda;
scl=0;
}
return tem;
}
bit check_Ack()
{
bit ack;
//只需要读一次
sda=1;//(mos管)引脚内部的场效应管不导通 (读数据专有)
scl=1;
delay10us();
ack=sda;//数据引脚的值
scl=0;//时钟引脚的值拉低
return ack;
}
void ack()
{
sda=0;//先写数据
scl=1; //读数据
delay10us();
scl=0;
}
void noack()
{
sda=1;//先写数据
scl=1; //读数据
delay10us();
scl=0;
}
IC2.h
#ifndef __IC_H__
#define ___IC_H__
#include<reg51.h>
sbit scl=P2^1;
sbit sda=P2^0;
void delay10us();
void IIC_Start();
void IIC_Stop();
void IIC_WritByte(unsigned char dat);
unsigned char IIC_ReadByte();
bit check_Ack();
void ack();
void noack();
#endif
矩阵键盘
#include"16key.h"
#include "1602_led.h"
char getkey()
{
char k1,k2,k3;
P1=0XF0;
delayms(1);
if(P1 != 0XF0)
{
delayms(10);
if(P1 !=0xF0)
{
switch(P1)
{
case 0x70:k1 = 0;break;
case 0xB0:k1 = 4;break;
case 0xD0:k1 = 8;break;
case 0xE0:k1 = 12;break;
}
P1 = 0x0F;
delayms(1);
switch(P1)
{
case 0x07:k2=0;break;
case 0x0B:k2=1;break;
case 0x0D:k2=2;break;
case 0x0E:k2=3;break;
}
k3 = k1+k2;
while(P1 !=0x0F);
delayms(10);
return k3;
}
}
return -1;
}
矩阵键盘.h
#ifndef __16KEY_H__
#define ___16KEY_H__
#include<reg51.h>
char getkey();
#endif