完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
/*-----------------------------------------------
名称:18B20温度测量报警 内容:在LCD1602第一行可以显示当前温度, 第二行显示设定的温度区间,超过此温度区间,蜂鸣器报警。 温度区间可以通过用户按键设置 ------------------------------------------------*/ #include #include #include #define uchar unsigned char #define uint unsigned int /******************************************************************/ /* 定义端口 */ /******************************************************************/ ***it buzzer=P2^3;//蜂鸣器引脚 ***it LED=P2^7;//led ***it DQ=P3^7;//ds18b20 端口 ***it RS = P2^0;//1602数据/命令选择端(H:数据寄存器L:指令寄存器) ***it RW = P2^1;//1602读/写选择端 ***it E = P2^2;//1602使能信号端 ***it IN1=P2^4; ***it IN2=P2^5; ***it ENA=P2^6; ***it key1=P1^1;//用户按键 ***it key2=P1^2; ***it key3=P1^3; ***it key4=P1^4; /******************************************************************/ /* 全局变量 */ /******************************************************************/ int temp;//测得温度 char temp_max=30,temp_min=10;//设定的温度 char TempH,TempL; uchar flag_get,num=0; uchar code tab[]={'0','1','2','3','4','5','6','7','8','9'};//液晶显示 uchar tab1[]=" TL:010 TH:030";//液晶第二行显示内容 uchar str[8]; /******************************************************************/ /* 延时函数 */ /******************************************************************/ void delay1(uint i)//短延时函数 { while(i--); } void delay(uint z) //长延时函数 { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void delay2(unsigned int N) { unsigned int i; for(i=0;i /******************************************************************/ /* DS18B20 初始化 */ /******************************************************************/ void Init_DS18B20(void) { /*uchar x=0; DQ = 0; //单片机将DQ拉低 delay1(480); //精确延时 大于 480us DQ = 1; //拉高总线,等待 delay1(10); x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 delay1(5);*/ unsigned char x=0; DQ = 1; //DQ复位 delay1(8); //稍做延时 DQ = 0; //单片机将DQ拉低 delay1(80); //精确延时 大于 480us DQ = 1; //拉高总线 delay1(14); x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 delay1(20); } /******************************************************************/ /* DS18B20读一个字节 */ /******************************************************************/ uchar ReadOneChar(void) // DS18B20读一个字节 { uchar i=0; uchar dat = 0; for (i=8;i>0;i--) { DQ = 0; // 给脉冲信号 dat>>=1; DQ = 1; // 给脉冲信号,主机在读时隙期间必须释放总线 if(DQ) dat|=0x80; delay1(5); } return(dat); } /******************************************************************/ /* DS18B20写一个字节 */ /******************************************************************/ void WriteOneChar(uchar dat) //DS18B20写一个字节 { uchar i=0; for (i=8; i>0; i--) { DQ = 0; DQ = dat&0x01;//取最低位 delay1(5); DQ = 1; dat>>=1;//右移 } delay1(5); } /******************************************************************/ /* DS18B20读取温度 */ /******************************************************************/ uint ReadTemperature(void) //DS18B20读取温度 { uchar a=0; uint b=0; uint t=0; Init_DS18B20();//DS18B20初始化 WriteOneChar(0xCC); // 跳过读序号列号的操作 WriteOneChar(0x44); // 启动温度转换 delay1(200); //延时以求信号的稳定 Init_DS18B20(); //DS18B20再次初始化 WriteOneChar(0xCC); //跳过读序号列号的操作 WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度 a=ReadOneChar(); //低位 b=ReadOneChar(); //高位 b<<=8; //b左移8位 t=a+b; //把a与b结合,放在16位的t中 return(t); } /******************************************************************/ /* LCD1602写命令操作 */ /******************************************************************/ void WriteCommand(uchar com) { delay(5);//操作前短暂延时,保证信号稳定 E=0; RS=0; RW=0; P0=com; E=1; delay(5); E=0; } /******************************************************************/ /* LCD1602写数据操作 */ /******************************************************************/ void WriteData(uchar dat) { delay(5); //操作前短暂延时,保证信号稳定 E=0; RS=1; RW=0; P0=dat; E=1; delay(5); E=0; } /******************************************************************/ /* LCD1602初始化程序 */ /******************************************************************/ void InitLcd() { uchar i; delay(15); WriteCommand(0x38); //display mode WriteCommand(0x38); //display mode WriteCommand(0x38); //display mode WriteCommand(0x06); //显示光标移动位置 WriteCommand(0x0c); //显示开及光标设置 WriteCommand(0x01); //显示清屏 WriteCommand(0x80+0x40);//将光标移到第二行 for(i=0;i<16;i++)//显示初始化内容 { WriteData(tab1); delay(10); } } /******************************************************************/ /* 蜂鸣器报警程序 */ /******************************************************************/ void alarm() { if(TempH>=temp_max||TempH buzzer=0; delay(50); buzzer=1; delay(50); LED=0; } else//报警解除 { buzzer=1; LED=1; } } void motorgo() { if(TempH>temp_max) { ENA=1; IN1=1; IN2=0; } else if(TempH ENA=1; IN1=0; IN2=1; } else { ENA=0; } } /******************************************************************/ /* 显示测得的温度 */ /******************************************************************/ void handle_T() { uchar i; str[0]=0x20;//显示为空 str[1]=tab[TempH/100]; //百位温度 str[2]=tab[(TempH%100)/10]; //十位温度 str[3]=tab[(TempH%100)%10]; //个位温度,带小数点 str[5]=tab[TempL]; str[4]='.'; str[6]=0xdf; str[7]='C'; if(flag_get==1) //定时读取当前温度 { flag_get=0; //清标志位 temp=ReadTemperature();//读取温度值 if(temp&0x8000) { str[0]=0xb0;//负号标志 temp=~temp; // 取反加1 temp +=1; } TempH=temp>>4; //由权重表知移4位就是整数位 TempL=temp&0x0F; TempL=TempL*6/10;//小数近似处理 alarm(); //判断是否需要报警 motorgo();//判断风机是否转动 } WriteCommand(0x80+0x04);//光标指向第一行第一个字符 for(i=0;i<8;i++)// 显示 { WriteData(str); delay(10); } } void display_range(uchar add,int t) { uchar i; if(t<0) { str[0]=0xb0;//负号标志 } else str[0]=tab[abs(t)/100]; //百位温度 str[1]=tab[(abs(t)%100)/10]; //十位温度 str[2]=tab[(abs(t)%100)%10]; //个位温度 WriteCommand(0x80+0x40+add); for(i=0;i<3;i++) { WriteData(str); delay(5); } } /******************************************************************/ /* 独立键盘扫描函数并显示设定的温度 */ /******************************************************************/ void keyscan() { uchar flag1=0,flag2=0;//有按键按下标记 P1=0xff;//拉高P2口,以读取P2口的值 if(key3==0)//最高温加 { delay(5);//延时消抖 if(key3==0) { temp_max++; if(temp_max>=85) temp_max=85; } while(!key3);//松手检测 flag1=1; } if(key4==0)//最高温减 { delay(5); if(key4==0) { temp_max--; if(temp_max<=temp_min) temp_max=temp_min; } while(!key4); flag1=1; } if(key1==0)//最低温加 { delay(5);//延时消抖 if(key1==0) { temp_min++; if(temp_min>=temp_max) temp_min=temp_max; } while(!key1);//松手检测 flag2=1; } if(key2==0)//最低温减 { delay(5); if(key2==0) { temp_min--; if(temp_min<=-10) temp_min=-10; } while(!key2); flag2=1; } if(flag1)//如有设置最高温度的键按下,更新设定的温度 { flag1=0;// 清标记 display_range(0x0d,temp_max); } if(flag2)//如有设置最低温度的键按下,更新设定的温度 { flag2=0;// 清标记 display_range(0x04,temp_min); } } ///////功能:串口初始化,波特率9600,方式1///////// void send_int(void) { TMOD = 0x20;//工作方式2,8位自动重装定时器 PCON = 0x00; SCON = 0x50;//串口方式1, 8-n-1, 允许接收. TH1 = 0xFd; TL1 = 0xFd; TR1 = 1; ES=1; } /****************************************************************/ /* 主函数 */ /******************************************************************/ void main() { TMOD|=0x01;//定时器设置 TH0=0xef;//装初始值 TL0=0xf0; EA=1;// 开总中断 ET0=1;//允许定时器0中断 TR0=1;//开定时器0中断 InitLcd();//lcd1602初始化 flag_get=1; //send_int(); while(1) { handle_T();// 处理温度:获得、显示、报警 keyscan(); //独立按键扫描 //temp=ReadTemperature(); SBUF=temp; while(!ti); TI=0; } } /******************************************************************/ /* 定时0中断处理程序,用于温度检测间隔,大约1秒测一次温度 */ /******************************************************************/ void timer0(void) interrupt 1 using 1 { TH0=0xef;//定时器重装值 TL0=0xf0; num++; if (num==50) { num=0; flag_get=1;//标志位有效,开始测温 } }
|
|
相关推荐 |
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
205 浏览 0 评论
求助一下关于51系列单片机的Timer0的计时问题,TH0、TL0+1的时间是怎么算的?
1253 浏览 1 评论
【RA-Eco-RA4E2-64PIN-V1.0开发板试用】开箱+Keil环境搭建+点灯+点亮OLED
848 浏览 0 评论
【敏矽微ME32G070开发板免费体验】使用coremark测试敏矽微ME32G070 跑分
853 浏览 0 评论
【敏矽微ME32G070开发板免费体验】开箱+点灯+点亮OLED
1073 浏览 2 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
12011 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 22:57 , Processed in 0.643790 second(s), Total 69, Slave 51 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号