[资料] 使用AT24C02设计密码锁1602显示的程序
838 查看
4 回复
 楼主 | 发布于 2019-10-26 | 只看楼主
分享到:

//rs----PD4
//rw----PD5
//en----PD6
//data---PORTB
//SDA---PC1
//SCL---PC0
//beep--PA6
//开锁---PB7
//开锁状态----PB5
//如果把uchar const initpassword[6]={0,0,0,0,0,0};改为_flash  uchar   initpassword[6]={0,0,0,0,0,0};
//则出现这错误found `unsigned' expecting `;'可我没找到错误在哪???

#include <iom16v.h>
#include<macros.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define uchar unsigned char
#define uint  unsigned int
#define w 6 //定义密码位数
uchar  operation=0; //操作标志位
uchar  pass=0; //密码正确标志
uchar  ReInputEn=0; //重置输入充许标志
uchar  s3_keydown=0; //3秒按键标志位
uchar  key_disable=0; //锁定键盘标志
uchar countt0,second; //t1中断计数器,秒计数器
//void Delay5Ms(void);
uchar InputData[6]; //输入密码暂存区
uchar CurrentPassword[6]={1,3,1,4,2,0}; //当前密码值
uchar TempPassword[6];
uchar N=0; //密码输入位数记数
uchar ErrorCont; //错误次数计数
uchar CorrectCont; //正确输入计数
uchar ReInputCont; //重新输入计数
#pragma data:code
uchar const a[]={0xFE,0xFD,0xFB,0xF7}; //控盘扫描控制表
uchar const start_line[] = {"password:       "};
uchar const name[]   = {"===Coded Lock==="};      //显示名称
uchar const Correct[] = {"     correct    "}; //输入正确
uchar const Error[]    = {"      error     "};   //输入错误
uchar const codepass[] = {"      pass      "};
uchar const LockOpen[] = {"      open      "}; //OPEN
uchar const SetNew[] = {"SetNewWordEnable"};
uchar const Input[]    = {"input:          "}; //INPUT
uchar const ResetOK[] = {"ResetPasswordOK "};
uchar const initword[] = {"Init password..."};
uchar const Er_try[] = {"error,try again!"};
uchar const again[] = {"input again     "};
uchar const initpassword[6]={0,0,0,0,0,0};
/***************************************************************************************************/
void port_init()
{
  DDRA|=BIT(6);
  PORTA|=BIT(6);
  DDRB=0xFF;
  PORTB=0xFF;
  DDRC=0xFF;
  PORTC=0xFF;
}
/***********************************************************************************************/
void segg()//关数码显示管函数
{
   DDRA|=BIT(PA3); //PA3设置为输出状态
   DDRA|=BIT(PA4); //PA4设置为输出状态
   DDRB=0xff; //PB口设置为输出状态
   PORTB=0xff;    //发送模码
   PORTA|=BIT(PA3); //PA3输出高电平,DU拉高
   PORTA&=~BIT(PA3); //PA3输出低电平,DU拉低,段选锁存
   
   PORTB=0xff; //发送为选  关掉数码管显示
   PORTA|=BIT(PA4); //PA4输出高电平,WE拉高
   PORTA&=~BIT(PA4); //PA4输出低电平,WE拉低,位选锁存
   
   DDRA|=BIT(PA2); //PA2设置为输出状态 用于LED流水灯控制IO
   PORTA&=~BIT(PA2); //PA2输出低电平,DU拉低,段选LED流水灯锁存
}
/****************************************5ms延时*************************************/
void Delay5Ms(void)
{
uint TempCyc = 5552;
while(TempCyc--);
}
/****************************************400ms延时*************************************/
void Delay400Ms(void)
{
 uchar TempCycA = 5;
 uint TempCycB;
 while(TempCycA--)
 {
  TempCycB=7269;
  while(TempCycB--);
 }
}
/****************************************24C02****************************************/
void mDelay(uint t) //延时
{
uchar i;
    while(t--)
    {
    for(i=0;i<125;i++)
    {;}
    }
}
/*******************************************************************************************/
void Nop(void)   //空操作
{
  _nop_();
  _nop_();
  _nop_();
  _nop_();
}
/*****************************************起始条件*****************************************/
void Start(void)
{
  //Sda=1;
PORTC|=BIT(1);//
  //Scl=1;
PORTC|=BIT(0);//
  Nop();
  //Sda=0;
PORTC&=~BIT(1);//
  Nop();
}
 /*****************************************停止条件*****************************************/
