返回首页
当前位置: 主页 > PIC单片机 >

QL200板练习测温电路

时间:2009-11-24 17:58来源:网络 作者:admin 点击:
QL200板练习测温电路

//QL200板,PIC16F877A芯片。lcd1602显示,利用ds1302、ds18b20实现实时时钟(小时、分钟、秒、年、月、日、星期)、 实时温度显示。
//通过按键校时:K10(小时) K11(分钟) K12(秒,归零) K13(星期) RB1(年) RB2(月) RB3(日)
#include<pic.h>
__CONFIG(0X1832);

#define rs    RA1                      //ds1602接口定义
#define rw    RA2
#define e     RA3
#define dq    RA0                      //定义DS18B20的数据口
#define i_o   RB4                      //定义DS1302的数据口
#define sclk  RB0                      //定义DS1302的时钟口
#define rst   RB5                      //定义DS1302的复位口

unsigned char bai,shi,ge,shifen;       //温度百位 十位 个位 十分位
float temp;                            //温度
void display();                        //显示函数
void get_time();                       //读取ds1302时间
void change_time();                    //校时程序
unsigned char table1[7];               //定义读取时间和日期存放表格
unsigned char count,sec,min,hour,day,mon,week,year,time;

 

 

//****************************************
//**************lcd1602*******************
//****************************************
//延时程序
void delay()
 {
 unsigned char i;
  for(i=100;i>0;i--);
 }

//****************************************
//LCD写一个字节数据
void lcd_write_byte(unsigned char code)
 {
   PORTD=code;
   rs=1;
   rw=0;
   e=0;
   delay();
   e=1;
 }

//****************************************
//lcd写命令函数
void lcd_enable(unsigned char code)
 {
  PORTD=code;
  rs=0;
  rw=0;
  e=0;
  delay();
  e=1;  
 }
//*****************************************
//lcd显示设置
void lcd_init()
 {
  lcd_enable(0x01); //清除显示
  lcd_enable(0x38); //设置16X2显示,5X7点阵
  lcd_enable(0x0c); //开显示,不显示光标
  lcd_enable(0x06); //光标左移
 }

 


//****************************************
//*********ds18b20部分********************
//****************************************
//延时程序
void delay1(unsigned char x)
 {
   unsigned char i;
   for(i=x;i>0;i--);
 }

//****************************************
//写ds18b20一个字节
void ds18b20_write_byte(unsigned char val)
{
 unsigned char i;
 unsigned char temp;
 for(i=8;i>0;i--)
 {
   temp=val&0x01;                            //最低位移出
   TRISA0=0;
   dq=0;
   NOP();
   NOP();
   NOP();
   NOP();
   NOP();                                    //从高拉至低电平,产生写时间隙
   if(temp==1)  TRISA0=1;                   //如果写1,拉高电平
   delay1(16);                               //延时60us
   TRISA0=1;
   NOP();
   NOP();
   val=val>>1;                               //右移一位
  }
}

//***************************************
//读ds18b20
unsigned char  ds18b20_read_byte2()
 {
   unsigned char i,k;
   for(i=8;i>0;i--)
   {
     k=k>>1;
     TRISA0=0;
     dq=0;             //数据线拉低再拉高产生读时间片
     asm("nop");
     asm("nop");
     TRISA0=1;
     asm("nop");
     asm("nop");
     if(dq==1)  k=k|0x80;  //读1
     delay1(20);        //延时71us后释放总线
   }
   return (k);
 }

 

//***************************************
//初始化ds18b20
void ds18b20_init()
{
  unsigned char i=5;
  while(i)
  {
    TRISA0=0;                                 //主机拉至低电平
    dq=0;
    delay1(170);                              //延时520us(要求480-960us)
    TRISA0=1;                                 //释放总线等电阻拉高总线,并保持15~60us
    delay1(20);                               //延时70us,不能大于300us
    if(dq==1)
       i--;                                   //连续5次无应答则跳过
    else
       i=0;                                   //接收到应答则不再初始化
    delay1(140);                              //延时430us (70us+430us>480us)
   }
  }

