?? ds18b20a.c
字號:
//*************DS18B20數字溫度計*******************//
//*MCU: AT892051 //
//*MCU-crystal: 12M //
//*Version: 01 //
//*Last Updata: 2007-6-9 //
//*Author: zhaojun //
//*Description: //
//DS18B20的讀寫程序,數據腳P3.4 //
//溫度傳感器18B20匯編程序,采用器件默認的12位轉化 //
//最大轉化時間750微秒,顯示溫度-55到+125度,顯示精度 //
//為0.1度,顯示采用4位LED共陽顯示測溫值 //
//P1口為段碼輸入,P0~P3為位選 //
//***************WAVE-E6000/T**********************//
#include "reg52.h"
#define uchar unsigned char
#define uint unsigned int
#define Disdata P1 // 段碼入口
sbit DQ=P3^4; // 溫度輸入口
uint temp; // variable of temperature 定義一個變量
uchar flag1; // 定義一個標志,標志溫度是負還是正,1為負,0為正
sbit DIN=P1^7; // 小數點控制
uchar h; // 定義變量
//位選位定義
sbit DEC=P3^0; // 小數
sbit POS=P3^1; // 個位
sbit TEN=P3^2; // 十位
sbit HUN=P3^3; // 百位,符號位
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};
//共陽數碼管段碼表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "滅" "-"
unsigned char code table1[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//帶小數點的編碼
//共陽數碼管帶小數點段碼表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
uchar data temp_data[2]={0x00,0x00};//讀出溫度暫放
uchar data Dis_play[5]={0x00,0x00,0x00,0x00,0x00};//顯示單元數據,共4個數據和一個運算暫用
uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
//小數部分對應十進制 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F"
/***************************************/
/* 延時子程序 */
/***************************************/
void delay(uint i) //delay
{
while(i--);
}
/************************************************/
/* 初始化ds18b2子函數* */
/************************************************/
Init_DS18B20(void)
{
uchar x=0;
DQ = 1; //DQ復位
delay(8); //稍做延時
DQ = 0; //單片機將DQ拉低
delay(80); //精確延時 大于 480us
DQ = 1; //拉高總線
delay(14);
x=DQ; //稍做延時后 如果x=0則初始化成功 x=1則初始化失敗
delay(20);
}
/*************************************************/
/* 讀字節子函數 */
/*************************************************/
ReadOneChar(void)
{
uchar i = 0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 給脈沖信號
dat>>=1; // 數據右移一位
DQ = 1; // 給脈沖信號
if(DQ) // DQ為1
dat|=0x80; // 讀出數據
delay(4); // 延時
}
return(dat);
}
/*************************************************/
/* 寫字節子函數 */
/*************************************************/
WriteOneChar(unsigned char dat)
{
uchar i = 0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01; //寫入一位數據
delay(5);
DQ = 1;
dat>>=1; //右移一位數據
}
}
/*************************************************/
/* DS18B20寫命令函數 */
/*************************************************/
/*void tmpwritebyte(uchar dat) // write a byte to ds18b20
{ // 給溫度傳感器寫一個字節
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //寫入 1
{
DQ=0;
i++;i++;
DQ=1;
i=8;while(i>0)i--; // 適當延時
}
else //寫入 0
{
DQ=0;
i=8;while(i>0)i--; // 適當延時
DQ=1;
i++;i++;
}
}
}*/
/******************************************/
/* 發送溫度轉換命令 */
/******************************************/
void tmpchange(void) // DS18B20 begin change
{
Init_DS18B20(); // 初始化DS18B20
delay(200); // 延時
WriteOneChar(0xcc); // 跳過序列號命令
WriteOneChar(0x44); // 發送溫度轉換命令
}
/******************************************/
/* 讀出溫度函數 */
/******************************************/
uint tmp() //get the temperature
{
// float tt;
Init_DS18B20(); // 初始化ds18b2子函數
delay(1);
WriteOneChar(0xcc); // 跳過ROM命令
WriteOneChar(0xbe); // 發送讀取數據命令
temp_data[0]=ReadOneChar(); // 連續讀兩個字節數據
temp_data[1]=ReadOneChar();
temp=temp_data[1];
temp<<=8;
temp=temp|temp_data[0]; // 兩字節合成一個整型變量。
// tt=temp*0.0625; // 得到真實十進制溫度值,因為DS18B20
// 可以精確到0.0625度,所以讀回數據的最低位代表的是
// 0.0625度。
// temp=tt*10+0.5; // 放大十倍,這樣做的目的將小數點后第一位
// 也轉換為可顯示數字,同時進行一個四舍五入操作。
return temp; // 返回溫度值
}
/******************************************/
/* 讀出序列號函數 */
/******************************************/
/*void readrom() // read the serial 讀取溫度傳感器的序列號
{ // 本程序中沒有用到此函數
uchar sn1,sn2;
Init_DS18B20(); // DS18B20初始化
delay(1);
WriteOneChar(0x33); // Read ROM
sn1=ReadOneChar(); // 8位系列編碼
sn2=ReadOneChar(); // 8位CRC碼
}*/
/******************************************/
/* 顯示延時函數 */
/******************************************/
//延時時,主要時間的控制,否則會不斷閃爍
void delay_ms()
{
uchar a,b;
for(a=50;a>0;a--)
for(b=40;b>0;b--);
}
/******************************************/
/* 溫度數據顯示處理函數 */
/******************************************/
void tem_deal(uint tem)
{
/*************溫度數據處理*****************/
if(tem>6348) // 溫度值正負判斷
{tem=65536-tem;flag1=1;} // 負溫度求補碼,標志位置1
Dis_play[4]=tem&0x0f; // 取小數部分的值
Dis_play[0]=ditab[Dis_play[4]]; // 存入小數部分顯示值
Dis_play[4]=tem>>4; // 取中間八位,即整數部分的值
Dis_play[3]=Dis_play[4]/100; // 取百位數據暫存
Dis_play[1]=Dis_play[4]%100; // 取后兩位數據暫存
Dis_play[2]=Dis_play[1]/10; // 取十位數據暫存
Dis_play[1]=Dis_play[1]%10; // 取個位數據暫存
if(!Dis_play[3]) // 最高位為0都不顯示
{
Dis_play[3]=0x0a; // 先判斷百位是否為0
if(!Dis_play[2])
{
Dis_play[2]=0x0a; // 再判斷十位是否為0
}
}
if(flag1)
{
Dis_play[3]=0x0b; // 為負數時,最高位顯示 "-"
}
}
/******************溫度數據顯示********************/
void display()
{
Disdata=table[Dis_play[3]]; // 輸入百位顯示數據
HUN=0;TEN=1;POS=1;DEC=1; // 開百位,關其他位
delay_ms(); // 適當延時
Disdata=table[Dis_play[2]]; // 輸入十位顯示數據
TEN=0;HUN=1;POS=1;DEC=1; // 開十位,關其他位
delay_ms(); // 適當延時
Disdata=table1[Dis_play[1]]; // 輸入個位顯示數據
POS=0;HUN=1;TEN=1;DEC=1; // 開個位,關其他位
delay_ms(); // 適當延時
Disdata=table[Dis_play[0]]; // 輸入小數顯示數據
DEC=0;HUN=1;TEN=1;POS=1; // 開小數位,關其他位
// delay_ms(); // 適當延時
}
/******************************************/
/* 主函數 */
/******************************************/
void main()
{
Disdata=0xff; //端口初始化
P3=0xff;
//開機顯示"888.8";這段程序可以不要.
for(h=0; h<4; h++)
{
Dis_play[h]=8;
}
for(h=0; h<50; h++)
{
display(); //顯示數據
delay_ms(); //延時
}
//溫度顯示
do
{
tmpchange(); //溫度轉換
tem_deal(tmp()); //顯示溫度值
display();
}
while(1);
}
//*****************結束**********************//
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -