pcf8574c语言测试程序,51单片机+PCF8574简易密码锁程序 带详细注释 1602显示

#include

#include "intrins.h"

#define uchar unsigned char

#define uint unsigned int

#define KeyPort P0                                //外接键盘,低四位接行,高四位接列

uchar  KEY_TABLE[16] =

{

0xEE, 0xDE, 0xBE, 0x7E,

0xED, 0xDD, 0xBD, 0x7D,

0xEB, 0xDB, 0xBB, 0x7B,

0xE7, 0xD7, 0xB7, 0x77

};

int flag1=0;                                                                                                                                                                                                                                                                                        //修改密码标志位

uchar num,i=0,j;

uchar passwordtemp[16],password[16]={'1','2','3','4'},newpassword[16];       //输入的密码,默认的密码

uchar inputtimes;                                                                                                                                                                                                      //密码输入错误次数

uint n,m;                                                                                                                                                                                                                                                                    //输入密码长度,实际密码长度

bit Flag=0;\

uchar light,light1=0,light2=0xf0;                                                                                                                                                        //设置成功,开锁,错误,

sbit SCL = P1^0;

sbit SDA = P1^1;

char ADDR = 0x4e;    // PCF8574  T  模块的地址码

//char ADDR = 0x7e;    // PCF8574   AT  模块的地址码

//***************************** 延时 y  ms ***********************************************

void delay1(int y)   //

{

;

while(y--)

{

unsigned char a,b,c;

for(c=1;c>0;c--)

for(b=142;b>0;b--)

for(a=2;a>0;a--);

}

}

//******************************** IIC 串口开始 ********************************************

void IIC_start(void)

{

SDA=1;

_nop_();

SCL=1;

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

SDA=0;

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

SCL=0;

_nop_();

_nop_();

}

//********************************** IIC 串口写1个字节 ******************************************

void IIC_writeByte(char temp)

{

char i;

for(i=0;i<8;i++)

{

SDA=(bit)(temp & 0x80) ;   // 根据规定1602的数据最高位必须为  1

temp <<=1;

_nop_();

_nop_();

SCL=1;

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

SCL=0;

}

_nop_();

_nop_();

_nop_();

_nop_();

SDA=1;

_nop_();

_nop_();

_nop_();

_nop_();

SCL=1;

_nop_();

_nop_();

_nop_();

while(SDA);

_nop_();

SCL=0;

}

//******************************** 1602写命令 ********************************************

void LCD_write_command(char comm)

{

char tmp;

IIC_start();          // 串口开始

IIC_writeByte(ADDR);  // 先选PCF 8574T 的地址  (应该是相当于选中的意思吧)

tmp = comm & 0xF0;    // 与0xf0 应该是取第四位的意思吧

tmp |= 0x0C;         //保留高4位为指令的高四位,低四位为   RS = 0, RW = 0, EN = 1

IIC_writeByte(tmp);  //从串口送出

delay1(20);

tmp &= 0xFB;        //Make EN = 0

IIC_writeByte(tmp);

tmp = (comm & 0x0F) << 4 ;  //将指令的低四位 送到高位置保存

tmp |= 0x0C;        //RS = 0, RW = 0, EN = 1

IIC_writeByte(tmp);

delay1(20);

tmp &= 0xFB; // Make EN = 0

IIC_writeByte(tmp);

}

//******************************** 1602写数据 ********************************************

void LCD_write_data(char data1)

{

char tmp;

IIC_start();

IIC_writeByte(ADDR);   // 先选PCF 8574T 的地址  (应该是相当于选中的意思吧)

tmp = data1 & 0xF0;

tmp |= 0x0D; //RS = 1, RW = 0, EN = 1

IIC_writeByte(tmp);

delay1(20);

tmp &= 0xFB; //Make EN = 0

IIC_writeByte(tmp);

tmp = (data1 & 0x0F) << 4 ;

tmp |= 0x0D; //RS = 0, RW = 0, EN = 1

IIC_writeByte(tmp);

delay1(20);

tmp &= 0xFB ; // Make EN = 0

IIC_writeByte(tmp);

}