//****************************************
//温度转换
void get_temp()
{
  int i;
  unsigned char TLV,THV;
  signed int t;
  TRISA0=1;
  ds18b20_init();                             //复位等待从机应答
  ds18b20_write_byte(0XCC);                   //忽略ROM匹配
  ds18b20_write_byte(0X44);                   //发送温度转化命令 
  for(i=46;i>0;i--)
    {
     get_time();                              //调用取时间函数
     change_time();
     display();                               //757us,调用多次显示函数,确保温度转换完成所需要的时间
    }
  ds18b20_init();                             //再次复位,等待从机应答
  ds18b20_write_byte(0XCC);                   //忽略ROM匹配
  ds18b20_write_byte(0XBE);                   //发送读温度命令
  TLV=ds18b20_read_byte2();                   //读出温度低8
  THV=ds18b20_read_byte2();                   //读出温度高8位
  TRISA0=1;                                   //释放总线
  t=THV<<8;
  t=t|TLV;
  if(t<0)                                     //负温度
   {
     temp=(~t+1)*0.0625*10+0.5;               //负温度时,取反加1再乘以0.0625得实际温度,乘10+0.5显示小数点一位,且四舍五入
   }
  else
     temp=t*0.0625*10+0.5;                    //正温度
  if(t<0)
     bai='-';                                 //负温度时百位显示负号
  else
    bai=(unsigned int) temp/1000+0x30;        //百位
  shi=((unsigned int) temp%1000)/100;         //十位
  ge=((unsigned int) temp%1000)%100/10;       //个位
  shifen=((unsigned int) temp%1000)%100%10;   //十分位
}


//****************************************
//***********DS1302部分*******************
//****************************************
//写一个字节数据函数
void write_byte(unsigned char data)
 {
    int j;                            //设置循环变量
    for(j=0;j<8;j++)                  //连续写8bit
      {
        i_o=0;                        //先设置数据为0
        sclk=0;                       //时钟信号拉低
        if(data&0x01)              //判断待发送的数据位是0或1
          {
            i_o=1;                    //待发送数据位是1
          }
        data=data>>1;           //待发送的数据右移1位
        sclk=1;                       //拉高时钟信号
       }
      sclk=0;                         //写完一个字节,拉低时钟信号
  }

//***************************************
//读一个字节函数
unsigned char read_byte()
 {
   unsigned char data;
   int j;                            //设置循环变量
   TRISB4=1;                         //设置数据口方向为输入
   for(j=8;j--;)                  //连续读取8bit
      {
        sclk=0;                      //拉低时钟信号
        data=data>>1;         //接收寄存器右移1位
        if(i_o==1) data=data|0x80;
        sclk=1;                       //拉高时钟信号
      }
    TRISB4=0;                        //恢复数据口方向为输出
    sclk=0;                          //拉低时钟信号
    return(data);                 //返回读取到的数据
  }

//***************************************
//写DS1302
 void write_ds1302(unsigned char addr,unsigned char code)
  {
   rst=0;
   sclk=0;
   rst=1;
   write_byte(addr);
   write_byte(code);
   sclk=0;
   rst=1;
  }


//***************************************
//读DS1302
 unsigned char read_ds1302(unsigned char addr)
  {
   unsigned char data;
   rst=0;
   sclk=0;
   rst=1;
   write_byte(addr);
   data=read_byte();
   return(data);
  }

//***************************************
//读取时间函数
void get_time()
 {
  
   int i;                             //设置循环变量
   rst=1;                             //使能DS1302
   write_byte(0xbf);                //发送多字节读取命令
   for(i=0;i<7;i++)                   //连续读取7个字节数据
     {
        table1[i]=read_byte();      //调用读取1个字节数据的函数
     }
    rst=0;                            //复位DS1302
 }


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
//***************************************
//DS1302初始化函数
void ds1302_init()
  {
   sclk=0;                            //拉低时钟信号
   rst =0;                            //复位DS1302
   rst=1;                             //使能DS1302
   write_ds1302(0x8e,0);                //发控制命令
   rst=0;                             //复位
  }

