单片机设计程序.docx
《单片机设计程序.docx》由会员分享,可在线阅读,更多相关《单片机设计程序.docx(30页珍藏版)》请在冰豆网上搜索。
单片机设计程序
用STC52编的,下面是C程序,调试已经成功,自己看程序吧……
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineLCD_dataP0
sbitSDA=P3^5;
sbitSCL=P3^4;//24C08控制口设置
sbitLCD_RS=P3^3;//寄存器选择输入
sbitLCD_RW=P3^6;//液晶读/写控制
sbitLCD_EN=P3^7;//液晶使能控制
sbitLCD_PSB=P3^2;//串/并方式控制
sbitFM=P2^4;//蜂鸣器控制口
sbitRS=P2^5;
sbitT_CLK=P2^0;//实时时钟时钟线引脚//
sbitT_IO=P2^1;//实时时钟数据线引脚//
sbitT_RST=P2^2;//实时时钟复位线引脚//
sbitds=P2^3;
sbitEN=P2^6;
sbitZZ=P2^7;
sbitFZ=P3^1;
sbitACC0=ACC^0;
sbitACC7=ACC^7;
uinttemp1,s_temp;//定义整形变量
floatf_temp;//定义浮点型变量
uchartime[]=":
:
";
ucharday[]="20//()";
uchartemp0[]="温度:
.度";
ucharnum,num1,flag,count,a,b;
ucharunlock_i;//解密标志位
uchart[4];
uchart1[4];
voiddelay_ms(uintz)//长延时
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
voiddelay()//短延时,大约5us
{
;;
}
voidreshi()
{
if(RS==1)
{unlock_i=1;
}
else
{
unlock_i=0;
}
}
ucharcodemima[]={'0','1','2','3','4','5','6','7','8','9','0','*'};
voidlcd_xieping0(ucharx,uchary,uchardate);
voidlcd_xieping(ucharx,uchary,uchar*str);
//********************************************************
//开机显示
//********************************************************
voidkjxs()
{
uinti,j;
lcd_xieping(0,0,"****************");
lcd_xieping(1,0,"欢迎进入");
lcd_xieping(2,0,"密码锁系统!
");
lcd_xieping(3,0,"****************");
delay_ms(4000);
lcd_xieping(0,0,"系统初始化中");
lcd_xieping(1,0,"请稍后…");
lcd_xieping(2,0,"————————");
lcd_xieping(3,0,"");
for(j=3;j>0;j--)
{
for(i=0;i<8;i++)
{
lcd_xieping(3,i,"*");
delay_ms(250);
}
lcd_xieping(3,0,"");
}
}
//********************************************************
//12864显示
//********************************************************
voidwrite_cmd(ucharcmd)
{
LCD_RS=0;
LCD_RW=0;
LCD_EN=0;
P0=cmd;
delay_ms(5);
LCD_EN=1;
delay_ms(5);
LCD_EN=0;
}
voidwrite_dat(uchardat)
{
LCD_RS=1;
LCD_RW=0;
LCD_EN=0;
P0=dat;
delay_ms(5);
LCD_EN=1;
delay_ms(5);
LCD_EN=0;
}
voidlcd_xieping0(ucharx,uchary,uchardate)
{
switch(x)
{
case0:
write_cmd(0x80+y);break;
case1:
write_cmd(0x90+y);break;
case2:
write_cmd(0x88+y);break;
case3:
write_cmd(0x98+y);break;
}
write_dat(date);
}
voidlcd_xieping(ucharx,uchary,uchar*str)
{
switch(x)
{
case0:
write_cmd(0x80+y);break;
case1:
write_cmd(0x90+y);break;
case2:
write_cmd(0x88+y);break;
case3:
write_cmd(0x98+y);break;
}
while(*str)
{
write_dat(*str);
str++;
}
}
voidlcd_init()
{
LCD_PSB=1;//并口方式
write_cmd(0x30);//基本指令操作
delay_ms(5);
write_cmd(0x0C);//显示开,关光标
delay_ms(5);
write_cmd(0x01);//清除LCD的显示内容
delay_ms(5);
}
//**************************************************************
//键盘扫描函数
//**************************************************************
ucharkeyscan1()//矩阵键盘扫描函数
{
uchartemp;
while(!
num)
{P1=0xfe;//赋值
temp=P1;//读回数据
temp=temp&0xf0;//与运算
if(temp!
=0xf0)//判断
{
delay_ms
(2);//延时消抖
temp=P1;//读回数据
temp=temp&0xf0;
if(temp!
=0xf0)
{
switch(temp)//多分支选择
{
case0x70:
num=1;break;//跳出
case0xb0:
num=2;break;
case0xd0:
num=3;break;
case0xe0:
num=4;break;
}
while(temp!
=0xf0)
{
temp=P1;
temp=temp&0xf0;
}//等待按键释放
}
}
P1=0xfd;//赋值
temp=P1;//读回数据
temp=temp&0xf0;//与运算
if(temp!
=0xf0)//判断
{
delay_ms
(2);//延时消抖
temp=P1;//读回数据
temp=temp&0xf0;
if(temp!
=0xf0)
{
switch(temp)//多分支选择
{
case0x70:
num=5;break;//跳出
case0xb0:
num=6;break;
case0xd0:
num=7;break;
case0xe0:
num=8;break;
}
while(temp!
=0xf0)
{
temp=P1;
temp=temp&0xf0;
}//等待按键释放
}
}
P1=0xfb;//赋值
temp=P1;//读回数据
temp=temp&0xf0;//与运算
if(temp!
=0xf0)//判断
{
delay_ms
(2);//延时消抖
temp=P1;//读回数据
temp=temp&0xf0;
if(temp!
=0xf0)
{
switch(temp)//多分支选择
{
case0x70:
num=9;break;//跳出
case0xb0:
num=10;break;
case0xd0:
num=11;break;
case0xe0:
num=12;break;
}
while(temp!
=0xf0)
{
temp=P1;
temp=temp&0xf0;
}//等待按键释放
}
}
}
return(num);//返回值
}
ucharkeyscan2()
{
uchartemp;
while(!
num1)
{P1=0xf7;//赋值
temp=P1;//读回数据
temp=temp&0xf0;//与运算
if(temp!
=0xf0)//判断
{
delay_ms
(2);//延时消抖
temp=P1;//读回数据
temp=temp&0xf0;
if(temp!
=0xf0)
{
switch(temp)//多分支选择
{
case0x70:
num1=1;break;//跳出
case0xb0:
num1=2;break;
case0xd0:
num1=3;break;
case0xe0:
num1=4;break;
}
while(temp!
=0xf0)
{
temp=P1;
temp=temp&0xf0;
}//等待按键释放
}
}
}
return(num1);
}
//**************************************************************
//直流电机
//**************************************************************
voiddianjiZZ()
{
EN=1;
ZZ=1;
FZ=0;
}
voiddianjiFZ()
{
EN=1;
ZZ=0;
FZ=1;
}
voiddianji_stop()
{
EN=0;
}
//**************************************************************
//EPPROM
//**************************************************************
voidstart()//启动信号
{
SDA=1;
delay();
SCL=1;
delay();
SDA=0;
delay();
}
voidstop()//停止信号
{
SDA=0;
delay();
SCL=1;
delay();
SDA=1;
delay();
}
voidrespons()//响应信号
{
uchari;
SCL=1;
delay();
while((SDA==1)&&(i<250))
i++;
SCL=0;
delay();
}
voidwritebyte(uchardate)//写一个字节
{
uchari,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
SCL=0;
delay();
SDA=CY;
delay();
SCL=1;
delay();
}
SCL=0;
delay();
SDA=1;//释放总线
delay();
}
ucharreadbyte()//读一个字节
{
uchari,k;
SCL=0;
delay();
SDA=1;
for(i=0;i<8;i++)
{
SCL=1;
delay();
k=(k<<1)|SDA;
SCL=0;
delay();
}
delay();
return(k);
}
voidwrite(ucharadd,uchardate)//在一个地址写一个字节
{
start();
writebyte(0xa0);
respons();
writebyte(add);
respons();
writebyte(date);
respons();
stop();
}
ucharread(ucharadd)//在一个地址读一个字节
{
start();
writebyte(0xa0);
respons();
writebyte(add);
respons();
start();
writebyte(0xa1);
respons();
b=readbyte();
respons();
stop();
return(b);
}
//**************************************************************
//时间日期函数
//**************************************************************
voidv_WTInputByte(ucharucDa)
{
uchari;
ACC=ucDa;
for(i=8;i>0;i--)
{
T_IO=ACC0;//*相当于汇编中的RRC
T_CLK=1;
T_CLK=0;
ACC=ACC>>1;
}
}
ucharuc_RTOutputByte(void)
{
uchari;
for(i=8;i>0;i--)
{
ACC=ACC>>1;//*相当于汇编中的RRC
ACC7=T_IO;
T_CLK=1;
T_CLK=0;
}
return(ACC);
}
voidv_W1302(ucharucAddr,ucharucDa)
{
T_RST=0;
T_CLK=0;
T_RST=1;
v_WTInputByte(ucAddr);/*地址,命令*/
v_WTInputByte(ucDa);/*写1Byte数据*/
T_CLK=1;
T_RST=0;
}
ucharuc_R1302(ucharucAddr)
{
ucharucDa;
T_RST=0;
T_CLK=0;
T_RST=1;
v_WTInputByte(ucAddr);//地址,命令//
ucDa=uc_RTOutputByte();//读1Byte数据//
T_CLK=1;
T_RST=0;
return(ucDa);
}
voidInit1302(void)
{
v_W1302(0x8e,0x00);//控制写入WP=0
v_W1302(0x80,0x80);
v_W1302(0x90,0xa9);
v_W1302(0x80,0x00);//秒
v_W1302(0x82,0x24);//分
v_W1302(0x84,0x12);//时
v_W1302(0x86,0x29);//日
v_W1302(0x88,0x10);//月
v_W1302(0x8a,0x05);//星期
v_W1302(0x8c,0x10);//年//
v_W1302(0x8e,0x80);
}
voiddonetime(void)
{
uchard;
d=uc_R1302(0x87);
day[10]=(d&0x0f)+48;
day[9]=((d>>4)&0x03)+48;
d=uc_R1302(0x89);
day[7]=(d&0x0f)+48;
day[6]=((d>>4)&0x01)+48;
d=uc_R1302(0x8b);
day[13]=(d&0x07)+48;
d=uc_R1302(0x8d);
day[4]=(d&0x0f)+48;
day[3]=(d>>4)+48;
d=uc_R1302(0x81);
time[15]=(d&0x0f)+48;
time[14]=(d>>4)+48;
d=uc_R1302(0x83);
time[12]=(d&0x0f)+48;
time[11]=(d>>4)+48;
d=uc_R1302(0x85);
time[9]=(d&0x0f)+48;
time[8]=(d>>4)+48;
}
//**************************************************************
//温度检测函数
//**************************************************************
voiddsreset(void)//18B20复位,初始化函数
{
uinti;
ds=0;
i=103;
while(i>0)i--;
ds=1;
i=4;
while(i>0)i--;
}
bittempreadbit(void)//读1位函数
{
uinti;
bitdat;
ds=0;i++;//i++起延时作用
ds=1;i++;i++;
dat=ds;//读数据
i=8;while(i>0)i--;
return(dat);
}
uchartempread(void)//读1个字节
{
uchari,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tempreadbit();
dat=(j<<7)|(dat>>1);//读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat);
}
voidtempwritebyte(uchardat)//向18B20写一个字节数据
{
uinti;
ucharj;
bittestb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;//判断最后一位是1还是0
dat=dat>>1;
if(testb)//写1
{
ds=0;
i++;i++;
ds=1;
i=8;while(i>0)i--;
}
else
{
ds=0;//写0
i=8;while(i>0)i--;
ds=1;
i++;i++;
}
}
}
voidtempchange(void)//DS18B20开始获取温度并转换
{
dsreset();//初始化,每次对18B20的操作都首先要初始化
delay_ms
(1);
tempwritebyte(0xcc);//写跳过读ROM指令
tempwritebyte(0x44);//写温度转换指令
}
voidget_temp()//读取寄存器中存储的温度数据
{
uchara,b;
dsreset();//初始化
delay_ms
(1);
tempwritebyte(0xcc);//写跳过读ROM指令
tempwritebyte(0xbe);//写读指令
a=tempread();//读低8位
b=tempread();//读高8位
temp1=b;
temp1<<=8;//两个字节组合为1个字
temp1=temp1|a;
f_temp=temp1*0.0625;//温度在寄存器中为12位分辨率位0.0625°
}
//**************************************************************
//解密函数
//**************************************************************
voidunlock()
{
ucharin,i;
if(num==0)
{
l