原创 语音温度计

2010-10-9 23:46 2027 5 5 分类: MCU/ 嵌入式

//使用AT89C2051单片机,12MHz晶体,用共阳LED数码管


//P1口输出段码,P3口扫描,P3.4接DS18B20


//#Pragma src(d:\aa.asm)


#include <reg51.h>


#include "intrins.h"                            //_nop_();延时函数用


#define  Disdata P1                             //段码输出口


#define  discan  P2                             //扫描口


#define  disdate1 P0


#define  uchar unsigned char


#define  uint  unsigned int


sbit     DQ=P3^7;                               //温度输入口


sbit     DIN=P1^7;  //LED小数点控制


sbit     pw =P3^0;


uint     h;


char n;


char z;


 


//


//


//**************温度小数部分用查表法***********//


uchar code ditab[16]=


{0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};


//


uchar code dis_7[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};


//共阳LED段码表        "0"  "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9" "不亮" "-"             


uchar code scan_con[4]={0xfe,0xfd,0xfb,0xf7};    //列扫描控制字


uchar data temp_data[2]={0x00,0x00};             //读出温度暂放


uchar data display[5]={0x00,0x00,0x00,0x00,0x00};     //显示单元数据,共4个数据和一个运算暂用


uchar code dis_8[18]={0x00,0x10,0x1c,0x22,0x26,0x2a,0x2e,0x32,0x36,0x3a,0x3e,0x42,0x46,0x4a,0x4e,0x52,0x5a,0xef};


               


                     //当前,摄氏度,零下,点,1, 2,  3,  4,   5, 6,  7,   8,  9,  十, 0, 报警,当前零下


 


//


//


/*****************11us延时函数*************************/


//


void delay(uint t)


{


  for (;t>0;t--);


}


void delay15us(void)


{


       uchar i;


       for(i=0;i<6;i++);


}


//


/****************显示扫描函数***************************/


scan()


{


  char k;


     for(k=0;k<4;k++)                     //4位LED扫描控制


  {


   Disdata=dis_7[display[k]];          //数据显示


   if (k==1){DIN=0;}                   //小数点显示


   discan=scan_con[k];                 //位选


   delay(90);                          //延时


   discan=0xff;


  }


}


//


//


/****************DS18B20复位函数************************/


ow_reset(void)


{


 char presence=1;


 while(presence)


 {


  while(presence)


   {


    DQ=1;


       _nop_();_nop_();//从高拉倒低


 DQ=0;                                      


 delay(50);           //550 us


 DQ=1;                                       


 delay(6);            //66 us


 presence=DQ;         //presence=0 复位成功,继续下一步


   }


   delay(45);            //延时500 us


   presence=~DQ;        


 }


 DQ=1;                   //拉高电平


}


//


//


/****************DS18B20写命令函数************************/


//向1-WIRE 总线上写1个字节


void write_byte(uchar val)


{


  uchar i;


  for(i=8;i>0;i--)


  {


   DQ=1;_nop_();_nop_();                  //从高拉倒低


   DQ=0;_nop_();_nop_();_nop_();_nop_();  //5 us


   DQ=val&0x01;                           //最低位移出


   delay(6);                              //66 us


   val=val/2;                             //右移1位


   }


   DQ=1;


   delay(1);


}


//


/****************DS18B20读1字节函数************************/


//从总线上取1个字节


uchar read_byte(void)


{


 uchar i;


 uchar value=0;


 for(i=8;i>0;i--)


 {


  uchar readdata;


       uchar i;


       for(i=0;i<8;i++)


       {


              DQ=0;


              _nop_();


              _nop_();


              _nop_();


              DQ=1;             //释放总线


              delay15us();


              if(DQ==0)         //如果读到的是0


              {


                     readdata=readdata&0x7f;


                     delay(6);


              }


              else                //读到的是1


              {


                     readdata=readdata|0x80;


                     delay(6);


              }


              if(i<7)


             


              readdata=_cror_(readdata,1);


       }


       return readdata;


 }


DQ=1;


return(value);


}


//


/****************读出温度函数************************/


//


read_temp()


{


  ow_reset();                                  //总线复位


  write_byte(0xcc);                            //发命令


  write_byte(0xbe);                            //发读命令


  temp_data[0]=read_byte();                    //温度低8位


  temp_data[1]=read_byte();                    //温度高8位    ????????


  ow_reset();


  write_byte(0xcc);                            //Skip ROM


  write_byte(0x44);                            //发转换命令


}


//


/****************温度数据处理函数************************/


