- #include<reg52.h> // 晶振為 11.0592MHz
- #define uint unsigned int
- #define uchar unsigned char
- sbit DQ=P2^5;// 接溫度傳感器
- sbit duan=P2^6;// 數碼管段選
- sbit wei=P2^7; // 數碼管位選
- uchar code numw[]={0x01,0x02,0x04,0x08,0x10,// 數碼管位選
- 0x20,0x40,0x80,0x00};
- uchar code numd[]={0x3f,0x06,0x5b,0x4f,0x66,// 數碼管段選顯示( 0—9)
- 0x6d,0x7d,0x07,0x7f,0x6f};
- uchar code numdg[]={0xbf,0x86,0xdb,0xcf,0xe6,// 數碼管“個”位段選顯示因為保留一位小數,
- 0xed,0xfd,0x87,0xff,0xef};// 所以各位后要顯示小數點,所以需要重新編碼( 0— 9)
- uchar code numfh[]={0x40,0x00}; // 溫度 + — 符號位
- /******************1ms 延時函數 ****************/
- void delay0(uint z)
- {
- uchar x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- /******************15us 延時函數 ****************/
- void delay(uint z)
- {
- while(z--);
- }
- /****************** 初始化 DS18B20函數 ****************/
- void reset_ds18b20()
- {
- uchar stat=0;
- DQ=1;
- delay(8);
- DQ=0;
- delay(80); //600us/12mhz
- DQ=1;
- delay(8);
- stat=DQ; // 高電平為存在,低電平為不存在( stat 應該為 0)
- delay(4);
- // while(!DQ);/* 等待 DQ 變為高電平
- // 因為存在脈沖檢測結束后自動拉高 */
- //return stat;
- }
- /****************** 寫一個字節函數 ****************/
- void write_byte(uchar dat)
- {
- uchar i;
- DQ=1; // 先拉高電平,為寫作準備
- for(i=0;i<8;i++)
- {DQ=0;
- DQ=dat&0x01;
- delay(4);//DS18B20 采樣單片機寫給 DQ 線上的數據( 45us) ***************
- DQ=1;
- dat>>=1;
- }
- delay(4);
- }
- /****************** 讀一個字節函數 ****************/
- uchar read_byte()
- {
- uchar vaul,i;
- DQ=1; // 先拉高電平,為讀作準備
- for(i=0;i<8;i++)
- {
- DQ=0;
- vaul>>=1;
- DQ=1;
- if(DQ)
- vaul|=0x80;
- delay(4);
- }
- return vaul;
- }
- /****************** 讀取溫度值函數 ****************/
- int read_temper()
- {
- uchar templ,temph, flag;
- int temp;
- reset_ds18b20();// 復位操作
- write_byte(0xcc);// 跳過 ROM
- write_byte(0x44);// 溫度轉換
- delay(300);//***************************
- reset_ds18b20();// 復位操作
- write_byte(0xcc);// 跳過 ROM
- write_byte(0xbe);// 讀內部 RAM 內容
- templ=read_byte();
- temph=read_byte();
- flag=(temph&0x80)>>7;// 判斷高字節符號位是 1 還是 0(1 為負溫度, 0 為正溫度)
- if(flag==0)
- //temp=(temph<<=4)+((templ&=0xf0)>>4);
- temp=(templ+temph*256)*0.625;// 將精度 0.0625 擴大 10 倍,因為 temp 為整形,小數部分讀不到
- // 此項目需要保留一位小數,所以 x10,小數點后移一位
- // 所以可得要保留幾位小數點就擴大 10 的幾次方
- else
- temp=(~((templ+temph*256)-1))*(-0.625);
- return temp;}
- /****************** 顯示函數 ****************/
- void display(int num)
- {
- uchar i,zf,bai,shi,ge,fen;
- if(num<0)
- {
- zf=0;// 溫度 — 符號位
- num=num*(-1);
- }
- else
- zf=1;// 溫度 + 符號位
- bai=num/1000;
- shi=num%1000/100;
- ge=num%100/10;
- fen=num%10;
- for(i=0;i<6;i++)
- {
- duan=1;
- switch(i)
- {
- case 0: if(zf==0)
- P0=numfh[zf];
- else
- if(bai!=0)
- P0=numd[bai];
- else
- if(shi!=0)
- P0=numd[shi];
- else
- P0=numdg[ge];
- break;
- case 1: if(zf==0&&shi!=0)
- P0=numd[shi];
- else
- if(zf==0&&shi==0)
- P0=numdg[ge];
- else
- if(zf!=0&&bai!=0)
- P0=numd[shi];
- else
- if(zf!=0&&bai==0&&shi!=0)
- P0=numdg[ge];
- else
- if(zf!=0&&bai==0&&shi==0)
- P0=numd[fen];
- break;
- case 2: if(zf==0&&shi!=0)
- P0=numdg[ge];
- else
- if(zf==0&&shi==0)
- P0=numd[fen];
- else
- if(zf!=0&&bai!=0)
- P0=numdg[ge];
- else
- if(zf!=0&&bai==0&&shi!=0)
- P0=numd[fen];
- else
- if(zf!=0&&bai==0&&shi==0)
- P0=0x63;
- break;
- case 3: if(zf==0&&shi!=0)
- P0=numd[fen];
- else
- if(zf==0&&shi==0)
- P0=0x63;
- else
- if(zf!=0&&bai!=0)
- P0=numd[fen];
- else
- if(zf!=0&&bai==0&&shi!=0)
- P0=0x63;
- else
- if(zf!=0&&bai==0&&shi==0)
- P0=0x39;
- break;
- case 4: if(zf==0&&shi!=0)
- P0=0x63;
- else
- if(zf==0&&shi==0)
- P0=0x39;
- else
- if(zf!=0&&bai!=0)
- P0=0x63;
- else
- if(zf!=0&&bai==0&&shi!=0)
- P0=0x39;
- else
- P0=0x00;
- break;
- case 5: if(zf==0&&shi!=0)
- P0=0x39;else
- if(zf!=0&&bai!=0)
- P0=0x39;
- else
- P0=0x00;
- break;
- }
- duan=0;
- P0=0x00;// 消影
- wei=1;
- P0=numw[i];
- wei=0;
- P1=0x00;// 消影
- delay0(10);
- }
- }
- /****************** 主函數 ****************/
- void main()
- {
- while(1)
- {
- display(read_temper());
- }
- }
復制代碼 |