A. c語言題目 鎖屏密碼,如何避免時間超時,簡潔的方法
這就是一道模擬題,不涉及什麼演算法,不大可能超時。如果超時可能是你方法不對。
#include<stdio.h>
int main()
{
char s[20];
int n;
while(scanf("%d", &n), n!=0)
{
scanf("%s", s);
for(int i=0; i<n; i++)
{
int j = (s[i]-(s[i]<'s'?'a':'b'))/3+2;
if(j>9) j=9;
printf("%d", j);
}
printf("\n");
}
return 0;
}
B. 用單片機C語言控制6位密碼鎖。要求有一個清除鍵和確認鍵,密碼輸錯了會有報警音。請高手幫助了
我找到了一個,來自《51單片機C語言應用技術開發大全》
SCH圖正在繪制中。。。
#include <REGX51.H>//51單片機的頭文件
typedef unsigned char uchar; //類型定義,定義uchar類型
typedef unsigned int uint; //類型定義,定義uint 類型
//鍵盤子程序相關說明。
#define BLANKCHAR 10 //定義空白常量
#define PCHAR 11 //定義字元P常量
#define OPENCHAR 12 //定義開鎖字元常量
#define ALARMCHAR 13 //定義字元A常量
#define LINECHAR 14 //定義字元-常量
#define BACKKEY 0X0D //定義退格鍵常量
#define ENTERKEY 0X0F //定義確認鍵常量
#define LOCKKEY 0X0E //定義閉鎖鍵常量
#define NO_KEY 20 //定義無按鍵返回值
#define KEYPORT P2 //定義鍵盤埠
//Delay1Ms
void Delay1Ms()
{
uint i;
for (i=0;i<1000;i++);
}
//定義按鍵掃描碼表 按鍵掃描時,4位列線和4位行線組成位元組數據表
uchar code KEYCODE[]=
{0XEE,0XED,0XEB,0XE7,
0XDE,0XDD,0XDB,0XD7,
0XBE,0XBD,0XBB,0XB7,
0X7E,0X7D,0X7B,0X77};
uchar KeyPre; //保存上次掃描按鍵的鍵值
uchar KeyUp;
//用於控制按鍵去抖動操作。1:掃描時去抖動 2:等待釋放 3:釋放時去抖動。
#define LEDPORT P0 //定義顯示器段碼輸出埠
#define LEDCON P1 //定義顯示器位控制埠
uchar code SEGCODE[]=
{0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,// 0~9的共陽極代碼
0xff,//不顯示的共陽極段碼
0X8C,//字元P的共陽極段碼
0X8F,//┝的共陽極段碼
0X88,//字元A的共陽極段碼
0XBF,//字元-的共陽極段碼
};
//定義LED位碼控制碼
uchar code BITCODE[]={0Xfe,0Xfd,0Xfb,0Xf7,0Xef,0Xdf,0Xbf,0X7f};
uchar DispBuf[6]; //保存顯示的字元
bit DispNormal; //控制顯示時,是正常顯示還是閃爍顯示。
uchar DispCnt; //控制閃爍顯示時的頻率。
#define SHORT_TIME 10 //蜂鳴器響200ms
#define LONG_TIME 100 //蜂鳴器響2s
#define LONGER_TIME 9000 //蜂鳴器響3 minutes
sbit ALARMCON=P3^4; //定義報警控制引腳
bit AlarmEnable; //是否報警或聲音提示
uint AlarmTime; //控制報警時間長度
sbit LOCKCON=P3^3; //定義電子鎖控制引腳
uchar code PassWord[]={1,2,3,4,5}; //定義初時密碼表
uchar PassInBuf[6]; //保存輸入的密碼字元
uchar PassPosi; //用戶輸入密碼字元存放在PassInBuf[]的位置。
bit TimerBit; //20ms定時時間到
uchar SysMode; //系統所處模式 0:輸入密碼模式 1:報警模式 2:開鎖模式
uchar ErrorCnt; //用戶連續輸入密碼出錯次數。
/*
入口參數:
FillChar:寫入緩沖區的字元
出口參數:無
*/
void Fill_Buf(uchar FillChar)
{
uchar i;
for(i=0;i<6;i++)
{
DispBuf[i]=FillChar;//用字元FillChar填充DispBuf[i]
PassInBuf[i]=FillChar; //用字元FillChar填充PassInBuf [i]
}
}
void Fill_Buf_P()
{
Fill_Buf(BLANKCHAR); // DispBuf[1..5]= ' '
DispBuf[0]=PCHAR;// DispBuf[0]='P'
}
void Fill_Buf_O()
{
Fill_Buf(BLANKCHAR); // DispBuf[1..5]= ' '
DispBuf[0]=OPENCHAR; // DispBuf[0]='┝'
}
void Fill_Buf_A()
{
Fill_Buf(LINECHAR); // DispBuf[1..5]= ' -----'
DispBuf[0]=ALARMCHAR; // DispBuf[0]='A'
}
/*
入口參數:
DispPosi:要顯示數據的LED號。
DispChar:要顯示的內容。
出口參數:無
*/
void Disp_Led_Sin(uchar DispChar,uchar DispPosi)
{
LEDPORT=SEGCODE[DispChar];//輸出顯示段碼
LEDCON&=BITCODE[DispPosi];//輸出顯示位碼
Delay1Ms(); //延時1MS
LEDCON|=0X3F;//關閉顯示器
}
/*(2)關閉顯示函數Disp_Led_OFF。
函數Disp_Led_OFF在顯示器上顯示空白字元,主要用在閃爍顯示。函數通過6次調用Disp_Led_Sin實現所需功能。代碼如下:*/
void Disp_Led_OFF()
{
uchar i;
LEDCON|=0X3F;// 關閉顯示器
for(i=0;i<6;i++)
{
Disp_Led_Sin(BLANKCHAR,i);//逐個顯示空白字元
}
}
void Disp_Led_All()
{
uchar i;
LEDCON|=0X3F; // 關閉顯示器
for(i=0;i<6;i++)
{
Disp_Led_Sin(DispBuf[i],i); //顯示DispBuf[]中的數值
}
}
void Disp_LED()
{
DispCnt++;
DispCnt%=10;
if(DispCnt==0)
{
DispNormal=~DispNormal;//200ms將閃爍顯示控制位取反
}
if(SysMode==1)
{//報警模式,閃爍顯示
if(!DispNormal)
{
Disp_Led_OFF();//顯示空白字元
return;
}
}
Disp_Led_All();//顯示DispBuf[]中的數值
}
/*
入口參數:
stime:蜂鳴器鳴叫時間。
出口參數:無
*/
void Sys_Speaker(uint stime)
{
AlarmEnable=1;//允許報警
AlarmTime=stime;//報警時間長短
}
void Sys_Alarm()
{
if(AlarmEnable==1)
{//允許報警
ALARMCON=0;//報警
AlarmTime--;
if(AlarmTime==0)
{//停止報警時間到
AlarmEnable=0;
ALARMCON=1;//禁止報警
if(SysMode==1)
{//報警發生在模式1時,要返回模式0
SysMode=0;
Fill_Buf_P();//顯示P
}
}
}
}
/*
入口參數:無
出口參數:按鍵值或無按鍵
*/
uchar Find_Key()
{
uchar KeyTemp,i;
KEYPORT=0xf0;//行線輸出0,列線輸出全1
KeyTemp=KEYPORT;//讀按鍵埠值
if(KeyTemp==0xf0)
return NO_KEY;//無鍵按下,返回
KEYPORT=KeyTemp|0x0f;//列線輸出,行線輸入
KeyTemp=KEYPORT;//讀取按鍵埠值
for(i=0;i<16;i++)
{
if(KeyTemp==KEYCODE[i])//根據按鍵埠掃描值,查找按鍵值
return i;//返回按鍵值
}
return NO_KEY;
}
/*
入口參數:無
出口參數:按鍵值或無按鍵
*/
uchar Scan_Key()
{
uchar KeyTemp;
KeyTemp=Find_Key();//掃描鍵盤,獲得按鍵值
if(KeyTemp==NO_KEY)
{
if(KeyUp<2)
{//無按鍵按下,返回
KeyUp=0;
return NO_KEY;
}
if(KeyUp==2)
{//按鍵要釋放,延時去抖動
KeyUp=3;
return NO_KEY;
}
if(KeyUp==3)
{//按鍵釋放,返回鍵值
KeyUp=0;
return KeyPre;
}
}
else
{
if(KeyUp==0)
{//有鍵按下,保存鍵值
KeyUp=1;
KeyPre=KeyTemp;
}
else if(KeyUp==1)
{//去抖動後,再次測到有按鍵按下
if( KeyPre==KeyTemp)
KeyUp=2;
else
KeyPre=KeyTemp;
} else if(KeyUp==3)
{//等待按鍵釋放
KeyUp=2;
}
}
return NO_KEY;
}
/*
入口參數:
Key:按鍵值
出口參數:無
*/
void Key_Process(uchar Key)
{
uchar i;
if(Key==NO_KEY)
return ;//無按鍵,不處理
switch(SysMode)
{
case 0://輸入密碼
switch(Key)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
DispBuf[PassPosi]=LINECHAR;//顯示'-'
PassInBuf[PassPosi]=Key;//保存用戶輸入的密碼
if(PassPosi<5)
PassPosi++;//調整密碼輸入位置
Sys_Speaker(SHORT_TIME);//發按鍵提示音
break;
case BACKKEY://退格鍵
DispBuf[PassPosi]=BLANKCHAR;//顯示' '
PassInBuf[PassPosi]=BLANKCHAR;//清除當前位置的密碼
if(PassPosi>1)
PassPosi--;//調整顯示位置
Sys_Speaker(SHORT_TIME);//發按鍵提示音
break;
case ENTERKEY://確定按鍵
for(i=0;i<5;i++)
{//比較用戶輸入密碼與系統預設密碼是否一致
if(PassInBuf[i+1]!=PassWord[i])
break;
}
if(i>=5)
{//輸入密碼正確
Fill_Buf_O();//顯示開鎖狀態
PassPosi=1;
LOCKCON=1;//開鎖
ErrorCnt=0;
Sys_Speaker(LONG_TIME);//發長提示音
SysMode=2;//轉模式2
}
else
{
ErrorCnt++;//出錯次數加一
if(ErrorCnt>2)
{//次數超過3次
ErrorCnt=0;
Fill_Buf_A();//顯示報警狀態
PassPosi=1;
Sys_Speaker(LONGER_TIME);//發報警音
SysMode=1;
}
else
{//出錯次數少於3次,用戶重新輸入
Fill_Buf_P();
PassPosi=1;
Sys_Speaker(LONG_TIME);
}
}
break;
case LOCKKEY://閉鎖鍵
Fill_Buf_P();//顯示P
PassPosi=1;
Sys_Speaker(SHORT_TIME);
break;
}
break;
case 2://開鎖狀態
if(Key==LOCKKEY)
{//用戶按動閉鎖按鍵
Fill_Buf_P();
SysMode=0;
LOCKCON=0;//閉鎖
Sys_Speaker(SHORT_TIME);
}
break;
}
}
void Ini_Timer0()
{
TMOD&=0XF0;
TMOD|=0X01;// 初始化T0,模式1
TR0=0;
TH0=(65536-20000)/256;//T0 賦計數初值
TL0=(65536-20000)%256;
TR0=1;//啟動T0
ET0=1;//允許T0中斷
}
void Timer0() interrupt 1
{
TR0=0;
TH0=(65536-20000)/256; //T0 賦計數初值
TL0=(65536-20000)%256;
TR0=1;
TimerBit=1;//定時時間到
}
void Ini_System()
{
PassPosi=1;
LOCKCON=0;//閉鎖
Ini_Timer0();//初始化T0
Fill_Buf_P();
EA=1;//允許系統中斷
}
void main()
{
uchar KeyTemp;
Ini_System();
while(1)
{
if (TimerBit==1)
{//定時時間到
Disp_LED();//刷新顯示器
Sys_Alarm();//報警處理
KeyTemp=Scan_Key();//掃描按鍵
Key_Process(KeyTemp);//按鍵處理
TimerBit=0;
}
}
}
C. c語言單片機密碼鎖控製程序,用4個按鍵輸入狀態分別代表4位二進制數,可組成16種密碼,范圍0000
用51單片機,假設p1·0至p1·3接4個開關,P2·0接開鎖按鍵S1
While(s1!=0);//等待按開鎖按鈕
delayms(10);//延時
While(s1==0);//等待按鍵抬起
mima=0x0F&P1;//讀取P1低4位
if(mima==12)lock=1;//如果與設定密碼相等開鎖
else Fmq=1;//否則,報警
D. 單片機c語言密碼鎖程序
include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#define DataPort P0 //定義數據埠 程序中遇到DataPort 則用P0 替換
#define KeyPort P1
sbit LATCH1=P2^2;//定義鎖存使能埠 段鎖存
sbit LATCH2=P2^3;// 位鎖存
unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};// 顯示段碼值0~F
unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分別對應相應的數碼管點亮,即位碼
unsigned char TempData[10]; //存儲顯示值的全局變數
unsigned char code password[8]={1,2,3,4,5,6,7,8};
//可以更改此密碼做多組測試
void DelayUs2x(unsigned char t);//us級延時函數聲明
void DelayMs(unsigned char t); //ms級延時
void Display(unsigned char FirstBit,unsigned char Num);//數碼管顯示函數
unsigned char KeyScan(void);//鍵盤掃描
unsigned char KeyPro(void);
void Init_Timer0(void);//定時器初始化
/*------------------------------------------------
主函數
------------------------------------------------*/
void main (void)
{
unsigned char num,i,j;
unsigned char temp[8];
bit Flag;
Init_Timer0();
while (1) //主循環
{
num=KeyPro();
if(num!=0xff)
{
if(i==0)
{
for(j=0;j<8;j++)//清屏
TempData[j]=0;
}
if(i<8)
{
temp[i]=dofly_DuanMa[num];//把按鍵值輸入到臨時數組中
for(j=0;j<=i;j++) //通過一定順序把臨時數組中
//的值賦值到顯示緩沖區,從右往左輸入
TempData[7-i+j]=temp[j];
}
i++; //輸入數值累加
if(i==9)//正常等於8即可,由於我們需要空一個用於清屏,
//清屏時的按鍵不做輸入值
{
i=0;
Flag=1;//先把比較位置1
for(j=0;j<8;j++)//循環比較8個數值,
//如果有一個不等 則最終Flag值為0
Flag=Flag&&(temp[j]==dofly_DuanMa[password[j]]);
//比較輸入值和已有密碼
for(j=0;j<8;j++)//清屏
TempData[j]=0;
if(Flag)//如果比較全部相同,標志位置1
{
TempData[0]=0x3f; // "o"
TempData[1]=0x73; // "p"
TempData[2]=0x79; // "E"
TempData[3]=0x54; // "n"
//說明密碼正確,輸入對應操作 顯示"open"
}
else
{
TempData[0]=0x79; // "E"
TempData[1]=0x50; // "r"
TempData[2]=0x50; // "r"
//否則顯示"Err"
}
}
}
}
}
/*------------------------------------------------
uS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字元變數,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
長度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字元變數,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延時1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
顯示函數,用於動態掃描數碼管
輸入參數 FirstBit 表示需要顯示的第一位,如賦值2表示從第三個數碼管開始顯示
如輸入0表示從第一個顯示。
Num表示需要顯示的位數,如需要顯示99兩位數值則該值輸入2
------------------------------------------------*/
void Display(unsigned char FirstBit,unsigned char Num)
{
static unsigned char i=0;
DataPort=0; //清空數據,防止有交替重影
LATCH1=1; //段鎖存
LATCH1=0;
DataPort=dofly_WeiMa[i+FirstBit]; //取位碼
LATCH2=1; //位鎖存
LATCH2=0;
DataPort=TempData[i]; //取顯示數據,段碼
LATCH1=1; //段鎖存
LATCH1=0;
i++;
if(i==Num)
i=0;
}
/*------------------------------------------------
定時器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01; //使用模式1,16位定時器,使用"|"符號可以在使用多個定時器時不受影響
//TH0=0x00; //給定初值
//TL0=0x00;
EA=1; //總中斷打開
ET0=1; //定時器中斷打開
TR0=1; //定時器開關打開
}
/*------------------------------------------------
定時器中斷子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
TH0=(65536-2000)/256; //重新賦值 2ms
TL0=(65536-2000)%256;
Display(0,8); // 調用數碼管掃描
}
/*------------------------------------------------
按鍵掃描函數,返回掃描鍵值
------------------------------------------------*/
unsigned char KeyScan(void) //鍵盤掃描函數,使用行列反轉掃描法
{
unsigned char cord_h,cord_l;//行列值中間變數
KeyPort=0x0f; //行線輸出全為0
cord_h=KeyPort&0x0f; //讀入列線值
if(cord_h!=0x0f) //先檢測有無按鍵按下
{
DelayMs(10); //去抖
if((KeyPort&0x0f)!=0x0f)
{
cord_h=KeyPort&0x0f; //讀入列線值
KeyPort=cord_h|0xf0; //輸出當前列線值
cord_l=KeyPort&0xf0; //讀入行線值
while((KeyPort&0xf0)!=0xf0);//等待松開並輸出
return(cord_h+cord_l);//鍵盤最後組合碼值
}
}return(0xff); //返回該值
}
/*------------------------------------------------
按鍵值處理函數,返回掃鍵值
------------------------------------------------*/
unsigned char KeyPro(void)
{
switch(KeyScan())
{
case 0x7e:return 0;break;//0 按下相應的鍵顯示相對應的碼值
case 0x7d:return 1;break;//1
case 0x7b:return 2;break;//2
case 0x77:return 3;break;//3
case 0xbe:return 4;break;//4
case 0xbd:return 5;break;//5
case 0xbb:return 6;break;//6
case 0xb7:return 7;break;//7
case 0xde:return 8;break;//8
case 0xdd:return 9;break;//9
case 0xdb:return 10;break;//a
case 0xd7:return 11;break;//b
case 0xee:return 12;break;//c
case 0xed:return 13;break;//d
case 0xeb:return 14;break;//e
case 0xe7:return 15;break;//f
default:return 0xff;break;
}
}
E. 密碼鎖c語言編程代碼
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
intmain()
{
charpassword[10],password2[10];
memset(password,0,sizeof(password));
memset(password2,0,sizeof(password2));
printf("請設置8位數以內密碼: ");
scanf("%s",password);
printf("請設置校驗密碼: ");
scanf("%s",password2);
if(atoi(password2)==atoi(password))
{
printf("密碼輸入正確!: ");
}
else
{
printf("密碼輸入錯誤!: ");
}
return0;
}
F. 求AT89C51單片機控制電子密碼鎖的程序 最好是C語言
;完成功能說明:
; 基本功能以及OK,可以在線修改密碼Ok,開機默認密碼:123456,在線可修改
;功能改進說明:
; 將代碼繼續優化,將其中的清楚按鍵設置成具有連按功能的按鍵,對於SET和SET_OUT利用一個按鍵來做(利用按鍵的3S長按進入重新設置密碼模式,利用相同按鍵的短擊退出密碼設置模式),設置報警模式以及退出報警設置,利用剩餘的按鍵來做。;===============================================
;==============MCU:AT89C52=====================
;============名稱:電子密碼鎖===================
;===========程序編寫人:DAIVD===================
;=========程序編寫時間:2010年8月3日============
;=功能描述:六位數碼管顯示,4*4矩陣鍵盤作為外設=
;=====通過矩陣鍵盤可以輸入密碼以及修改密碼======
;=====通過數碼管以及LED顯示當前密碼鎖狀態=======
;===============版本:V1.0======================
;=====項目完成時間: ==========
;===============================================
BT0 EQU 20H.0 ;節拍法標志位每個節拍為20MS
CHANGE_PW_FLAG EQU 20H.1 ;重新設置密碼標志位
OK_FLAG EQU 20H.2 ;確認密碼輸入標志位
CLR_FLAG EQU 20H.3 ;清楚輸入密碼標志位
KEY_REG EQU 20H.4 ;按鍵按下標志位
FLASHING_FLAG EQU 20H.5 ;閃爍標志位
ONCE_TIME EQU 20H.6 ;第一次進入標志位
MEMORY_FLAG EQU 20H.7 ;修改密碼是兩次輸入第一次需要記憶
DIGITAL_FLAG EQU 21H.0 ;是否需要鍵入數字標志位
NUM_FLAG EQU 21H.1 ;數字鍵標志位
;FUNCTION_FLAG EQU 21H.2 ;功能鍵標志位
D_DONG_FLAG EQU 21H.3 ;消抖標志位
KEY_HAVE_REG EQU 21H.4 ;一次按鍵多次響應標志位
SET_OUT EQU 21H.5 ;設置密碼狀態退出標志位
OTI EQU 21H.6 ;第一次進入重置密碼模式標志位
COMPARE_EN EQU 21H.7
OTII EQU 22H.0
ALARM EQU 22H.1 ;報警標志位
ALARM_OUT EQU 22H.2 ;報警退出標志位
ORIGINAL_PW_1 EQU 30H ;原始密碼存儲寄存器
ORIGINAL_PW_2 EQU 31H
ORIGINAL_PW_3 EQU 32H
ORIGINAL_PW_4 EQU 33H
ORIGINAL_PW_5 EQU 34H
ORIGINAL_PW_6 EQU 35H
CURRENT_PW_1 EQU 40H ;當前密碼存儲器
CURRENT_PW_2 EQU 41H
CURRENT_PW_3 EQU 42H
CURRENT_PW_4 EQU 43H
CURRENT_PW_5 EQU 44H
CURRENT_PW_6 EQU 45H
CURRENT_PW_1_REG EQU 46H ;當前密碼暫存器
CURRENT_PW_2_REG EQU 47H ;用於密碼修改時比較兩次輸入是否相同
CURRENT_PW_3_REG EQU 48H
CURRENT_PW_4_REG EQU 49H
CURRENT_PW_5_REG EQU 4AH
CURRENT_PW_6_REG EQU 4BH
DISPLAY_REG_0 EQU 36H ;顯示寄存器
DISPLAY_REG_1 EQU 37H
DISPLAY_REG_2 EQU 38H
DISPLAY_REG_3 EQU 39H
DISPLAY_REG_4 EQU 3AH
DISPLAY_REG_5 EQU 3BH
COUNT_0 EQU 3CH ;用於閃爍標志位的計數200MS
TH0_BUFFER EQU 3DH ;定時器賦初值寄存器
TL0_BUFFER EQU 3EH
MAZHI_REG EQU 3DH ;4*4矩陣鍵盤掃描得到的碼值
COUNT_1 EQU 3FH ;用於設置密碼標志位的計數超過3S則置一
COUNT_2 EQU 51H ;用於輸入密碼次數是否超過3次
R2_REG EQU 50H
CHIP_SELECT EQU P1 ;P1作為片選口
OUTPUT EQU P0 ;P0口作為輸出口
GREEN_LED EQU P3.4 ;綠燈代表輸入密碼正確
YELLOW_LED EQU P3.3 ;黃燈代表正在輸入密碼過程中
RED_LED EQU P3.2 ;紅燈代表輸入密碼錯誤
SPK EQU P3.1 ;蜂鳴器代表輸入密碼超過3次報警
ORG 0000H
LJMP START
ORG 0003H ;中斷入口地址寫RETI防止出現誤判對程序影響
RETI
ORG 000BH
LJMP T0_SER
ORG 0013H
RETI
ORG 001BH
RETI
ORG 0023H
RETI
ORG 002BH
RETI
ORG 0030H
START: MOV ORIGINAL_PW_1,#01 ;設置初始密碼
MOV ORIGINAL_PW_2,#02
MOV ORIGINAL_PW_3,#03
MOV ORIGINAL_PW_4,#04
MOV ORIGINAL_PW_5,#05
MOV ORIGINAL_PW_6,#06
MOV TMOD,#01H ;設置定時器0工作方式1採用中斷方式
SETB EA
SETB ET0
MOV DPTR,#65536-20000
MOV TH0,DPH
MOV TL0,DPL
MOV TH0_BUFFER,DPH
MOV TL0_BUFFER,DPL
SETB TR0
MOV R0,#CURRENT_PW_1 ;對當前密碼以及當前密碼暫存器賦初值
REFRESH_PW: MOV @R0,#0B9H ;其中當前密碼暫存器用於修改密碼時
INC R0 ;比較兩次重新輸入的密碼是否相等用
CJNE R0,#04CH,REFRESH_PW
MOV 20H,#00H
MOV 21H,#00H
MOV 22H,#00H
MOV COUNT_0,#00H
MOV COUNT_1,#00H
MOV COUNT_2,#00H
;=========================================
MAIN: JNB BT0,MAIN
CLR BT0
JNB CHANGE_PW_FLAG,LOOP ;判斷是否需要修改密碼
;===============修改原始密碼模式========== ;當CHANGE_PW_FLAG=1表明進入修改密碼模式
JB OTII,LP0
SETB OTII
MOV R2,#0
LP0: JNB SET_OUT,LP
MOV R2,#0
LJMP LP4
LP: JNB OK_FLAG,LOOP1 ;判斷是否輸入密碼完成
CLR OK_FLAG
JNB OTI,LP1 ;判斷是不是第一次進入要在輸入密碼正確的前提下
JNB COMPARE_EN,SAVE_MODE ;記錄兩次輸入的密碼是否一致才確定是否需要重置
CALL COMPARE_CODE
LJMP LOOP1
SAVE_MODE: CALL SAVE_CODE
LJMP LOOP1
LP1: CALL ENTER_PW_MODE
CJNE R2,#0,LP2
LJMP LOOP1
LP2: CJNE R2,#7,LP3 ;等於7代表原始密碼輸入正確,下一步記憶新密碼
SETB OTI
MOV R2,#0
LJMP LOOP1
LP3: MOV R2,#8
LP4: CLR ALARM_OUT
CLR SET_OUT
CLR OTI ;清零所有內容恢復等待密碼輸入狀態
CLR OTII
CLR COMPARE_EN
CLR CHANGE_PW_FLAG
LJMP LOOP1
;===============常規輸入密碼模式==========
LOOP: CLR SET_OUT ;非設置密碼格式下也會掃描到SET_OUT
;防止程序進入設置密碼狀態下直接退出
JNB ALARM,L1
JB ALARM_OUT,L2
CLR SPK
LJMP LOOP3
L2: SETB SPK
CLR ALARM_OUT
CLR ALARM
LJMP LOOP1
L1: JNB OK_FLAG,LOOP1 ;判斷是否輸入密碼完成
CLR OK_FLAG
CALL ENTER_PW_MODE
;==========================================
LOOP1: JNB CLR_FLAG,LOOP2 ;判斷是否需要清除所輸入密碼
CLR CLR_FLAG
LCALL CLR_INPUT_PW
LOOP2: JNB DIGITAL_FLAG,LOOP3 ;判斷是否需要輸入密碼
CLR DIGITAL_FLAG
LCALL INPUT_PW
LJMP LOOP3
;=========================================
LOOP3: LCALL DISPLAY
LCALL KEY_SCAN
INC COUNT_0
MOV A,COUNT_0
CJNE A,#5,LOOP4
MOV COUNT_0,#0
CPL FLASHING_FLAG
LOOP4:
LJMP MAIN
;=============下面是具體的子程序===========
;================檢測密碼是否正確==========
ENTER_PW_MODE:
CLR OK_FLAG ;比較是否為零,為零的時候
CJNE R2,#0,ENTER_PW_MODE_0 ;代表還沒密碼輸入,直接跳出
LJMP ENTER_PW_MODE_OUT
ENTER_PW_MODE_0:
CJNE R2,#7,$+3 ;用來比較R2是否為7或者8
JC ENTER_PW_MODE_2
MOV R2,#00 ;如果8在BAD的模式下切換到輸入密碼狀態
LJMP ENTER_PW_MODE_OUT ;如果7在GOOD的模式下切換到輸入密碼狀態
ENTER_PW_MODE_2:
CJNE R2,#6,ENTER_PW_MODE_3 ;如果R2里的數字不為6代表密碼位數不夠,肯定錯
MOV R0,#ORIGINAL_PW_1 ;如果R2里的數字等於6那麼在比較是否相同
MOV R1,#CURRENT_PW_1
ENTER_PW_MODE_4:
MOV A,@R0
XRL A,@R1 ;相異或內容相同為0
CJNE A,#00H,ENTER_PW_MODE_3
INC R0
INC R1
CJNE R0,#36H,ENTER_PW_MODE_4
MOV R2,#7 ;如果相同代表密碼輸入正確GOOD
MOV COUNT_2,#0
LJMP ENTER_PW_MODE_OUT
ENTER_PW_MODE_3:MOV R2,#8 ;如果不相同則代表密碼不正確BAD
INC COUNT_2
MOV A,COUNT_2
CJNE A,#3,$+3
JC KK
FUZHI: MOV COUNT_2,#00H
SETB ALARM
KK: MOV R0,#CURRENT_PW_1 ;對當前密碼以及當前密碼暫存器賦初值
REF_PW: MOV @R0,#0B9H ;其中當前密碼暫存器用於修改密碼時
INC R0 ;比較兩次重新輸入的密碼是否相等用
CJNE R0,#04CH,REF_PW
ENTER_PW_MODE_OUT:
RET
;==========================================
;=============清除所輸入的密碼=============
CLR_INPUT_PW:
CLR CLR_FLAG
CJNE R2,#0,CLR_INPUT_PW_0 ;如果為零則不操作
LJMP CLR_INPUT_PW_OUT
CLR_INPUT_PW_0:
CJNE R2,#7,$+3 ;用來比較R2是否為7或者8
JC CLR_INPUT_PW_1
MOV R2,#00 ;如果8在BAD的模式下切換到輸入密碼狀態
LJMP CLR_INPUT_PW_OUT ;如果7在GOOD的模式下切換到輸入密碼狀態
CLR_INPUT_PW_1:
DEC R2 ;正常模式下將R2減一
CLR_INPUT_PW_OUT:
RET
;==========================================
;============輸入單位密碼子程序============
INPUT_PW: JB NUM_FLAG,INPUT_PW_0
LJMP INPUT_PW_OUT
INPUT_PW_0: CLR NUM_FLAG
CJNE R2,#7,$+3 ;比較R2是否大於7,大於C=0
JC INPUT_PW_2
MOV R2,#01 ;數字鍵按下輸入密碼
LJMP INPUT_PW_3_3
INPUT_PW_2: CJNE R2,#6,INPUT_PW_3 ;如果當前R2等於則6位密碼已經輸滿則不操作
LJMP INPUT_PW_OUT
INPUT_PW_3: INC R2
INPUT_PW_3_3: MOV R1,#01
MOV R2_REG,R2 ;根據R2的給相應的位送密碼
MOV R0,#CURRENT_PW_1
JMP I_LOOP
I_LOOP1: INC R0
INC R1
I_LOOP: MOV A,R1
CJNE A,R2_REG,I_LOOP1
MOV A,R3
MOV @R0,A
INPUT_PW_OUT: RET
;==========================================
;===============SAVE_CODE==================
SAVE_CODE: CJNE R2,#6,SAVE_CLR ;如果R2不等於6代表密碼輸入錯誤直接退出
SAVE_IN: MOV R0,#CURRENT_PW_1_REG ;將輸入的新密碼先保存在密碼暫存區
MOV R1,#CURRENT_PW_1 ;46H
SAVE_IN_LOOP: MOV A,@R1
MOV @R0,A
INC R0
INC R1
MOV A,R1
CJNE A,#46H,SAVE_IN_LOOP
SETB COMPARE_EN
MOV R2,#0 ;密碼輸入正確則程序處於等待輸入狀態
LJMP SAVE_OUT
SAVE_CLR: MOV R2,#8
CLR SET_OUT
CLR OTI ;清零所有內容恢復等待密碼輸入狀態
CLR OTII
CLR COMPARE_EN
CLR CHANGE_PW_FLAG
SAVE_OUT: RET
;===========================================
;=================COMPARE_CODE==============
COMPARE_CODE: CJNE R2,#6,COMPARE_FAIL ;如果R2不等於6代表上次輸入密碼數不足6位
COMPARE_IN: MOV R0,#CURRENT_PW_1_REG
MOV R1,#CURRENT_PW_1 ;46H
COMPARE_IN_LOOP:
MOV A,@R1
XRL A,@R0
CJNE A,#00H,COMPARE_FAIL
INC R0
INC R1
MOV A,R1
CJNE A,#46H,COMPARE_IN_LOOP
MOV R0,#ORIGINAL_PW_1
MOV R1,#CURRENT_PW_1 ;46H
TIHUAN_LOOP: MOV A,@R1
MOV @R0,A
INC R0
INC R1
MOV A,R1
CJNE A,#46H,TIHUAN_LOOP
MOV R2,#7
CLR SET_OUT
CLR OTI ;清零所有內容恢復等待密碼輸入狀態
CLR OTII
CLR COMPARE_EN
CLR CHANGE_PW_FLAG
LJMP COMPARE_OUT
COMPARE_FAIL: MOV R2,#8
CLR SET_OUT
CLR OTI ;清零所有內容恢復等待密碼輸入狀態
CLR OTII
CLR COMPARE_EN
CLR CHANGE_PW_FLAG
COMPARE_OUT: RET
;===========================================
;==================顯示子程序==============
DISPLAY: MOV R4,#0
MOV DPTR,#TAB_0
MOV A,R2
RL A
JMP @A+DPTR
TAB_0: AJMP DISPLAY_0
AJMP DISPLAY_1
AJMP DISPLAY_2
AJMP DISPLAY_3
AJMP DISPLAY_4
AJMP DISPLAY_5
AJMP DISPLAY_6
AJMP DISPLAY_7
AJMP DISPLAY_8
DISPLAY_0: MOV DPTR,#TAB_1
LJMP REFRESH_DISPLAY
DISPLAY_1: MOV DPTR,#TAB_2
LJMP REFRESH_DISPLAY
DISPLAY_2: MOV DPTR,#TAB_3
LJMP REFRESH_DISPLAY
DISPLAY_3: MOV DPTR,#TAB_4
LJMP REFRESH_DISPLAY
DISPLAY_4: MOV DPTR,#TAB_5
LJMP REFRESH_DISPLAY
DISPLAY_5: MOV DPTR,#TAB_6
LJMP REFRESH_DISPLAY
DISPLAY_6: MOV DPTR,#TAB_7
LJMP REFRESH_DISPLAY
DISPLAY_7: MOV DPTR,#TAB_8
LJMP REFRESH_DISPLAY
DISPLAY_8: MOV DPTR,#TAB_9
REFRESH_DISPLAY:
MOV R0,#DISPLAY_REG_0
DISPLAY_LOOP:
MOV A,R4
MOVC A,@A+DPTR
MOV @R0,A
INC R4
INC R0
MOV A,R0
CJNE A,#3CH,DISPLAY_LOOP ;此時表明數碼管顯示的數值已送完
DISPLAY_SHOW:
MOV R0,#DISPLAY_REG_0 ;數碼管動態顯示
MOV R5,#0FEH
NEXT_0: MOV CHIP_SELECT,R5
MOV A,@R0
MOV OUTPUT,A
LCALL DELAY
MOV OUTPUT,#0FFH
INC R0
MOV A,R5
RL A
MOV R5,A ;片選
CJNE R0,#3CH,NEXT_0
CJNE R2,#0,NEXT_6
MOV P3,#0FFH
LJMP DISPLAY_OUT
NEXT_6: CJNE R2,#7,NEXT_1
CLR GREEN_LED
SETB YELLOW_LED
SETB RED_LED
LJMP DISPLAY_OUT
NEXT_1: CJNE R2,#8,NEXT_2
SETB YELLOW_LED
SETB GREEN_LED
CLR RED_LED
LJMP DISPLAY_OUT
NEXT_2: JNB CHANGE_PW_FLAG,NEXT_3
JNB FLASHING_FLAG,NEXT_4
MOV P3,#0FFH
LJMP DISPLAY_OUT
NEXT_4: MOV P3,#00H
LJMP DISPLAY_OUT
NEXT_3: JNB FLASHING_FLAG,NEXT_5
MOV P3,#0F7H
LJMP DISPLAY_OUT
NEXT_5: MOV P3,#0FFH
DISPLAY_OUT: RET
;=======================================
;============按鍵掃描程序===============
KEY_SCAN: MOV R3,#00H ;對碼表掃描進行初始化可以訪問到第一位
JNB D_DONG_FLAG,PANDUAN ;判斷是否進行過消抖
LCALL FANZHUAN_SCAN ;反轉掃描確定碼值
CJNE A,#0FFH,L4 ;如果碼值等於0FFH可能是抖動或者按鍵抬起
L3: CLR D_DONG_FLAG ;表明是按鍵抬起,此時要對D_DONG_FLAG/
CLR KEY_HAVE_REG ;KEY_HAVE_REG進行清零;;;;;;;;;;
CLR COUNT_1
LJMP KEY_SCAN_OUT
L4: JNB ALARM,KEY_SCAN_1
CJNE A,#0B7H,L3
SETB ALARM_OUT
CLR D_DONG_FLAG
LJMP KEY_SCAN_OUT
PANDUAN: LCALL FANZHUAN_SCAN ;第一次進入沒有經過消抖判斷是否有按鍵按下
CJNE A,#0FFH,KEY_SCAN_0 ;對所掃描的碼值進行比較如果為0FFH沒按鍵按下
LJMP KEY_SCAN_OUT
KEY_SCAN_0: SETB D_DONG_FLAG ;所掃到的碼值不等於0FFH可能是按鍵按下
LJMP KEY_SCAN_OUT
KEY_SCAN_1:
JNB KEY_HAVE_REG,KEY_SCAN_1_1;一次按鍵多次響應標志位
CJNE A,#0E7H,KEY_SCAN_1_1_1
INC COUNT_1 ;長按處理
MOV A,COUNT_1
CJNE A,#150,KEY_SCAN_1_1_1
MOV COUNT_1,#00H
SETB CHANGE_PW_FLAG
CLR D_DONG_FLAG
CLR KEY_HAVE_REG
KEY_SCAN_1_1_1:
LJMP KEY_SCAN_OUT
KEY_SCAN_1_1: MOV MAZHI_REG,A
KEY_SCAN_LOOP:
MOV DPTR,#TAB_10
MOV A,R3
MOVC A,@A+DPTR
CJNE A,#0FFH,KEY_SCAN_2 ;如果查出的碼表值為0FFH代表已經查完了
MOV R3,#0 ;但是沒有符合的就代表是亂碼不處理
CLR D_DONG_FLAG
CLR KEY_HAVE_REG
LJMP KEY_SCAN_OUT
KEY_SCAN_2: CJNE A,MAZHI_REG,KEY_SCAN_3 ;比較是哪個鍵按下
CJNE R3,#10,$+3 ;通過比較後形成小於等於9或者大於9兩種情況
JNC COMPARE
SHUZI_MODE: SETB KEY_HAVE_REG
SETB NUM_FLAG
SETB DIGITAL_FLAG
LJMP KEY_SCAN_OUT
COMPARE: SETB KEY_HAVE_REG
CJNE R3,#10,COMPARE_0 ;此時R3內的數值大於9則CY=1
SETB OK_FLAG ;等於10為OK鍵按下
LJMP KEY_SCAN_OUT
COMPARE_0: CJNE R3,#11,COMPARE_1 ;等於11為清除按鍵按下
SETB CLR_FLAG
LJMP KEY_SCAN_OUT ;等於12為設置密碼按鍵在長按裡面加處理
COMPARE_1: CJNE R3,#13,COMPARE_2 ;等於13為設置密碼跳出標志
SETB SET_OUT
LJMP KEY_SCAN_OUT
;COMPARE_2: CJNE R3,#14,COMPARE_3
; SETB ALARM
; LJMP KEY_SCAN_OUT
COMPARE_2: CJNE R3,#14,COMPARE_4
SETB ALARM_OUT
LJMP KEY_SCAN_OUT
COMPARE_4: LJMP KEY_SCAN_OUT ;按鍵加功能
KEY_SCAN_3: INC R3
LJMP KEY_SCAN_LOOP
KEY_SCAN_OUT:
RET
;=======================================
FANZHUAN_SCAN: MOV P2,#0F0H ;反轉掃描確定碼值
MOV A,P2
ANL A,#0F0H
MOV B,A
MOV P2,#0FH
MOV A,P2
ANL A,#0FH
ORL A,B
RET
;===============顯示的碼表==============
TAB_1: DB 0BFH,0BFH,0BFH,0BFH,0BFH,0BFH ;------
TAB_2: DB 0B9H,0BFH,0BFH,0BFH,0BFH,0BFH ;+-----
TAB_3: DB 0B9H,0B9H,0BFH,0BFH,0BFH,0BFH ;++----
TAB_4: DB 0B9H,0B9H,0B9H,0BFH,0BFH,0BFH ;+++---
TAB_5: DB 0B9H,0B9H,0B9H,0B9H,0BFH,0BFH ;++++--
TAB_6: DB 0B9H,0B9H,0B9H,0B9H,0B9H,0BFH ;+++++-
TAB_7: DB 0B9H,0B9H,0B9H,0B9H,0B9H,0B9H ;++++++
TAB_8: DB 090H,0A3H,0A3H,0A1H,0FFH,0FFH ;good
TAB_9: DB 083H,0A0H,0A1H,0FFH,0FFH,0FFH ;bad
TAB_10: DB 0EEH,0DEH,0BEH,07EH,0EDH,0DDH,0BDH,07DH ;4*4矩陣鍵盤的碼表
DB 0EBH,0DBH,0BBH,07BH,0E7H,0D7H,0B7H,77H,0FFH
;=======================================
;==============延時子程序===============
;輸入:無
;輸出:無
;功能:延時一段時間穩定數碼管的顯示2.4MS
DELAY:
MOV R7,#30
DL: MOV R6,#40
DJNZ R6,$
DJNZ R7,DL
RET
;=======================================
;============定時器中斷服務程序=========
T0_SER:
MOV TMOD,#01H
SETB BT0
MOV TH0,TH0_BUFFER
MOV TL0,TL0_BUFFER
RETI
;=======================================
END
G. 求51單片機C語言編的密碼鎖程序
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
#define BIN(a,b,c,d,e,f,g,h) ((a<<7)+(b<<6)+(c<<5)+(d<<4)+(e<<3)+(f<<2)+(g<<1)+(h<<0))
//下面的code表示數組存放在ROM中,因為這個數組的值不需要改寫
uchar code KeyCode[16]={15,14,12,8,30,28,24,16,60,56,48,32,120,112,96,64};//值為m*(n+1)的乘積,用於Key()
uchar dis[6];
msdelay(uint x)//延時子函數
{uchar j;
while(x--)
{for(j=0;j<125;j++){;}
}
}
//鍵盤子程序一,鍵盤值與數組值對比得到
uchar Key(void)
{uchar temp,m,n,i,j,matrix,k;
P1=0xF0; /*行線電平為高,列線為低*/
temp=P1&0xf0;
if (temp==0xf0) return(16); /*行仍為高,無按健,退出*/
else msdelay(10);
for(i=1;i<16;i=i*2)
{m=i;
for(j=1;j<16;j=j*2)
{n=(~j)&0x0f;
P1=(m<<4)|n; /*m為P1的行值由i循環得到,n為列值,由j循環並取反得到*/
temp=P1&0xf0;
if (!temp)
{do{temp=P1&0xf0;}while(!temp);
matrix=m*(n+1);/*為避免乘積重復,n+1*/
for(k=0;k<16;k++){if (matrix==KeyCode[k]) return(k);} //KeyCode:見前
return(16);
} //if loop
}//j loop
}//i loop
}//Key end
//用Switch...case語句得到鍵盤值*/
uchar Key1(void)
{uchar temp,m,n,i,j,matrix;
P1=0xF0; /*行線電平為高,列線為低*/
temp=P1&0xf0;
if (temp==0xf0) return(16); /*行仍為高,無按健,退出*/
else msdelay(10);
for(i=1;i<16;i=i*2)
{m=i;
for(j=1;j<16;j=j*2)
{n=(~j)&0x0f;
P1=(m<<4)|n;/*m為P1的行值由i循環得到,n為列值,由j循環並取反得到*/
temp=P1&0xf0;
if (!temp)
{do{temp=P1&0xf0;}while(!temp);
matrix=m*(n+1);
switch(matrix) //此方法的基本思路:
{case 15:return(1); break; //由循環得到的m,n值賦於P1埠實現逐個鍵掃描
case 14:return(2); break; //同時由m,n+1的值相乘得到對應鍵點de的積
case 12:return(3); break; //m*(n+1)值掃描鍵點對應而得出鍵值
case 8:return(4); break; //
case 30:return(5); break; //
case 28:return(6); break; //
case 24:return(7); break; //
case 16:return(8); break;
case 60:return(9); break;
case 56:return(0); break;
case 48:return(10); break;
case 32:return(11); break;
case 120:return(12); break;
case 112:return(13); break;
case 96:return(14); break;
case 64:return(15); break;
default:return(16);
} //switch end
} //if loop
}//j loop
}//i loop
}//Key end
//依次掃描16個按鍵
uchar Key2(void)
{uchar temp;
P1=0xF0; /*使P1=1111 0000,行線電平為高,列線為低*/
temp=P1&0xf0;
if (temp==0xf0) return(16); /*讀P1=1111 xxxx,表示行仍為高,無按健,退出(x表示不關心)?/
else msdelay(10);
P1=0x1e; /*P1=0001 1110,行一為高,列一為低,掃描第一個按鍵*/
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(1);}
P1=0x1d; /*P1=0001 1101,行一為高,列二為低,掃描第二個按鍵,下面掃描其餘按鍵*/
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(2);}
P1=0x1b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(3);}
P1=0x17;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(4);}
P1=0x2e;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(5);}
P1=0x2d;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(6);}
P1=0x2b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(7);}
P1=0x27;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(8);}
P1=0x4e;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(9);}
P1=0x4d;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(0);}
P1=0x4b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(10);}
P1=0x47;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(11);}
P1=0x8e;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(12);}
P1=0x8d;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(13);}
P1=0x8b;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(14);}
P1=0x87;
temp=P1&0xf0;
if (!temp) {do{temp=P1&0xf0;}while(!temp);
return(15);}
return(16); //掃描all按鍵都未按下,則輸出16
}//Key2 end.
////////時鍾中斷顯示子程序
void T0_int() interrupt 1
{static uchar i;
if (i==6){i=0;}
P0=5-i;
P0=P0|(dis[i]<<4);
i++;
TL0=0;
TH0=252;}
void distri(uint disnum)
{uint temp;
dis[0]=0;
dis[1]=disnum/10000;
temp=disnum%10000;
dis[2]=temp/1000;
temp=temp%1000;
dis[3]=temp/100;
temp=temp%100;
dis[4]=temp/10;
dis[5]=temp%10;
}
Main()
{uchar KeyVal,i=0;
TMOD=0x01;
IE=0x82;
TH0=252;
TL0=0;
TR0=1;
distri(0);
do{
KeyVal=Key();
if (KeyVal!=16) dis[1]=KeyVal; //注意:當有按鍵時才賦於顯示位dis[1],否則出錯,請分析!
}while(1);
}
H. 請問,用四個獨立按鍵來製作簡易密碼鎖C語言程序該怎麼編寫
這個可以模擬那種撥碼形式的密碼鎖方式來設計,比如OFO共享單車的撥碼方式。
#include<reg51.h>
#define uchar unsigned char
uchar mima[4]={1,2,3,4};
uchar keymm[4]={0,0,0,0};
sbit key1=P1^0;
sbit key2=P1^1;
sbit key3=P1^2;
sbit key4=P1^3;
sbit led=P1^4;
bit flag=0;
void delay(uchar a)
{
uchar i;
while(a--)for(i=0;i<120;i++);
}
main()
{
uchar i;
led=1;
while(1)
{
if(key1==0)
{
while(key1==0);
keymm[0]++;
keymm[0]%=10;
}
if(key2==0)
{
while(key2==0);
keymm[1]++;
keymm[1]%=10;
}
if(key3==0)
{
while(key3==0);
keymm[2]++;
keymm[2]%=10;
}
if(key4==0)
{
while(key4==0);
keymm[3]++;
keymm[3]%=10;
}
for(i=0;i<4;i++)
{
if(keymm[i]!=mima[i])break;
if(i==3)flag=1;
}
if(flag)
{
i=10;
while(i--)
{
led=~led;
delay(100);
}
flag=0;
}
}
}
I. 電子密碼鎖的C語言程序
親 這程序是我自己當時寫的,51單片機1602液晶,可以更改密碼。
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit lcden=P2^6;
sbit lcdrs=P2^4;
sbit lcdrw=P2^5;
bit flag;
bit flag1;
bit flag2;
bit flag3;
bit flag4;
uchar a[6];
uchar b[6];
uchar c[6];
uchar num,key,,num1,num2,i,temp,ss,num3,num4,num5,num6;
uchar code table[]=" input password: ";
uchar code table1[]="right!";
uchar code table2[]="error!";
uchar code table3[]={'0','1','2','3','4','5','6','7','8','9'};
uchar code table4[]="wrong!";
uchar code table5[]="change password:";
uchar code table6[]="password again: ";
uchar code table7[]="new passwordsure";
uchar password[]={'0','0','0','0','0','0'};
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com)
{
lcdrs=0;
lcdrw=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date)
{
lcdrs=1;
lcdrw=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
{
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<16;num++)
{
write_data(table[num]);
delay(5);
}
//write_com(0x80+0x40);
}
uchar keyscan(void)
{
uchar temp,;
P3=0x7f;
temp=P3&0x7f;
if(temp!=0x7f)
{
delay(1);
P3=0x7f;
temp=P3&0x7f;
if(temp!=0x7f)
{
P3=0x7f;
temp=P3&0x7f;
switch (temp)
{
case 0x7e:=1;break;
case 0x7d:=2;break;
case 0x7b:=3;break;
case 0x77:=4;break;
}
while(temp!=0x7f)
{
P3=0x7f;
temp=P3&0x7f;
}
return ;
}
}
//**********
P3=0xbf;
temp=P3&0xbf;
if(temp!=0xbf)
{
delay(1);
P3=0xbf;
temp=P3&0xbf;
if(temp!=0xbf)
{
P3=0xbf;
temp=P3&0xbf;
switch (temp)
{
case 0xbe:=5;break;
case 0xbd:=6;break;
case 0xbb:=7;break;
case 0xb7:=8;break;
}
while(temp!=0xbf)
{
P3=0xbf;
temp=P3&0xbf;
}
return ;
}
}
//***********
P3=0xdf;
temp=P3&0xdf;
if(temp!=0xdf)
{
delay(1);
P3=0xdf;
temp=P3&0xdf;
if(temp!=0xdf)
{
P3=0xdf;
temp=P3&0xdf;
switch (temp)
{
case 0xde:=9;break;
case 0xdd:=10;break;
case 0xdb:=11;break;
case 0xd7:=12;break;
}
while(temp!=0xdf)
{
P3=0xdf;
temp=P3&0xdf;
}
return ;
}
}
//********
P3=0xef;
temp=P3&0xef;
if(temp!=0xef)
{
delay(1);
P3=0xef;
temp=P3&0xef;
if(temp!=0xef)
{
P3=0xef;
temp=P3&0xef;
switch (temp)
{
case 0xee:=13;break;
case 0xed:=14;break;
case 0xeb:=15;break;
case 0xe7:=16;break;
}
while(temp!=0xef)
{
P3=0xef;
temp=P3&0xef;
}
return ;
}
else
{
=0;
return ;
}
}
}
void changepassword()
{
uchar j=0,k=0,m=0;
flag2=0;
flag3=0;
flag4=0;
write_com(0x01);
delay(10);
write_com(0x0c);
delay(10);
write_com(0x80);
for(num4=0;num4<16;num4++)
{
write_data(table5[num4]);
}
while(!flag2)
{
key=keyscan();
if(key==1||key==2||key==3||key==4||key==5||key==6||key==7||key==8||key==9||key==10)
{
b[j]=table3[key-1];
write_data(table3[key-1]);
delay(10);
write_com(0x80+0x40+3+j);
delay(10);
write_data('*');
j++;
if(j==6)
{
j=0;
flag2=1;
flag3=1;
write_com(0x01);
delay(10);
write_com(0x80);
for(num5=0;num5<16;num5++)
{
write_data(table6[num5]);
}
}
}
}
while(flag3)
{
key=keyscan();
if(key==1||key==2||key==3||key==4||key==5||key==6||key==7||key==8||key==9||key==10)
{
c[k]=table3[key-1];
write_data(table3[key-1]);
delay(10);
write_com(0x80+0x40+3+k);
delay(10);
write_data('*');
k++;
if(k==6)
{
flag3=0;
write_com(0x01);
if((b[0]==c[0])&&(b[1]==c[1])&&(b[2]==c[2])&&(b[3]==c[3])&&(b[4]==c[4])&&(b[5]==c[5]))
{
flag4=1;
password[0]=b[0];
password[1]=b[1];
password[2]=b[2];
password[3]=b[3];
password[4]=b[4];
password[5]=b[5];
write_com(0x80);
//delay(10);
}
}
}
while(flag4)
{
flag4=0;
write_com(0x80);
for(num6=0;num6<16;num6++)
{
write_data(table7[num6]);
}
delay(2000);
write_com(0x80);
for(num=0;num<16;num++)
{
write_data(table[num]);
delay(5);
}
}
}
}
void main()
{
init();
while(1)
{
key=100;
key=keyscan();
if((!flag)&&(!flag1))
{
if((key==1||key==2||key==3||key==4||key==5||key==6||key==7||key==8||key==9||key==10)&&(i<6))
{
write_com(0x0f);
write_com(0x06);
a[i]=table3[key-1];
write_data(table3[key-1]);
delay(10);
write_com(0x80+0x40+4+i);
delay(50);
write_data('*');
i++;
}
}
if((!flag)&&(!flag1))
{
if(key==11)
{
i=0;
if((a[0]==password[0])&&(a[1]==password[1])&&(a[2]==password[2])&&(a[3]==password[3])&&(a[4]==password[4])&&(a[5]==password[5]))
{
flag1=1;
write_com(0x01);
delay(10);
write_com(0x0c);
delay(10);
write_com(0x80+4);
for(num1=0;num1<6;num1++)
{
write_data(table1[num1]);
}
}
else
{
write_com(0x01);
delay(10);
write_com(0x0c);
delay(10);
write_com(0x80+4);
for(num2=0;num2<6;num2++)
{
write_data(table2[num2]);
}
ss++;
if(ss==3)
{
flag=1;
write_com(0x01);
write_com(0x0c);
write_com(0x80+0x40+4);
for(num3=0;num3<6;num3++)
{
write_data(table4[num3]);
}
}
}
}
}
if(key==12)
{
changepassword();
}
}
}
J. 數字密碼鎖C語言編程
近年來,隨著生活水平的不斷改善,個人財富日益增長,人們對安全防盜的要求也逐漸提高。安全可靠、使用方便的電子密碼鎖成了人們防盜的首選。以Max +PlusⅡ(Multiple Array Matrix and ProgrammingLogic User SystemⅡ,多陣列矩陣及可編程邏輯用戶系統Ⅱ)為工作平台,使用PLD可編程器件和VHDL語言設計的帶音樂的電子密碼鎖具有密碼預置,誤碼鎖死及開鎖音樂提示等功能。這種設計不僅簡化了系統結構,降低了成本,更提高了系統的可靠和保密性。採用PLD可編程邏輯器件開發的數字系統,可以方便地升級和改進。
1 設計思路
密碼鎖電路由鍵盤控制、密碼設置和音樂演奏三大功能模塊組成,原理如圖1所示。Count,Keyvalue,Contrl,Smdisplay構成鍵盤控制模塊,Songer是音樂演奏模塊,Set是密碼設置模塊。
1.1 鍵盤控制
鍵盤主要完成向系統輸入數據,傳送命令等功能。它是一個機械彈性按鍵開關的集合,利用機械觸點的合、斷作用產生高、低電平。通過對電平高低狀態的檢測,以確認按鍵按下與否。一個電壓信號通過機械觸點的斷開、閉合過程的波形如圖2所示。
在該鍵盤電路中,Count模塊提供鍵盤的行掃描信號Q[3..0]。在沒有按鍵按下時,信號EN為高電平,行掃描輸出信號Q[3..0]的循環變化順序為0001 OO100100 1000 0001(依次掃描4行按鍵);當有按鍵按下時,信號EN為低電平,行掃描輸出信號Q[3..0]停止掃描,並鎖存當前的行掃描值。例如按下第一行的按鍵,那麼Q[3..O]=0001。
Keyvalue模塊的主要功能是對輸入按鍵的行信號Q[3..0]和列信號14[3..0]的當前組合值進行判斷來確定輸入按鍵的鍵值。
Contrl模塊的主要功能是實現按鍵的消抖,判斷是否有按鍵按下。確保對按鍵的提取處於圖2所示的閉合穩定時間范圍內,這就對本模塊的輸入時鍾信號有一定的要求,在本設計中該模塊輸入的時鍾信號頻率為64 Hz。Smdisplay模塊主要是完成數碼管動態掃描和七段解碼顯示的功能。
1.2 音樂演奏電路Songer
根據聲樂學知識,組成樂曲的每個音符的發音頻率值及其持續的時間是樂曲能連續演奏所需的兩個基本要素。獲得這兩個要素所對應的數值以及通過純硬體的手段來利用這些數值實現所希望樂曲的演奏效果是關鍵。如圖3所示,該電路需要由NOTETABS(音調發生器)、TONETABA、SPEAKER(數控分頻器)三個模塊組成,分別實現了聲音產生、節拍控制、音調控制的功能。
1.3 密碼設置
Set模塊是實現密碼鎖功能的核心模塊。其主要作用是設置密碼,Set為設置密碼的有效信號,可以實現修改密碼的功能。En為輸入密碼確認信號,當輸入完六位密碼後確認輸入,一旦輸入的密碼跟所設置的密碼一致時,則輸出信號OP有效(高電平);OP控制演奏音樂,此時音樂響起。若密碼不正確,則指示輸入錯誤及輸入次數,輸完三次無效後密碼鎖鎖死,必須由RESET信號(啟動信號,給一個低電平)重新打開密碼鎖功能。
2 電路的VHDL描述
鍵盤控制電路,音樂演奏電路以及密碼設置模塊均使用硬體描述語言VHSIC Hardware Description Lan-guage(VHDL)設計而成。例如:TONETABA的VHDL模型如下:
VHDL語言具有很強的電路描述和建模能力,能從多個層次對數字系統進行建模和描述,支持各種模式的設計方法:自頂向下與自底向上或混合方法,從而大大簡化了硬體的設計任務,提高了設計效率和可靠性。它同時具有與具體硬體電路無關和與設計平台無關的特性,所以用VHDL進行電子系統設計,設計者可以專心致力於其功能的實現,而不需要對其他相關因素花費過多的時間和精力。
設計步驟
3.1 設計輸入
首先在合適的路徑下建立本設計的文件夾,然後用VHDL語言編輯Count,Keyvalue,Contrl,Smdisplay等電路,並在Max+PlusⅡ軟體中使用文本編輯器輸入上述各電路模塊的VHDL程序,編譯生成各模塊;最後在Max+PlusⅡ軟體中使用圖形編輯器以自底向上的方法編輯原理圖。先編輯圖3電路,以Singer.gdf命名,其次使用「Create default Symbol」生成Songer模塊,然後再編輯如圖1所示原理電路圖。
3.2 模擬測試及編程下載配置
將設計好的項目存檔,並將其設置成Project。選擇目標器件為ACEX系列中的EP1K30QC208-2,啟動編譯,如果發現編譯出現錯誤,修正後再次編譯。編譯後即可對波形文件進行模擬,並進行測試和波形分析。分析完成後進行編程下載配置。
3.3 硬體測試
在高電平時,通過鍵盤的0~F號鍵進行6位密碼輸入,密碼輸入完畢後通過單擊確認鍵進行密碼設置確認。當輸入的密碼與設置的密碼一致時,揚聲器開始循環演奏樂曲,且數碼管SM8顯示輸入密碼的次數,數碼管SM7顯示密碼輸入是否正確。如果密碼正確,則SM7顯示『0』;如果密碼錯誤,則SM7顯示『E』。數碼管SM6~SM1顯示輸入的6位密碼。在密碼輸入正確開始演奏樂曲時,如果將撥位開關KD4撥向上,則數碼管SM8顯示樂曲的音符,而此時若將撥位開關KD3撥向上則停止演奏樂曲。發光二極體LED1~LED4顯示輸入按鍵的鍵值,LED16監控是否有按鍵按下。
4 結 語
使用Max+PlusⅡ軟體和VHDL語言設計電路,思路簡單,功能明了;不僅可以進行邏輯模擬,還可以進行時序模擬;使用PLD器件不僅省去了電路製作的麻煩,還可以反復多次進行硬體實驗,非常方便地修改設計,且設計的電路保密性很強。總之,採用Max+PlusⅡ軟體和VHDL語言使得復雜的電子系統的設計變得簡單容易,大大提高了設計效率。
如果對您有幫助,請記得採納為滿意答案,謝謝!祝您生活愉快!