📄 ds18b20_pwm.c
字号:
#include<reg51.h>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
void keyscan();
void delay20ms(void);
sbit DQ=P3^3;//ds18b20与单片机连接口
sbit RS=P2^0;
sbit RW=P2^1;
sbit EN=P2^2;
unsigned char code str1[]={"D/C: % T: 3S "};
unsigned char code str2[]={"t C Set:50C"};
uchar data disdata[5];
uint tvalue;//温度值
uchar tflag;//温度正负标志
//uint Tset=60; //设置周期
sbit Light = P2^3; //控制LED显示
sbit key = P1^0; //调整设置温度加
sbit key2 = P1^1; //调整设置温度减
sbit key3 = P1^2; //调整周期加,步进20
sbit key4 = P1^3; //调整周期减,步进20
int SetTemp=50; //温度初始值
unsigned long int Tset=60; //设置周期
int temp=0; //温度中间变量
uint count1=0;
unsigned long int count=0; //计数器
/*************************lcd1602程序**************************/
void delay1ms(unsigned int ms)//延时1毫秒(不够精确的)
{unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<100;j++);
}
void Write_Com(unsigned char com)//写指令//
{ delay1ms(1);
RS=0;
RW=0;
EN=0;
P0=com;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
void Write_Dat(unsigned char dat)//写数据//
{ delay1ms(1);;
RS=1;
RW=0;
EN=0;
P0=dat;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
void lcd_init()//初始化设置//
{delay1ms(15);
Write_Com(0x38);delay1ms(5);
Write_Com(0x08);delay1ms(5);
Write_Com(0x01);delay1ms(5);
Write_Com(0x06);delay1ms(5);
Write_Com(0x0c);delay1ms(5);
}
void display(unsigned char *p)//显示//
{
while(*p!='\0')
{
Write_Dat(*p);
p++;
delay1ms(1);
}
}
init_play()//初始化显示
{ lcd_init();
Write_Com(0x80);
display(str1);
Write_Com(0xc0);
display(str2);
}
/******************************ds1820程序***************************************/
void delay_18B20(unsigned int i)//延时1微秒
{
while(i--);
}
void ds1820rst()/*ds1820复位*/
{ unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(4); //延时
DQ = 0; //DQ拉低
delay_18B20(100); //精确延时大于480us
DQ = 1; //拉高
delay_18B20(40);
}
uchar ds1820rd()/*读数据*/
{ unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{ DQ = 0; //给脉冲信号
dat>>=1;
DQ = 1; //给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(10);
}
return(dat);
}
void ds1820wr(uchar wdata)/*写数据*/
{unsigned char i=0;
for (i=8; i>0; i--)
{ DQ = 0;
DQ = wdata&0x01;
delay_18B20(10);
DQ = 1;
wdata>>=1;
}
}
read_temp()/*读取温度值并转换*/
{uchar a,b;
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0x44);//*启动温度转换*/
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0xbe);//*读取温度*/
a=ds1820rd();
b=ds1820rd();
tvalue=b;
tvalue<<=8;
tvalue=tvalue|a;
if(tvalue<0x0fff)
tflag=0;
else
{tvalue=~tvalue+1;
tflag=1;
}
tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数
temp=tvalue/10;
return(tvalue);
}
/*******************************************************************/
void ds1820disp()//温度值显示
{ uchar flagdat;
disdata[0]=tvalue/1000+0x30;//百位数
disdata[1]=tvalue%1000/100+0x30;//十位数
disdata[2]=tvalue%100/10+0x30;//个位数
disdata[3]=tvalue%10+0x30;//小数位
if(tflag==0)
flagdat=0x20;//正温度不显示符号
else
flagdat=0x2d;//负温度显示负号:-
if(disdata[0]==0x30)
{disdata[0]=0x20;//如果百位为0,不显示
if(disdata[1]==0x30)
{disdata[1]=0x20;//如果百位为0,十位为0也不显示
}
}
Write_Com(0x8a);
Write_Dat(Tset/2000+0x30);//显示周期百位 Tset/20/100+0x30
Write_Com(0x8b);
Write_Dat(Tset/200%10+0x30);//显示周期十位 Tset/20/10%10+0x30
Write_Com(0x8c);
Write_Dat(Tset/20%10+0x30);//显示周期个位 Tset/20%10+0x30
Write_Com(0xc1);
Write_Dat(flagdat);//显示符号位
Write_Com(0xc2);
Write_Dat(disdata[0]);//显示百位
Write_Com(0xc3);
Write_Dat(disdata[1]);//显示十位
Write_Com(0xc4);
Write_Dat(disdata[2]);//显示个位
Write_Com(0xc5);
Write_Dat(0x2e);//显示小数点
Write_Com(0xc6);
Write_Dat(disdata[3]);//显示小数位
Write_Com(0xcd);
Write_Dat(SetTemp/10+0x30); //显示设置温度十位
Write_Com(0xce);
Write_Dat(SetTemp%10+0x30); //显示设置温度各位
Write_Com(0xcf);
Write_Dat('C');
}
void TO_Service (void) interrupt 1 using 3
{
TH0 = 0x3C;
TL0 = 0x0B0;
if(count==Tset) {count = 0;}
count++;
if(count<=Tset/20*(SetTemp-temp)) Light=1;
else Light=0;
}
void initTO(void)
{
TMOD=0X11;
EA=1;
ET0=0;
TH0 = 0x3C;
TL0 = 0x0B0;
TH1 = 0x3C;
TL1 = 0x0B0;
ET1 = 1;
TR1 = 1;
TR0=0;
}
void Timer1Interrupt(void) interrupt 3
{
TH1 = 0x3C;
TL1 = 0x0B0;
if(count1==10) {count1=0;read_temp();} //0.5S读一次温度
count1++;
// keyscan();
}
void delay20ms(void) //误差 0us
{
unsigned char a,b;
for(b=215;b>0;b--)
for(a=45;a>0;a--);
_nop_; //if Keil,require use intrins.h
_nop_; //if Keil,require use intrins.h
}
void keyscan()
{
if(key==0||key2==0||key3==0)
delay20ms();
{
if(key==0)
{SetTemp++;
ds1820disp();
if(SetTemp==100) SetTemp=0;
}
if(key2==0)
{SetTemp--;
ds1820disp();
if(SetTemp==-1) SetTemp=99;
}
if(key3==0)
{
Tset+=20;count=0;//count必须清零,否则中断里的count不知道加到多少,造成紊乱
ds1820disp();
if(Tset==20000) Tset=20;
}
if(key4==0)
{
if(Tset==20) Tset=20000;
Tset-=20;count=0;//count必须清零,否则中断里的count不知道加到多少,造成紊乱
ds1820disp();
}
}
}
/********************主程序***********************************/
void main()
{ init_play();//初始化显示
initTO(); //TO初始化
while(1)
{ keyscan();
ds1820disp();//显示
if((SetTemp-20)>0){
if(temp>=SetTemp) {ET0=0;Light=0;
Write_Com(0x84);Write_Dat('0');
Write_Com(0x85);Write_Dat('0');
Write_Com(0x86);Write_Dat('*');
} //如果温度值大于等于50度,灯灭
if(temp>=(SetTemp-20)&&temp<SetTemp) {TR0=1;ET0=1;
Write_Com(0x84);Write_Dat(((SetTemp-temp)*100/20)/10+0x30);
Write_Com(0x85);Write_Dat(((SetTemp-temp)*100/20)%10+0x30);
Write_Com(0x86);Write_Dat('%');} //如果温度值在30和50度之间,开中断,输出PWM波,显示占空比
if(temp<SetTemp-20) {ET0=0;Light=1;
Write_Com(0x84);Write_Dat('0');
Write_Com(0x85);Write_Dat('1');
Write_Com(0x86);Write_Dat('*');}// 如果温度值小于30度,关中断,灯亮
}
if ((SetTemp-20)<=0){ET0=0;Light=0;
Write_Com(0x84);Write_Dat('0');
Write_Com(0x85);Write_Dat('0');
Write_Com(0x86);Write_Dat('*');}//如果设置温度小于当前温度,占空比显示00*
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -