亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码
標題:
51單片機學習:DS18B20測溫程序
[打印本頁]
作者:
51黑電子迷
時間:
2017-1-14 23:34
標題:
51單片機學習:DS18B20測溫程序
#include "my51.h"
#include "smg.h"
#include "ds18b20.h"
void main() //測試 ,6位數碼管顯示溫度值
{
u8 i=0;
u16 temp=0;
while(1)
{
temp=ds18b20_readTemperaData();
for(i=0;i<100;i++)
{
displaySMG(ds18b20_processTempData(temp));
}
}
}
復制代碼
#ifndef _DS18B20_H
#define _DS18B20_H
#include "my51.h"
#include "smg.h"
extern u8 smgWela[7]; //數碼管位選數據
sbit DQ=P2^2; //總線定義
bool ds18b20_init(); //初始化函數
u8* ds18b20_processTempData(u16 temp);//將temp數據處理成數碼管可顯示數據
u16 ds18b20_readTemperaData(); //讀溫度
u8 ds18b20_readByte() ; //讀一個字節(jié)
void ds18b20_writeByte(u8 dat); //mcu向18b20寫一個字節(jié)
#endif
復制代碼
#include "ds18b20.h"
/******************************************************************
當主機總線t0時刻從高拉至低電平時就產生寫時間隙
從to 時刻開始的1us之后,15us之前將所需寫的位送到總線上
DSl820 在t0后的15-60us 對總線采樣若低電平寫入的位是0 ,若高電平寫入的位是1
連續(xù)寫2 個位之間的間隙應大于1us
寫1,總時間大于60us,在t0開始延時1us就可以寫1,15us之后ic來采樣,采樣時間最大45us
寫0,總時間是60~120us,15~60us是ic在采樣,120以外就沒必要了,mcu總得釋放總線吧
不管寫1還是寫0,大于60us的話,ic肯定已經采樣完成了,那mcu就可以釋放了
*******************************************************************/
void ds18b20_writeByte(u8 dat) //mcu向ic寫一個字節(jié)
{
u8 i;
u8 tmep=dat;
for(i=0;i<8;i++)
{
DQ=0; //產生讀寫時序的起始信號
_nop_(); //要求至少1us的延時
DQ=dat & 0x01; //對總線賦值,從最低位開始寫起
delayXus(10);//延時74us,寫0在60~120us之間釋放,寫1的話大于60us均可釋放
DQ=1; //釋放總線,為下一次mcu送數據做準備,
dat>>=1; //有效數據移動到最低位,2次寫數據間隙至少需1us
}
}
/**************************************************************************
下降沿產生讀時序
整個讀時序必須至少有60us的持續(xù)時間,相鄰兩個讀時序必須要有至少1us的恢復時間
DS18B20在讀時序產生1us后輸出數據到總線上,也有可能需要2~3個微秒,但不會更多
而要求主機釋放總線和采樣總線等動作要在15μs內完成,那么讓mcu采樣的最佳時機
是讀時序產生后的5~13us之間,在15~60us這段時間是18b20的私有時間,它會在這段
時間內的任意時刻釋放總線,是不穩(wěn)定期,我們不要讓mcu在這段時間里對總線操作
*******************************************************/
u8 ds18b20_readByte() //mcu讀一個字節(jié)
{
u8 i,value=0;
for(i=0;i<8;i++)
{
DQ=0; //起始信號
value>>=1; //順便延時3~4個機器周期
DQ=1; //mcu釋放總線
_nop_();_nop_();_nop_(); //再延時3.3us
if(DQ)
{
value|=0x80;//保存高電平數據,低電平的話不用保存,移位后默認是0
}
delayXus(8); //延時60.76us
}
return value;
}
u16 ds18b20_readTemperaData() //讀取溫度值
{
u16 temp=0;
if(ds18b20_init())
{
ds18b20_writeByte(0xcc); //寫指令:跳過rom檢測
ds18b20_writeByte(0x44); //寫指令:溫度轉換
//delayms(750);// 轉換延時需要750ms以上,我們不等它
//首次轉換未完成時,得到的初始化數據是85度,處理一下就可以了
//溫度轉換電路是硬件獨立的,不會阻塞初始化功能
if(ds18b20_init())
{
ds18b20_writeByte(0xcc); //寫指令:跳過檢測rom
ds18b20_writeByte(0xbe); //寫指令:讀取溫度值
temp=ds18b20_readByte(); //先讀低8位數據
temp|=(u16)ds18b20_readByte()<<8; //再讀高8位數據,然后合并
temp&= 0x0FFF; //高4位數據反正沒用上,我們用來存放錯誤碼
}
else
{
led5=0; //調試代碼
temp=0x2000; //錯誤碼,初始化失敗
}
}
else
{
led6=0; //調試代碼
temp=0x1000; //錯誤碼,初始化失敗,可能器件損壞
}
return temp;
}
bool ds18b20_init() //初始化
{
u8 checkState=0;
DQ=1; //總線初始狀態(tài)
_nop_();_nop_();
DQ=0; //mcu先將總線拉低
delayXus(80); //延時530us,要求480us~960us的低電平信號
//當ic接受到此復位信號后會回發(fā)一個存在信號
//mcu若要接收此存在信號則先要釋放總線,讓ic控制該總線
//當mcu釋放總線后的15~60us之后,ic才向總線發(fā)一個低電平信號
//該信號存在時間為60~240us
DQ=1; //mcu釋放總線
delayXus(10); //mcu釋放15~60us以上,(8+6*10)*1.085=73us,
//這時DS18B20已經拉低信號,大約60~240us應答保持時間,
checkState=DQ; //在這段60~240us時間內,mcu采樣是否有器件響應,0表示有響應
delayXus(70); //延時464us,加上之前的73us,共537us
//雖然ic在拉低電平60~240us之后,會釋放總線,但整個時間至少480us
//故我們共用時537us,這樣是為了不影響后續(xù)的操作
if(checkState) //checkstate為0說明有器件響應,為1無器件響應
{
return FALSE;
}
return TRUE; //初始化成功
}
u8* ds18b20_processTempData(u16 temp) //返回數碼管可直接顯示的數據指針
{
u8 i=0;
if(0x0550==temp) //如果初始化溫度數據是85度的話
{
led7=0; //亮燈報警,調試
smgWela[5]=18; //當溫度是85度,第6個數碼管顯示負號
return smgWela; //一般剛上電時能看到這個負號
}
if(1==(temp&0x0800)) //檢測第11位是否為1,為1是負溫度
{
temp&=0x07ff; //只取第0~10共11個位
temp=(~temp+1) & 0x07ff;//將補碼還原
smgWela[0]=18; //第一個數碼管顯示18號元素,即負號
}
else
{
smgWela[0]=dark; //正溫度的話這個數碼管就不要顯示了
}
temp=(u16)(temp*6.25); //精度的1000倍,我們將小數點另外疊加顯示
if(temp>=10000)
{
smgWela[1]=1; //第二個數碼管顯示1,是百位上,100度以上啊
}
else
{
smgWela[1]=dark; //百位上是0的話不要顯示這個0
}
smgWela[2]=temp%10000/1000; //第三個數碼管 十位
smgWela[3]=temp%1000/100; //第四個數碼管 個位疊加小數點
smgWela[4]=temp%100/10; //第五個數碼管
smgWela[5]=temp%10; //第六個數碼管
smgWela[6]=0xf7; //第4個數碼管疊加小數點
return smgWela; //返回數組
}
復制代碼
#ifndef _51SMG_H_
#define _51SMG_H_
#include <reg52.h>
#include "mytype.h"
sbit dula =P2^6; //段選鎖存器控制 控制筆段
sbit wela =P2^7; //位選鎖存器控制 控制位置
#define dark 0x11//在段中,0x11是第17號元素,0x00是低電平,數碼管不亮,即table[17]
#define dotDark 0xff//小數點全暗
void displaySMG(u8* pWela); //數碼管顯示函數,參數是數組指針
#endif
復制代碼
#include "smg.h"
#include "my51.h"
static u8 code table[]= { //0~F外加小數點和空輸出的數碼管編碼
0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3
0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7
0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B
0x39 , 0x5e , 0x79 , 0x71 , // C D E F
0x80 , 0x00 ,0x40 // . 空 負號 空為第17號元素
};
/* 由于此表只能一次顯示一個小數點,故已注釋掉,僅供查詢
例如想要第一個和第六個數碼管小數點同時點亮,
則執(zhí)行 pWela->dot = 0xfe & 0xdf 即可
u8 code dotTable[]={ //小數點位置,某一位置0時,小數點亮
0xff , //全暗
0xfe , 0xfd , 0xfb , //1 2 3
0xf7 , 0xef , 0xdf //4 5 6
};*/
u8 data smgWela[7]={0,0,0,0,0,0,0}; //第一位到第六位,最后一個是小數點位置控制
//P0口的數碼管位選控制鎖存器只用了低6位,我們保留高2位的數據,留作它用
void displaySMG(u8* pWela)
{
u8 i=0;
//控制6位數碼管顯示函數,不顯示的位用參數dark
u8 preState=P0|0x3f; //保存高2位狀態(tài),其中最高位是ADC0804的片選信號
wela=0;dula=0;_nop_();//先鎖定數據,防止吳亮及位選鎖存器高2位數據被改變
P0=0; //由于數碼管是共陰極的,陽極送低電平,燈不亮
dula=1;_nop_();
dula=0; //段選數據清空并鎖定
P0=preState; //共陰極數碼管是陰極置高不亮,低6位置1,高2位保留
wela=1;_nop_(); //注:wela和dula上電默認為1
wela=0; //位選鎖定,初始保留高2位的數據,低6位置高不亮
for(i=0;i<6;i++) //顯示6位數碼管
{
P0=table[pWela[i]]|(((1<<i) & pWela[6])?0x00:0x80);
dula=1;_nop_(); //送段數據,疊加小數點的顯示,0x00點亮小數點
dula=0;
P0=preState&~(1<<i); //不影響高2位數據,低6位是數碼管位選,低電平有效
wela=1; _nop_(); //送位選號
wela=0;
delayms(1); //稍作延時,讓燈管亮起來
{ //消除疊影及誤亮,陰極置1不亮,低6位置1,高2位保留并鎖定
P0=preState;
wela=1; _nop_();
wela=0;
}
}
}
復制代碼
#ifndef _MY51_H
#define _MY51_H
#include <reg52.h>
//#include <math.h>
#include <intrins.h>
#include "mytype.h"
#define high 1 //高電平
#define low 0 //低電平
#define led P1 //燈總線控制
sbit led0=P1^0; //8個led燈,陰極送低電平點亮
sbit led1=P1^1;
sbit led2=P1^2;
sbit led3=P1^3;
sbit led4=P1^4;
sbit led5=P1^5;
sbit led6=P1^6;
sbit led7=P1^7;
sbit ledLock=P2^5; //led鎖存的狀態(tài),0鎖定 ,1不鎖定
sbit beep=P2^3; //蜂鳴器
void delayms(u16 ms);
void delayXus(u8 us); //函數執(zhí)行(8+6x)個機器周期, 即t=(8+6x)*1.085
/////////////////////////////////////////////////////////////////////////////
#endif
復制代碼
#include "MY51.h"
void delayms(u16 ms) //毫秒級軟延時函數
{
u16 i,j;
for(i=ms;i>0;i--)
{
for(j=113;j>0;j--)
{}
}
}
/****************************************************************
若使用12分頻模式的mcu,晶振頻率為11059200Hz
則每個機器周期用時12/11059200=1.085微秒
keil4編譯,在默認的8級優(yōu)化方式下
參數us=0時,函數執(zhí)行9個機器周期,即t=9*1.085=9.77 us
參數us!=0時,函數執(zhí)行(8+6x)個機器周期, 即t=(8+6x)*1.085 us
*****************************************************************/
void delayXus(u8 us) //微秒級軟延時函數
{
while(us) //這種寫法有利于減小us=0時的機器周期
{
us--;
}
}
復制代碼
作者:
毛士新
時間:
2022-2-7 14:13
:loveliness::hug::'(
歡迎光臨 (http://www.denmoz.com/bbs/)
Powered by Discuz! X3.1