资源描述
.
仿真截图:
//仿真文件网盘地址:pan.baidu./s/1qW8sGQK
//程序:
#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)//延时?个 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--);
}
}
/*
//**********字符串复制函数**********
void string_copy(uchar *target,uchar *source)//字符串复制 target:目标 source:源
{
uchar i = 0;
for(i = 0;source[i] != '\0';i++)//注意target的长度 无保护措施!
{
target[i] = source[i];
}
target[i] = '\0';
}
//**********字符串比较函数**********
uchar string_cmp(uchar *target,uchar *source)//字符串比较 target:目标 source:源
{
uchar revalue;
uchar i = 0;
for(i = 0;target[i] != '\0' && source[i] != '\0';i++) //两个都不等于'\0'才执行 出现一个等于'\0'就跳出
{
if(target[i] == source[i])
{
revalue = 1;
}
else
{
revalue = 0;
break;
}
}
if(revalue == 1)
{
if(target[i] == '\0' && source[i] == '\0')
revalue = 1;
else
revalue = 0;
}
return(revalue);
}
*/
//**************** 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;
} */
delayms(2);//仿真时用延时法 下载到真实单片机上时,将这句注释掉,采用上面的语句。
}
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 printuint(uchar x,uchar y,uchar num_ws_max,uint num)//显示无符号整形 0~65535 x:行 y:列 num_ws_max 变量的最大位数
{
uchar i = 0;
uchar str[5] = {0x20,0x20,0x20,0x20,0x20};
if(num >= 10000)
{
str[0] = num/10000 + '0';
str[1] = num%10000/1000 + '0';
str[2] = num%1000/100 + '0';
str[3] = num%100/10 + '0';
str[4] = num%10 + '0';
// str[5] = '\0'; //手动加字符串结束标志
}
else if(num >= 1000)
{
str[0] = num/1000 + '0';
str[1] = num%1000/100 + '0';
str[2] = num%100/10 + '0';
str[3] = num%10 + '0';
str[4] ='\0';
}
else if(num >= 100)
{
str[0] = num/100 + '0';
str[1] = num%100/10 + '0';
str[2] = num%10 + '0';
str[3] = '\0';
}
else if(num >=10)
{
str[0] = num/10 + '0';
str[1] = num%10 + '0';
str[2] = '\0';
}
else if(num >= 0)
{
str[0] = num + '0';
str[1] = '\0';
}
for(i = 0;i <= 5;i++) //uint类型 最大值65535 为5位数
{
if(str[i] != '\0' && i < num_ws_max)
{
address(x,y + i);
lcdwrdata(str[i]);
}
else if(str[i] == '\0' && i < num_ws_max)
{
address(x,y+i);
lcdwrdata(' ');//空格 // 实现功能:在此变量的位数围,把没数字的位存0x20(空格)
//例如:最大有3位:999 当变为99时,存为9+'0' 9+'0' 0x20
}
}
}
*/
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);
}
}
}
22 / 22
展开阅读全文