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