|
- #include <reg52.h>
- #include <intrins.h>
- #define T_MAX 25 // 最大温度限定值
- #define T_MIN 22 // 最小温度限定值
- sbit BUZZ = P1^6;
- //_nop_()函数所在头文件
- /*----------------音乐函数申明------------------------------*/
- void InitBuzz();
- bit isBuzz = 0; //蜂鸣器是否在响
- /*----------------温度传感器申明----------------------------*/
- bit Start18B20(); //初始化DS18B20
- bit Get18B20Temp(int *temp);//读取温度
- bit isGetTemp = 0; //是否在获取温度
- /*----------------LCD1602显示模块申明------------------------*/
- void InitLcd1602(); //LCD1602初始化函数
- void display(); //显示控制模块
- /*-------------------LCD1602显示缓存-------------------------*/
- //LCD1602函数调用申明
- void LcdShowStr(unsigned char x, unsigned char y,unsigned char *str, unsigned char len);
- unsigned char strbuff[4];//格式:“25°C”
- unsigned char code waringStrHot[] = " Hot! ";//报警显示文字
- unsigned char code waringStrCol[] = " Cold! ";//报警显示文字
- unsigned char code striswaring[] = " ";//取消报警显示文字
- /*----------------------其他全局变量-------------------------*/
- int Temp = 0; //读取到的当前温度值(16bit二进制)
- int intT; //温度值的整数和小数部分
- bit iswaring = 0; //是否报警标志位
- void main()
- {
- // int n = 0;
- // char s[1];
- bit isReay = 0;
- bit sta; //是否成功读取标志
- unsigned int cnt = 0; //检测标志,主要用于控制检测温度的频率
-
- InitBuzz(); //蜂鸣器初始化
- Start18B20(); //启动DS18B20
- InitLcd1602(); //初始化LCD1602液晶模块
-
- while(1)
- {
- if(isReay == 0)
- {
- cnt++;
- }
- if((cnt>28000&&isBuzz == 0)||(cnt>14000&&isBuzz == 1)) //大约0.8s(仿真得到) DS18B20最多750ms转化好
- {
- cnt = 0;
- isReay = 1;
- }
-
- if(isReay == 1 && isBuzz == 0)
- {
- // n++;
- // s[0] = n+'0';
- // LcdShowStr(0, 0,s, 1);
- isGetTemp = 1;
- sta = Get18B20Temp(&Temp); //读取当前温度
- isGetTemp = 0;
- if (sta) //读取成功时,刷新当前温度显示
- {
- intT = Temp >> 4; //分离出温度值整数部分
- }
- Start18B20(); //重新启动下一次转换
-
- if(intT > T_MAX || intT < T_MIN)
- {
- iswaring = 1;
- }else{
- iswaring = 0;
- }
- isReay = 0;
- }
- display();//显示
- }
- }
- /*-----------------------以下是LCD1602显示驱动------------------*/
- //定义LCD1602显示相关的IO接口
- #define LCD1602_DB P0
- sbit LCD1602_RS = P1^0;
- sbit LCD1602_RW = P1^1;
- sbit LCD1602_E = P1^5;
- //显示控制模块
- void display()
- {
- static int intTb; //温度值的整数部分备份
- static bit isBuzzb;
- if(isBuzzb != isBuzz)
- {
- if(isBuzz == 0 && iswaring == 1)
- {
- if(intT > T_MAX)
- {
- LcdShowStr(0,1,waringStrHot,16);
- }else{
- LcdShowStr(0,1,waringStrCol,16);
- }
-
- }else{
- LcdShowStr(0,1,striswaring,11);
- }
- isBuzzb = isBuzz;
- }
- if(intTb != intT)//如果有变化
- {
- /*备份当前值*/
- intTb = intT;
-
- if((intT/10) == 0)strbuff[0] = ' ';else strbuff[0] = ((intT/10)%10)+0x30;//十位
- strbuff[1] = ((intT/1)%10)+0x30;//个位
- LcdShowStr(6,0,strbuff,4); //显示,初始位置随意,只要能显示完整就好
- }
- }
- //等待液晶准备好
- void LcdWaitReady()
- {
- unsigned char sta;
-
- LCD1602_DB = 0xFF;
- LCD1602_RS = 0;
- LCD1602_RW = 1;
- do {
- LCD1602_E = 1; //使能LCD1602
- sta = LCD1602_DB; //读取状态字
- LCD1602_E = 0; //避免干扰其他器件
- } while (sta & 0x80); //第七位等于1表示液晶正忙,重复检测直到第七位等于0为止
- }
- //向LCD1602液晶写入一字节命令,cmd为待写入命令值
- void LcdWriteCmd(unsigned char cmd)
- {
- LcdWaitReady();
- LCD1602_RS = 0;
- LCD1602_RW = 0;
- LCD1602_DB = cmd;
- LCD1602_E = 1;
- LCD1602_E = 0;
- }
- //向LCD1602液晶写入一字节数据,dat为待写入数据值
- void LcdWriteDat(unsigned char dat)
- {
- LcdWaitReady();
- LCD1602_RS = 1;
- LCD1602_RW = 0;
- LCD1602_DB = dat;
- LCD1602_E = 1;
- LCD1602_E = 0;
- }
- //设置显示RAM起始地址,亦即光标位置,(x,y)对应屏幕上的字符的坐标
- void LcdSetCursor(unsigned char x, unsigned char y)
- {
- unsigned char addr;
-
- if (y == 0) //由输入的屏幕坐标计算显示RAM的地址
- addr = 0x00 + x; //第一行字符地址从0x00起始
- else
- addr = 0x40 + x; //第二行字符地址从0x40起始
- LcdWriteCmd(addr | 0x80); //设置RAM地址
- }
- //在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,
- //str-字符串指针,len-需显示的字符长度
- void LcdShowStr(unsigned char x, unsigned char y,unsigned char *str, unsigned char len)
- {
- LcdSetCursor(x, y); //设置起始地址
- while (len--) //连续写入len个字符数据
- {
- LcdWriteDat(*str++); //先取str指向的数据,然后str自加1
- }
- }
- void InitLcd1602()//初始化1602液晶
- {
- strbuff[2] = 0XDF;
- strbuff[3] = 'C';
- LcdWriteCmd(0x38); //16*2显示,5*7点阵,8位数据接口
- LcdWriteCmd(0x0C); //显示器开,光标关闭
- LcdWriteCmd(0x06); //文字不动,地址自动+1
- LcdWriteCmd(0x01); //清屏
- }
- /*-----------------------以下是温度传感器驱动------------------*/
- //DS18B20通信引脚
- sbit IO_18B20 = P3^2;
- void DelayX10us(unsigned char t)
- {
- do {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- } while (--t);
- /*_nop_()函数在12M晶振中延迟1us,为什么这里是8个_nop_()
- 因为while和--t也是需要时间的,这里不一定是准确的10us/循环
- 只是大致的时间*/
- }
- bit Get18B20Ack() //DS18B20存在检测函数
- {
- bit ack;
- EA = 0; //关中断
- IO_18B20 = 0; //拉低引脚
- DelayX10us(50); //延时500us(480us - 960us)
- IO_18B20 = 1; //释放总线
- DelayX10us(6); //延时60us(15us - 60us)
- ack = IO_18B20; //读取响应(60us - 240us)
- while(!IO_18B20); //等待DS18B20释放总线 (60us - 240us)
- EA = 1; //取消关中断
- return ack; //返回是否存在 (0:存在 1:不存在)
- }
- void Write18B20(unsigned char dat) //写DS18B20
- {
- unsigned char mask; //临时变量定义
- EA = 0; //关中断
- for(mask=0x01; mask!= 0; mask<<=1) //循环发送单个bit位
- {
- IO_18B20 = 0; //拉低(请求读写操作)
- _nop_(); //延时(1us < time <= 15us)
- _nop_();
- if((mask&dat) == 0) //按位读取dat
- IO_18B20 = 0; //本位是0,拉低
- else
- IO_18B20 = 1; //本位是1,拉高
- //上面这个操作DS18B20读取(最小时间 0us<time<15us,
- //典型时间 15us,最大时间45us)
- DelayX10us(6); //等待60us(足够DS18B20读取)
- IO_18B20 = 1; //释放总线
- }
- EA = 1; //取消关中断
- }
- unsigned char Read18B20() //读DS18B20
- {
- unsigned char dat; //数据缓存变量
- unsigned char mask; //临时变量
- EA = 0; //关中断
- for(mask=0x01; mask!=0; mask<<=1)//同上循环按位操作
- {
- IO_18B20 = 0; //读写请求
- _nop_(); //等待(1us < time < 15us)
- _nop_();
- IO_18B20 = 1; //初始化读操作
- _nop_(); //等待DS18B20输出
- _nop_();
- if(!IO_18B20) //读
- dat &= ~mask; //“0”
- else
- dat |= mask; //“1”
- DelayX10us(6); //等待DS18B20释放总线
- }
- EA = 1; //取消关中断
- return dat; //返回数据
- }
- bit Start18B20() //初始化DS18B20
- {
- bit ack; //存在标志
- ack = Get18B20Ack();//检测存在
- if(ack == 0) //存在
- { //写命令使工作
- Write18B20(0xCC); //跳过ROM检测
- Write18B20(0x44); //启动温度转换
- }
- return ~ack; //返回是否成功(1是,0否)
- }
- bit Get18B20Temp(int *temp) //获取DS18B20温度存于temp
- {
- bit ack; //存在标志
- unsigned char LSB, MSB; //数据低/高位
- ack = Get18B20Ack(); //检测存在
- if(ack == 0) //存在
- { //写指令
- Write18B20(0xCC); //跳过ROM检测
- Write18B20(0xBE); //读寄存器
- LSB = Read18B20(); //读低位
- MSB = Read18B20(); //读高位
- *temp = ((int)MSB<<8) + LSB; //合并
- }
- return ~ack; //返回结果(1成功,0失败)
- }
- //下面是蜂鸣器
- void InterruptTimer0() interrupt 1
- {
- static unsigned int timer;
- TH0 = 0x00;
- TL0 = 0x00;
- timer++;
- if(iswaring)
- {
- if(timer>3000)
- {
- isBuzz = 1;
- if(timer%5==1)
- {
- BUZZ = ~BUZZ;
- }
- if(timer>6000)
- {
- timer = 0;
- }
- }else{
- isBuzz = 0;
- }
- }else{
- isBuzz = 0;
- }
- }
- void InitBuzz()
- {
- TMOD = 0x02;
- TR0 = 1;
- ET0 = 1;
- }
复制代码
|
|