標(biāo)題:
51單片機密碼鎖程序 存儲在I2C 密碼掉電不丟失
[打印本頁]
作者:
fqs_lda
時間:
2024-12-19 19:43
標(biāo)題:
51單片機密碼鎖程序 存儲在I2C 密碼掉電不丟失
設(shè)計內(nèi)容:
1、密碼存儲在I2C器件中,實現(xiàn)密碼掉電不丟失。
2、電路板一上電四個數(shù)碼管顯示“-“
3、實現(xiàn)數(shù)字鍵0-9和功能鍵的設(shè)計:
4、四個功能鍵:
(1)密碼輸入
(2)退出
(3)密碼修改:當(dāng)密碼密碼修改鍵按下,若輸入密碼正確后,按下此鍵時,將修改的密碼進(jìn)行存儲。輸入密碼正確顯示”8888“
輸入失敗顯示”HHHH“
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
1734608550065.jpg
(112.87 KB, 下載次數(shù): 0)
下載附件
2024-12-19 19:43 上傳
單片機源程序如下:
#include <reg51.h>
#include <intrins.h>
#include <string.h>
typedef unsigned char u8;
typedef unsigned int u16;
#define SMG_PORT P0
#define KEY_MATRIX_PORT P1
#define AT24C02_ADDRESS 0xA0
u8 gsmg_code[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f,0x40,0x76};//0-9 "-" "H"
u8 e_mima[4] = {1, 2, 3, 4}; // 初始密碼是1234
u8 read_mima[4];
u8 entered_password[4]; // 存儲用戶輸入的密碼
u8 input_index = 0;
u8 key = 0;
u8 wei=0;
u8 panduan=0;//判斷密碼是否正確
u8 state=0;
u8 xiugai=0;
u8 wdata=0;
u8 show_h=0;
sbit led=P2^7;
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
sbit sda=P2^0;
sbit scl=P2^1;
u8 chushi = 1;
//@11.0592MHz
void Delay10ms()
{
unsigned char i, j;
i = 108;
j = 145;
do
{
while (--j);
} while (--i);
}
//@11.0592MHz
void delay_us(unsigned int us)
{
unsigned int i;
while(us--)
{
i = 11; // 11 是根據(jù) 11.0592MHz 晶振頻率調(diào)整的數(shù)值
while (--i);
}
}
void delayms(u16 x)
{
u8 i;
while(x--)
{
for(i=150;i>0;i--);
}
}
void nop()
{
_nop_();
_nop_();
}
/////////24C02讀寫驅(qū)動程序////////////////////
void delay1(unsigned int m)
{ unsigned int n;
for(n=0;n<m;n++);
}
void init() //24c02初始化子程序
{
scl=1;
nop();
sda=1;
nop();
}
void start() //啟動I2C總線
{
sda=1;
nop();
scl=1;
nop();
sda=0;
nop();
scl=0;
nop();
}
void stop() //停止I2C總線
{
sda=0;
nop();
scl=1;
nop();
sda=1;
nop();
}
void writebyte(unsigned char j) //寫一個字節(jié)
{
unsigned char i,temp;
temp=j;
for (i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
nop();
sda=CY; //temp左移時,移出的值放入了CY中
nop();
scl=1; //待sda線上的數(shù)據(jù)穩(wěn)定后,將scl拉高
nop();
}
scl=0;
nop();
sda=1;
nop();
}
unsigned char readbyte() //讀一個字節(jié)
{
unsigned char i,j,k=0;
scl=0; nop(); sda=1;
for (i=0;i<8;i++)
{
nop(); scl=1; nop();
if(sda==1)
j=1;
else
j=0;
k=(k<<1)|j;
scl=0;
}
nop();
return(k);
}
void clock() //I2C總線時鐘
{
unsigned char i=0;
scl=1;
nop();
while((sda==1)&&(i<255))
i++;
scl=0;
nop();
}
////////從24c02的地址address中讀取一個字節(jié)數(shù)據(jù)/////
unsigned char read24c02(unsigned char address)
{
unsigned char i;
start();
writebyte(0xa0);
clock();
writebyte(address);
clock();
start();
writebyte(0xa1);
clock();
i=readbyte();
stop();
delay1(10);
return(i);
}
//////向24c02的address地址中寫入一字節(jié)數(shù)據(jù)info/////
void write24c02(unsigned char address,unsigned char info)
{
start();
writebyte(0xa0);
clock();
writebyte(address);
clock();
writebyte(info);
clock();
stop();
delay1(50);
}
u8 key_matrix_ranks_scan(void)
{
u8 key_value = 0;
KEY_MATRIX_PORT = 0xf7; //第一列為低電平
if (KEY_MATRIX_PORT!= 0xf7) //有按鍵按下
{
Delay10ms();
switch(KEY_MATRIX_PORT)
{
case 0x77: key_value = 1; break; //S1按下時
case 0xb7: key_value = 4; break;
case 0xd7: key_value = 7; break;
case 0xe7: key_value = 10; break;
}
}
while(KEY_MATRIX_PORT!= 0xf7); //等待釋放,當(dāng)按鍵按下時KEY值不等于0xf7,一直循環(huán),當(dāng)按鍵釋放時,KEY等于0xf7,跳出循環(huán)
KEY_MATRIX_PORT = 0xfb; //第二列為低電平
if (KEY_MATRIX_PORT!= 0xfb) //有按鍵按下
{
Delay10ms();
switch(KEY_MATRIX_PORT)
{
case 0x7b: key_value = 2; break;
case 0xbb: key_value = 5; break;
case 0xdb: key_value = 8; break;
case 0xeb:/* key_value = 11;*/ break;
}
}
while(KEY_MATRIX_PORT!= 0xfb);
KEY_MATRIX_PORT = 0xfd; //第三列為低電平
if (KEY_MATRIX_PORT!= 0xfd) //有按鍵按下
{
Delay10ms();
switch(KEY_MATRIX_PORT)
{
case 0x7d: key_value = 3; break;
case 0xbd: key_value = 6; break;
case 0xdd: key_value = 9; break;
case 0xed:/* key_value = 12; */break;
}
}
while(KEY_MATRIX_PORT!= 0xfd);
KEY_MATRIX_PORT = 0xfe; //第四列為低電平
if (KEY_MATRIX_PORT!= 0xfe)
{
Delay10ms();
switch(KEY_MATRIX_PORT)
{
case 0x7e: key_value = 13; break; //S1按鍵按下時
case 0xbe: key_value = 14; break;
case 0xde: key_value = 15; break;
case 0xee: key_value = 16; break;
}
}
while(KEY_MATRIX_PORT!= 0xfe);
return key_value;
}
// 顯示單個數(shù)字到指定的數(shù)碼管位
void display_on_smg(u8 num, u8 pos)
{
switch (pos)
{
case 1: LSC = 1; LSB = 1; LSA = 1; break; // 第1位
case 2: LSC = 1; LSB = 1; LSA = 0; break; // 第2位
case 3: LSC = 1; LSB = 0; LSA = 1; break; // 第3位
case 4: LSC = 1; LSB = 0; LSA = 0; break; // 第4位
}
SMG_PORT = 0x00;
SMG_PORT = gsmg_code[num];
delay_us(5);
SMG_PORT = 0x00;
}
void clear_display(void)
{
LSC = 1; LSB = 0; LSA = 0;
SMG_PORT = 0x00; // 清空顯示
}
void show_8888(void)
{
display_on_smg(8,1);
display_on_smg(8,2);
display_on_smg(8,3);
display_on_smg(8,4);
}
void show_HHHH(void)
{
display_on_smg(11,1);
display_on_smg(11,2);
display_on_smg(11,3);
display_on_smg(11,4);
}
void show____(void)
{
display_on_smg(10,1);
display_on_smg(10,2);
display_on_smg(10,3);
display_on_smg(10,4);
}
//輸入密碼
void import_ss()
{
u8 i;
for (i = 0; i < 4; i++)
{
e_mima[i] = read_mima[i];
}
if (key!= 0 && key!=13 && key!=14 && key!=15 && key!=16)
{
wei++;
entered_password[input_index] = key-1;
input_index++;
if (input_index >= 4)
{
input_index = 0;
}
}
if(wei==1)
{
display_on_smg(10, 1);
}
else if(wei==2)
{
display_on_smg(10, 1);
display_on_smg(10, 2);
}
else if(wei==3)
{
display_on_smg(10, 1);
display_on_smg(10, 2);
display_on_smg(10, 3);
}
else if(wei==4)
{
display_on_smg(10, 1);
display_on_smg(10, 2);
display_on_smg(10, 3);
display_on_smg(10, 4);
panduan=1;
wei=0;
}
if(panduan==1)
{
if(panduan==1)
{
// 比較密碼
if (entered_password[0] == e_mima[0] && entered_password[1] == e_mima[1] && entered_password[2] == e_mima[2] && entered_password[3] == e_mima[3])
{
show_8888();
led=0;
}
else
{
show_HHHH();
led=1;
}
}
}
}
// 密碼修改
void xiugai_ss(void)
{
u8 i,j;
for (i = 0; i < 4; i++)
{
e_mima[i] = read_mima[i];
}
if (key!= 0 && key!= 13 && key!= 14 && key!= 15 && key!= 16)
{
entered_password[input_index] = key - 1;
input_index++;
if (input_index >= 4)
{
if (state == 0)
{
// 輸入原密碼階段
if (entered_password[0] == e_mima[0] && entered_password[1] == e_mima[1] && entered_password[2] == e_mima[2] && entered_password[3] == e_mima[3])
{
state = 1; // 原密碼正確,進(jìn)入輸入新密碼狀態(tài)
input_index = 0;
clear_display();
led=0;
show_h=0;
}
else
{
show_h=1;
state = 0;
input_index = 0;
}
}
else if (state == 1)
{
// 輸入新密碼階段
if (input_index == 4 )
{
// 輸入新密碼階段
if (input_index == 4)
{
state = 2; // 輸入新密碼完成,進(jìn)入確認(rèn)狀態(tài)
input_index = 0;
}
}
}
}
}
// 顯示已輸入的密碼
for (j = 0; j < input_index; j++)
{
display_on_smg(10, j + 1);
}
if (state == 2 && key == 16)
{
led=1;
// 確認(rèn)修改密碼
for (i = 0; i < 4; i++)
{
e_mima[i] = entered_password[i];
}
wdata=1;
show_8888();
state = 0;
input_index = 0;
chushi = 1;
xiugai = 0;
show____(); // 修改完成后返回初始界面顯示
}
}
void main()
{
u8 i;
led=1;
init(); //初始化24C02
// 上電從 24C02 讀取數(shù)據(jù)
for (i = 0; i < 4; i++)
{
read_mima[i] = read24c02(i);
delayms(3);
}
while(1)
{
// 上電從 24C02 讀取數(shù)據(jù)
for (i = 0; i < 4; i++)
{
read_mima[i] = read24c02(i);
delayms(3);
}
if(wdata==1)
{
write24c02(0, entered_password[0]); // 將修改后的密碼發(fā)送給 24C02
delayms(3);
write24c02(1, entered_password[1]);
delayms(3);
write24c02(2, entered_password[2]);
delayms(3);
write24c02(3, entered_password[3]);
delayms(3);
wdata=0;
}
if(show_h==1)
{
show_HHHH();
}
key = key_matrix_ranks_scan();
if (key == 13)//輸入鍵
{
chushi = 0;
panduan=0;
clear_display();
}
if(key==14)//退出鍵
{
chushi=1;
}
if(key==15)//密碼修改
{
show_h=0;
chushi=2;
panduan=0;
clear_display();
}
if(key==16)
{
xiugai=1;
}
if(chushi==1)
{
show____();
led=1;
}
else if (chushi == 0)
{
import_ss();
}
else if(chushi==2)
{
xiugai_ss();
}
}
}
復(fù)制代碼
仿真程序.7z
(222.12 KB, 下載次數(shù): 0)
2024-12-19 22:06 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
wkman
時間:
2025-1-22 09:10
mcu 有 IAP功能,當(dāng)eeprom 可
省略iic的24c
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1