#include <msp430x14x.h>
typedef unsigned char uchar;
typedef unsigned int uint;
/**************宏定義***************/
#define DataDir P4DIR
#define DataPort P4OUT
#define Busy 0x80
#define CtrlDir P3DIR
#define CLR_RS P3OUT&=~BIT0; //RS = P3.0
#define SET_RS P3OUT|=BIT0;
#define CLR_RW P3OUT&=~BIT1; //RW = P3.1
#define SET_RW P3OUT|=BIT1;
#define CLR_EN P3OUT&=~BIT2; //EN = P3.2
#define SET_EN P3OUT|=BIT2;
#define DQ1 P1OUT |= BIT6
#define DQ0 P1OUT &= ~BIT6
#define DQ_in P1DIR &= ~BIT6
#define DQ_out P1DIR |= BIT6
#define DQ_val (P1IN & BIT6)
uint tvalue;
uchar tflag;
uchar disdata[4];
/*******************************************
函數名稱:Delay5ms
功 能:延時約5ms
參 數:無
返回值 :無
********************************************/
void Delay5ms(void)
{
uint i=40000;
while (i != 0)
{
i--;
}
}
/*******************************************
函數名稱:DelayNus
功 能:實現N個微秒的延時
參 數:n--延時長度
返回值 :無
說明 :定時器A的計數時鐘是1MHz,CPU主頻8MHz
所以通過定時器延時能夠得到極為精確的
us級延時
********************************************/
void DelayNus(uint n)
{
CCR0 = n;
TACTL |= MC_1; //增計數到CCR0
while(!(TACTL & BIT0)); //等待
TACTL &= ~MC_1; //停止計數
TACTL &= ~BIT0; //清除中斷標志
}
/*******************************************
函數名稱:WaitForEnable
功 能:等待1602液晶完成內部操作
參 數:無
返回值 :無
********************************************/
void WaitForEnable(void)
{
P4DIR &= 0x00; //將P4口切換為輸入狀態
CLR_RS;
SET_RW;
_NOP();
SET_EN;
_NOP();
_NOP();
while((P4IN & Busy)!=0); //檢測忙標志
CLR_EN;
P4DIR |= 0xFF; //將P4口切換為輸出狀態
}
/*******************************************
函數名稱:write_com
功 能:向液晶模塊寫入命令
參 數:cmd--命令,
chk--是否判忙的標志,1:判忙,0:不判
返回值 :無
********************************************/
void write_com(uchar cmd)
{
WaitForEnable(); // 檢測忙信號?
CLR_RS;
CLR_RW;
_NOP();
DataPort = cmd; //將命令字寫入數據端口
_NOP();
SET_EN; //產生使能脈沖信號
_NOP();
_NOP();
CLR_EN;
}
/*******************************************
函數名稱:write_data
功 能:向液晶顯示的當前地址寫入顯示數據
參 數:data--顯示字符數據
返回值 :無
********************************************/
void write_data( uchar data )
{
WaitForEnable(); //等待液晶不忙
SET_RS;
CLR_RW;
_NOP();
DataPort = data; //將顯示數據寫入數據端口
_NOP();
SET_EN; //產生使能脈沖信號
_NOP();
_NOP();
CLR_EN;
}
void zifuchuan(uchar *ch)
{
while(*ch!=0)
write_data(*ch++);
Delay5ms();
}
/*******************************************
函數名稱:LcdReset
功 能:對1602液晶模塊進行復位操作
參 數:無
返回值 :無
********************************************/
void LcdReset(void)
{
CtrlDir |= 0x07; //控制線端口設為輸出狀態
DataDir = 0xFF; //數據端口設為輸出狀態
write_com(0x38); //規定的復位操作
Delay5ms();
write_com(0x38);
Delay5ms();
write_com(0x38);
Delay5ms();
write_com(0x38); //顯示模式設置
write_com(0x08); //顯示關閉
write_com(0x01); //顯示清屏
write_com(0x06); //寫字符時整體不移動
write_com(0x0c); //顯示開,不開游標,不閃爍
}
/*******************************************
函數名稱:Init_18B20
功 能:對DS18B20進行復位操作
參 數:無
返回值 :初始化狀態標志:1--失敗,0--成功
********************************************/
uchar Init_18B20(void)
{
uchar Error;
DQ_out;
_DINT();
DQ0;
DelayNus(500);
DQ1;
DelayNus(55);
DQ_in;
_NOP();
if(DQ_val)
{
Error = 1; //初始化失敗
}
else
{
Error = 0; //初始化成功
}
DQ_out;
DQ1;
_EINT();
DelayNus(400);
return Error;
}
/*******************************************
函數名稱:Write_18B20
功 能:向DS18B20寫入一個字節的數據
參 數:wdata--寫入的數據
返回值 :無
********************************************/
void Write_18B20(uchar wdata)
{
uchar i;
_DINT();
for(i = 0; i < 8;i++)
{
DQ0;
DelayNus(6); //延時6us
if(wdata & 0X01) DQ1;
else DQ0;
wdata >>= 1;
DelayNus(50); //延時50us
DQ1;
DelayNus(10); //延時10us
}
_EINT();
}
/*******************************************
函數名稱:Read_18B20
功 能:從DS18B20讀取一個字節的數據
參 數:無
返回值 :讀出的一個字節數據
********************************************/
uchar Read_18B20(void)
{
uchar i;
uchar temp = 0;
_DINT();
for(i = 0;i < 8;i++)
{
temp >>= 1;
DQ0;
DelayNus(6); //延時6us
DQ1;
DelayNus(8); //延時9us
DQ_in;
_NOP();
if(DQ_val) temp |= 0x80;
DelayNus(45); //延時45us
DQ_out;
DQ1;
DelayNus(10); //延時10us
}
_EINT();
return temp;
}
/*******************************************
函數名稱:Skip
功 能:發送跳過讀取產品ID號命令
參 數:無
返回值 :無
********************************************/
void Skip(void)
{
Write_18B20(0xcc);
}
/*******************************************
函數名稱:Convert
功 能:發送溫度轉換命令
參 數:無
返回值 :無
********************************************/
void Convert(void)
{
Write_18B20(0x44);
}
/*******************************************
函數名稱:Read_SP
功 能:發送讀ScratchPad命令
參 數:無
返回值 :無
********************************************/
void Read_SP(void)
{
Write_18B20(0xbe);
}
/*******************************************
函數名稱:ReadTemp
功 能:從DS18B20的ScratchPad讀取溫度轉換結果
參 數:無
返回值 :讀取的溫度數值
********************************************/
uint ReadTemp(void)
{
uchar temp_low;
uint temp;
temp_low = Read_18B20(); //讀低位
temp = Read_18B20(); //讀高位
temp = (temp<<8) | temp_low;
return temp;
}
uint Do1Convert(void)
{
uchar i;
uchar temp_low;
uint temp;
do
{
i = Init_18B20();
}
while(i);
//此處的i就是等于前面的Error,Error = 1,就會出現死循環,表示18B20可能壞了
Write_18B20(0xcc);//送跳過讀取產品ID號命令
Write_18B20(0x44);//發送溫度轉換命令
for(i = 20;i > 0;i--)
DelayNus(60000); //延時800ms以上
do
{
i = Init_18B20();
}
while(i);
//此處的i就是等于前面的Error,Error = 1,就會出現死循環,表示18B20可能壞了
Write_18B20(0xcc);//送跳過讀取產品ID號命令
Write_18B20(0xbe);//發送讀ROM命令
temp_low = Read_18B20(); //讀低位
temp = Read_18B20(); //讀高位
temp = (temp<<8) | temp_low;
if(temp<0x0fff)
tflag=0;
else
{temp=~temp+1;
tflag=1;
}
tvalue=temp*(0.625);//溫度值擴大10倍,精確到1位小數
return tvalue;
}
void display(int dat)
{
disdata[0]=dat/1000;
disdata[1]=dat%1000/100;
disdata[2]=dat%100/10;
disdata[3]=dat%10;
write_com(0x80+0x40);
write_data(disdata[0]+0x30);
write_data(disdata[1]+0x30);
write_data(disdata[2]+0x30);
write_com(0x80+0x43);
write_data(0x2e);
write_data(disdata[3]+0x30);
write_data(0xdf);//寫入攝氏度的小圈
write_data('C');
}
/*************************主函數*************************/
void main( void )
{
/*下面六行程序關閉所有的IO口*/
P1DIR = 0XFF;P1OUT = 0XFF;
P2DIR = 0XFF;P2OUT = 0XFF;
P3DIR = 0XFF;P3OUT = 0XFF;
P4DIR = 0XFF;P4OUT = 0XFF;
P5DIR = 0XFF;P5OUT = 0XFF;
P6DIR = 0XFF;P6OUT = 0XFF;
uchar i;
WDTCTL = WDTPW + WDTHOLD; //關狗
P6DIR |= BIT2;P6OUT |= BIT2; //關閉電平轉換
/*------選擇系統主時鐘為8MHz-------*/
BCSCTL1 &= ~XT2OFF; //打開XT2高頻晶體振蕩器
do
{
IFG1 &= ~OFIFG; //清除晶振失敗標志
for (i = 0xFF; i > 0; i--); //等待8MHz晶體起振
}
while ((IFG1 & OFIFG)); //晶振失效標志仍然存在?
BCSCTL2 |= SELM_2 + SELS; //MCLK和SMCLK選擇高頻晶振
//計數時鐘選擇SMLK=8MHz,1/8分頻后為1MHz
TACTL |= TASSEL_2 + ID_3;
//打開全局中斷
_EINT();
LcdReset();
zifuchuan("Temperature is:");
//循環讀數顯示
while(1)
{
display(Do1Convert());
}
}