void Stop(void)
{
  //Sda=0;
PORTC&=~BIT(1);//
  //Scl=1;
PORTC|=BIT(0);//
  Nop();
  //Sda=1;
PORTC|=BIT(1);//
  Nop();
}
/*****************************************应答位*****************************************/
void Ack(void)
{
//Sda=0;
PORTC&=~BIT(1);//
Nop();
//Scl=1;
PORTC|=BIT(0);//
Nop();
//Scl=0;
PORTC&=~BIT(0);//
}
/*****************************************反向应答位*****************************************/
void NoAck(void)
{
  //Sda=1;
PORTC|=BIT(1);//
  Nop();
  //Scl=1;
PORTC|=BIT(0);//
  Nop();
  //Scl=0;
PORTC&=~BIT(0);//
}
 /****************************发送数据子程序,Data为要求发送的数据***********************/
void Send(uchar Data)
{
    uchar BitCounter=8;
    uchar temp;
    do
    {
    temp=Data;
    //Scl=0;
PORTC&=~BIT(0);//
    Nop();
    if((temp&0x80)==0x80)
    //Sda=1;
PORTC|=BIT(1);
    else 
    //Sda=0;
PORTC&=~BIT(1);//
    //Scl=1;
PORTC|=BIT(0);//
    temp=Data<<1;
    Data=temp;
    BitCounter--;
    }
    while(BitCounter);
    //Scl=0;
PORTC&=~BIT(0);//
}
/********************读一字节的数据,并返回该字节值************************************/
uchar Read(void)
{
    uchar temp=0;
uchar temp1=0;
uchar BitCounter=8;
//Sda=1;
PORTC|=BIT(1);//
do{
//Scl=0;
PORTC&=~BIT(0);//
Nop();
//Scl=1;
PORTC|=BIT(0);//
Nop();
//if(Sda)
if(PORTC&0xF2)/////////////
temp=temp|0x01;
else
temp=temp&0xfe;
if(BitCounter-1)
{
temp1=temp<<1;
temp=temp1;
}
BitCounter--;
}
while(BitCounter);
return(temp);
}
/****************************************************************************************/
void  WrToROM(uchar  Data[],uchar Address,uchar Num)