//***************************************
//设置时间函数
void set_time()
  {
   //定义待设置的时间: 秒、 分、 时、 日、月、星期、年、控制字
   const char table[]={0x00,0x00,0x12,0x23,0x10,0x05,0x09,0x00};
   int i;                             //定义循环变量
   rst=1;                             //使能DS1302
   write_byte(0xbe);                //时钟多字节写命令
   for(i=0;i<8;i++)                   //连续写8个字节数据
     {
       write_byte(table[i]);        //调用写一个字节函数
     }
   rst=0;                             //复位
   }

//***************************************
//8位二进制数转换为十进制数
 void two_to_ten(unsigned char i)
   {
     time=(table1[i]&0x0f)+(table1[i]>>4)*0x0a;  
   }

//***************************************
//十进制数转换为BCD码
  void ten_to_bcd(unsigned char i)
   {
     time=((i/0x0a)<<4)|(i%0x0a);
   }

//***************************************
//校时程序
void change_time()
  {
    if(RC0==0)                                                //改变星期---k13
      {
       delay();
        if(RC0==0)
         {
           if(count==0)
             {
               count=1;
               two_to_ten(5);
               week=time;
               week++;
               if(week>=8)
                {
                  week==1;
                  write_ds1302(0x8A,1);
                }
               else
                 write_ds1302(0x8A,week); 
             }
         }
      }
   else if(RC1==0)                                              //秒归零--k12
      {
        delay();
       if(RC1==0)
          {
            if(count==0)
              {
                count=1;
                write_ds1302(0x80,0);
              }
          }
      }
    else if(RC2==0)                                            //改变分位--k11
      {
        delay();
        if(RC2==0)
          {
            if(count==0)
              {
                count=1;
                two_to_ten(1);                                  //BCD码转换成十进制数
                min=time;
                min++;
                if(min>=60)
                 {
                  min=0;
                  write_ds1302(0x82,min);
                 }
               else
                {
                  ten_to_bcd(min);                              //十进制数转换为BCD码存进DS1302
                  write_ds1302(0x82,time);
                }
              }
          }
      }

     else if(RC3==0)                                            //改变小时位--k10
       {
         delay();
         if(RC3==0)
           {
             if(count==0)
               {
                 count=1;
                 two_to_ten(2);                                 //BCD码转换成十进制数
                 hour=time;
                 hour++;
                 if(hour>=24)
                   {
                     hour=0;
                     write_ds1302(0x84,hour);
                   }
                 else
                  {
                     ten_to_bcd(hour);
                     write_ds1302(0x84,time);
                  }
               }
           }
       }

      else if(RB2==0)
         {
           delay();
           if(RB2==0)
             {
              if(count==0)
                {
                  count=1;
                  two_to_ten(4);                                   //BCD码转换成十进制数
                  mon=time;
                  mon++;
                  if(mon>=13)
                   {
                     mon=1;
                     write_ds1302(0x88,mon);
                   }
                  else
                   {  
                     ten_to_bcd(mon);
                     write_ds1302(0x88,time);
                   }
                }
             }
         }

      else if(RB3==0)
         {
           delay();
           if(RB3==0)
            {
              if(count==0)
               {
                 count=1;
                 two_to_ten(3);                                      //BCD码转换成十进制数
                 day=time;
                 day++;
                 if((table1[6]%4==0)&&(table1[4]==2)&&(day>=30))     //润年2月
                    {
                      day=1;   
                      write_ds1302(0x86,day);                 
                    }
                else if(((table1[6]%4)!=0)&&(table1[4]==2)&&(day>=29))//非润年的2月
                    {
                      day=1;
                      write_ds1302(0x86,day);
                    }
                else if(((table1[4]==1)||(table1[4]==3)||(table1[4]==5)||(table1[4]==7)||(table1[4]==8)||(table1[4]==0x10)||(table1[4]==0x12))&&(day>=32))
                    {    
                      day=1;  
                      write_ds1302(0x86,day);
                    }
                else if(((table1[4]==4)||(table1[4]==6)||(table1[4]==9)||(table1[4]==0x11))&&(day>=31))
                    {    
                      day=1; 
                      write_ds1302(0x86,day);                     
                    }            
                else
                    {    
                      ten_to_bcd(day);
                      write_ds1302(0x86,time);
                    }
               }
            }
         }

     else if(RB1==0)
          {
            delay();
            if(RB1==0)
              {
                if(count==0)
                 {
                   count=1;
                   two_to_ten(6);//BCD码转换成十进制数
                   year=time;
                   year++;
                   if(year>=16)
                     {
                       year=0x00;
                       write_ds1302(0x8c,0);
                     }
                   else
                      {
                        ten_to_bcd(year);
                        write_ds1302(0x8c,time);
                      }
                 }
              }
          }
     else
       count=0;

  }


