分享

51单片机温度测量

 昵称49875672 2017-11-20
//学会DS18B20与单片机的连接方法,掌握程序设计思路及编程调试
#include <REGX52.h>
#include <intrins.h>            //使用NOP函数
#define uchar unsigned char
#define uint unsigned int
#define NOP _nop_()

sbit OE=P3^0;            //ADC0808的OE端,转换结果数据允许输出
sbit EOC=P3^1;           //ADC0808的EOC端,转换结束的信息
sbit CLOCK=P2^6;         //ADC0808工作必需的时钟信号
sbit ST=P3^2;            //ADC0808的START和ALE端,开始转换的命令
sbit LED4=P2^3;
sbit LED3=P2^2;
sbit LED2=P2^1;
sbit LED1=P2^0;

//温度测量数据线
sbit DQ=P3^5;            //温度读取数据线
//共阴数码管显示段码
uchar code tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0,0x40};
//带小数点数字
uchar code tab1[]={0xbF,0x86,0xdB,0xcF,0xe6,0xeD,0xfD,0x87,0xfF,0xeF};
//温度的小数位
uchar code tab2[]={0x00,0x06,0x12,0x19,0x25,0x31,0x38,0x44,0x50,0x56,0x63,0x69,0x75,0x81,0x88,0x94};
uchar dat[]={0,0,0,0};  //显示缓冲区
uchar adc;              //存放ADC0809转换后的数据
unsigned int  tmp;

uchar temp_h,temp_l; /*温度值变量*/
bit flag;     /*正负标志位*/

void Delay(void)
{
  unsigned char i;
     for(i=0;i<250;i++);
}


//温度DS18B20子程序
//函数功能:延时 us

void Delay_us(uchar n)
{
uchar i;
i=0;
while(i<n)
{i++;}
return;
}

//DS18B20复位
void dsreset(void)
{
unsigned int i;
DQ=0;
i=103;
while(i>0)i--;
DQ=1;
i=4;
while(i>0)i--;
}

//读1个字节数据
uchar ReadByte(void)
{
uchar i,k;
i=8;
k=0;
while(i--)             //8位数据循环读
{
DQ=1;
Delay_us(1);       //延时1us
DQ=0;
k=k>>1;
DQ=1;
NOP;
if(DQ)k |= 0x80;   //读出数据存入K
Delay_us(4);
}
return(k);
}

//写入1个字节数据
void tmpwrite(unsigned char dat)
{ unsigned int i;
unsigned char j;
bit testb;             //定义位变量
for(j=1;j<=8;j++)
{ testb=dat&0x01;    //求出位数据
dat=dat>>1;
if(testb)
{ DQ=0;i++;i++;  //i用于确定高低电平时间
DQ=1;
i=8;while(i>0)i--;
}
else
{
DQ=0;
i=8;while(i>0)i--;
DQ=1;i++;i++;
}
}
}

//启动温度转换
void tmpchange(void)
{
dsreset(); /*复位*/
Delay();
tmpwrite(0xcc); //跳过序列号命令
tmpwrite(0x44); //转换命令
}


