?? wds18b20.#3
字號:
//參考程序A: 程序名WDS18B20.C 數(shù)字溫度傳感器DS18b20測溫實驗:P0.0連接SDA, P0.1`連接SCL. SAA1064驅(qū)動四位數(shù)碼管顯示溫度值:< 0 1 3. 4>
#include <c8051f020.h> // SFR declarations
#include <intrins.h>
#define WRITE 0x00 // 寫位
#define READ 0x01 // 讀位
#define CHIP_B 0x70 // SA1064地址
#define SMB_START 0x08 // 主收發(fā)器發(fā)送起始位成功.再將從機寫地址送SMB0DAT
#define SMB_MTADDACK 0x18 //(MT) 主收發(fā)器發(fā)送從地址+W成功;收到 ACK(從機應(yīng)答)
#define SMB_MTDBACK 0x28 // (MT) 主收發(fā)器發(fā)送數(shù)據(jù)字節(jié)成功;收到ACK(從機應(yīng)答)
#define SMB_MRADDACK 0x40 // (MR) 主收發(fā)器發(fā)送從地址+R成功;收到 ACK(從機應(yīng)答)
#define SMB_MRADDNACK 0x48 //主收發(fā)器發(fā)送從地址+R成功;收到NACK(從機無應(yīng)答)
#define SMB_MRDBACK 0x50 // (MR) 主收發(fā)器接收數(shù)據(jù)成功;
#define SMB_MRDBNACK 0x58 // (MR) 主收發(fā)器接收數(shù)據(jù)成功;
char COMMAND; // 保存從地址加讀/寫位,用在中斷服務(wù)程序SMBus ISR中
char WORD; // 保存在SUMBUS總線上傳送的數(shù)或剛被接受到的數(shù)據(jù)。
unsigned char totalnumber,sendnumber;
unsigned char xdata OP_CODE;
unsigned char xdata SENDMODE;
bit SM_BUSY; //該位在開始接收數(shù)據(jù)或發(fā)送數(shù)據(jù)時被置位。在中斷完成后被清0
sbit DataPortDS1820 = P0^2; //1 WIRE 用P0.2這一條信號線
unsigned char wr_data[8]; //數(shù)組wr_data[8]中存放要寫入SAA1064的數(shù)據(jù)
unsigned char rd_data[8]; //數(shù)組rd_data[8]中存放從DS18B20中讀出的數(shù)據(jù)
void Delay1us(unsigned char us) //延時
{
while (us)
{
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
--us;
}
}
void Delay15us(void)
{
Delay1us(15); //延時15秒
}
void Delay10us(void)
{
Delay1us(10);
}
bit RstDS1820(void) //返回0-有設(shè)備連接1-無設(shè)備連接
{
unsigned char i;
bit RstFlag;
RstFlag=1;
DataPortDS1820=0;
for (i=0;i<40;i++) //480us 延時
Delay15us();
DataPortDS1820=1;
for(i=0;i<4;i++) //15us-60us 延時
{
Delay15us();
}
for (i=0;i<16;i++) //60us-240us 延時
{
Delay15us();
if (DataPortDS1820==0) RstFlag=0;
}
for (i=0;i<16;i++) //240us
{
Delay15us();
}
return RstFlag;
}
void WriteDS1820(unsigned char ch)
{
unsigned char i;
DataPortDS1820=1;
Delay1us(1);
for (i=0;i<8;i++)
{
EA=0;
DataPortDS1820=0;
Delay15us();
DataPortDS1820=ch&0x1;
EA=1;
Delay15us();Delay15us();Delay15us();
DataPortDS1820=1;
ch=ch>>1;
Delay1us(1);
}
}
unsigned char ReadDS1820(void)
{
unsigned char i,ch;
ch=0;
DataPortDS1820=1;
Delay1us(1);
for (i=0;i<8;i++)
{
EA=0;
DataPortDS1820=0;
Delay10us();
DataPortDS1820=1;
Delay1us(2);
ch=ch>>1;
if (DataPortDS1820==1)
{
ch=ch+0x80;
}
EA=1;
Delay15us();Delay15us();Delay15us();
}
return ch;
}
void SkipROMCode(void) //主機發(fā)跳過讀序列號的操作命令:0xcc
{
RstDS1820();
WriteDS1820(0xcc);
}
void StartADC(void)
{
RstDS1820(); //復(fù)位
WriteDS1820(0xcc); //廣播
WriteDS1820(0x44); //啟動溫度轉(zhuǎn)換轉(zhuǎn)換 12bit700ms
}
unsigned int GetTempValue(void)//讀取溫度值的程序
{
unsigned char i,j;
unsigned int T;
SkipROMCode();
WriteDS1820(0xBE); //發(fā)布讀取溫度值的命令(0xBE)
i=ReadDS1820();
j=ReadDS1820();
StartADC();
T=i+j*256;
if (T==0xffff) return 0xffff;
if (T>0x8000) //溫度為負(fù)號
{
T=-T;
return(0x8000+T*5/8); //計算溫度值
}
else //溫度為正號
return(T*5/8);
}
void sleep_ms(unsigned int count) //延時
{
unsigned char ii,jj;
for(ii=0;ii<count;ii++)
{
for(jj=0;jj<250;jj++)
_nop_();
}
}
void SYSCLK_Init (void) // 時鐘初始化
{
int i; // 延時計數(shù)器
OSCXCN = 0x67; // 啟動外部晶振(11.0592MH)
for (i=0; i < 256; i++); // 等待外部晶振穩(wěn)定
while (!(OSCXCN & 0x80));
OSCICN = 0x88; // 選擇外部晶振,允許時鐘丟失檢測
}
void PORT_Init (void)
{
XBR0 = 0x01; // 允許 SMBus,P0.0-SDA,P0.1--SCL
XBR2 = 0x40; // 使能交叉開關(guān)和弱上拉
}
void SLA_SEND(char chip_select, char *wr_data, char number)
{
SENDMODE=0x01;
totalnumber=number;
sendnumber=number;
while(SM_BUSY); // SMBus 忙碌則等待
SM_BUSY = 1; // SMBus 忙碌標(biāo)志置1
SMB0CN = 0x44; // 允許SMBus , ACK 應(yīng)答信號為低
COMMAND = (chip_select | WRITE); // COMMAND = 7位地址加讀/寫位
STO = 0;
STA = 1; // 數(shù)據(jù)傳送開始
while(SM_BUSY);
}
void Init18b20(void)
{
SkipROMCode(); //主機發(fā)跳過讀序列號的操作命令:0xcc
WriteDS1820(0x44); //啟動溫度轉(zhuǎn)換
}
void main (void)
{
unsigned char temp;
unsigned int w;
unsigned char data Number[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
WDTCN = 0xde;
WDTCN = 0xad; //關(guān)看門狗
SYSCLK_Init (); //初始化時鐘
PORT_Init (); //初始化IO口
Init18b20();
SMB0CN = 0x44; // 使能 SMBus ,應(yīng)答低電平(AA = 1)
SMB0CR = 0xc9; // SMBus 速率 = 100 kHz(系統(tǒng)時鐘:11.0592MHZ)
EIE1 |= 2; // SMBus 中斷使能
SM_BUSY = 0; // 釋放總線,為第一次傳送.
SI = 0;
EA=1; //開中斷
for (;;)
{
sleep_ms(250);
sleep_ms(250);
sleep_ms(250);
w = GetTempValue(); //讀出溫度值的原始數(shù)據(jù)存入W
wr_data[0] = 0x00; //將SAA1064的子地址存入數(shù)組wr_data[0]
wr_data[1] = 0x17; //將SAA1064的命令存入數(shù)組wr_data[1]
wr_data[2] = 0x3f;
temp = (w%1000)/100; //計算溫度值 十位
wr_data[3] = Number[temp]; //查表,得到要顯示的子型碼
temp = (w%100)/10; //個位
wr_data[4] = Number[temp]|0x80;//查表,得到要顯示的子型碼,再加小數(shù)點
temp = (w%10); //小數(shù)位
wr_data[5] = Number[temp];
SLA_SEND(CHIP_B,wr_data,0x06);//向SAA1064送出6位數(shù):00,17H 加四位溫度值
sleep_ms(250);
sleep_ms(250);
_nop_();
sleep_ms(250);
sleep_ms(250);
}
}
void SMBUS_ISR (void) interrupt 7
{
switch (SMB0STA){ // 判別SUMBUS狀態(tài)碼(SMB0STA 寄存器)
case SMB_START: //SMB0STA=0x08
SMB0DAT = COMMAND ; // 裝入從地址
STA = 0; // 人工清除啟動位
SI = 0; // 清除中斷標(biāo)志位
break;
case SMB_MTADDACK: //SMB0DAT=0x18
SMB0DAT = wr_data[0];
SI = 0; // 清除中斷標(biāo)志位
break;
case SMB_MTDBACK: //SMB0DAT=0x28
switch (SENDMODE){ //檢查低四位
case 1:
sendnumber--;
if(sendnumber)
SMB0DAT = wr_data[totalnumber-sendnumber];
else{
STO=1;
SM_BUSY=0;
}
break;
case 0:
STO = 0;
STA = 1;
break;
default:
STO = 1;
SM_BUSY = 0;
break;
}
SI = 0;
break;
case SMB_MRADDACK: //SMB0DAT=0x40
AA = 0; // 主機送AA = 0;
SI = 0; //清除中斷標(biāo)志位
break;
case SMB_MRADDNACK: //SMB0DAT=0x48
STO = 0;
STA = 1;
SI = 0;
break;
case SMB_MRDBACK: //SMB0DAT=0x50
STO = 1;
SM_BUSY = 0;
SI = 0;
break;
case SMB_MRDBNACK: //SMB0DAT=0x58
rd_data[0] = SMB0DAT;
STO = 1;
SM_BUSY = 0;
AA = 1; // AA=1,準(zhǔn)備下一次傳輸
SI = 0;
break;
default:
STO = 1;
SM_BUSY = 0;
break;
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -