- #include<reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit P00 = P0^0;
- sbit P01 = P0^1;
- sbit P02 = P0^2;
- sbit P03 = P0^3;
- sbit P04 = P0^4;
- sbit P05 = P0^5;
- sbit P06 = P0^6;
- sbit P07 = P0^7;
- sbit P10 = P1^0;
- sbit P11 = P1^1;
- sbit P12 = P1^2;
- sbit P13 = P1^3;
- sbit P14 = P1^4;
- sbit P15 = P1^5;
- sbit P16 = P1^6;
- sbit P17 = P1^7;
- sbit P20 = P2^0;
- sbit P21 = P2^1;
- sbit P22 = P2^2;
- sbit P23 = P2^3;
- sbit P24 = P2^4;
- sbit P25 = P2^5;
- sbit P26 = P2^6;
- sbit P27 = P2^7;
- sbit P30 = P3^0;
- sbit P31 = P3^1;
- sbit P32 = P3^2;
- sbit P33 = P3^3;
- sbit P34 = P3^4;
- sbit P35 = P3^5;
- sbit P36 = P3^6;
- sbit P37 = P3^7;
- //****** DS18B20 ******
- #define DQ P17
- /*************精确延时函数*****************/
- void delay10us(void) //误差 0us
- {
- unsigned char a,b;
- for(b=1;b>0;b--)
- for(a=2;a>0;a--);
- }
- void delay20us(void) //误差 0us
- {
- unsigned char a,b;
- for(b=1;b>0;b--)
- for(a=7;a>0;a--);
- }
- void delay30us() //误差 0us
- {
- unsigned char a,b;
- for(b=3;b>0;b--)
- for(a=3;a>0;a--);
- }
- void delay100us() //误差 0us
- {
- unsigned char a,b;
- for(b=1;b>0;b--)
- for(a=47;a>0;a--);
- }
- void delay200us(void) //误差 0us
- {
- unsigned char a,b;
- for(b=1;b>0;b--)
- for(a=97;a>0;a--);
- }
- void delay500us() //误差 0us
- {
- unsigned char a,b;
- for(b=71;b>0;b--)
- for(a=2;a>0;a--);
- }
- void DS18B20_init() //DS18B20初始化 复位
- {
- DQ = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_(); //延时几个时钟周期 保证DQ引脚稳定在高电平
- DQ = 0;
- delay500us(); //最短为480us的低电平信号 复位
- DQ = 1; //拉高总线 15-60us
- delay30us();
-
- delay200us(); //延时足够时间 复位基本上都会成功
- DQ = 1; //释放总线
- }
- uchar Read_One_Byte()
- {
- uchar i;
- uchar byte = 0;
- for(i = 0;i < 8;i++)
- {
- DQ = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_(); //延时几个时钟周期 保证DQ引脚稳定在高电平
- DQ = 0;
- byte >>= 1;
- delay20us();
- DQ = 1; //给脉冲 产生读时间间隙
- delay10us(); //延时一定时间后,读DQ的值
- if(DQ)
- { byte |= 0x80;} //读得DQ为1 将1写到dat最高位 ;读得DQ为0 不必处理
- delay100us();
- DQ = 1;
- }
- return(byte);
- }
- void Write_One_Byte(uchar byte)
- {
- uchar i = 0;
- for(i = 0;i < 8;i++)
- {
- DQ = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_(); //延时几个时钟周期 保证DQ引脚稳定在高电平
- DQ = 0;
- DQ = byte & 0x01; //写所给数据最低位
- delay30us();
- byte >>= 1;
- }
- }
- int Read_Temp() ////////***读取温度值***********///// 每次读写均要先复位
- {
- int t;
- float tep;
- uchar a,b;
- DS18B20_init();
- Write_One_Byte(0xcc); //跳过ROM命令 单个传感器所以不必读取ROM里的序列号
- Write_One_Byte(0x44); //开始转换
- DS18B20_init();
- Write_One_Byte(0xcc); //跳过ROM命令
- Write_One_Byte(0xbe); //读寄存器,共九字节,前两字节为转换值
- a = Read_One_Byte(); //a存低字节
- b = Read_One_Byte(); //b存高字节
- t = b;
- t <<= 8;//高字节转换为10进制
- t = t|a;
- tep = t*0.0625;//转换精度为0.0625/LSB
- t = tep*10 + 0.5;//保留1位小数并四舍五入****后面除10还原正确温度值)
- return(t);
- }
- /*********** LCD ************/
- #define RS P22
- #define RW P21
- #define LCDEN P20
- #define LCD_DATA P0 //P0口接LCD数据口
- #define LCD_BUSY P07 //lcd1602忙碌标志位
- uchar idata lcd_code[10];//用来标记lcd1602 什么时候清显示 每个页面都设一个code,code不想同时清显示
- //*****************************************延时函数***************************************//
- void delayms(uint ms)//延时
- {
- uchar a,b,c;
- while(ms--)
- {
- for(c=1;c>0;c--)
- for(b=142;b>0;b--)
- for(a=2;a>0;a--);
- }
- }
- //**************** LCD ********************
- //LCD基本函数:
- void busy_check() //忙碌检测
- {
- RW = 1; //读
- RS = 0; //指令寄存器
- LCD_DATA = 0xFF;//实验证明读数时要将I/O口要置1
- LCDEN = 0;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- LCDEN = 1;// EN高电平读信息 负跳变执行指令
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- while(1)
- {
- if(LCD_BUSY == 0)//P07 == 0跳出循环
- break;
- }
-
- }
- void lcdwrcom(uchar command)//写指令
- {
- busy_check();
- RW = 0;//写
- RS = 0;//指令寄存器
- LCD_DATA = command;
- LCDEN = 1;//负跳变写入指令
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- LCDEN = 0;
- }
- void lcdwrdata(uchar lcd_data)//写数据 数字、字母、标点符号都是数据
- {
- busy_check();
- RW = 0;//写
- RS = 1;//数据寄存器
- LCD_DATA = lcd_data;
- LCDEN = 1;//负跳变写入指令
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- LCDEN = 0;
- }
- void lcd_init()
- {
- delayms(15);//必要 lcd1602上电到电压稳定需要时间
- RW = 0;//写
- RS = 0;//指令寄存器
- LCD_DATA = 0x38;// 0x38设置显示模式为:16X2 显示,5X7 点阵,8 位数据接口'
- LCDEN = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- LCDEN = 0;
- delayms(5);
- lcdwrcom(0x0c);//打开显示 无光标 不闪烁
- lcdwrcom(0x06);//指令3 光标右移 屏幕所有文字移动无效
- lcdwrcom(0x01);// 清显示,光标复位到地址00H位置。
- }
- //LCD扩展函数:
- void address(uchar x,uchar y) //定位下一步要写数的地址
- {
- uchar location;
- if(x == 0)
- location = 0x80|y;
- else
- location = 0xC0|y;
- lcdwrcom(location);
- }
- void printchar(uchar x,uchar y,uchar letter)//显示字母、单个字符
- {
- address(x,y);
- lcdwrdata(letter);
- }
- void printword(uchar x,uchar y,uchar *word) //显示单词(字符数组)
- {
- uchar i = 0;
- for(i = 0;word[i] != '\0';i++)
- {
- address(x,y + i);
- lcdwrdata(word[i]);
- }
- }
- void printtemp(uchar x,uchar y ,uint temp) //显示温度 显示一位小数 【显示效果相当于将一个数除以10并保存一位小数】
- {
- if(temp < 100)
- {
- address(x,y);
- lcdwrdata(temp/10 + '0');
- address(x,y + 1);
- lcdwrdata('.');
- address(x,y + 2);
- lcdwrdata(temp%10 + '0');
- address(x,y + 3);
- lcdwrdata(' ');
- address(x,y + 4);
- lcdwrdata(' ');
- }
- else if(temp < 1000)
- {
- address(x,y);
- lcdwrdata(temp/100 + '0');
- address(x,y + 1);
- lcdwrdata(temp%100/10 + '0');
- address(x,y + 2);
- lcdwrdata('.');
- address(x,y + 3);
- lcdwrdata(temp%10 + '0');
- address(x,y + 4);
- lcdwrdata(' ');
- }
- else if(temp < 10000)
- {
- address(x,y);
- lcdwrdata(temp/1000 + '0');
- address(x,y + 1);
- lcdwrdata(temp%1000/100 + '0');
- address(x,y + 2);
- lcdwrdata(temp%100/10 + '0');
- address(x,y + 3);
- lcdwrdata('.');
- address(x,y + 4);
- lcdwrdata(temp%10 + '0');
- }
- }
- void main()
- {
- int temp; //温度值
- lcd_init();
- printword(0,0,"temp:");
- while(1)
- {
- temp = Read_Temp();
- if(temp > 0 )
- {
- printchar(0,5,'+');
- printtemp(0,6,temp);
- }
- else if(temp == 0)
- {
- printchar(0,5,' ');
- printchar(0,6,'0');
- }
- else
- {
- temp = -temp;
- printchar(0,5,'-');
- printtemp(0,6,temp);
- }
- }
- }
复制代码 |