//二进制高字节的低半字节和低字节的高半字节组成一字节,这个


//字节的二进制转换为十进制后,就是温度值的百、十、个位值,而剩


//下的低字节的低半字节转化成十进制后,就是温度值的小数部分


/********************************************************/


work_temp()


{uint sum=0;


   int i;


   n=0;


if(temp_data[1]&0x80)//判断正负


  {


    temp_data[1]=(256-temp_data[1]);temp_data[0]=(256-temp_data[0]);n=1; //负温度求补码


 


  sum=((temp_data[1]*256+temp_data[0])*0.0625-16);


   if(sum%16==0)


     sum=sum+16;


 


  }


 else{ display[4]=temp_data[0]&0x0f;  //取低字节的低4位--小数部分


 


  display[0]=ditab[display[4]];  //存放小数部分


  //display[4]=((temp_data[0]&0xf0>>4)|((temp_data[1]&0x0f)<<4));//取整数部分


 sum=((temp_data[1]*256+temp_data[0])>>4);


 } 


  display[3]=sum/100;     //取百位数


  display[1]=sum%100;     //


  display[2]=display[1]/10;      //取十位数


  display[1]=display[1]%10;      //取个位数


 


/******************符号位显示判断**************************/


 


  if(n){display[3]=0x0b;}      //负温度时最高位显示"-"


}


void Timer0_Overflow() interrupt 1 using 0


 {


 


 z=z+1;}


Vart_Init()


 {TMOD=0x20;


  TCON=0x69;


  TH1=0xf3;}


shengyin()


  {if(z==0)


    { if(n==0)


       disdate1=dis_8[0];


         else disdate1=dis_8[17];


      


       }


      


    if (z==1)


    {switch(display[2])


      { case(0):z=z+2;break;         


        case(2):disdate1=dis_8[5];break;


        case(3):disdate1=dis_8[6];break;


        case(4):disdate1=dis_8[7];break;


        case(5):disdate1=dis_8[8];break;


        case(6):disdate1=dis_8[9];break;


        case(7):disdate1=dis_8[10];break;


        case(8):disdate1=dis_8[11];break;


        case(9):disdate1=dis_8[12];break;


        case(1):z=z+1;break;


      }


     }


  if(z==2)


      disdate1=dis_8[13];


  if (z==3)


     {switch(display[1])


        {   case(0):z=z+1;break;


            case(2):disdate1=dis_8[5];break;


            case(3):disdate1=dis_8[6];break;


            case(4):disdate1=dis_8[7];break;


            case(5):disdate1=dis_8[8];break;


            case(6):disdate1=dis_8[9];break;


            case(7):disdate1=dis_8[10];break;


            case(8):disdate1=dis_8[11];break;


            case(9):disdate1=dis_8[12];break;


            case(1):disdate1=dis_8[4];break;


        }


      }


  if (z==4)


   disdate1=dis_8[3];


  if (z==5)


  switch(display[0])


    {   case(0):disdate1=dis_8[14];break;


        case(2):disdate1=dis_8[5];break;


        case(3):disdate1=dis_8[6];break;


        case(4):disdate1=dis_8[7];break;


        case(5):disdate1=dis_8[8];break;


        case(6):disdate1=dis_8[9];break;


        case(7):disdate1=dis_8[10];break;


        case(8):disdate1=dis_8[11];break;


        case(9):disdate1=dis_8[12];break;


        case(1):disdate1=dis_8[4];break;


  }


  if (z==6)


  { disdate1=dis_8[1];


    } 


  }


 


 


//


//


/****************主函数************************/


main()


{pw=1;


  Disdata=0xff;                       //初始化端口


  discan=0xff;


  for(h=0;h<4;h++)                    //开机显示"8888"


      {display[h]=8;}


  ow_reset();                         //开机先转换一次


  write_byte(0xcc);                   //Skip ROM


  write_byte(0x44);                   //发转换命令


  for(h=0;h<500;h++)                  //开机显示"8888"


      {scan();}


TMOD|=0x06;


    TH0=0xff;


    TL0=0xff;


    ET0=1;


    EA=1;


    TF0=0;


    TR0=1;


    z=0;


  while(1)


  {


    read_temp();                      //读出DS18B20温度数据


 work_temp();                      //处理温度数据


 for(h=0;h<200;h++)                //显示温度值2s


    {scan();}


       if(pw==0)


       //{if (n==0)


       shengyin();


       //else fshengyin();}


       else {disdate1=0xff;


       z=0;}


       }


       ow_reset();


}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
5
关闭 站长推荐上一条 /3 下一条