//******************************** 1602初始化 ********************************************

void Init_Lcd(void)

{

LCD_write_command(0x33); //将8位总线转为4位总线

delay1(50) ;

LCD_write_command(0x32); //

delay1(50) ;

LCD_write_command(0x28); // 4位数据线,显示2行,5*7点阵字符  !如果是0x38  则为8位数据线,显示2行,5*7点阵字符

delay1(50) ;

LCD_write_command(0x0C); // 开显示,关闭光标,不闪烁

delay1(50) ;

LCD_write_command(0x06); // 设定输入方式,增量不位移

delay1(50) ;

LCD_write_command(0x01); // 清屏

delay1(50) ;

}

//*************************************** 在指定位置显示字符串 *************************************

void Write_LCD(int x, int y, char *str)

{

char addr;

if( x < 0)

{

x = 0;

}

if(x > 15)

{

x = 15;

}

if(y<0)

{

y = 0;

}

if(y > 1)

{

y = 1;

}

addr = 0x80 + 0x40 * y + x;   // Move cursor  移动光标

LCD_write_command(addr);

while (*str)

{

LCD_write_data(*str++);

}

}

//-------------------------------------------- 显示字符串的函数 ----------------------------------------------------

void LCD_write_word(unsigned char *s)                  //显示字符串的函数

{

while(*s>0)

{

LCD_write_data(*s);

s++;

}

}

//********************************* 指定位置显示一个字符*******************************************

/*

void Print_Char (unsigned char line,unsigned char num,unsigned char date)

{

LCD_write_command(line+num);

LCD_write_data(date);

}

*/

//按指定位置显示一个字符(针对1602液晶)-用在温度显示

void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)

{

Y &= 0x1;

X &= 0xF;                 //限制X不能大于15,Y不能大于1

if (Y) X |= 0x40;        //当要显示第二行时地址码+0x40;

X |= 0x80;               // 算出指令码

LCD_write_command(X);    //这里不检测忙信号,发送地址码

LCD_write_data(DData);

}

//--------------------------------------初始化----------------------------------------------------------------

void initial()

{

P1M0=0;

P1M1=0;

P2M0=0;

P2M1=0;

P0M0=0;

P0M1=0;

}

/*------------------------------------------------

按键扫描函数,返回扫描键值

------------------------------------------------*/

unsigned char KeyScan(void)  //键盘扫描函数,使用行列反转扫描法

{

uchar cord_h,cord_l;            //行列值中间变量

uchar tempt;

uint i;

KeyPort=0xf0;                                                    //列线输出全为0

cord_l=KeyPort&0xf0;     //读入行线值

if(cord_l!=0xf0)    //先检测有无按键按下

{

delay1(10);        //去抖

if(cord_l!=0xf0)

{

cord_l=KeyPort&0xf0;  //读入列线值

KeyPort=0x0f;                                        //行线输出为0

cord_h=KeyPort&0x0f;  //读入行线值

while((KeyPort&0x0f)!=0x0f);//等待松开并输出

tempt = cord_l+cord_h;

for(i=0;i<16;i++)

if(KEY_TABLE[i]==tempt)

break;

return(KEY_TABLE[i]);

}

}

return(0xff);     //返回该值

}

/*------------------------------------------------

按键值处理函数,返回扫键值

------------------------------------------------*/

unsigned char KeyPro(void)

{

switch(KeyScan())

{

case 0xee:return '0';break;//0 按下相应的键显示相对应的码值

case 0xde:return '1';break;//1

case 0xbe:return '2';break;//2

case 0x7e:return '3';break;//3

case 0xed:return '4';break;//4

case 0xdd:return '5';break;//5

case 0xbd:return '6';break;//6

case 0x7d:return '7';break;//7

case 0xeb:return '8';break;//8

case 0xdb:return '9';break;//9

case 0xbb:return 'a';break;//a

case 0x7b:return 'b';break;//b

case 0xe7:return 'c';break;//c

case 0xd7:return 'd';break;//d

case 0xb7:return 'e';break;//e

case 0x77:return 'f';break;//f

default:return 0xff;break;

}

}

