找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 7871|回復(fù): 4
打印 上一主題 下一主題
收起左側(cè)

PIC16F877單片機(jī)DS18B20數(shù)碼管溫度計(jì)仿真程序 可顯示負(fù)溫度

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:21069 發(fā)表于 2018-12-21 23:44 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
電路原理圖如下:


//*********************************************************
//        實(shí)現(xiàn)的功能:數(shù)碼管顯示實(shí)時(shí)溫度,支持負(fù)溫度
//        芯片PIC16F877
//        XT:4MHZ
//*********************************************************
#include <pic.h>       //包含單片機(jī)內(nèi)部資源預(yù)定義
#define LVP 0x3f39

// 晶振:XT;代碼:沒有代碼保護(hù);上電延時(shí)定時(shí)器關(guān)閉;
// 低電壓復(fù)位禁止;看門狗關(guān)閉 ;低電壓編程禁止
__CONFIG (XT & UNPROTECT & PWRTDIS & BORDIS & WDTDIS & LVP);

#define  uch  unsigned char                     //給unsigned char起別名 uch
#define DQ RA2                                //定義18B20數(shù)據(jù)端口
#define DQ_DIR TRISA2                         //定義18B20D口方向寄存器
#define DQ_HIGH() DQ_DIR =1                   //設(shè)置數(shù)據(jù)口為輸入
#define DQ_LOW() DQ_DIR = 0;DQ = 0            //設(shè)置數(shù)據(jù)口為輸出

const unsigned char ledcode[12]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40};
//不帶小數(shù)點(diǎn)的共陰極數(shù)碼管0123456789段碼,正負(fù)符號位
const unsigned char ledcode1[12]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x00,0x40};   
//帶小數(shù)點(diǎn)的共陰極數(shù)碼管0123456789段碼 ,正負(fù)符號位

void init_port(void);
void delay(char x,char y);
void delay_1ms(void);
void delay_ms(unsigned int time);
void interrupt dealtime();
void tmint(void);
void timetoseg(uch fh_temp,uch bai_temp,uch shi_temp,uch ge_temp,uch sf_temp,uch bf_temp,uch qf_temp,uch wf_temp);
void binary_temp(uch TL , signed char TH);
void reset(void);
void write_byte(uch val);
uch read_byte(void);
void get_temp(void);

unsigned char display_data[8];
unsigned char intcount=0;
uch  TLV=0 ;                        //采集到的溫度高8位
uch  THV=0;                         //采集到的溫度低8位

union temp                         //定義一個(gè)聯(lián)合體
{
int T;        
uch TV[2];        
}temp;

signed char TZ=0;                     //轉(zhuǎn)換后的溫度值整數(shù)部分,有符號位
uch TX=0;                            //轉(zhuǎn)換后的溫度值小數(shù)部分

unsigned int wd;                              //轉(zhuǎn)換后的溫度值BCD碼形式

unsigned char fh;                               //符號位
unsigned char bai;                             //整數(shù)百位
unsigned char shi;                             //整數(shù)十位
unsigned char ge;                              //整數(shù)個(gè)位
unsigned char shifen;                          //十分位
unsigned char baifen;                          //百分位
unsigned char qianfen;                         //千分位
unsigned char wanfen;                          //萬分位


//*********************************************************
//                        主程序
//*********************************************************
void main(void)
{
init_port();
tmint();
while(1)
  {         
   get_temp();
   timetoseg(fh,bai,shi,ge,shifen,baifen,qianfen,wanfen);  

  }
}
//*********************************************************
//        端口初始化
//        PORTD作為數(shù)碼管段驅(qū)動(dòng)(高有效)
//        PORTE作為數(shù)碼管位選擇驅(qū)動(dòng)(低有效)
//*********************************************************
void init_port(void)
{
  RBPU=0;
//  PORTB=0xFF;
  TRISB=0xFF;
  PORTD=0x00;           //
  TRISC=0x00;           //C口控制LED指示燈,設(shè)置成輸出
  TRISD=0;                   //D口當(dāng)作數(shù)碼管段,設(shè)置成輸出
  ADCON1=0x07;                //使A口,E口全為數(shù)字I/O口
  TRISE=0x00;           //E口當(dāng)作數(shù)碼管位選擇控制腳,設(shè)置成輸出   
  PORTE=0x00;
}
//*********************************************************
//                延時(shí)程序
//*********************************************************
void delay(char x,char y)
{
  char z;
  do{
      z=y;
      do{;}while(--z);
     }while(--x);
}
//其指令時(shí)間為:7+(3*(Y-1)+7)*(X-1)如果再加上函數(shù)調(diào)用的call 指令、頁面設(shè)定、傳遞參數(shù)花掉的7 個(gè)指令。
//則是:14+(3*(Y-1)+7)*(X-1)。
//*********************************************************
//                延遲程序
//*********************************************************
void delay_1ms(void)
{
  unsigned int n;
  for(n=0;n<50;n++)
   {
    NOP();
   }
}
//*********************************************************
void delay_ms(unsigned int time)
{
  for(;time>0;time--)
   {
    delay_1ms();
   }
}