//****************************************
//****************************************
//显示函数
void display()
 {
     lcd_enable(0X80);                     //小时
     lcd_write_byte((table1[2]>>4)+0x30);
     lcd_enable(0x81);
     lcd_write_byte((table1[2]&0x0f)+0x30); 

     lcd_enable(0x82);
     lcd_write_byte(':');
  
     lcd_enable(0x83);                     //分钟
     lcd_write_byte((table1[1]>>4)+0x30);
     lcd_enable(0x84);
     lcd_write_byte((table1[1]&0x0f)+0x30); 
 
     lcd_enable(0x85);
     lcd_write_byte(':');
  
     lcd_enable(0x86);                     //秒
     lcd_write_byte((table1[0]>>4)+0x30);
     lcd_enable(0x87);
     lcd_write_byte((table1[0]&0x0f)+0x30);
 
     lcd_enable(0XC0);                     //年               
     lcd_write_byte((table1[6]>>4)+0x30);   
     lcd_enable(0XC1);
     lcd_write_byte((table1[6]&0x0f)+0x30);

     lcd_enable(0XC2);
     lcd_write_byte('-');

     lcd_enable(0XC3);                     //月
     lcd_write_byte((table1[4]>>4)+0x30);
     lcd_enable(0XC4);
     lcd_write_byte((table1[4]&0x0f)+0x30);

     lcd_enable(0XC5);
     lcd_write_byte('-');
  
     lcd_enable(0XC6);                     //日
     lcd_write_byte((table1[3]>>4)+0x30);
     lcd_enable(0XC7);
     lcd_write_byte((table1[3]&0x0f)+0x30);    

     lcd_enable(0XCD);                    //星期
     lcd_write_byte((table1[5]&0x0f)+0x30);

     lcd_enable(0x8A);                    //温度百位,当为负温度时显示'-'
     lcd_write_byte(bai);

     lcd_enable(0x8B);                    //温度十位
     lcd_write_byte(shi+0x30);

     lcd_enable(0x8C);                    //温度个位
     lcd_write_byte(ge+0x30);

     lcd_enable(0x8D);
     lcd_write_byte('.');

     lcd_enable(0x8E);                   //温度十分位
     lcd_write_byte(shifen+0x30);

     lcd_enable(0x8F);
     lcd_write_byte('C');
  
 }
//****************************************
//端口初始化
void port_init()
 {
    TRISA=0x00;                     //设置A口全输出
    TRISD=0X00;                     //设置D口全输出
    ADCON1=0X06;                    //设置A口为普通I/O口
    TRISB=0X0E;                     //
    OPTION=0X00;                    //开启B口弱上拉
    PORTA=0XFF;              
    PORTD=0XFF;                     //先熄灭所有显示
    lcd_init();
    TRISC=0XEF;                     //RC3输出,其他为输入
    PORTC=0XEF;
    count=0;
 }

//*****************************************
//主函数
void main()
  {
     port_init();                   //调用引脚初始化函数
     lcd_init();
     if(read_ds1302(0x81)&0x80)     //否,则初始化DS1302
      {
        ds1302_init();              //调用DS1302初始化函数
        set_time();                 //调用设置时间函数
      }
     while(1)
      {
        get_time();                 //调用取时间函数
        change_time();              //按键程序
        get_temp();                 //调用温度转换函数
        display();                  //调用显示函数
      }
  }

 

转自:PIC单片机论坛

(责任编辑:admin)
顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名:密码: 验证码:点击我更换图片