原创 整版测试2:数码管+DS1302+DS18B20+蜂鸣器+独立按键

2011-3-24 09:06 1959 7 7 分类: MCU/ 嵌入式

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

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条