{
  uchar i;
  uchar *PData;
  PData=Data;
  for(i=0;i<Num;i++)
  {
  Start();
  Send(0xa0);
  Ack();
  Send(Address+i);
  Ack();
  Send(*(PData+i));
  Ack();
  Stop();
  mDelay(20);
  }
}
/********************************************************************************/
void RdFromROM(uchar Data[],uchar Address,uchar Num)
{
  uchar i;
  uchar *PData;
  PData=Data;
  for(i=0;i<Num;i++)
  {
  Start();
  Send(0xa0);
  Ack();
  Send(Address+i);
  Ack();
  Start();
  Send(0xa1);
  Ack();
  *(PData+i)=Read();
  //Scl=0;
  PORTC&=~BIT(0);
  NoAck();
  Stop();
  }
}
//**********************************LCD1602*********************************************//
#define yi 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1100000000=80
#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40
//*********************************************************************************************//
void delay(uint xms)//延时函数,有参函数
{
uint x,y;
for(x=xms;x>0;x--)
 for(y=110;y>0;y--);
}
/**********************************写指令****************************************/
write_1602com(uchar com)//****液晶写入指令函数****
{
PORTD&=~BIT(4);////数据/指令选择置为指令
PORTD&=~BIT(5);////读写选择置为写
PORTB=com;//送入数据
delay(1);
PORTD|=BIT(6);//拉高使能端,为制造有效的下降沿做准备
delay(1);
PORTD&=~BIT(6);//en由高变低,产生下降沿,液晶执行命令
}
/**********************写数据*****************************************************/
write_1602dat(uchar dat)//***液晶写入数据函数****
{
PORTD|=BIT(4);//////数据/指令选择置为数据
PORTD&=~BIT(5);////读写选择置为写
PORTB=dat;//送入数据
delay(1);
PORTD|=BIT(6);////en置高电平,为制造下降沿做准备
delay(1);
PORTD&=~BIT(6);////en由高变低,产生下降沿,液晶执行命令
}
/************************************初始化***************************************/
void lcd_init(void)
{
write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据
write_1602com(0x0c);//开显示不显示光标
write_1602com(0x06);//整屏不移动,光标自动右移
write_1602com(0x01);//清显示
}
/*******************************************将按键值编码为数值*************************/
uchar coding(uchar m)  
{
uchar k;
switch(m)
{
case (0x18): k=1;break;
case (0x28): k=2;break;
case (0x48): k=3;break;
case (0x88): k='A';break;
case (0x14): k=4;break;
case (0x24): k=5;break;
case (0x44): k=6;break;
case (0x84): k='B';break;
case (0x12): k=7;break;
case (0x22): k=8;break;
case (0x42): k=9;break;
case (0x82): k='C';break;
case (0x11): k='*';break;
case (0x21): k=0;break;
case (0x41): k='#';break;
case (0x81): k='D';break;
}
return(k);
}
/******************************按键检测并返回按键值*************************************/
uchar keynum(void)
{
  uchar row,col,i;
DDRD=0x0F;
PORTD=0xF0;
//KeyRead=PIND; //读取键盘结果
//KeyRead&=0x0f; //屏蔽高四位
  //if((P1&0xf0)!=0xf0)
if((PIND&0xf0)!=0xf0)
  {
    Delay5Ms();
        Delay5Ms();
    if((PIND&0xf0)!=0xf0)
{          
row=PIND^0xf0; //确定行线
i=0;           
PORTD=a[i];////精确定位
while(i<4)
{
  if((PIND&0xf0)!=0xf0)
   {
    col=~(PIND&0xff);   //确定列线
    break;            //已定位后提前退出   
}
else 
   {
    i++;
PORTD=a[i];
   }
}
}
else 
{
return 0;
}
while((PORTD&0xf0)!=0xf0);
return (row|col);   //行线与列线组合后返回
  }
  else return 0;           //无键按下时返回0
}
/********************************一声提示音,表示有效输入*************************************/
void OneAlam(void)
{
PORTA&=~BIT(6);//
Delay5Ms();
PORTA|=BIT(6);//
}
/*********************************二声提示音,表示操作成功*********************************/
void TwoAlam(void)
{
PORTA&=~BIT(6);//
Delay5Ms();
PORTA|=BIT(6);//
    Delay5Ms();
PORTA&=~BIT(6);//
Delay5Ms();
PORTA|=BIT(6);//
}
/*******************************三声提示音,表示错误************************************/
void ThreeAlam(void)
{
PORTA&=~BIT(6);//
Delay5Ms();
PORTA|=BIT(6);//
    Delay5Ms();
PORTA&=~BIT(6);//
Delay5Ms();
PORTA|=BIT(6);//
    Delay5Ms();
PORTA&=~BIT(6);//
Delay5Ms();  
PORTA|=BIT(6);//
}
/*****************显示输入的N个数字,用H代替以便隐藏*************************************/
void DisplayOne(void)
{
// DisplayOneChar(9+N,1,'*');
write_1602com(yi+5+N);
write_1602dat('*');
}
/***********************************显示提示输入**************************************/
void DisplayChar(void)
{
unsigned char i;
if(pass==1)
{
//DisplayListChar(0,1,LockOpen);
write_1602com(er);
for(i=0;i<16;i++)
{
write_1602dat(LockOpen[i]);
}
}
else

{
if(N==0)
{
//DisplayListChar(0,1,Error);
write_1602com(er);
for(i=0;i<16;i++)
{
write_1602dat(Error[i]);
}
}
else
{
//DisplayListChar(0,1,start_line);
write_1602com(er);
for(i=0;i<16;i++)
{
write_1602dat(start_line[i]);
}
}
}
}
/**************************************************************************************/
void DisplayInput(void)
{
uchar i;
if(CorrectCont==1)
{
//DisplayListChar(0,0,Input);
write_1602com(er);
for(i=0;i<16;i++)
{
write_1602dat(Input[i]);
}
}
}
/******************************************重置密码*******************************/
void ResetPassword(void)
{
uchar i;
uchar j;
if(pass==0)
{
pass=0;
DisplayChar();
ThreeAlam();
}
else
{
     if(ReInputEn==1)
{
if(N==6)
{
ReInputCont++;
if(ReInputCont==2)
{
for(i=0;i<6;)
{
if(TempPassword[i]==InputData[i]) //将两次输入的新密码作对比
i++;
else
{
//DisplayListChar(0,1,Error);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(Error[j]);
}
ThreeAlam(); //错误提示
pass=0;
ReInputEn=0; //关闭重置功能,
ReInputCont=0;
DisplayChar();
break;
}
}
if(i==6)
{
//DisplayListChar(0,1,ResetOK);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(ResetOK[j]);
}
TwoAlam(); //操作成功提示
  WrToROM(TempPassword,0,6); //将新密码写入24C02存储/////////
ReInputEn=0;
}
ReInputCont=0;
CorrectCont=0;
}
else
{
OneAlam();
//DisplayListChar(0, 1, again); //显示再次输入一次
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(again[j]);
}
for(i=0;i<6;i++)
{
TempPassword[i]=InputData[i]; //将第一次输入的数据暂存起来
}
}
N=0; //输入数据位数计数器清零
   }
    }
}
}

