?? ds18b20.c
字號:
//-----------------------------------------------------------------
// 名稱: 多點DS18B20控制程序
//-----------------------------------------------------------------
#include <pic.h>
#include <string.h>
#include <stdio.h>
#include "DS18B20.h"
#include "LM044L.h"
//溫度小數(shù)位對照表(不使用該表時,還可以通過計算法得到溫度小數(shù)部分)
const INT8U df_Table[] = {0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9 };
INT8U DS18B20_STATUS; //器件狀態(tài),為0時在線,否則表示被撥出或無響應
INT8U Temp_Value[2]; //存放所讀取的兩字節(jié)溫度數(shù)據(jù)
INT8U ROMCODE[8]; //存放搜索到的64位設(shè)備ROMCODE
INT8U Level,Last_Level; //當前分支點和上次搜索的最底層分支點
INT8U DS_CNT; //搜索到的器件個數(shù)
INT8U CRC; //校驗變量
bit bit_A,bit_B; //讀ROMCODE的當前位原碼與反碼
bit bj; //臨時位變量
extern INT8U LCD_Buffer[]; //液晶顯示緩沖
float Temp_i,Temp_f; //溫度的整數(shù)與小數(shù)部分
//-----------------------------------------------------------------
// 延時nx100ms
//-----------------------------------------------------------------
void DelayX100ms(INT8U n)
{
while (n--) __delay_ms(100);
}
//-----------------------------------------------------------------
// 從1-Wire總線讀取1位
//-----------------------------------------------------------------
INT8U Read_Romcode_bit()
{
}
//-----------------------------------------------------------------
// 搜索1-Wire總線上一只器件的64位ROMCODE
// 返回0表示搜索一個ROMCODE,否則表示無器件或搜索的ROMCODE最后校驗出錯
//-----------------------------------------------------------------
INT8U Search_ROM1()
{
volatile INT8U i, j, k;
RESET(); //復位
if (DS18B20_STATUS) return 0; //無器件在線時返回
Write_Byte(SERACH_ROM); //發(fā)送ROM搜索命令
for (i = 0; i < 64; i++) //從0位開始索64位ROMCODE
{ bit_A = Read_Romcode_bit(); //讀取第i位的原碼
bit_B = Read_Romcode_bit(); //讀取第i位的反碼
//---------------------------------------------------------11
//讀取的結(jié)果為"11"時,搜索結(jié)束,程序返回
if (bit_A == 1 && bit_B == 1) return 1;
//-----------------------------------------------------10或01
//讀取的結(jié)果為"10"或"01"時,表示所有從機的此位均為"0"或"1"
//將此位保存到8字節(jié)共64位的數(shù)組ROMCODE中.
//如果為0表示所有從機此位均為"0",故發(fā)送"0"使所有從機繼續(xù)通信
//如果為1表示所有從機此位均為"1",故發(fā)送"1"使所有從機繼續(xù)通信
else if (bit_A != bit_B) //兩位為01或10
{
}
//---------------------------------------------------------00
//讀取的結(jié)果為"00"時,表示從機中此位同時有"0"與"1",在該層出現(xiàn)搜索分支
else if (bit_A == 0 && bit_B == 0)
{
//"="=====================================================
//當前搜索遇到的分支層位置等于前一搜索路徑中最低的分支層位置
if(i == Last_Level)
{
}
//">"=====================================================
//當前搜索遇到的分支層低于前一趟搜索的最低分支層
else if (i > Last_Level)
{
}
//"<"=====================================================
//當前搜索遇到的分支層高于上一次搜索的最低分支層
//此時的“左右分支選擇”決定于上一次ROMCODE搜索結(jié)果中的對應位
else if (i < Last_Level)
{
}
} //完成1位搜索------------------------------------------------
} //完成64位搜索-------------------------------------------------
//對8字(64位)ROMCODE執(zhí)行CRC8校驗
//CRC正確時返回0,否則返回1
}
//-----------------------------------------------------------------
// 轉(zhuǎn)換并顯示當前找到的器件的8字節(jié)(64位)ROMCODE
//-----------------------------------------------------------------
void Show_Romcode(INT8U r, INT8U c,INT8U *RID)
{
INT8U i; char buf[3];
for (i = 0; i < 8; i++) //讀取8字節(jié)(64位)光刻碼,從低字節(jié)開始讀取
{ sprintf(buf,"%02X",ROMCODE[i]); //將當前字節(jié)轉(zhuǎn)換為十六進制字符串
//將各字節(jié)轉(zhuǎn)換后的兩個十六進制字符由后向前存入RomCodeString
//各字節(jié)的兩字符存入順序依次是:(14,15)(12,13)(10,11)......(2,3)(0,1)
//上面這一行還可以改成以下兩行
}
LCD_Buffer[16] = '\0';
LCD_ShowString(r,c,LCD_Buffer);//顯示ROMCODE
}
//-----------------------------------------------------------------
// 搜索1-Wire上掛載的所有器件的ROMCODE
//-----------------------------------------------------------------
INT8U Search_ALL_ROM()
{
INT8U i;
DS_CNT = 0; //初始時搜索到的器件個數(shù)歸0
Level = 0; //初始時設(shè)搜索分支層為0
//開始搜索第一個器件之前將64位的ROMCODE清0
for (i = 0; i < 8; i++) ROMCODE[i] = 0x00;
//開始搜索所有在線器件的ROMCODE
while(1)
{
//保存上次搜索遇到的最低分支層
Last_Level = Level;
//當前分支層暫設(shè)為0
Level = 0;
//搜索一個新的ROMCODE,未找到或出錯時退出
if (Search_ROM1()) break;
//轉(zhuǎn)換并顯示當前找到的器件的8字節(jié)(64位)ROMCODE
Show_Romcode(2,0,ROMCODE);
//僅保存DS18B20器件的ROMCODE
//(限于EEPROM空間,本例僅最多只保存32個ROMCODE)
if (DS_CNT < 32 && ROMCODE[0] == 0x28)
{ //將所找到的器件ROMCODE寫入PIC EEPROM
for (i = 0; i < 8; i++)
{ EEPROM_WRITE(DS_CNT * 8 + i,ROMCODE[i]);
while(WR);
}
__delay_ms(100); DS_CNT++; //累加所找到的總器件數(shù)
}
//顯示當前找到的總器件數(shù)
sprintf(LCD_Buffer,"Found:%d",DS_CNT);
LCD_ShowString(1,0,LCD_Buffer);
//如果完成某次搜索后當前分支層仍為0則結(jié)束查找
if (Level == 0) break;
__delay_ms(100);
}
//將所搜索到的總器件數(shù)寫入EEPROM 0xFF地址
EEPROM_WRITE(0xFF,DS_CNT); while(WR);
return DS_CNT; //返回所搜索到的器件總數(shù)
}
//-----------------------------------------------------------------
// 讀取存放于8字節(jié)數(shù)組A中的ROMCODE的第i位(0/1)
//-----------------------------------------------------------------
INT8U Read_ROMCODE_Bit(INT8U A[],INT8U i)
{
//得出64位ROMCODE中第i位所處的字節(jié)值,及該位的掩碼字節(jié)k
}
//-----------------------------------------------------------------
// 將存放于8字節(jié)數(shù)組A中的ROMCODE的第i位設(shè)為0/1
//-----------------------------------------------------------------
void Save_ROMCODE_Bit(INT8U A[],INT8U i,INT8U b)
{
//先求出64位中的第i位所在的字節(jié)在數(shù)組中的索引j
//再根據(jù)該位在此字節(jié)內(nèi)8位中的位置(i % 8)再得出掩碼字節(jié)k
//例如要設(shè)第3位為1,則有k = 0x01 << 3 = 0B00001000.
//相應位設(shè)為1或0
}
//-----------------------------------------------------------------
// 根據(jù)ROMCODE碼讀取溫度數(shù)據(jù)
//-----------------------------------------------------------------
float Get_Temperature(char *rom_code)
{
float sign = 1;
RESET(); //復位
ROMCODE_Match(rom_code); //發(fā)ROMCODE匹配命令
Write_Byte(CONVERT); //溫度轉(zhuǎn)換命令
DelayX100ms(7); //12位分辯率轉(zhuǎn)換時間為750ms
__delay_ms(50);
RESET(); //復位
ROMCODE_Match(rom_code); //發(fā)ROMCODE匹配命令
Write_Byte(READ_SCRATCHPAD); //讀RAM命令
Temp_Value[0] = Read_Byte(); //讀取兩字節(jié)溫度數(shù)據(jù)
Temp_Value[1] = Read_Byte();
//如果為負數(shù)則取反加1,并設(shè)置負數(shù)標識
//按技術(shù)手冊說明,高5位為符號位,與上0xF8進行+/-判斷
if ( (Temp_Value[1] & 0xF8) == 0xF8)
{
}
}
//-----------------------------------------------------------------
// 發(fā)送匹配命令,并發(fā)送64位的ROMCODE
//-----------------------------------------------------------------
void ROMCODE_Match(INT8U ROMCODE[])
{
//先發(fā)送ROM匹配命令,然后發(fā)送64位的ROMCODE
}
//-----------------------------------------------------------------
// 向1-Wire總線寫1字節(jié)
//-----------------------------------------------------------------
void Write_Byte(INT8U A)
{
for (INT8U i = 0x01;i != 0x00; i <<= 1)
{
if (A & i) Write_DQ_bit(1); else Write_DQ_bit(0);
}
}
//-----------------------------------------------------------------
// 從1-Wire總線讀取1字節(jié)
//-----------------------------------------------------------------
INT8U Read_Byte()
{
INT8U i,d = 0x00;
for (i = 0; i < 8; i++)
{
Read_Slot(); if (DQ == 1) d |= (1<<i); __delay_us(52);
}
return d;
}
//-----------------------------------------------------------------
// 向1-Wire總線寫1位0/1
//-----------------------------------------------------------------
void Write_DQ_bit(INT8U b)
{
DQ_DIR = 0; DQ = 0; //DQ輸出
if (b) { __delay_us(5); DQ_DIR = 1; __delay_us(72); }
else { __delay_us(82); DQ_DIR = 1; }
}
//-----------------------------------------------------------------
// 發(fā)送讀時隙時序
//-----------------------------------------------------------------
void Read_Slot()
{
DQ_DIR = 0; DQ = 0; NOP(); NOP(); DQ_DIR = 1; NOP(); NOP();
}
//-----------------------------------------------------------------
// 1-Wire總線復位
//-----------------------------------------------------------------
void RESET()
{
}
//-----------------------------------------------------------------
// CRC8校驗函數(shù) (基于該函數(shù)可得出256字節(jié)的校驗碼表,改用查表法進行校驗)
// 校驗多項式: x^8 + x ^ 5 + x ^ 4 + 1, 去高位后倒序:0x8C
//-----------------------------------------------------------------
void CRC8(INT8U d)
{
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -