attachment download/*****整版测试2:数码管+DS1302+DS18B20+蜂鸣器+独立按键*****/
//现象:按照位定义用杜邦线连接好相应的电路,然后按独立按键
//(也就是外部中断按键),每按下一次会(蜂鸣器响一声)
//相应依次显示时间、日期、温度
//在显示温度时,可以用手触摸DS18B20,温度值会上升
//松手后温度值会下降
/****作者:爱因斯尼@SCUT***/
/****时间:2010.08.29******/
//注意:
//{设置日期和时间初值(默认是2010.8.31星期2 19:12:00)以后,可以在main函数中把函数set_rtc();
//去掉,这样可以保证51烧了其他程序后,再次烧写这个程序
//后,而时间还是正确的(电池供电的前提下)}
#include<reg52.h>//51单片机的头文件
#include<intrins.h>
#define uint unsigned int//两个常用的宏定义
#define uchar unsigned char
//#define port P3
//sbit DS=P1^0; //串行数据输入
//sbit OE=P1^1; //输出有效(低电平)
//sbit SH=P1^2; //移位寄存器时钟输入
//sbit ST=P1^3; //存储寄存器时钟输入
sbit bell=P1^4;//位定义蜂鸣器接口
sbit duan=P1^5;//位定义数码管的段选端
sbit wei=P1^6;//位定义数码管的位选端
sbit lie=P1^7;//位定义8*8点阵的列选端
sbit rst=P3^0;//位定义DS1302
sbit io=P3^1;
sbit sck=P3^3;
sbit key=P3^2;//模式切换
sbit DQ= P3^4;//DS18B20接入口
uchar mo=0;//定义模式选择变量
/***数码管字模,放在程序的代码区***/
uchar code SMG_table[]={
0xfc,0x60,0xda,0xf2,//0,1,2,3,
0x66,0xb6,0xbe,0xe0, //4,5,6,7,
0xfe,0xf6,0xee,0x3e, //8,9,A,b,
0x9c,0x7a,0x9e,0x8E,0x01,0x01,0x02};//C,d,E,F,小数点'.'
uchar time_dat[7]={10,8,31,2,19,12,00};//年月日周时分秒
uchar wr_add[7]={0x8c,0x88,0x86,0x8a,0x84,0x82,0x80};//写地址
uchar read_add[7]={0x8d,0x89,0x87,0x8b,0x85,0x83,0x81};//度地址
uchar disp1[8];//保存读到的时分秒
uchar disp2[8];//保存读到的年月日周
/************************************************************/
/*void delay(uchar ms)
{uchar mk=1141;while(ms--)while(mk--);}*/
/***带形参的延时子函数***/
void delay_us(uint m)
{uint i,j;
for(i=0;i<m;i++)
for(j=0;j<50;j++); }
/****带两个形参的数码管显示子函数****/
void show(uchar num,uchar awei)
{uchar aa=0x7f;
P0=0X00;
duan=1;
P0=SMG_table[num];
duan=0;
P0=0xff;
wei=1;
P0=(aa>>awei)|(aa<<(8-awei));
delay_us(2);
wei=0;
}
/*********数码管的初始化函数***************/
void Init_smg()
{
P0=0x00;
duan=1;
P0=0x00;//关段选端
duan=0;
P0=0xff;
wei=1;
P0=0xff;//关位选端
wei=0;
lie=1;
P0=0xff;//点阵全灭
lie=0;
}
/********外部中断0处理子函数*********/
void INT_wai0() interrupt 0 using 1
{
bell=~bell;
delay_us(80);//按一次外部中断0蜂鸣器响一下
bell=~bell;
if(mo<2 ) mo++;
else mo=0;
}
/*****写一个字节*****/
void wr_ds1302_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
sck=0;
io=dat&0x01;
dat=dat>>1;
sck=1;
}
}
/*****在一个地址写入一个data*****/
void wr_ds1302(uchar add,uchar dat)
{
rst=0;
_nop_();
sck=0;
_nop_();
rst=1;
_nop_();
wr_ds1302_byte(add);
wr_ds1302_byte(dat);
rst=0;
_nop_();
io=1;
sck=1;
}
/*****读取相应地址的数值*****/
uchar read_ds1302(uchar add)
{ uchar i,value;
rst=0;
_nop_();
sck=0;
_nop_();
rst=1;
_nop_();
wr_ds1302_byte(add);
for(i=0;i<8;i++)
{value=value>>1;
sck=0;
if(io)
{value=value|0x80;}
sck=1;
}
rst=0;
_nop_();
sck=0;
_nop_();
sck=1;
io=1;
return value;//返回值
}
/*****对DS1302时钟时间进行初始化设置*****/
void set_rtc()
{uchar i,j;
for(i=0;i<7;i++)
{
j=time_dat/10;
time_dat=time_dat%10;
time_dat=time_dat+j*16;
}
wr_ds1302(0x8e,0x00);//去除写保护
for(i=0;i<7;i++)
{
wr_ds1302(wr_add,time_dat);
}
wr_ds1302(0x8e,0x80);
}
/*****读取DS1302的当前的时间值*****/
void read_rtc()
{
uchar i;
for(i=0;i<7;i++)
{
time_dat=read_ds1302(read_add);
}
}
/*****对读取到的时间进行转换,用于数码管的显示(时分秒)*****/
void time_pros1()
{
disp1[7]=time_dat[6]%16;
disp1[6]=time_dat[6]/16;
disp1[5]=18;
disp1[4]=time_dat[5]%16;
disp1[3]=time_dat[5]/16;
disp1[2]=18;
disp1[1]=time_dat[4]%16;
disp1[0]=time_dat[4]/16;
}
/*****对读取到的时间进行转换,用于数码管的显示(年月日周)*****/
void time_pros2()
{
disp2[7]=time_dat[3]%16;
disp2[6]=time_dat[3]/16;
disp2[5]=time_dat[2]%16;
disp2[4]=time_dat[2]/16;
disp2[3]=time_dat[1]%16;
disp2[2]=time_dat[1]/16;
disp2[1]=time_dat[0]%16;
disp2[0]=time_dat[0]/16;
}
/*****显示时分秒*****/
void display1()
{
uchar i;
for(i=0;i<8;i++)
{
show(disp1,i);
delay_us(2);
}
}
/*****显示年月日周*****/
void display2()
{
uchar i;
for(i=0;i<8;i++)
{
show(disp2,i);
delay_us(2);
}
show(17,1);show(16,3);show(16,5); //显示小数点
}
/*****延时子函数*****/
void delay_DS18B20(uint num)
{while(num--) ;
}
/*************DS18b20温度传感器函数*********************/
Init_DS18B20() //传感器初始化
{
uchar x=0;
DQ=1; //DQ复位
delay_DS18B20(10); //稍做延时
DQ=0; //单片机将DQ拉低
delay_DS18B20(80); //精确延时 大于 480us
DQ=1; //拉高总线
delay_DS18B20(20);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay_DS18B20(30);
}
/***读一个字节***/
Read_OneChar()
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DQ=0; // 给脉冲信号
dat>>=1;
DQ=1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_DS18B20(8);
}
return(dat);
}
/***写一个字节***/
Write_OneChar(uchar dat)
{
uchar i=0;
for (i=8; i>0; i--)
{
DQ=0;
DQ=dat&0x01;
delay_DS18B20(10);
DQ=1;
dat>>=1;
}
delay_DS18B20(8);
}
/***读取温度***/
int Read_Temperature()
{
uchar a=0;
uchar b=0;
int t=0;
float tt=0;
Init_DS18B20();
Write_OneChar(0xCC); // 跳过读序号列号的操作
Write_OneChar(0x44); // 启动温度转换
Init_DS18B20();
Write_OneChar(0xCC); //跳过读序号列号的操作
Write_OneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=Read_OneChar();//低位(先低后高)
b=Read_OneChar();//高位
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
t= tt*10+0.5;
return(t);
}
/******显示函数*****/
void display(uchar bai,uchar shi,uchar ge)
{show(bai,5);
show(shi,6);
show(16,6);
show(ge,7);
}
/**************只是显示当前的所测的温度****************/
void show_DS18B20()
{int temp;
uchar bai,shi,ge;
// while(1)
{temp=Read_Temperature();//读温度
bai=temp%1000/100;//显示百位
shi=temp%100/10;//显示十位
ge=temp%10;//显示个位
display(bai,shi,ge);//显示函数
}
}
/*****主函数******/
void main()
{Init_smg();
EA=1;
IT0=1;
EX0=1;
set_rtc(); //设置初始时间
while(1)
{read_rtc();
time_pros1();
time_pros2();
switch(mo) //模式选择
{
case 0:display1();break; //显示时分秒
case 1:display2();break; //显示年月日周
case 2:show_DS18B20();break; //显示当前温度值
default:display1();break; //默认情况下是显示时分秒
}
}
}
欢迎光临我们的淘宝网店:http://item.taobao.com/auction/item_detail.htm?item_num_id=9447334857
文章评论(0条评论)
登录后参与讨论