/****************************输入密码错误超过三过,报警并锁死键盘********************************/
void Alam_KeyUnable(void)
{
PORTD=0x00;//
{
PORTA^=BIT(6);//
Delay5Ms();
}
}
/*************************************取消所有操作***********************/
void Cancel(void)
{
uchar i;
uchar j;
//DisplayListChar(0, 1, start_line);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(start_line[j]);
}
TwoAlam(); //提示音
for(i=0;i<6;i++)
{
InputData[i]=0;
}
PORTB|=BIT(7);//关闭锁
PORTA|=BIT(6);//报警关
operation=0; //操作标志位清零
pass=0; //密码正确标志清零
ReInputEn=0; //重置输入充许标志清零
ErrorCont=0; //密码错误输入次数清零
CorrectCont=0; //密码正确输入次数清零
ReInputCont=0; //重置密码输入次数清零
PORTB|=BIT(5);
s3_keydown=0;
key_disable=0;
N=0; //输入位数计数器清零
}
/*******************************确认键,并通过相应标志位执行相应功能************************/
void Ensure(void)
{
uchar i,j;
RdFromROM(CurrentPassword,0,6); //24C02里读出存储密码
    if(N==6)
{
    if(ReInputEn==0) //重置密码功能未开启
{
for(i=0;i<6;)
    {
if(CurrentPassword[i]==InputData[i])
{
i++;
}
else 
{
ErrorCont++;
if(ErrorCont==3) //错误输入计数达三次时,报警并锁定键盘
{
write_1602com(er);
for(i=0;i<16;i++)
{
write_1602dat(Error[i]);
}
do
Alam_KeyUnable();
while(1);
}
else
{
TIMSK|=BIT(2); //开启定时

key_disable=1; //锁定键盘
pass=0;
break;
}
}
}
if(i==6)
{
CorrectCont++;
if(CorrectCont==1) //正确输入计数,当只有一次正确输入时,开锁,
{
//DisplayListChar(0,1,LockOpen);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(LockOpen[j]);
}
TwoAlam(); //操作成功提示音
PORTB&=~BIT(7);//开锁///////////////////////////////////
pass=1; //置正确标志位
TIMSK|=BIT(2); //开启定时/////////////////////////
PORTB&=~BIT(5);//开锁指示灯亮//////////////////////////////
for(j=0;j<6;j++) //将输入清除
{
InputData[i]=0;
}
}
else //当两次正确输入时,开启重置密码功能
{
//DisplayListChar(0,1,SetNew);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(SetNew[j]);
}
TwoAlam();     //操作成功提示
ReInputEn=1; //允许重置密码输入
CorrectCont=0; //正确计数器清零
}
   }

else //============当第一次使用或忘记密码时可以用131420对其密码初始化

{
if((InputData[0]==1)&&(InputData[1]==3)&&(InputData[2]==1)&&(InputData[3]==4)&&(InputData[4]==2)&&(InputData[5]==0))
     {
WrToROM(initpassword,0,6); //强制将初始密码写入24C02存储
//DisplayListChar(0,1,initword); //显示初始化密码
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(initword[j]);
}
TwoAlam();
Delay400Ms();
TwoAlam();
N=0;
}
else
{
//DisplayListChar(0,1,Error);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(Error[j]);
}
  ThreeAlam(); //错误提示音
pass=0;
}
}
}
else //当已经开启重置密码功能时,而按下开锁键,
{
//DisplayListChar(0,1,Er_try);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(Er_try[j]);
}
ThreeAlam();
}
}
else
{
//DisplayListChar(0,1,Error);
write_1602com(er);
for(j=0;j<16;j++)
{
write_1602dat(Error[j]);
}
  ThreeAlam(); //错误提示音
pass=0;
}
N=0; //将输入数据计数器清零,为下一次输入作准备
operation=1;
}
/********************************************************************************************/
void main(void)
{
  uchar KEY,NUM;
uchar i,j;
segg();
port_init();
Delay400Ms(); //启动等待,等LCM讲入工作状态
  lcd_init(); //LCD初始化
write_1602com(yi);//日历显示固定符号从第一行第0个位置之后开始显示
PORTD=0xFF;
TCCR1B=0X05;//1024分频//5ms
TCNT1H=0XFF;//
TCNT1L=0XC5;//
TIMSK|=BIT(2);
SREG|=BIT(7);
for(i=0;i<16;i++)
{
write_1602dat(name[i]);//向液晶屏写日历显示的固定符号部分
}
write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示
for(i=0;i<16;i++)
{
write_1602dat(start_line[i]);//写显示时间固定符号,两个冒号
}
write_1602com(er+9); //设置光标位置
write_1602com(0x0f); //设置光标为闪烁
  Delay5Ms(); //延时片刻(可不要)
  N=0; //初始化数据输入位数
  while(1)
  {
if(key_disable==1)
Alam_KeyUnable();
else
PORTA|=BIT(6); //关报警
KEY=keynum();
if(KEY!=0)
{
if(key_disable==1)
{
second=0;
}
else
{
NUM=coding(KEY);
{
switch(NUM)
{
case ('A'): ; break;
case ('B'): ;      break;
case ('C'): ; break;
case ('D'): ResetPassword(); break;      //重新设置密码
case ('*'): Cancel(); break;      //取消当前输入
case ('#'): Ensure(); break;    //确认键,
default:
{
//DisplayListChar(0,1,Input);
write_1602com(er);
for(i=0;i<16;i++)
{
write_1602dat(Input[i]);
}
    operation=0;
if(N<6)    //当输入的密码少于6位时,接受输入并保存,大于6位时则无效。
{  
OneAlam(); //按键提示音
//DisplayOneChar(6+N,1,'*');
  for(j=0;j<=N;j++)
{
write_1602com(er+6+j);
write_1602dat('*');
}
InputData[N]=NUM;
N++;
}
else //输入数据位数大于6后,忽略输入
{
N=6;
  break;
}
}
}
}
}
  }
}
}
/*********************************中断服务函数*****************************************/
#pragma interrupt_handler init:9
void  time0_int(void)
{
  TCNT1H=0xFF;//
TCNT1L=0xC5;//
  //TR0=1;
  countt0++;
   if(countt0==20)
    {
countt0=0;
second++;
if(pass==1)
{
if(second==1)
{
PORTB|=BIT(5);//关指示灯
TIMSK=0x00; //关定时器
TCNT1H=0xFF;//
            TCNT1L=0xC5;//
second=0;
}
}
else
{
if(second==3)
{
TIMSK=0x00;
second=0;
key_disable=0;
s3_keydown=0;
TCNT1H=0xFF;//
            TCNT1L=0xC5;//
}
else
    TIMSK|=BIT(2);
}

    }
}


本帖有更多资源,需 登录 才可以下载,没有帐号?立即 注册

(0 ) (0 )
回复 举报

回复于 2019-10-26 沙发

谢谢分享
(0 )
评论 (1) 举报

回复于 2019-10-28 2#

thanks
(0 )
评论 (1) 举报

回复于 2019-10-29 3#

感谢分享,欢迎关注我,资料持续更新中。有需要机械臂,电源,硬件电路设计,软件编程,开发板等各种定制的可以私聊我哦,相互学习,共同进步
(0 )
评论 (1) 举报

回复于 2023-12-08 4#

非常感谢!!
(0 )
评论 (0) 举报
  • 发表回复
    0/3000





    举报

    请选择举报类别

    • 广告垃圾
    • 违规内容
    • 恶意灌水
    • 重复发帖

    全部板块

    返回顶部