找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 7830|回復(fù): 4
收起左側(cè)

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

  [復(fù)制鏈接]
ID:21069 發(fā)表于 2018-12-21 23:44 | 顯示全部樓層 |閱讀模式
電路原理圖如下:
QQ截圖20181221234210.jpg

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

// 晶振:XT;代碼:沒有代碼保護;上電延時定時器關(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ù)點的共陰極數(shù)碼管0123456789段碼,正負符號位
const unsigned char ledcode1[12]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x00,0x40};   
//帶小數(shù)點的共陰極數(shù)碼管0123456789段碼 ,正負符號位

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                         //定義一個聯(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ù)個位
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ū)動(高有效)
//        PORTE作為數(shù)碼管位選擇驅(qū)動(低有效)
//*********************************************************
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;
}
//*********************************************************
//                延時程序
//*********************************************************
void delay(char x,char y)
{
  char z;
  do{
      z=y;
      do{;}while(--z);
     }while(--x);
}
//其指令時間為:7+(3*(Y-1)+7)*(X-1)如果再加上函數(shù)調(diào)用的call 指令、頁面設(shè)定、傳遞參數(shù)花掉的7 個指令。
//則是: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() ;                                //主機拉至低電平
    delay(2,90);                              //延時>480503us
    DQ_HIGH();                                //釋放總線等電阻拉高總線,并保持15~60us
    delay(2,8);                               //延時>60us
    if(DQ==1) presence=1;                     //沒有接收到應(yīng)答信號,繼續(xù)復(fù)位
    else presence=0;                          //接收到應(yīng)答信號
    delay(2,70);                              //延時>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)生寫時間隙
   if(temp==1)  DQ_HIGH();                   //如果寫1,拉高電平
   delay(2,7);                               //延時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();          //每次讀時隙由主機發(fā)起,拉低總線至少1μs。
   NOP();
   NOP();
   NOP();
   NOP();
   NOP();
   NOP();                                   //6us
   DQ_HIGH();          //讀時隙開始后的15μs內(nèi)釋放總線,拉至高電平,準(zhǔn)備采樣總線。
   NOP();
   NOP();
   NOP();  
   NOP();
   NOP();                                  //5us
   j=DQ;               //采樣總線
   if(j) value|=0x80;  //把采樣到的數(shù)據(jù)放入value
   delay(2,7);               //所有讀時隙至少60μs,這里大約63us
  }
  return(value);
}

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

reset();                                 //再次復(fù)位,等待從機應(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)的溫度二進制值轉(zhuǎn)換成十進制數(shù)
}

//將相應(yīng)的溫度溫度整數(shù)部分和小數(shù)部分的二進制值轉(zhuǎ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;//個位                          //整數(shù)部分個位

    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                                       //否則,是負溫度,要求補碼
{
  temp.TV[0]=TL;temp.TV[1]=TH ;
  temp.T=(~temp.T)+0x0010;              //補碼形式,起反加1      
  TL=temp.TV[0];
  TH=temp.TV[1];

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

    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];
}


//*********************************************************
//                        定時中斷初始化(OPTION_REG)
//*********************************************************
void tmint(void)
{
  T0CS=0;             //時鐘源為內(nèi)部指令周期                  
  PSA=0;           //分頻器分配給TMR0
//  
  PS2=0;          //TMR0的分頻比為1:16         
  PS1=1;
  PS0=1;
//
  GIE=1;          //允許總中斷
  T0IE=1;         //允許定時器0溢出中斷
  T0IF=0;         //清楚定時器0中斷標(biāo)志
  TMR0=0X06;      //預(yù)置初值 T=(256-6)x16=4000uS
}
//*********************************************************
void interrupt dealtime()   //中斷入口,該中斷完成數(shù)碼管的動態(tài)掃描
{                          //每中斷一次的時間為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 共享資料的黑幣獎勵!
鉆牛尖滴劉尖尖 + 10
shuisheng + 15 贊一個!
Trump1438 + 10 贊一個!
Sawardeakar + 10 贊一個!
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復(fù)

使用道具 舉報

ID:297903 發(fā)表于 2022-2-15 09:03 | 顯示全部樓層
下載來測試下,謝謝��!
回復(fù)

使用道具 舉報

ID:582276 發(fā)表于 2022-4-7 23:15 | 顯示全部樓層
放到XC8中轉(zhuǎn)換試下
回復(fù)

使用道具 舉報

ID:362692 發(fā)表于 2022-5-4 12:11 | 顯示全部樓層
你怎么回事?  源文件發(fā)一下不是更省事
回復(fù)

使用道具 舉報

ID:192215 發(fā)表于 2022-5-27 11:30 | 顯示全部樓層
下載資料包里面沒有源文件嗎?
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

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