按鍵實(shí)現(xiàn)攝氏度華氏度轉(zhuǎn)換
#include "reg52.h"
#include "intrins.h"
#include "stdio.h"
//================關(guān)鍵字別名定義===========================
typedef unsigned char uint8;
typedef char int8;
typedef unsigned int uint16;
typedef int int16;
typedef unsigned long uint32;
typedef long int32;
//======================端口定義=========================
sbit key = P2^0;
sbit DS18B20_IO = P2^3; //DS18B20通信端口
#define IO_18B20_L() DS18B20_IO = 0
#define IO_18B20_H() DS18B20_IO = 1
#define IO_18B20_R() (DS18B20_IO)
#define LCD1602_DATA P0 //定義LCD1602的數(shù)據(jù)端口
sbit LCD1602_RS = P2^6;//定義LCD1602的RS腳
sbit LCD1602_RW = P2^5;//定義LCD1602的RW腳
sbit LCD1602_E = P2^4;//定義LCD1602的E腳
uint8 buffer[16];//顯示緩沖數(shù)組
int16 DS18B20_tpr;
bit HuaShiDuFlg=0;
//10微秒精確延時(shí)
void Delay10us(void)
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
//50微秒精確延時(shí)
void Delay50us(void)
{
Delay10us();
Delay10us();
Delay10us();
Delay10us();
Delay10us();
}
//N毫秒精確延時(shí)
void DelayNms(uint16 i)
{
uint8j;
for(;i;i--)
{
j=83; //延時(shí)精度調(diào)節(jié)
for(;j;j--) Delay10us();
}
}
/****************對(duì)LCD1602寫入1個(gè)字節(jié)數(shù)據(jù)*****************
*@style - 待寫入數(shù)據(jù)的類型:0表示指令,1表示數(shù)據(jù)
*@dat - 待寫入的指令或數(shù)據(jù)
**********************************************************/
void LCD1602_WriteOneByte(bit style,uint8dat)
{
LCD1602_E = 0;
_nop_();
_nop_();
LCD1602_RS = style; //寫入指令或數(shù)據(jù)標(biāo)志置位
LCD1602_RW = 0;
LCD1602_DATA = dat; //首先送入數(shù)據(jù)
_nop_();
_nop_();
LCD1602_E = 1; //使能置1
_nop_();
_nop_();
LCD1602_E = 0;
}
//LCD1602忙等待,當(dāng)讀取的數(shù)據(jù)最高位為0時(shí),才可以進(jìn)行讀寫操作
void LCD1602_WaitBusy(void)
{
LCD1602_E = 0;
LCD1602_DATA = 0xFF;
LCD1602_RS = 0;
LCD1602_RW = 1;
_nop_();
_nop_();
LCD1602_E = 1; //使能
_nop_();
_nop_();
_nop_();
_nop_();
while( LCD1602_DATA & 0x80 ); //檢測(cè)忙信號(hào),如果為最高位為1則等待
LCD1602_E = 0;
}
/***************LCD1602在指定位置顯示字符串****************
*@hang - 待顯示數(shù)據(jù)的行坐標(biāo):0~1 行
*@lie - 待顯示數(shù)據(jù)的列坐標(biāo):0~15列
*@pDat - 數(shù)據(jù)指針,指向待顯示數(shù)據(jù)
**********************************************************/
void LCD1602_DisStr(uint8 hang,uint8lie,uint8 *pDat)
{
if(hang==0) lie=0x80+lie;
else if(hang==1) lie=0xc0+lie;
LCD1602_WaitBusy();//寫入前需要讀忙信號(hào)
LCD1602_WriteOneByte(0,lie); //發(fā)送地址
while(*pDat)
{
LCD1602_WaitBusy();//寫入前需要讀忙信號(hào)
LCD1602_WriteOneByte(1,*pDat);//發(fā)送數(shù)據(jù)
pDat++; //數(shù)據(jù)指針遞增
}
}
void LCD1602_ClrScreen(void)
{
// LCD1602_WaitBusy();//寫入前需要讀忙信號(hào)
// LCD1602_WriteOneByte(0,0x01); //清屏
LCD1602_DisStr(0,0," ");
LCD1602_DisStr(1,0," ");
}
//LCD1602初始化,開機(jī)時(shí)需要初始化一次
void LCD1602_Init(void)
{
LCD1602_WriteOneByte(0,0x38); //顯示模式設(shè)置,16*2顯示,5*7點(diǎn)陣
DelayNms(5);
LCD1602_WriteOneByte(0,0x38); //顯示模式設(shè)置,16*2顯示,5*7點(diǎn)陣
DelayNms(5);
LCD1602_WriteOneByte(0,0x38); //顯示模式設(shè)置,16*2顯示,5*7點(diǎn)陣
DelayNms(5);
LCD1602_WriteOneByte(0,0x38); //顯示模式設(shè)置,16*2顯示,5*7點(diǎn)陣
DelayNms(5);
LCD1602_WriteOneByte(0,0x08); //關(guān)閉顯示,關(guān)閉光標(biāo)
DelayNms(5);
LCD1602_WriteOneByte(0,0x01); //清屏
DelayNms(5);
LCD1602_WriteOneByte(0,0x06); //設(shè)置顯示光標(biāo)地址遞增
DelayNms(5);
LCD1602_WriteOneByte(0,0x0C); //開顯示
}
//DS18B20初始化
void DS18B20_init(void)
{
uint8 i;
IO_18B20_H(); // DQ復(fù)位
_nop_();_nop_(); // 稍做延時(shí)
IO_18B20_L(); // 單片機(jī)將DQ拉低至少480us以初始化器件
for(i=0;i<10;i++) Delay50us();
IO_18B20_H(); // 釋放總線
// 主機(jī)釋放總線后15~60us(實(shí)測(cè)30us左右),器件將總線拉低60~240us(這叫存在脈沖,實(shí)測(cè)100us左右)后再釋放總線
// 這里延時(shí)300us,確保器件已經(jīng)釋放總線
for(i=0;i<6;i++) Delay50us();
}
//寫一個(gè)字節(jié)
void DS18B20_WriteOneByte(uint8 dat)
{
uint8i;
for(i=0;i<8; i++)
{
IO_18B20_L(); // 啟動(dòng)寫時(shí)序
if(dat&0x01) // 寫1時(shí)要在15us內(nèi)釋放總線;寫0至少要拉低60us總線,然后再釋放
{
_nop_();_nop_();
IO_18B20_H();
}
Delay50us();Delay10us();
IO_18B20_H();
_nop_(); // 寫周期間隔時(shí)間最小為1us
dat>>= 1;
}
}
//讀一個(gè)字節(jié)
uint8 DS18B20_ReadOneByte(void)
{
uint8i;
uint8dat=0;
for(i=0;i<8; i++)
{
IO_18B20_L();// 啟動(dòng)讀時(shí)序,低電平至少保持1us
dat>>=1;
_nop_();
IO_18B20_H();// 釋放總線,在15us內(nèi)讀數(shù)據(jù)
_nop_();_nop_();
if(IO_18B20_R()) dat |= 0x80;
Delay10us();Delay10us();Delay10us();Delay10us();
}
returndat;
}
//讀取溫度,結(jié)果支持負(fù)溫度值
void DS18B20_GetTpr(int16 *pTemper)
{
staticuint8 step=0;
static uint8 i=0;
uint8 LByte;
uint8HByte;
int16dat;
if(step==0)
{
DS18B20_init();
DS18B20_WriteOneByte(0xCC); // 跳過讀序列號(hào)的操作
DS18B20_WriteOneByte(0x44); // 啟動(dòng)溫度轉(zhuǎn)換
step=1;
i=0;
}
else if(step==1) // 延時(shí)500ms左右去取溫度值
{
i++;
if(i>=50)
{
i=0;
step=2;
}
}
else if(step==2)
{
DS18B20_init();
DS18B20_WriteOneByte(0xCC); // 跳過讀序列號(hào)的操作
DS18B20_WriteOneByte(0xBE); // 讀取溫度寄存器等(共可讀9個(gè)寄存器) 前兩個(gè)就是溫度
LByte = DS18B20_ReadOneByte(); // 先讀溫度的低字節(jié)
HByte = DS18B20_ReadOneByte(); // 再讀溫度的高字節(jié)
dat = ((uint16)HByte<<8) |LByte; // 合成數(shù)據(jù)
// 分辨率為0.0625,結(jié)果 = dat*0.0625 = dat*5/80,結(jié)果范圍為-55 ~ 125
*pTemper = dat*5/8; // 換算溫度,放大10倍
step=0;
}
}
void KeyScan(void)
{
static uint8 KeyCnt=0;
if(key==0)
{
if(KeyCnt<0xff) KeyCnt++;
if(KeyCnt==10)
{
HuaShiDuFlg=!HuaShiDuFlg;
}
}
else KeyCnt=0;
}
void LcdDisplay(void)
{
float buf;
if(HuaShiDuFlg==0) // 顯示攝氏度
{
sprintf(buffer,"T:%05.1f C",DS18B20_tpr/10.0);
LCD1602_DisStr(0,0,buffer);
}
else // 顯示華氏度, 華氏度 = 攝氏度*1.8+32
{
buf = DS18B20_tpr*0.18+32; // 因?yàn)闇囟仁浅肆?/font>10保留了1個(gè)小數(shù)位在里面,所以這里要先除10,算下來就是乘0.18
sprintf(buffer,"T:%05.1f F",buf);
LCD1602_DisStr(0,0,buffer);
}
}
void main(void)
{
LCD1602_Init();
while(1)
{
DS18B20_GetTpr(&DS18B20_tpr);
KeyScan();
LcdDisplay();
DelayNms(10);
}
}
|