//将温度值读出来并转化为显示数组
void temp(void)
{
uint dis;                       //数据变量
char xiaos,xsxs,jh;            //温度的小数位,显示小数数据
dsreset();                      //DS18B20复位
Delay();
tmpwrite(0xcc);                 //写入命令
tmpwrite(0xbe);                 //写入命令
temp_l=ReadByte(); //读取温度,低位在前
temp_h=ReadByte(); //读取温度,高位在后
flag=temp_h&0xf8;               //判断温度正负值
if(flag)                        //flag1=1,温度为负值
{
temp_h=~temp_h; //把补码变为反码
if(temp_l==0)temp_h++; //若低8位全为0且温度为负,取补时就要向高位进1
temp_l=~temp_l+1;
}
dis=(temp_h*256+temp_l)/16;     //求出温度值(此求法只求整数温度值)
    xiaos=temp_l&0x0f;
/* switch(xiaos)
{ case 0x00:
      xsxs=0;
 case 0x01:
           xsxs=0x06;
      break;
 case 0x02:
  xsxs=0x12;
      break;
 case 0x03:
  xsxs=0x19;
      break;
 case 0x04:
  xsxs=0x25;
      break;
 case 0x05:
  xsxs=0x31;
      break;
 case 0x06:
  xsxs=0x38;
      break;
 case 0x07:
  xsxs=0x44;
      break;
 case 0x08:
  xsxs=0x50;
      break;
 case 0x09:
  xsxs=0x56;
      break;
 case 0x0a:
  xsxs=0x63;
      break;
 case 0x0b:
  xsxs=0x69;
      break;
 case 0x0c:
  xsxs=0x75;
      break;
 case 0x0d:
  xsxs=0x81;
      break;
 case 0x0e:
  xsxs=0x88;
      break;
 case 0x0f:
  xsxs=0x94;
      break;
      } */
xsxs=tab2[xiaos];
if (flag)                        //如果温度是负数,只显示1位整数,1位符号,2位小数
 {
  dat[0]=tab[11];               //显示符号
  dat[1]=tab1[dis%10];          //显示1位整数和小数点
  jh=(xsxs>>4);
  dat[2]=tab[jh];               //显示两位小数
  dat[3]=tab[(xsxs&0x0f)];
   }
if((dis<10)&&(!flag)) //温度只1位整数值,最高位不显示
{
  dat[0]=tab[10];               //不显示
  dat[1]=tab1[dis%10];          //显示1位整数和小数点
  jh=(xsxs>>4);
  dat[2]=tab[jh];               //显示两位小数
  dat[3]=tab[(xsxs&0x0f)];
}
else
{  if ((dis<100)&&(!flag))    //显示2位整数
         {
  dat[0]=tab[dis/10];            //整数十位
  dat[1]=tab1[dis%10];           //显示整数个位和小数点
  jh=(xsxs>>4);
  dat[2]=tab[jh];                //显示两位小数
  dat[3]=tab[(xsxs&0x0f)];
          }
         else                      //显示3位整数
          {if ((dis>100)&&(!flag))
   { dat[0]=tab1[(dis/10)%10];      //整数十位并标记百位
         dat[1]=tab1[dis%100];          //显示整数个位和小数点
 jh=(xsxs>>4);
         dat[2]=tab[jh];                //显示两位小数
         dat[3]=tab[(xsxs&0x0f)];
}
          }
}
}

//显示子程序
void disp()
{  uchar i1,wei;
    wei=0xfe;
    for (i1=0;i1<4;i1++)
      {
        P0=dat[i1];
        P2=wei;
        Delay();
        P2=0xff;
        wei=(wei<<1)|0x01;
       }
}

//----------------------------主函数-----------------------------//
void main(void)
{
SP=0x70;
/*
  EA=1; ET0=1;
  TMOD=0x02;    // T0方式2计时
  TH0=0x01;     // 晶振:12MHz
  TL0=0x01;     // 晶振:12MHz
  TR0=1;        // 开中断,启动定时器

*/
  //DS18B20读取、转换、显示
  while(1)
  {
        tmpchange(); /*启动温度转换*/
// Delay(); /*等待转换结束,可不用,会对显示产生影响*/
temp(); /*读取温度转换结果*/
disp(); /*温度显示和报警*/

/*ADC0809
    ST=0;
    ST=1;
    ST=0;         //启动转换
    while(!EOC);  //等待转换结束
    OE=1;         //允许输出
    adc=P1;       //取转换结果


 //数据处理,已备显示
 tmp=adc*196;  //乘以19.6MV
 dat[3]=tmp/10000;
 dat[2]=tmp/1000%10;
 dat[1]=tmp/100%10;
 dat[0]=tmp/10%10;

*/
/*
 //数码管显示转换结果
 LED1=0;
 P0=tab[dat[3]]+0x80; 
 Delay();
 LED1=1;
 LED2=0;
 P0=tab[dat[2]];
 Delay();
 LED2=1;
 LED3=0;
 P0=tab[dat[1]];
 Delay();
 LED3=1;
 LED4=0;
 P0=tab[dat[0]];
 Delay();
 LED4=1;*/
  }   //  end while
}     //  end main




/* 定时计数器0的中断服务子程序 */
//*
void timer0(void)  interrupt 1 using 1    // 50mS中断一次
{
   CLOCK=~CLOCK;
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多