標題:
AT89C51單片機DS18B20溫度檢測應用設計 Proteus仿真
[打印本頁]
作者:
yymy
時間:
2020-6-23 16:51
標題:
AT89C51單片機DS18B20溫度檢測應用設計 Proteus仿真
一、設計目的
1、學習并掌握One-Wire總線的工作原理
2、學習并掌握DS18B20溫度傳感器工作原理;
3、學習并掌握溫度采集程序設計方法;
4、學習并掌握串行通信程序設計;
二、實驗設備
1、計算機;
2、單片機開發(fā)板;
3、Keil C51編程軟件;
4、Proteus仿真軟件;
三、設計內容
1、完成功能
(1)檢測溫度并顯示一位小數(shù)(XX.X),
(2)將溫度值通過串口發(fā)送到上位機串口調試助手,
(3)上位機串口調試助手顯示(文本形式顯示):“T:XX.X”回車(XX.X是溫度值,逐行顯示)
2、硬件電路原理圖
3、設計程序(5號、宋體、單倍行距、分兩欄,要求程序設計規(guī)范化,添加必要的說明和注釋)
/****************************************************************
* 實 驗 名 :DS18B20溫度實驗
* 實驗說明 :數(shù)碼管顯示當前溫度
* 連接方式 :將DS18B20插到數(shù)字溫度檢測模塊的U5上(注意方向),DS_RD接P2.2
*****************************************************************/
//包含文件
#include<reg52.h>
#include<intrins.h>
//宏定義
#defineBAUD 9600 //波特率設置,bps
#defineFOSC 11059200L //晶振設置,默認使用11.0592MHz
//#defineFOSC 12000000L //晶振設置,使用12M Hz
//#defineFOSC 24000000L //晶振設置,使用24M Hz
//IO接口定義
#defineLED_PORT P0
sbitwela_1 = P2^4;
sbitwela_2 = P2^5;
sbitwela_3 = P2^6;
sbitwela_4 = P2^7;
sbitDQ = P2^2; //定義DS18B20端口DQ
//全局變量定義
unsignedchar temperature;
unsignedchar temperature_dec;
unsignedchar qian,bai,shi,ge;
//LED顯示字模 0-F 共陽模式
unsignedcode table[]={0Xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsignedchar RomCode[8]; //DS18B20中的RomCode
/*******************************************************************************
* 函 數(shù) 名 :Delayms
* 函數(shù)功能 :實現(xiàn) ms級的延時
* 輸 入:ms
* 輸 出:無
*******************************************************************************/
voidDelayms(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
#if FOSC == 11059200L
for(j=0;j<114;j++);
#elif FOSC == 12000000L
for(j=0;j<123;j++);
#elif FOSC == 24000000L
for(j=0;j<249;j++);
#else
for(j=0;j<114;j++);
#endif
}
/*******************************************************************************
* 函 數(shù) 名 :LEDdisplay
* 函數(shù)功能 :循環(huán)顯示各個位上的數(shù)據(jù)
* 輸 入:num要顯示的數(shù)據(jù)
* 輸 出:無
*******************************************************************************/
voidLEDdisplay()
{
wela_1 = 1; //關閉所有數(shù)碼管
wela_2 = 1;
wela_3 = 1;
wela_4 = 1;
wela_4=0; //顯示千位
LED_PORT=table[qian];
Delayms(1);
LED_PORT = 0xff;
wela_4=1;
wela_3=0; //顯示百位
LED_PORT=table[bai];
Delayms(1);
LED_PORT = 0xff;
wela_3=1;
wela_2=0; //顯示十位
LED_PORT=table[shi] & 0x7F;
Delayms(1);
LED_PORT = 0xff;
wela_2=1;
wela_1=0; //顯示個位
LED_PORT=table[ge];
Delayms(1);
LED_PORT = 0xff;
}
/*******************************************************************/
/*us級延時函數(shù) 執(zhí)行一次US--所需6.5us進入一次函數(shù)需要11.95us */
/*******************************************************************/
voidDelay(unsigned int num)
{
while( --num ) ;
}
/*******************************************************************/
/*初始化ds1820 */
/*******************************************************************/
bitInit_DS18B20(void)
{
bit presence;
DQ = 1; //DQ復位
Delay(8); //稍做延時
DQ = 0; //單片機將DQ拉低
Delay(90); //精確延時 大于 480us
DQ = 1; //拉高總線
Delay(4); //稍做延時
presence = DQ; //如果=0則初始化成功 =1則初始化失敗
Delay(20); //稍做延時
DQ = 1;
return(presence); //返信號,0=presence,1= no presence
}
/*******************************************************************/
/* 讀一個字節(jié) */
/*******************************************************************/
unsignedchar ReadOneChar(void)
{
unsigned char i = 0;
unsigned char dat = 0;
for (i = 8; i > 0; i--)//循環(huán)8次,通過dat變量的依次右移裝入8位數(shù)據(jù)
{
DQ = 0; //單片機將DQ拉低
dat >>= 1; //dat右移1位,準備讀取1位數(shù)據(jù)
DQ = 1; //單片機將DQ拉高
if(DQ) //判斷DQ狀態(tài),DQ=1則dat的最高位為1,DQ=0則dat的最高位為0
dat |= 0x80;//dat或10000000,控制dat的最高位:DQ=1則為1,DQ=0則為0
//proteus仿真設置為Delay(40)
Delay(40); //延時
//Delay(4);
}
return (dat); //返回值dat即為讀到的一字節(jié)數(shù)據(jù)
}
/*******************************************************************/
/* 寫一個字節(jié) */
/*******************************************************************/
void WriteOneChar(unsigned char dat)
{
unsigned char i = 0;
for (i = 8; i > 0; i--)//循環(huán)8次,通過dat變量的依次右移發(fā)出8位數(shù)據(jù)
{
DQ = 0; //單片機將DQ拉低
DQ = dat&0x01; //DQ=dat與00000001,則DQ=dat的最低位(0或1)
Delay(5); //延時
DQ = 1; //單片機將DQ拉高
dat>>=1; //dat右移1位,準備取下一位數(shù)據(jù)
}
}
/*******************************************************************/
/* 溫度報警值寫入DS18B20 */
/*******************************************************************/
voidWrite_Temperature_alarm(unsigned char Temp_h , unsigned char Temp_l)
{
Init_DS18B20(); //初始化
WriteOneChar(0xCC); //跳過讀序列號的操作
WriteOneChar(0x4e); //將設定的溫度報警值寫入DS18B20
WriteOneChar(Temp_h); //寫TH
WriteOneChar(Temp_l); //寫TL
WriteOneChar(0x7f); //12位精確度
Init_DS18B20(); //初始化
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0x48); //把暫存器里的溫度報警值拷貝到EEROM
}
/*******************************************************************/
/* 讀取64位序列碼 */
/*******************************************************************/
voidRead_RomCord(void)
{
unsigned char j;
Init_DS18B20(); //初始化
WriteOneChar(0x33); // 讀序列碼的操作命令
for (j = 0; j < 8; j++)
{
RomCode[j] = ReadOneChar() ;
}
}
/*******************************************************************/
/*DS18B20的CRC8校驗程序 */
/*******************************************************************/
unsignedchar CRC8()
{
unsigned char i,x;
unsigned char crcbuff,crc;
crc=0;
for(x = 0; x <8; x++)
{
crcbuff=RomCode[x];
for(i = 0; i < 8; i++)
{
if(((crc ^ crcbuff)&0x01)==0)
crc >>= 1;
else
{
crc ^= 0x18; //CRC=X8+X5+X4+1
crc >>= 1;
crc |= 0x80;
}
crcbuff >>= 1;
}
}
return crc;
}
/*******************************************************************/
/* 讀取溫度 */
/*******************************************************************/
unsignedchar* Read_Temperature(void)
{
//unsigned char i;
unsigned char temp_comp[2];
unsigned char temp_data[2];
unsigned char temp_alarm[2];
//unsigned int t;
Init_DS18B20(); //初始化
WriteOneChar(0xCC); //跳過讀序列號的操作
WriteOneChar(0x44); //啟動溫度轉換
Init_DS18B20(); //初始化
//實際器件:匹配ROM或跳過序列號均可
//WriteOneChar(0x55); //匹配ROM命令
//for(i=0;i<8;i++)
// WriteOneChar(RomCode);
//proteus仿真:跳過序列號
WriteOneChar(0xCC); //跳過讀序列號的操作
WriteOneChar(0xBE); //讀取溫度寄存器
temp_data[0] = ReadOneChar(); //溫度低8位
temp_data[1] = ReadOneChar(); //溫度高8位
temp_alarm[0] = ReadOneChar(); //溫度報警TH
temp_alarm[1] = ReadOneChar(); //溫度報警TL
temp_comp[0]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//取溫度整數(shù)值
temp_comp[1] = temp_data[0]&0x0f;//讀取小數(shù)
//課件程序:
//t=temp_data[1];
//t<<=8;
//t=t|temp_data[0];
//temp_comp=t*0.0625;
return &temp_comp;
}
/*******************************************************************************
* 函 數(shù) 名 :UsartConfiguration
* 函數(shù)功能 :串口設置
* 輸 入:無
* 輸 出:無
*******************************************************************************/
voidUsartConfiguration()
{
SCON = 0X50; //設置為工作方式1:10位異步收發(fā)器
TMOD |= 0x20; //設置計數(shù)器工作方式2:8位自動重裝計數(shù)器
PCON = 0X80; //波特率加倍:SMOD = 1
TH1 = 256 -(FOSC/12/32/(BAUD/2)); //計算定時器1初值
TL1 = 256 -(FOSC/12/32/(BAUD/2));
TR1 = 1;//啟動定時器T1
ES=1; //開串口中斷
EA = 1; //開總中斷
}
/*******************************************************************************
* 函 數(shù) 名 :UsartSendTemper
* 函數(shù)功能 :串口發(fā)送溫度
* 輸 入:無
* 輸 出:無
*******************************************************************************/
voidUsartSendTemper()
{
//發(fā)送 T
TI = 0; //清除發(fā)送中斷標志位TI
SBUF='T'; //收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動串口發(fā)送
while(!TI); //等待發(fā)送數(shù)據(jù)完成
//發(fā)送 :
TI = 0; //清除發(fā)送中斷標志位TI
SBUF=':'; //收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動串口發(fā)送
while(!TI); //等待發(fā)送數(shù)據(jù)完成
//發(fā)送溫度十位
TI = 0; //清除發(fā)送中斷標志位TI
SBUF=temperature/10+'0';//收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動串口發(fā)送
while(!TI); //等待發(fā)送數(shù)據(jù)完成
//發(fā)送溫度個位
TI = 0; //清除發(fā)送中斷標志位TI
SBUF=temperature%10+'0';//收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動串口發(fā)送
while(!TI); //等待發(fā)送數(shù)據(jù)完成
//發(fā)送小數(shù)點
TI = 0; //清除發(fā)送中斷標志位TI
SBUF='.';//收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動串口發(fā)送
while(!TI); //等待發(fā)送數(shù)據(jù)完成
//發(fā)送溫度小數(shù)位
TI = 0; //清除發(fā)送中斷標志位TI
SBUF=temperature_dec+'0';//收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動串口發(fā)送
while(!TI); //等待發(fā)送數(shù)據(jù)完成
//發(fā)送換行符
TI = 0; //清除發(fā)送中斷標志位TI
SBUF='\n'; //收到的數(shù)據(jù)放入到發(fā)送SBUF,啟動串口發(fā)送
while(!TI); //等待發(fā)送數(shù)據(jù)完成
TI=0;
}
/*******************************************************************/
/* 主函數(shù) */
/*******************************************************************/
voidmain(void)
{
unsigned char* temp;
int count = 0;
temperature = 0;
//proteus仿真:不讀取64位序列碼
//Read_RomCord(); //讀取64位序列碼
UsartConfiguration();//串口配置
while(1)
{
if(count >= 200)//采集周期1s
{
temp = Read_Temperature(); //讀取溫度
temperature = temp[0];
temperature_dec = temp[1]*0.625;
count= 0;
UsartSendTemper();//串口發(fā)送溫度
}
qian=temperature/100;
bai=temperature%100/10;
shi=temperature%10;
ge=temperature_dec;
LEDdisplay();//顯示溫度
count++;
}
}
四、本任務中的幾個功能如何實現(xiàn)?(說明設計思路)
設計思路:
1. 溫度讀取和數(shù)碼管顯示套用DS18B20溫度讀取例程改寫,
2. 串口發(fā)送程序采用查詢法。
功能實現(xiàn):
溫度讀。
核心為OneWire總線的使用,嚴格對應時序圖編程,實現(xiàn)初始化、讀、寫一個字節(jié),要注意延時函數(shù)的控制。
顯示小數(shù):
將原來的讀函數(shù)改為usigned char*類型,返回一個長度為2的數(shù)組,分別存儲溫度的整數(shù)值和小數(shù)值。
將原來的數(shù)碼管顯示函數(shù)前三個顯示整數(shù)、最后一個數(shù)碼管顯示小數(shù)。小數(shù)處理和整數(shù)取完對應位之后的下一步處理有區(qū)別(小數(shù)需要乘0.625)
發(fā)送溫度:
發(fā)送時候要一字節(jié)一字節(jié)地發(fā)送。溫度處理之后,還要加‘0’將數(shù)字轉化為對應ASCII值。
DS18B20溫度檢測應用設計.rar
2020-6-23 16:51 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
5.14 MB, 下載次數(shù): 93, 下載積分: 黑幣 -5
作者:
冬至已至
時間:
2020-11-16 20:44
我想請問一下,如果吧AC89C51換成STC89C51程序可以照樣使用嗎?
作者:
1742413784
時間:
2020-12-29 00:32
不對啊 負數(shù)
作者:
13503412974
時間:
2020-12-29 08:59
這個簡單也,實用。剛入門的可以學習一下
作者:
740284370
時間:
2020-12-31 10:29
你好,我想問一下我接收不到數(shù)據(jù),是怎么回事?
作者:
740284370
時間:
2020-12-31 10:29
不顯示小數(shù)
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1