自己做的,有不足的地方请指出,一起学习进步!
这个设计由单片机最小系统、温度传感模块 (DS18B20)、显示模块(LCD1602)、按键模块和声光报警模块组成。
功能:①显示 时—分—秒和实时温度;②可以通过按键调整显示时间,还可以调整声光报警(7秒后自动关闭)的时间,并且还可以手动关闭声光报警
电路图和系统各框图:
单片机程序:
- #include <reg51.h>
- #include <intrins.h> //包含_nop_空函数指令的头文件
- #include <stdio.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define out P0
- uchar date[20]; //存放温度值
- sbit RS=P3^5; // 寄存器选择(1——数据寄存器;0——命令/状态寄存器)
- sbit RW=P3^6; // 读/写操作选择(1——读;0——写)
- sbit E=P3^4; // 使能信号
- sbit voise=P2^3; //蜂鸣器链接口
- sbit beeled=P1^7; //LED灯接口
- sbit CON = P3^0;
- sbit UP = P3^1;
- sbit DOWN = P3^2;
- sbit START= P3^3;
- sbit ds = P2^2; //温度传感器的输入/输出引脚
- void keyScan(); //按键调时间
- void keyclockdown(); //按下按键关闭闹钟
-
- void init(); //定时器T0的初始化
- void TIME(); //实现时间变化
- void lcd_initial(); //lcd1602初始化
- void check_busy(); //检查忙碌标志位
- void write_command(uchar com); //写命令
- void wtite_data(uchar dat); //写数据
- void string(uchar ad,uchar *s); //显示字符串
- uchar dis[ ]={0x30,0x38,0x2d,0x35,0x39,0x2d,0x35,0x37,'\0'}; //dis[]={0,8,-,5,9,-,5,7}
- void delayMs(uint a);
- void delay(uint);
- void bee(); //蜂鸣器
- uchar flag;
- uchar num;
- uchar over=0;
- void aoto(); //7s后自动关闭闹铃
- uchar a=0x30,b=0x38,c=0x30,d=0x30,e=0x30,f=0x30;
- void dsInit(); //DS18B20复位,初始化函数
- void dsWait();
- bit readBit(); //读一位数据函数
- unsigned char readByte(); //读一个字节数据函数
- void writeByte(unsigned char dat); //向DS18B20写一个字节数据函数
- void sendChangeCmd(); //DS18B20开始获取温度并转换
- void sendReadCmd(); //读取寄存器中存储的温度数据
- int getTmpValue(); //得到温度
- //*************************************************************
- void main()
- {
- float temp=0.0;
- lcd_initial (); //液晶显示初始化
- init(); //定时器的初始化
- while(1)
- {
- bee();
- keyScan(); //按键调时间
- keyclockdown(); //按下按键关闭闹钟
- aoto();
- delay(200);
- string(0x80,"TIME:");
- delay(200);
- string(0xcb,"^C");
- string(0x86,dis);
- delay(200);
- temp=getTmpValue()/100.0;
- sendChangeCmd();
- sprintf(date,"TEMP: %0.2f",temp);
- string(0xc0,date);
- delay(200);
- }
- }
- //**************************************************************
- //延迟函数
- void delayMs(uint a)
- {
- uint i, j;
- for(i = a; i > 0; i--)
- for(j = 100; j > 0; j--);
- }
- void delay (uint j) //延迟
- {
- uchar i=10;
- for(;j>0;j--)
- {
- while(--i);
- i=10;
- while(--i);
- i=10;
-
- }
- }
- //********************************************************
- void init() //定时器的初始化
- {
- TMOD=0x01; //定时器T0的方式1
- TH0=(65536-50000)/256; //50ms
- TL0=(65536-50000)%256;
- EA=1; //总中断允许
- ET0=1; //启动定时器T0中断
- TR0=1; //启动定时器T0
- }
- void timer0() interrupt 1 //T0中断程序
- {
- TH0=(65536-50000)/256; //50ms
- TL0=(65536-50000)%256;
- num++ ;
- TIME(); //实现时间变化
- }
- //***********************************************************
- void lcd_initial () //液晶显示初始化
- {
- write_command(0x38); //写入命令0x38;8位2行显示,5×7点阵字符
- _nop_();
- write_command(0x0c); //写入命令0x0c;整体显示,光标关闭,无闪烁
- _nop_();
- write_command(0x06); //写入命令0x05;光标右移
- _nop_();
- write_command(0x01); //写入命令0x01;清屏
- delay(1);
- }
- void check_busy () //检查忙标志
- {
- uchar dt; //dt变量单元 ,忙状态标志 0:不忙,0x80:忙
- do
- {
- dt=0xff; // 先往数据端口赋高电平,便于读数据
- E=0;
- RS=0;
- RW=1; //读
- E=1; // 数据端口读写使能
- dt=out; // 读数据端口的值
- }while(dt&0x80); // 如果忙位BF为1,就一直读端口数据,直到为0才退出忙判断。
- // BF:忙标志位,为数据端口的BIT7位。所以为0x80。
- E=0;
- }
- void write_command (uchar com) //写命令
- {
- check_busy();
- E=0; //RS=E=0;才可以写入命令
- RS=0;
- RW=0;
- out=com;
- E=1;
- _nop_(); //空操作1个机械周期
- E=0;
- delay(1);
- }
- void write_data (uchar dat) //写数据
- {
- check_busy(); //检测忙标志位BF=1则等待,BF=0则可对LCD写入
- E=0; //写数据时,E为正脉冲,所以E置0
- RS=1; //RS=1,RW=1时,才可以写入数据
- RW=0;
- out=dat; //将数据dat从P0口输出,即写入LCD
- E=1; //E产生正跳变
- _nop_(); //空操作1个机械周期
- E=0; //E由高电平变低电平,写操作结束
- delay(1);
- }
- void string(uchar ad,uchar *s)
- {
- write_command(ad);
- while(*s>0)
- {
- write_data(*s++); //输出字符传,指针加1
- delay(1);
- }
- }
- //*****************************************************
- void TIME() //实现时分秒变化
- {
- if(num==20)
- {
- num=0;
- over++;
- dis[7]++;
- if(dis[7]>0x39) //秒
- {
- dis[7]=0x30;
- dis[6]++;
- }
- if(dis[6]==0x36)
- {
- dis[6]=0x30;
- dis[4]++;
- }
- if(dis[4]>0x39) //分
- {
- dis[4]=0x30;
- dis[3]++;
- }
- if(dis[3]==0x36)
- {
- dis[3]=0x30;
- dis[1]++;
- }
- if(dis[1]>0x39) //时
- {
- dis[1]=0x30;
- dis[0]++;
- }
- if(dis[0]==0x32)
- {
- if(dis[1]>0x33)
- {
- dis[0]=0x30;
- dis[1]=0x30;
- }
- }
- }
- }
- //*******************************************************
- //扫描键盘程序
- void keyScan()
- {
- static uchar key;
- if(!CON){ while(!CON);key++;}
- if(key)
- {
- TR0=0; //时间先停下,再调整
- P1=~(key%7); //指示灯
- switch(key%7)
- {
- case 6: if(!UP) //秒的个位
- {
- while(!UP);
- dis[7]++;
- if(dis[7]>0x39) dis[7]=0x30;
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[7]--;
- if(dis[7]<0x30) dis[7]=0x39;
- }
- break;
- case 5: if(!UP) //秒的十位
- {
- while(!UP);
- dis[6]++;
- if(dis[6]>0x35) dis[6]=0x30;
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[6]--;
- if(dis[6]<0x30) dis[6]=0x35;
- }
- break;
- case 4: if(!UP) //分的个位
- {
- while(!UP);
- dis[4]++;
- if(dis[4]>0x39) dis[4]=0x30;
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[4]--;
- if(dis[4]<0x30) dis[4]=0x39;
- }
- break;
- case 3: if(!UP) //分的十位
- {
- while(!UP);
- dis[3]++;
- if(dis[3]>0x35) dis[3]=0x30;
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[3]--;
- if(dis[3]<0x30) dis[3]=0x35;
- }
- break;
- case 2: if(!UP) // 时的个位
- {
- while(!UP);
- dis[1]++;
- if(dis[0]==0x30||dis[0]==0x31)
- {
- if(dis[1]>0x39) dis[1]=0x30;
- }
- if(dis[0]==0x32)
- {
- if(dis[1]>0x33) dis[1]=0x30;
- }
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[1]--;
- if(dis[0]==0x30||dis[0]==0x31)
- {
- if(dis[1]<0x30) dis[1]=0x39;
- }
- if(dis[0]==0x32)
- {
- if(dis[1]<0x30) dis[1]=0x33;
- }
- }
- break;
- case 1: if(!UP) //时的十位
- {
- while(!UP);
- dis[0]++;
- if(dis[0]>0x32) dis[0]=0x30;
- }
- if(!DOWN)
- {
- while(!DOWN);
- dis[0]--;
- if(dis[0]<0x30) dis[0]=0x32;
- }
- break;
- }
- }
- if(!START)
- {
- while(!START);
- TR0=1;
- key=0;
- P0=0xff;
- }
- }
- //*******************************************************************************蜂鸣器
- void bee()
- {
- keyclockdown();
- if(dis[0]==a&&dis[1]==0x38&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //8点
- {
- flag=1;
- }
- if(dis[0]==a&&dis[1]==0x39&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //9点
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x30&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //10点
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x31&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) // 11点
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x32&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) // 12点
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x33&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //13点
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x34&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //14点
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x35&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //15点
- {
- flag=1;
- }if(dis[0]==0x31&&dis[1]==0x36&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //16点
- {
- flag=1;
- }if(dis[0]==0x31&&dis[1]==0x37&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //17点
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x38&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //18点
- {
- flag=1;
- }
- if(dis[0]==0x31&&dis[1]==0x39&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //19点
- {
- flag=1;
- }
- if(dis[0]==0x32&&dis[1]==0x30&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f) //20点
- {
- flag=1;
- }
- if(flag==1)
- {voise=0;beeled=0;}
- else
- {voise=1;beeled=1; }
- }
- //*************************按下按键关闭闹钟
- void keyclockdown()
- {
- if(!START) {flag=0;beeled=1;}
- }
- //*********************************************
- void aoto() //7s后自动关闭闹铃
- {
- if(flag==1)
- {
- if(over==10) {flag=0;over=0;}
- }
- }
- /******************温度部分**********************/
- void dsInit() //DS18B20复位,初始化函数
- {
-
- unsigned int i;
- ds = 0;
- i = 100;
- while(i>0) i--;
- ds = 1;
- i = 4;
- while(i>0) i--;
- }
-
- void dsWait() //
- {
- unsigned int i;
- while(ds);
- while(~ds);
- i = 4;
- while(i > 0) i--;
- }
- bit readBit() //读一位数据函数
- {
- unsigned int i;
- bit b;
- ds = 0;
- i++;
- ds = 1;
- i++; i++;
- b = ds;
- i = 8;
- while(i>0) i--;
- return b;
- }
- unsigned char readByte() //读一个字节数据函数
- {
- unsigned int i;
- unsigned char j, dat;
- dat = 0;
- for(i=0; i<8; i++)
- {
- j = readBit();
-
- dat = (j << 7) | (dat >> 1); //读出的数据最低位在最前面,这样刚好一个字节在dat里
- }
- return dat;
- }
- void writeByte(unsigned char dat) //向DS18B20写一个字节数据函数
- {
- unsigned int i;
- unsigned char j;
- bit b;
- for(j = 0; j < 8; j++)
- {
- b = dat & 0x01;
- dat >>= 1;
-
- if(b) //写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++;
- }
- }
- }
- void sendChangeCmd() //DS18B20开始获取温度并转换
- {
- dsInit();
- dsWait();
- delayMs(1);
- writeByte(0xcc); //写跳过读ROM指令
- writeByte(0x44); //写温度转换指令
- }
- void sendReadCmd() //读取寄存器中存储的温度数据
- {
- dsInit();
- dsWait();
- delayMs(1);
- writeByte(0xcc);
- writeByte(0xbe);
- }
- int getTmpValue() //得到温度
- {
- unsigned int tmpvalue;
- int value;
- float t;
- unsigned char low, high;
- sendReadCmd();
-
- low = readByte(); //读低8位
- high = readByte(); //读高8位
-
- tmpvalue = high;
- tmpvalue <<= 8; //两个字节组合为1个字节
- tmpvalue |= low;
- value = tmpvalue;
- t = value * 0.0625; //温度在寄存器中为12位,分辨率为0.0625度
- value = t * 100 + (value > 0 ? 0.5 : -0.5); //乘以100表示小数点后面只取1位,加0.5是四舍五入,大于0加0.5, 小于0减0.5。
- return value; //value是整型
- }
- //*****************************************************
复制代码
全部资料51hei下载地址:
ds18b20 lcd1602 声光报警_仿真电路.zip
(21.9 KB, 下载次数: 21)
|