//-----------------------------------------------
//復(fù)位DS18B20函數(shù)
void reset(void)
{
  uch presence=1;
  while(presence)
  {
    DQ_LOW() ;                                //主機(jī)拉至低電平
    delay(2,90);                              //延時(shí)>480503us
    DQ_HIGH();                                //釋放總線等電阻拉高總線,并保持15~60us
    delay(2,8);                               //延時(shí)>60us
    if(DQ==1) presence=1;                     //沒有接收到應(yīng)答信號,繼續(xù)復(fù)位
    else presence=0;                          //接收到應(yīng)答信號
    delay(2,70);                              //延時(shí)>240us
   }
  }

//-----------------------------------------------
//寫18b20寫字節(jié)函數(shù)
void write_byte(uch val)
{
uch i;
uch temp;
for(i=8;i>0;i--)
{
   temp=val&0x01;                            //最低位移出
   DQ_LOW();
   NOP();
   NOP();
   NOP();
   NOP();
   NOP();                                    //從高拉至低電平,產(chǎn)生寫時(shí)間隙
   if(temp==1)  DQ_HIGH();                   //如果寫1,拉高電平
   delay(2,7);                               //延時(shí)63us
   DQ_HIGH();
   NOP();
   NOP();
   val=val>>1;                               //右移一位
  }
}

//------------------------------------------------
//18b20讀字節(jié)函數(shù)
uch read_byte(void)
{
uch i;
uch value=0;                                //讀出溫度
static bit j;
for(i=8;i>0;i--)
{
   value>>=1;
   DQ_LOW();          //每次讀時(shí)隙由主機(jī)發(fā)起,拉低總線至少1μs。
   NOP();
   NOP();
   NOP();
   NOP();
   NOP();
   NOP();                                   //6us
   DQ_HIGH();          //讀時(shí)隙開始后的15μs內(nèi)釋放總線,拉至高電平,準(zhǔn)備采樣總線。
   NOP();
   NOP();
   NOP();  
   NOP();
   NOP();                                  //5us
   j=DQ;               //采樣總線
   if(j) value|=0x80;  //把采樣到的數(shù)據(jù)放入value
   delay(2,7);               //所有讀時(shí)隙至少60μs,這里大約63us
  }
  return(value);
}

//-------------------------------------------------
//啟動(dòng)溫度轉(zhuǎn)換函數(shù)
void get_temp()
{
int i;
DQ_HIGH();
reset();                                 //復(fù)位等待從機(jī)應(yīng)答
write_byte(0XCC);                        //忽略ROM匹配
write_byte(0X44);                        //發(fā)送溫度轉(zhuǎn)化命令  
for(i=10;i>0;i--)
    {   
        delay(201,132);                       
    }   

reset();                                 //再次復(fù)位,等待從機(jī)應(yīng)答
write_byte(0XCC);                        //忽略ROM匹配
write_byte(0XBE);                        //發(fā)送讀溫度命令

TLV=read_byte();                  //讀出溫度低8位
THV=read_byte();                  //讀出溫度高8位

DQ_HIGH();                               //釋放總線


TZ=(TLV>>4)|(THV<<4);           //溫度整數(shù)部分
TX=TLV<<4;                      //溫度小數(shù)部分,注意TX的后四位無效碼
binary_temp(TX, TZ );   //將相應(yīng)的溫度二進(jìn)制值轉(zhuǎn)換成十進(jìn)制數(shù)
}

//將相應(yīng)的溫度溫度整數(shù)部分和小數(shù)部分的二進(jìn)制值轉(zhuǎn)換成十進(jìn)制數(shù)

void binary_temp(char TL , signed char TH)
{
  if(TH>=0)                          //如果是正溫度
  {
    fh=0x0A;                                 //正數(shù)符號位
    bai=TH/100;                               //整數(shù)部分百位
    shi=(TH%100)/10;//十位                   //整數(shù)十位
    ge=(TH%100)%10;//個(gè)位                          //整數(shù)部分個(gè)位

    wd=0;  
    if (TL & 0x80) wd=wd+5000;
    if (TL & 0x40) wd=wd+2500;
    if (TL & 0x20) wd=wd+1250;
    if (TL & 0x10) wd=wd+625;                //以上4條指令把小數(shù)部分轉(zhuǎn)換為BCD碼形式            

    shifen=wd/1000;                          //十分位                    
    baifen=(wd%1000)/100;                    //百分位
    qianfen=(wd%100)/10;                     //千分位
    wanfen=wd%10;                            //萬分位
    NOP();
   }
else                                       //否則,是負(fù)溫度,要求補(bǔ)碼
{
  temp.TV[0]=TL;temp.TV[1]=TH ;
  temp.T=(~temp.T)+0x0010;              //補(bǔ)碼形式,起反加1      
  TL=temp.TV[0];
  TH=temp.TV[1];

    fh=0x0B;                                //負(fù)數(shù)符號位
    bai=TH/100;                               //整數(shù)部分百位
    shi=(TH%100)/10;//十位                   //整數(shù)十位
    ge=(TH%100)%10;//個(gè)位                          //整數(shù)部分個(gè)位

    wd=0;  
    if (TL & 0x80) wd=wd+5000;
    if (TL & 0x40) wd=wd+2500;
    if (TL & 0x20) wd=wd+1250;
    if (TL & 0x10) wd=wd+625;                //以上4條指令把小數(shù)部分轉(zhuǎn)換為BCD碼形式            

    shifen=wd/1000;                          //十分位                    
    baifen=(wd%1000)/100;                    //百分位
    qianfen=(wd%100)/10;                     //千分位
    wanfen=wd%10;                            //萬分位
    NOP();
}               
}

