1. 基於AT89C51單片機和DS18B20溫度感測器、LCD1602液晶顯示的高精度數字溫度計程序,用C語言編程
/***********ds18b20子程序*************************/
/***********ds18b20延遲子函數(晶振12MHz )*******/
#include<reg51.h>
sbit DQ=P1^2;
#define uchar unsigned char
void delay_18B20(unsigned int i)
{
while(i--);
}
/**********ds18b20初始化函數**********************/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ復位
delay_18B20(8); //稍做延時
DQ = 0; //單片機將DQ拉低
delay_18B20(80); //精確延時 大於 480us
DQ = 1; //拉高匯流排
delay_18B20(4);
x=DQ; //稍做延時後 如果x=0則初始化成功 x=1則初始化失敗
delay_18B20(20);
}
/***********ds18b20讀一個位元組**************/
unsigned char ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 給脈沖信號
dat>>=1;
DQ = 1; // 給脈沖信號
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/*************ds18b20寫一個位元組****************/
void WriteOneChar(uchar dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay_18B20(5);
DQ = 1;
dat>>=1;
}
}
/**************讀取ds18b20當前溫度************/
ReadTemp(void)
{ float val;
uchar temp_value,value;
unsigned char a=0;
unsigned char b=0;
unsigned char t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳過讀序號列號的操作
WriteOneChar(0x44); // 啟動溫度轉換
delay_18B20(100); // this message is wery important
Init_DS18B20();
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0xBE); //讀取溫度寄存器等(共可讀9個寄存器) 前兩個就是溫度
delay_18B20(100);
a=ReadOneChar(); //讀取溫度值低位
b=ReadOneChar(); //讀取溫度值高位
temp_value=b<<4;
temp_value+=(a&0xf0)>>4;
value=a&0x0f;
val=temp_value+value;
return(val);
}
以上是DS18B20的驅動程序。然後在主程序中直接調用函數就可以了。
以上是在主程序中的調用,你看關於溫度的那個就可以。
#include "reg51.h"
#include "18b20.h"
#define uchar unsigned char
#define uint unsigned int
uchar code table[]="Welcome To" ;//初始化日期和星期
uchar code table1[]="Our System!";//初始化時間
uchar code table2[]="Temperature is:";//初始化時間
//以下三個是定義LCD的引腳
sbit lcden=P2^2;
sbit lcdwrite=P2^1;
sbit lcdrs=P2^0;
char wen;
//延時程序
void delay(uint z)
{ uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//lcd的寫指令
void write_com(uchar com)
{
lcdrs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
//lcd的寫數據
void write_data(uchar da)
{ lcdrs=1;
lcden=0;
P0=da;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
//初始化
void init()
{
uchar num;
lcdwrite=0;
lcden=0;
write_com(0x38); //16*2顯示,5*7點陣,8位數據
write_com(0x0c);//顯示開,關游標
write_com(0x06); //移動游標
write_com(0x01);//清除LCD的顯示內容
write_com(0x80);
for (num=0;num<10;num++)
{
write_data(table[num]);
delay(5);
}
write_com(0x80+0x40);
for (num=0;num<11;num++)
{
write_data(table1[num]);
delay(5);
}
}
void write_wen(uchar add, char da)
{
uchar shi,ge;
shi=da/10;
ge=da%10;
write_com(0x80+0x40+add);
write_data(0x30+shi);
write_data(0x30+ge);
}
//主函數
void main ()
{
uchar num;
init();
delay(2000);
delay(2000);
delay(2000);
write_com(0x01);//清除LCD的顯示內容
while(1)
{
write_com(0x80);
for (num=0;num<15;num++)
{
write_data(table2[num]);
delay(5);
}
wen = ReadTemp( );
write_wen(2,wen);
}
}
2. 用單片機做溫度檢測系統 論文,
用DS18B20做的電子溫度計,非常簡單。
#include <reg51.h>
#include\"AscLed.h\"
#include <intrins.h>
#include <stdio.h>
//********************************************************
#define Seck (500/TK) //1秒中的主程序的系數
#define OffLed (Seck*5*60) //自動關機的時間5分鍾!
//********************************************************
#if (FHz==0)
#define NOP_2uS_nop_()
#else
#define NOP_2uS_nop_();_nop_()
#endif
//**************************************
#define SkipK 0xcc //跳過命令
#define ConvertK 0x44 //轉化命令
#define RdDs18b20K 0xbe //讀溫度命令
//*******************************************
extern LedOut(void);
//*************************************************
sbit PNP1=P3^4;
sbit PNP2=P3^5;
sbit BEEP=P3^2;
//***********************************
#defineDQ PNP2 //原來的PNP2 BEEP
//***********************************
static unsigned char Power=0;
//************************************
union{
unsigned char Temp[2]; //單位元組溫度
unsigned int Tt; //2位元組溫度
}T;
//***********************************************
typedef struct{
unsigned char Flag; //正數標志 0;1==》負數
unsigned char WenDu; //溫度整數
unsigned int WenDuDot; //溫度小數放大了10000
}WENDU;
//***********************************************
WENDU WenDu;
unsigned char LedBuf[3];
//----------------------------------
//功能:10us 級別延時
// n=1===> 6Mhz=14uS 12MHz=7uS
//----------------------------------
void Delay10us(unsigned char n){
do{
#if (FHz==1)
NOP_2uS;NOP_2uS;
#endif
}while(--n);
}
//-----------------------------------
//功能:寫18B20
//-----------------------------------
void Write_18B20(unsigned char n){
unsigned char i;
for(i=0;i<8;i++){
DQ=0;
Delay10us(1);//延時13us 左右
DQ=n & 0x01;
n=n>>1;
Delay10us(5);//延時50us 以上
DQ=1;
}
}
//------------------------------------
//功能:讀取18B20
//------------------------------------
unsigned char Read_18B20(void){
unsigned char i;
unsigned char temp;
for(i=0;i<8;i++){
temp=temp>>1;
DQ=0;
NOP_2uS;//延時1us
DQ=1;
NOP_2uS;NOP_2uS;//延時5us
if(DQ==0){
temp=temp&0x7F;
}else{
temp=temp|0x80;
}
Delay10us(5);//延時40us
DQ=1;
}
return temp;
}
//-----------------------------------
void Init (void){
DQ=0;
Delay10us(45);//延時500us
DQ=1;
Delay10us(9);//延時90us
if(DQ){ //0001 1111b=1f
Power =0; //失敗0
}else{
Power++;
DQ=1;
}
}
//----------------------------------
void Skip(void){
Write_18B20(SkipK);
Power++;
}
//----------------------------------
void Convert (void){
Write_18B20(ConvertK);
Power++;
}
//______________________________________
void Get_Ds18b20L (void){
T.Temp[1]=Read_18B20(); //讀低位
Power++;
}
//______________________________________
void Get_Ds18b20H (void){
T.Temp[0]=Read_18B20(); //讀高位
Power++;
}
//------------------------------------
//規范化成浮點數
// sssss111;11110000
// sssss111;1111(0.5,0.25,0.125,0.0625)
//------------------------------------
void ReadTemp (void){
unsigned char i;
unsigned intF1=0;
char j=1;
code int Code_F[]={6250,1250,2500,5000};
WenDu.Flag=0;
if (T.Temp[0] >0x80){ //負溫度
T.Tt =~T.Tt+1; //取反+1=源嗎 +符號S
WenDu.Flag=-1;
}
T.Tt <<= 4; //左移4位
WenDu.WenDu=T.Temp[0]; // 溫度整數
//**************************************************
T.Temp[1]>>=4;
//---------------------------
for (i=0;i<4;i++){ //計算小數位
F1 +=(T.Temp[1] & 0x01)*Code_F;
T.Temp[1]>>=1;
}
WenDu.WenDuDot=F1; //溫度的小數
Power=0;
}
//----------------------------------
void Delay1S (void){
static unsigned int i=0;
if (++i==Seck) {i=0ower++;}
}
//----------------------------------
void ReadDo (void){
Write_18B20(RdDs18b20K);
Power++;
}
/**********************************
函數指針定義
***********************************/
code void (code *SubTemp[])()={
Init,Skip,Convert,Delay1S,Init,Skip,ReadDo,Get_Ds18b20L,
Get_Ds18b20H,ReadTemp
};
//**************************************
void GetTemp(void){
(*SubTemp[Power])();
}
//---------------------------------------------------
//將溫度顯示,小數點放大了10000.
void GetBcd(void){
LedBuf[0]=WenDu.WenDu / 10;
LedBuf[1]=WenDu.WenDu % 10 +DotK;
LedBuf[2]=(WenDu.WenDuDot/1000)%10;
if(LedBuf[0]==0)LedBuf[0]=Black;
if(WenDu.Flag==0) return;
if(LedBuf[0] !=Black){
LedBuf[2]=LedBuf[1];
LedBuf[1]=LedBuf[0];
LedBuf[0]=Led_Pol; //'-'
}else{
LedBuf[0]=Led_Pol; //'-'
}
}
/*
//---------------------------------------------------
void JbDelay (void){
static long i;
if (++i>=OffLed){
P1=0xff;
P2=0xff;
PCON=0x02;
}
}
*/
/*****************************************************
主程序開始
1:2002_10_1 設計,採用DS18B20測量
2:採用函數數組讀取DS18B20.LED數碼管顯示正常!
3:改變FHz可以用6,12MHz工作!
******************************************************/
code unsigned char Stop[3] _at_ 0x3b;
void main (void){
P1=0xff;
WenDu.WenDu=0;
while (1){
GetTemp();
GetBcd();
// JbDelay();
LedOut();
}
}
復制代碼
20091012_[1].jpg (12 KB)
2009-10-21 23:21 上傳
下載次數:0
3. 求一個51單片機控制的溫度計顯示程序
這個程序完全沒問題的,我做過實驗。希望對你有幫助,,,,
//DS18B20的讀寫程序,數據腳P3.3 //
//溫度感測器18B20匯編程序,採用器件默認的12位轉化 //
//最大轉化時間750微秒,顯示溫度-55到+125度,顯示精度 //
//為0.1度,顯示採用4位LED共陽顯示測溫值 //
//P0口為段碼輸入,P24~P27為位選 //
/***************************************************/
#include "reg51.h"
#include "intrins.h" //_nop_();延時函數用
#define Disdata P0 //段碼輸出口
#define discan P2 //掃描口
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^3; //溫度輸入口
sbit DIN=P0^7; //LED小數點控制
uint h;
uchar flag;
//**************溫度小數部分用查表法***********//
uchar code ditab[16]=
{0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
//
uchar code dis_7[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};
//共陽LED段碼表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" "-"
uchar code scan_con[4]={0x7f,0xbf,0xdf,0xef}; //列掃描控制字
uchar data temp_data[2]={0x00,0x00}; //讀出溫度暫放
uchar data display[5]={0x00,0x00,0x00,0x00,0x00}; //顯示單元數據,共4個數據和一個運算暫用
//
//
//
/***********11微秒延時函數**********/
//
void delay(uint t)
{
for(;t>0;t--);
}
//
/***********顯示掃描函數**********/
scan()
{
char k;
for(k=0;k<4;k++) //四位LED掃描控制
{
Disdata=0xff;
Disdata=dis_7[display[k]];
if(k==1){DIN=0;}
discan=scan_con[k];delay(90);
discan=0xff;
}
}
//
//
/***********18B20復位函數**********/
ow_reset(void)
{
char presence=1;
while(presence)
{
while(presence)
{
DQ=1;_nop_();_nop_();
DQ=0; //
delay(50); // 550us
DQ=1; //
delay(6); // 66us
presence=DQ; // presence=0繼續下一步
}
delay(45); //延時500us
presence = ~DQ;
}
DQ=1;
}
//
//
/**********18B20寫命令函數*********/
//向 1-WIRE 匯流排上寫一個位元組
void write_byte(uchar val)
{
uchar i;
for (i=8; i>0; i--) //
{
DQ=1;_nop_();_nop_();
DQ = 0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us
DQ = val&0x01; //最低位移出
delay(6); //66us
val=val/2; //右移一位
}
DQ = 1;
delay(1);
}
//
/*********18B20讀1個位元組函數********/
//從匯流排上讀取一個位元組
uchar read_byte(void)
{
uchar i;
uchar value = 0;
for (i=8;i>0;i--)
{
DQ=1;_nop_();_nop_();
value>>=1;
DQ = 0; //
_nop_();_nop_();_nop_();_nop_(); //4us
DQ = 1;_nop_();_nop_();_nop_();_nop_(); //4us
if(DQ)value|=0x80;
delay(6); //66us
}
DQ=1;
return(value);
}
//
/***********讀出溫度函數**********/
//
read_temp()
{
ow_reset(); //匯流排復位
write_byte(0xCC); // 發Skip ROM命令
write_byte(0xBE); // 發讀命令
temp_data[0]=read_byte(); //溫度低8位
temp_data[1]=read_byte(); //溫度高8位
ow_reset();
write_byte(0xCC); // Skip ROM
write_byte(0x44); // 發轉換命令
}
//
/***********溫度數據處理函數**********/
void work_temp()
{
uchar n=0;
uchar doth,dotl;
uchar flag3=1,flag2=1; //數字顯示修正標記
if((temp_data[1]&0xf8)!=0x00)
{
temp_data[1]=~(temp_data[1]);
temp_data[0]=~(temp_data[0])+1;
n=1;
flag=1;
}//負溫度求補碼
if(temp_data[0]>255)
{
temp_data[1]++;
}
display[4]=temp_data[0]&0x0f;
display[0]=ditab[display[4]];
doth=display[0]/10;
dotl=display[0]%10;
display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x07)<<4);
display[3]=display[4]/100;
display[2]=display[4]/10%10;
display[1]=display[4]%10;
if(!display[3])
{
display[3]=0x0a;
flag3=0;
if(!display[2])
{
display[2]=0x0a;
flag2=0;
}
}//最高位為0時都不顯示
if(n)
{
display[3]=0x0b;//負溫度時最高位顯示"-"
flag3=0;
}
}
//
//
/**************主函數****************/
main()
{
Disdata=0xff; //初始化埠
discan=0xff;
for(h=0;h<4;h++){display[h]=8;}//開機顯示8888
ow_reset(); // 開機先轉換一次
write_byte(0xCC); // Skip ROM
write_byte(0x44); // 發轉換命令
for(h=0;h<500;h++)
{scan();} //開機顯示"8888"2秒
while(1)
{
read_temp(); //讀出18B20溫度數據
work_temp(); //處理溫度數據
scan(); //顯示溫度值2秒
}
}
//
//*********************結束**************************//