单片机+DS18B20+12864液晶显示温度及温度变化的波形

2019-04-15 12:30发布

#include
#include
#include//头文件
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P2^6;//ds18b20与单片机连接口
sbit PWM=P2^5;//控制信号的输出
unsigned char code str[]={"my name is zhb "};
unsigned char code str_[]={"MADE IN NUPT... "};
unsigned char code str1[]={"temper:"};
unsigned char code str2[]={"         "};
unsigned char code nul[]={"        "};
unsigned char code str3[]={"target:  "};
unsigned char  str4[6];//设定温度的存储
uchar data disdata[5]; uchar a[4]={0,0,0,0},j,i,k,num=0;      //定义变量
sbit js=P3^2;   //红外接收端
uchar zhb_flag=0;//保证一次解码,只执行一次代码 uint tvalue;//温度值
uchar tflag;//温度正负标志
uint  count=0;//按键次数初始化为0
uint  number=4;//暂时规定输入的温度为xx.x的形式
uchar j,key;
uint time_flag=0;
bit enterflag=0;     // 确认键按下与否标志
uint new_t;    //转化后的十进制实时温度
uint target=0;  //转化后的十进制的目标温度---有键盘输入 //------------定义接口-------------//
sbit RS=P2^2 ;
sbit RW=P2^3 ;
sbit E=P2^4;
sbit PSB= P2^5;   //H=并口; L="串口";
#define Lcd_Bus P0
// P0 接 LCM
#define uchar unsigned char
#define FIRST_ADDR 0
//定义字符/汉字显示起始位置
/*------------------检查忙位-----------------------------*/
void chk_busy()
{
    RS=0 ;
    RW=1 ;
    E=1 ;
    Lcd_Bus=0xff ;
    while((Lcd_Bus&0x80)==0x80);
    E=0 ;
}
/*------------------延时子程序-----------------------------*/
void lcd_delay(unsigned int t)
{
    unsigned int i,j ;
    for(i=0;i    for(j=0;j<10;j++);
} /*------------------写命令到LCD------------------------------*/
void write_com(unsigned char cmdcode)
{
    chk_busy();
    RS=0 ;
    RW=0 ;
    E=1 ;
    Lcd_Bus=cmdcode ;
    lcd_delay(5);
    //------------------在数据写入的时候加入适当的延时
    E=0 ;
    lcd_delay(5);
} /*-------------------写数据到LCD----------------------------*/
void write_data(unsigned char Dispdata)
{
    chk_busy();
    RS=1 ;
    RW=0 ;
    E=1 ;
    Lcd_Bus=Dispdata ;
    lcd_delay(5);
    //------------------在数据写入的时候加入适当的延时
    E=0 ;
    lcd_delay(5);
}
/*------------------初始化LCD屏--------------------------*/
void lcdreset()
{
    PSB = 1;
    lcd_delay(2000);
    write_com(0x30);
    lcd_delay(10);
    //选择基本指令集
    write_com(0x30);
    //选择8bit数据流
    lcd_delay(5);
    write_com(0x0c);
    //开显示(无游标、不反白)
    lcd_delay(10);
    write_com(0x01);
    //清除显示,并且设定地址指针为00H
    lcd_delay(500);
    write_com(0x06);
    //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位
    lcd_delay(0);
}
/*------------------显示字符串--------------------------*/
void hzkdis(unsigned char code*s)
{
    while(*s>0)
    {
        write_data(*s);
        s++;
        lcd_delay(50);
    }
}
/*------------------首屏显示--------------------------*/
void ceshi()
{
    write_com(0x01);
    //清除显示,并且设定地址指针为00H
    lcd_delay(5);
   
    write_com(0x80);
    //第一行(如果是地址是:80H,即LCD的第一行的第一个位置显示)
    hzkdis("南京邮电大学");
   
    write_com(0x90);
    //第二行(如果是地址是:90H,即LCD的第二行的第一个位置显示)
    hzkdis(str);
   
    write_com(0x88);
    //第三行(如果是地址是:88H,即LCD的第二行的第一个位置显示)
    hzkdis("电子信息工程");
   
    write_com(0x98);
    //第四行(如果是地址是:98H,即LCD的第二行的第一个位置显示)
    hzkdis("郑海波测试程序");
}
//------------------清整个GDRAM空间----------------------------
void clrgdram()
{
    unsigned char x,y ;
    for(y=0;y<64;y++)
    for(x=0;x<16;x++)
    {
        write_com(0x34);
        write_com(y+0x80);
        //行地址
        write_com(x+0x80);
        //列地址
        write_com(0x30);
        write_data(0x00);
        write_data(0x00);
    }
}
//------------------------------------------------------------
void clrscreen()
{
    write_com(0x01);
    lcd_delay(10);
}
unsigned char ReadByte(void)
{
    unsigned char byReturnValue ;
    chk_busy();
    Lcd_Bus=0xff ;
    RS=1 ;
    RW=1 ;
    E=0 ;
    E=1 ;
    byReturnValue=Lcd_Bus ;
    E=0 ;
   
    return byReturnValue ;
} /*增加画点子程序
函数功能:在坐标为(x,y)点画一个点
参数意义
X:12864屏幕的横坐标,范围是0到128(从左到右)
Y:12864的纵坐标,范围是0到64(从上到下)
Color:为1的时候表示为黑点
*/
void DrawPoint(unsigned char X,unsigned char Y,unsigned char Color)
{
    unsigned char Row,Tier,Tier_bit ;
    unsigned char ReadOldH,ReadOldL ;
    write_com(0x34);
    write_com(0x36);
    Tier=X>>4 ;
    Tier_bit=X&0x0f ;
    if(Y<32)
    {
        Row=Y ;
    }
    else
    {
        Row=Y-32 ;
        Tier+=8 ;
    }
    write_com(Row+0x80);
    write_com(Tier+0x80);
    ReadByte();
    ReadOldH=ReadByte();
    ReadOldL=ReadByte();
    write_com(Row+0x80);
    write_com(Tier+0x80);
    if(Tier_bit<8)
    {
        switch(Color)
        {
            case 0 :
            ReadOldH&=(~(0x01<<(7-Tier_bit)));
            break ;
            case 1 :
            ReadOldH|=(0x01<<(7-Tier_bit));
            break ;
            case 2 :
            ReadOldH^=(0x01<<(7-Tier_bit));
            break ;
            default :
            break ;
        }
        write_data(ReadOldH);
        write_data(ReadOldL);
    }
    else
    {
        switch(Color)
        {
            case 0 :
            ReadOldL&=(~(0x01<<(15-Tier_bit)));
            break ;
            case 1 :
            ReadOldL|=(0x01<<(15-Tier_bit));
            break ;
            case 2 :
            ReadOldL^=(0x01<<(15-Tier_bit));
            break ;
            default :
            break ;
        }
        write_data(ReadOldH);
        write_data(ReadOldL);
    }
    write_com(0x30);
}
void send_to_pc(void)
{
 uint pc_flag=0;
 SCON=0x50;//串口方式1,允许接收
 TMOD=0x20;//定时器1,定时方式2
 TCON=0x40;//设定时器1开始计数
 TH1=0xE8;//11.0592MHz, 1200波特率
 TL1=0xE8;
 TI=1;
 TR1=1;
 while(1)
 {
  if(pc_flag==1)
  {
   TMOD=1;
  }
  else
  {
   printf("Now temperture is ");
   printf(disdata);
   printf("*0.1 C");
   pc_flag++;
  }
 }
}  
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_temp1()/*读取温度值并转换*/
{
    ds1820rst();   
    ds1820wr(0xcc);//*跳过读序列号*/
    ds1820wr(0x44);//*启动温度转换*/
    ds1820rst();   
}
read_temp2()
{
    uchar a,b;
    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位小数
    return(tvalue);
}   /*******************************************************************/
void ds1820disp1()//温度值显示

    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也不显示
  }
 }
}   void ds1820disp2()
{
    lcd_delay(5);
 write_com(0x80);
    hzkdis("温度为:");
 lcd_delay(50);
 write_com(0x84);
 write_data(disdata[1]);
 write_com(0x85);
 write_data(disdata[2]);
 write_com(0x86);
 write_data(0x2e);
 write_com(0x87);
 write_data(disdata[3]);
 lcd_delay(50);
    new_t=disdata[1]*10+disdata[2];
} void delay(uint us)   //delay time
{
 while(us--);
}
void HW_key(void)
{
 if(zhb_flag==1)
 {
  if((a[2]+a[3])==0xff)  //判断接收到数据是否正确
  {
   switch(a[2])   //将接受到的数据与所建表一一对应
   { 
            case 0x00:
    {
     num=0;
     if (count     {
      str4[count]='0';
      count++;
     }break;//数字键0
    }
            case 0x01:
    {
     num=1;
     if (count     {
      str4[count]='1';
      count++;
     }break;//数字键1
    }
            case 0x02:
    {
     num=2;
     if (count     {
      str4[count]='2';
      count++;
     }break;//数字键2
    }
            case 0x03:
    {
     num=3;
     if (count     {
      str4[count]='3';
      count++;
     }break;//数字键3
    }
            case 0x04:
    {
     num=4;
     if (count     {
      str4[count]='4';
      count++;
     }break;//数字键4
    }
            case 0x05:
    {
     num=5;
     if (count     {
      str4[count]='5';
      count++;
     }break;//数字键5
    }
   case 0x06:
    {
     num=6;
     if (count     {
      str4[count]='6';
      count++;
     }break;//数字键6
    }
   case 0x07:
    {
     num=7;
     if (count     {
      str4[count]='7';
      count++;
     }break;//数字键7
    }
   case 0x08:
    {
     num=8;
     if (count     {
      str4[count]='8';
      count++;
     }break;//数字键8
    }
   case 0x09:
    {
     num=9;
     if (count     {
      str4[count]='9';
      count++;
     }break;//数字键9
    }
   case 0x0a:
    {
     num=10;
     if (count     {
      str4[count]='.';
      count++;
     }break;//键"--/-"
    }
   case 0x0b:
    {
     num=11;
     break;//键LG
    }
   case 0x0f:
    {
     num=12; break;//AV键
    }
   case 0x10:
    {
     num=13;
     send_to_pc();break;//静音键
    }
   case 0x15:
    {
     num=14;
     break;//开关键
    }
   case 0x16:
    {
     num=15;break;//选台键
    }
   case 0x17:
    {
    /* num=16; count = 0;//清零
     for (j=0;j     {
      str4[j]=' ';
     }
                    str4[j]='/0';
     PWM=1;
     time_flag=0;
     wr_com(0xcd);
     display(nul);
     target=0;
     enterflag = 0;break;//睡眠键*/
    }
   case 0x1a:
    {
     num=17;break;//音量+
    }
   case 0x1b:
    {
     num=18;break;//频道+
    }
   case 0x1c:
    {
     num=19;break;//屏显
    }
   case 0x1e:
    {
     num=20;break;//音量-
    }
   case 0x1f:
    {
     num=21;break;//频道-
    }
   case 0x30:
    {
     num=22;break;//小键'-'
    }
   case 0x4e:
    {
     num=23;break;//小键'+'
    }
   case 0x51:
    {
     num=24;break;//画中画
    }
   case 0x56:
    {
     num=25;break;//图像,菜单
    }
   case 0x57:
    {
     num=26;break;//声音
    }
   case 0x5a:
    {
     num=27;break;//方向上
    }
   case 0x5b:
    {
     num=28;break;//方向右
    }
   case 0x5c:
    {
     num=29;
     enterflag = 1;    // 确认键按下   
     str4[count]='/0';break;//完成
    }
   case 0x5e:
    {
     
     num=30;break;//方向下
    }
   case 0x5f:
    {  
     num=31;break;//方向左
    }
            default:break;
  }
  if (enterflag==1)     // 如果按下确认键
  {
   //   enterflag = 0;      // 标志位置回0
/*   wr_com(0xcd);
            wr_dat(0xdf);
            wr_dat(0x43);
   target=str4[0]*10+str4[1];
   time_flag=1;*/
  }
/*  wr_com(0xc0);
        display(str3);
        wr_com(0xc8);
        display(str4);
  zhb_flag=0;*/
  }
       }
}
/*void pitu_wave(void)
{
   uchar i,a;
   uchar colour=1;
   for(i=0;i<128;i+=2)
    {
         a=64-new_t;
         DrawPoint(i,a,colour);
    }
}*/
/********************主程序***********************************/
void main()
{
    uchar wave=0;
  uchar i=0,a;
   uchar colour=1;
    RW=0 ;
    lcdreset();
    ceshi();
    clrgdram();
    delay(2000);
    clrscreen();
    EA=1;    //初始化
 ET0=1;  //开计数中断0
 EX0=1;   //开外部中断0
 TMOD=1; //设置工作方式
 IT0=1;    //启动计时器
    while(1)
    { 
  read_temp1();//读取温度
  read_temp2();//读取温度
  ds1820disp1();//显示
  ds1820disp2();//显示
  wave++;
  if(wave>=10)
  {
        a=64-new_t;
     if(i>=128)
     {
       i=0;
    clrgdram();
             delay(2000);
             clrscreen();
     }
           DrawPoint(i++,a,colour);
     wave=0;
  }
  HW_key();
    }
}
void zhb(void) interrupt 0 // 外部中断子程序(译码过程)
{
    zhb_flag=1;
 TH0=0;   //计数器清零
 TL0=0;
 TR0=1;   //启动计数器
 while(!js)   //等待低电平结束
 {
  delay(5);
  if(TH0>45)  //判断低电平是否高于11.52ms如果高于则跳出等待和中断
   return;
 }
 TR0=0;
 if(TH0<30)  //判断低电平是否低于7.68ms如果低于跳出中断
  return;
 TH0=0;
 TR0=1;
 while(js)   //等待高电平结束
 {
  delay(5);
  if(TH0>28)  //判断高电平是否高于7.168ms如果高于则跳出等待和中断
   return;
 }
 
 //至此为起始信号检测
 
 TR0=0;
 TH0=0;
 for(i=0;i<4;i++)  //一次锁存红外接收的四个十六进制数到a[4]中
 {
  for(j=0;j<8;j++)
  {
   TR0=1;
   while(!js)  //判断低电平宽度是否大于3..40ms
   {
    delay(5);
    if(TH0>15)
     return;
   }
   TH0=0;
   while(js) //判断高电平是否大于1.012ms如果高于则为接受到1,否则为0
   {
    delay(5);
    if(TH0>15)
     return;
   }
   TR0=0;
   CY=0;
   k=(k>>1);
   if(TH0>4)
    k=k+0x80;
   TH0=0;
  }
  a[i]=k;
 }
}