//          溫度值各位轉(zhuǎn)換成段碼
//*********************************************************
void timetoseg(uch fh_temp,uch bai_temp,uch shi_temp,uch ge_temp,uch sf_temp,uch bf_temp,uch qf_temp,uch wf_temp)
{
   display_data[0] = ledcode[wf_temp];
   display_data[1] = ledcode[qf_temp];
   display_data[2] = ledcode[bf_temp];
   display_data[3] = ledcode[sf_temp];
   display_data[4] = ledcode1[ge_temp];
   display_data[5] = ledcode[shi_temp];
   display_data[6] = ledcode[bai_temp];
   display_data[7] = ledcode[fh_temp];
}


//*********************************************************
//                        定時(shí)中斷初始化(OPTION_REG)
//*********************************************************
void tmint(void)
{
  T0CS=0;             //時(shí)鐘源為內(nèi)部指令周期                  
  PSA=0;           //分頻器分配給TMR0
//  
  PS2=0;          //TMR0的分頻比為1:16         
  PS1=1;
  PS0=1;
//
  GIE=1;          //允許總中斷
  T0IE=1;         //允許定時(shí)器0溢出中斷
  T0IF=0;         //清楚定時(shí)器0中斷標(biāo)志
  TMR0=0X06;      //預(yù)置初值 T=(256-6)x16=4000uS
}
//*********************************************************
void interrupt dealtime()   //中斷入口,該中斷完成數(shù)碼管的動(dòng)態(tài)掃描
{                          //每中斷一次的時(shí)間為4毫秒
    T0IF=0;
    TMR0=0X06;

    PORTD = 0x00;            //先關(guān)閉顯示
   if(intcount==0)
     {
      PORTD = display_data[0];
      PORTE=0x00;
      intcount+=1;
     }
   else if(intcount==1)
     {
      PORTD = display_data[1];
      PORTE=0x01;
      intcount+=1;
     }
   else if(intcount==2)
     {
      PORTD = display_data[2];
      PORTE=0x02;
      intcount+=1;
     }
   else if(intcount==3)
     {
      PORTD = display_data[3];
      PORTE=0x03;
      intcount+=1;
     }
   else if(intcount==4)
     {
      PORTD = display_data[4];
      PORTE=0x04;
      intcount+=1;
     }
   else if(intcount==5)
     {
      PORTD = display_data[5];
      PORTE=0x05;
      intcount+=1;
     }
   else if(intcount==6)
     {
      PORTD = display_data[6];
      PORTE=0x06;
      intcount+=1;
     }   
    else if(intcount==7)
     {
      PORTD = display_data[7];
      PORTE=0x07;
      intcount = 0;
     }   

}



PIC16F877+DS18B20+數(shù)碼管.rar (25.75 KB, 下載次數(shù): 139)





評分

參與人數(shù) 6黑幣 +105 收起 理由
zwk34 + 10 共享資料的黑幣獎(jiǎng)勵(lì)!
鉆牛尖滴劉尖尖 + 10
shuisheng + 15 贊一個(gè)!
Trump1438 + 10 贊一個(gè)!
Sawardeakar + 10 贊一個(gè)!
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏6 分享淘帖 頂3 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:297903 發(fā)表于 2022-2-15 09:03 | 只看該作者
下載來測試下,謝謝�。�
回復(fù)

使用道具 舉報(bào)

板凳
ID:582276 發(fā)表于 2022-4-7 23:15 | 只看該作者
放到XC8中轉(zhuǎn)換試下
回復(fù)

使用道具 舉報(bào)

地板
ID:362692 發(fā)表于 2022-5-4 12:11 | 只看該作者
你怎么回事?  源文件發(fā)一下不是更省事
回復(fù)

使用道具 舉報(bào)

5#
ID:192215 發(fā)表于 2022-5-27 11:30 | 只看該作者
下載資料包里面沒有源文件嗎?
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表