//--------------------------------------------------------流水灯--------------------------------------------------------

void RuningLight()                                                                                                                                                                                                //流水灯

{

light=0xfe;

P2=light;

for(j=0;j<8;j++)

{ light<<=1 ;

delay1(250);

P2=light;

}

P2=0xff;

}

//--------------------------------------------------------密码验证--------------------------------------------------------

void VriefytPassword()                                                                                                                                                                        //验证密码

{        if(flag1)

m=sizeof(newpassword);                                                                                                                        //记录新密码的长度

else

m=sizeof(password);                                                                                                                                        //记录旧密码的长度

n=sizeof(passwordtemp);                                                                                                                        //记录输入密码的长度

if(m==n)                                                                                                        //长度判断

{

if(flag1)                                                                                                                                                                                        //修改密码后

for(j=0;j

{ if(passwordtemp[j]==newpassword[j])

Flag=0;

else

{ Flag=1;

break;

}

}

else                                                                                                                                                                                                //修改密码前

for(j=0;j

{ if(passwordtemp[j]==password[j])

Flag=0;

else

{ Flag=1;

break;

}

}

}

else

{         Flag=1;

Write_LCD(0,1,"                ");                //清除该行

delay1(10);

Write_LCD(0,1,"Wrong length!");                                //密码正确显示的信息

delay1(10);

}

if(Flag)                                                                                                                                        //输入错误提示和输入错误总次数判断,限定三次

{

Write_LCD(0,1,"                ");                //清除该行

delay1(10);

Write_LCD(0,1,"Wrong Retry!");                                //输入错误提示

for(j=0;j

passwordtemp[j]='\0';

inputtimes++;                                                                                                        //连续输入错误,则次数累加

i=0;

if(inputtimes==3)

{

Write_LCD(0,1,"                ");//清除该行

delay1(10);

Write_LCD(0,1,"Wrong 3 times!");//密码错误,提示重新输入

while(1)

P2=light2;                                                                                                 //停止该位置,重启电源后才能输入,实际实用中则需要等到一定时间后才能再次输入。

}

}

else

{

Write_LCD(0,1,"                ");//清除该行

delay1(10);

Write_LCD(0,1,"Right Open!>>>>");//密码正确显示的信息

P2=light1;

inputtimes=0;//输入正确则次数清零,重新计数

Flag=0;      //清除正确标志

i=0;

}

}

//--------------------------------------------------------修改密码时的密码验证--------------------------------------------------------

void SetPassword()                                                                                                                                                                                                                                        //设置新密码时,先验证

{ while(1)

{ num=KeyPro();  //扫描键盘

if(num!=0xff)  //如果扫描是按键有效值则进行处理

{

if(i==0)

Write_LCD(0,1,"                ");//清除该行

if(num=='f')                                                                                                                                                                                        //确定键按下,进入判断密码对错

{

i=0;

if(flag1)

m=sizeof(newpassword);

else

m=sizeof(password);

n=sizeof(passwordtemp);

if(m==n)                                                                                                        //长度判断

{ if(flag1)

for(j=0;j

{ if(passwordtemp[j]==newpassword[j])

Flag=0;

else

{ Flag=1;

break;

}

}

for(j=0;j

{ if(passwordtemp[j]==password[j])

Flag=0;

else

{ Flag=1;

break;

}

}

}

else

{  Flag=1;

Write_LCD(0,1,"                ");                //清除该行

delay1(10);

Write_LCD(0,1,"Wrong length!");                                //密码正确显示的信息

delay1(10);

i=0;

P2=light2;

inputtimes++;

}

if(Flag)                                                                                                                                        //输入错误提示和输入错误总次数判断,限定三次

{

Write_LCD(0,1,"                ");                //清除该行

delay1(10);

Write_LCD(0,1,"Wrong Retry!");                                //密码错误

for(j=0;j

passwordtemp[j]='\0';

inputtimes++;                                                                                                        //连续输入错误,则次数累加

if(inputtimes==3)

{

Write_LCD(0,1,"                ");//清除该行

delay1(10);

Write_LCD(0,1,"Wrong 3 times!");//密码错误,提示重新输入

while(1)

P2=light2;                                                                                                 //停止该位置,重启电源后才能输入,实际实用中则需要等到一定时间后才能再次输入。

}

}

else

{

Write_LCD(0,1,"                ");//清除该行

delay1(10);

Write_LCD(0,1,"Right Password!");//密码正确

RuningLight();

i=0;

inputtimes=0;//输入正确则次数清零,重新计数

Flag=0;      //清除正确标志

break;

}

}

else                                                                                                                                                                 //没有按确定键,保存键值

{

if(i<16)

{

passwordtemp[i]=num;                                                                                //保存密码

DisplayOneChar(i,1,num);                                                                //输入的密码用"*"代替

i++;                                                                                                                                                //计数,不能超过16位

}

else

{        Write_LCD(0,1,"                ");//清除该行

delay1(10);

Write_LCD(0,1,"Too Many Retry");

inputtimes++;

i=0;

P2=light2;

}

}

}

}

}

//--------------------------------------------------------新密码输入--------------------------------------------------------

void NewPasswordInput()                                                                                                                                                                                                        //新密码输入

{

while(1)

{        num=KeyPro();  //扫描键盘

if(num!=0xff)  //如果扫描是按键有效值则进行处理

{

if(i==0)

Write_LCD(0,1,"                ");//清除该行

if(num=='f')

{ i=0;

RuningLight();

break;

}

else if(i<16)                                                                                                                                                        //新密码不能超过16位

{

newpassword[i]=num;                                                                                //保存密码

DisplayOneChar(i,1,num);                                                                //显示新密码

i++;                                                                                                                                                //计数,不能超过16位

}

else

{        i=0;

Write_LCD(0,1,"                ");                        //清除该行

delay1(10);

Write_LCD(0,1,"Too Many Retry");                                //输入过多,报错

delay1(10);

for(j=0;j

newpassword[j]='\0';

P2=light2;

Write_LCD(0,1,"                ");                                                                                        //清除该行

delay1(10);

Write_LCD(0,1,"new password!");                                                                                                 //重新输入新密码

delay1(10);

}

}

}

}

//--------------------------------------------------------确认修改的密码--------------------------------------------------------

void AgainInput()                                                                                                                                                                                                                //新密码确认

{

while(1)

{

num=KeyPro();  //扫描键盘

if(num!=0xff)  //如果扫描是按键有效值则进行处理

{ if(i==0)

Write_LCD(0,1,"                ");//清除该行

if(num=='f')

{

i=0;

n=sizeof(passwordtemp);

m=sizeof(newpassword);

if(m==n)                                                                                                        //长度判断

{

for(j=0;j

{ if(passwordtemp[j]==newpassword[j])

Flag=0;

else

{ Flag=1;

break;

}

}

}

else

Flag=1;

if(Flag)                                                                                                                                        //输入错误提示和输入错误总次数判断,限定三次

{

Write_LCD(0,1,"                ");                //清除该行

delay1(10);

Write_LCD(0,1,"Difference!!");                                //密码正确显示的信息

for(j=0;j

passwordtemp[j]='\0';

i=0;

Flag=0;

P2=light2;

}

else

{

Write_LCD(0,1,"                ");//清除该行

delay1(10);

Write_LCD(0,1,"Right!");                                        //密码正确显示的信息

delay1(10);

Write_LCD(0,1,"                ");//清除该行

delay1(10);

Write_LCD(0,1,"Finish!");

RuningLight();

Write_LCD(0,1,"                ");//清除该行

delay1(10);

Write_LCD(0,1,"Right Open>>>");//清除该行

P2=light1;

inputtimes=0;//输入正确则次数清零,重新计数

Flag=0;      //清除正确标志

i=0;

break;

}

}

else if(i<16)                                                                                                                                                                                                        //密码不能超过16位

{

passwordtemp[i]=num;                                                                                //保存密码

DisplayOneChar(i,1,num);                                                                //显示新密码

i++;                                                                                                                                                //计数,不能超过16位

}

else

{        Write_LCD(0,1,"                ");                        //清除该行

delay1(10);

Write_LCD(0,1,"Too Many Retry");                                //输入过多,报错

delay1(10);

for(j=0;j

passwordtemp[j]='\0';

i=0;                                                                                                                                                //重新输入

P2=light2;

Write_LCD(0,1,"                ");                        //清除该行

delay1(10);

Write_LCD(0,1,"Input New Again!");                        //重新输入新密码

delay1(10);

}

}

}

}

//--------------------------------------------------------主函数--------------------------------------------------------

void main()

{

initial();

Init_Lcd();         //初始化液晶屏

delay1(10);        //延时用于稳定,可以去掉

Write_LCD(0,0,"  Welcome! ");    //写入第一行信息,主循环中不再更改此信息,所以在while之前写入

delay1(10);

Write_LCD(0,1,"Input password!");    //写入第二行信息,提示输入密码

delay1(10);

while (1)         //主循环

{

num=KeyPro();  //扫描键盘

if(num!=0xff)  //如果扫描是按键有效值则进行处理

{

if(i==0)

Write_LCD(0,1,"                ");                                                                                                //清除该行

if(num=='e')                                                                                                                                                                                        //设置新密码

{ P2=0xff;

for(j=0;j

newpassword[j] = '\0';

Write_LCD(0,1,"Set Password!");

delay1(10);

Write_LCD(0,1,"                ");                                                                                        //清除该行

delay1(10);

Write_LCD(0,1,"Input Password!");                                                                                                //用户验证

delay1(10);

SetPassword();                                                                                                                                                                        //验证密码

P2=0xff;

Write_LCD(0,1,"                ");                                                                                        //清除该行

delay1(10);

Write_LCD(0,1,"New Password!");                                                                                                         //新密码输入

delay1(10);

NewPasswordInput();                                                                                                                                                        //新密码输入

P2=0xff;

Write_LCD(0,1,"                ");

delay1(10);

Write_LCD(0,1,"Again Input!!");

AgainInput();                                                                                                                                                                                //新密码确认

for(j=0;j

passwordtemp[j] = '\0';

flag1=1;                                                                                                                                                                                                        //修改密码标志位

}

else if(num=='f')                                                                                                                                                                                        //确定键按下,进入判断密码对错

{ i=0;                                                                                                                                                                                                        //清除输入标志

VriefytPassword();                                                                                                                                                //密码认证

}

else if(num=='b')                                                                                                                                                                //上锁

{

P2=0xff;

delay1(10);

Write_LCD(0,1,"                ");                                                                                        //清除该行

delay1(10);

Write_LCD(0,1,"Input password!");

i=0;

for(j=0;j

passwordtemp[j] ='\0';

}

else                                                                                                                                                                                                                //没有按确定键,上锁键,设置键,保存键值

{

if(i<16)

{

passwordtemp[i]=num;                                                                                //保存密码

DisplayOneChar(i,1,num);                                                                //输入的密码用"*"代替

i++;                                                                                                                                                //计数,不能超过16位

}

else

{        Write_LCD(0,1,"                ");//清除该行

delay1(10);

Write_LCD(0,1,"Too Many Retry");

inputtimes++;

i=0;

}

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值