摘要:本應用筆記提供了一些利用Maxim API控制DS1WM 1-Wire總線主機的C語言例程。本文討論的內容基于DS1WM已經設計到FPGA或ASIC內,主控CPU通過API調用控制DS1WM。DS1WM通過兩個文件(DS1WM.c和DS1WM.h)進行通信,這兩個文件構成了API。本文討論的例程包括:初始化、1-Wire復位、ROM搜索算法,說明了1-Wire常見功能的使用。假設讀者已經了解1-Wire器件、DS1WM 1-Wire主機以及1-Wire總線協議。
圖1. 1-Wire網絡總線示例電路
圖1所示的電路配置適用于以下所有示例程序。主機CPU利用DS1WM與帶有鏈路模式和GPIO的1-Wire數字溫度傳感器DS28EA00以及1-Wire 1Kb EEPROM DS2431進行通信。示例程序重點演示API,而非從設備功能。16MHz的系統時鐘通過CLK引腳提供1-Wire主機時序。1-Wire主機的端口引腳需要映射到應用微處理器的引腳。API文件DS1WM.h中包含了引腳映射功能。API頭文件中的MaxNumberDevices宏必須更改為實際可能的最大器件數。DS1WM.c API文件中的ReadByteFromRegister和WriteByte2Register函數也需要進行修改,以便正確觸發微處理器端口。VPUP電壓典型值為5.0V,RPUP不大于2.2kΩ。
后續的示例程序中用到了表1所示的1-Wire操作。
表1. 1-Wire操作
*該表涵蓋了示例中用到的子程序,詳細說明請參見DS1WM.c文件。
注意:如果1-Wire總線上連接了不止一種器件類型(例如,具有相同的家族碼),則后續的方法無法對器件進行識別。不對總線上的多個1-Wire器件進行識別,則無法對特定的1-Wire器件發送功能命令。如果使用了兩個或更多的類似器件,則必須通過查找表才能正確訪問特定器件。
調用OWSearch函數可以識別總線上所有的1-Wire器件,該函數將8字節ROM ID排成一列。這期間無需調用OWReset函數,因為該函數已經包含在OWSearch函數中。OWSearch函數例外的包含了OWReset函數,是因為其搜索算法具有迭代過程。OWSearch函數的返回值為搜索到的1-Wire器件個數,并將每個64位ROM ID寫入一個名為ROMCodes的二維數組。
下列例程僅演示了調用一次OWSearch的情況,因此后續連接至該1-Wire總線的器件將無法通過該代碼進行識別。OWSearch函數成功執行后將返回搜索到的器件個數。如果搜索失敗,ErrorStatus變量將返回錯誤值,其中包括產生OWReset的故障條件。搜索成功后,對ROMCodes數組進行了遍歷,并保存每個器件的數組索引。這種器件索引方式是通過比較搜索到的每個器件的家族碼實現的。隨后調用數組索引,可以實現與搜索到的特定1-Wire器件進行通信。這相當于創建了一個簡單的鏈表(注:可以通過指針進行操作)。
引言
DS1WM1-Wire總線主機內部生成1-Wire時序和控制信號,無需CPU產生逐位控制時序。該控制功能使系統程序設計人員能夠使用API函數進行程序開發。DS1WM API采用ANSI C語言編寫,可以為多種支持ANSI C的微處理器平臺所用。以下例程介紹了如何在網絡中識別、選擇1-Wire從設備,并與其進行通信。圖1. 1-Wire網絡總線示例電路
圖1所示的電路配置適用于以下所有示例程序。主機CPU利用DS1WM與帶有鏈路模式和GPIO的1-Wire數字溫度傳感器DS28EA00以及1-Wire 1Kb EEPROM DS2431進行通信。示例程序重點演示API,而非從設備功能。16MHz的系統時鐘通過CLK引腳提供1-Wire主機時序。1-Wire主機的端口引腳需要映射到應用微處理器的引腳。API文件DS1WM.h中包含了引腳映射功能。API頭文件中的MaxNumberDevices宏必須更改為實際可能的最大器件數。DS1WM.c API文件中的ReadByteFromRegister和WriteByte2Register函數也需要進行修改,以便正確觸發微處理器端口。VPUP電壓典型值為5.0V,RPUP不大于2.2kΩ。
概述
通過Maxim支持中心,可以申請免費的DS1WM和API。下面討論了初始化和1-Wire復位控制的DS1WM代碼。此外還提供了一個示例,用于演示如何使用DS1WM ROM搜索引擎確定每個器件的唯一注冊碼(ROM ID)。使用存儲的注冊碼以及家族碼,可以識別每個1-Wire從設備,并通過匹配ROM命令進行訪問。家族碼列表,請參見應用筆記155:“1-Wire?軟件資源指南”。DS28EA00示例演示了如何進行溫度轉換。第二個示例給出了高速讀寫DS2431暫存器的兩種方法。總線主機基本操作
微處理器通過觸發復位引腳初始化DS1WM,API接口執行所有1-Wire通信。示例程序通過調用DS1WM API函數進行工作。由于響應中斷時會改變微處理器代碼,因此后續示例中采用輪詢方式替代中斷方式通信。后續的示例程序中用到了表1所示的1-Wire操作。
表1. 1-Wire操作
Operation* | Description |
OWReset | Sends the 1-Wire reset stimulus and checks for the pulses of 1-Wire slave devices that are present on the bus. |
OWWriteByte/OWReadByte | Sends or receives a single byte of data from the 1-Wire bus. |
OWWriteBytes/OWReadBytes | Sends or receives multiple bytes of data from the 1-Wire bus. |
OWSearch | Performs the 1-Wire Search Algorithm (see application note 187, "1-Wire Search Algorithm"). |
OverdriveEnable | Sets the 1-Wire communication speed for the DS1WM to overdrive. Note that this only changes the communication speed of the DS1WM; the 1-Wire slave device must be instructed to make the switch when going from normal to overdrive. The 1-Wire slave will always revert to standard speed when it encounters a standard-speed 1-Wire reset. |
OverdriveDisable | Sets the 1-Wire communication speed for the DS1WM to standard. Note that this only changes the communication speed of the DS1WM; a standard-speed 1-Wire reset is required for slave devices to exit overdrive. |
MatchROM | Selects device by issuing the Match ROM command followed by the 64-bit ROM ID selected. |
SetClockFrequency | Sets the clock frequency for the DS1WM. |
InterruptEnableRegisterWrite | Writes a single byte of data to the DS1WM Interrupt Enable register. |
InterruptRegisterRead | Reads a single byte of data from the DS1WM Interrupt register. |
ReceiveBufferRead | Reads a single byte of data from the DS1WM Receive Buffer register. |
初始化
通過初始化DS1WM,啟動主機,提供正確的1-Wire總線時序。主機將數值16 (代表頻率值)傳遞至SetClockFrequency函數,將0x90h寫入時鐘分頻寄存器(請參見DS1WM數據資料)。中斷使能寄存器設置為0x00h,防止INTR引腳產生中斷。上電時,接收緩存可能包含無效值,因此在發送1-Wire命令之前,最好對接收緩存進行清理。啟動時對中斷寄存器和接收緩存器的讀操作將清除其中的各個位。//---------------------------------------------------------------------------------------------------- //Start of initialization example SetClockFrequency(16); //Set clock frequency to 16MHz (power-on default) InterruptEnableRegisterWrite(0x00); //Clear interrupts //Flush receive buffer InterruptRegisterData = InterruptRegisterRead(); ReceiveBufferRead(); //End of initialization example //----------------------------------------------------------------------------------------------------
1-Wire復位(OWReset API函數)
初始化完成后,主機必須確定1-Wire總線上是否接有設備。主機調用OWReset函數,以實現該目的。如果檢測到器件存在脈沖,該函數返回1;如果沒有檢測到器件或發送錯誤,則函數返回0。如果返回值為0,需要檢查ErrorStatus變量,以確定故障狀態。1-Wire復位的優先級高于所有1-Wire命令(例如,Match ROM、Skip ROM、Read ROM),但調用OWSearch函數時除外,該函數自身帶有復位。軟件設計人員應當在程序中加入適當的故障處理代碼,在發生故障時能夠觸發執行這些代碼。ErrorStatus值意味著發生了如下錯誤中的一種:沒有進行在線檢測;沒有檢測到器件;存在1-Wire短路;1-Wire總線始終處于低電平狀態。Result = OWReset(); if(!Result){ switch(ErrorStatus){ case -1: //DS1WM did not recognize 1-Wire reset (PD=0) //To d add your error code here break; case -2: //No device found (PDR=1) //To d add your error code here break; case -7: //1-Wire IO is shorted (OW_SHORT=1) //To d add your error code here break; case -8: //1-Wire IO is shorted (OW_LOW=1) //To d add your error code here break; } }
利用ROM搜索引擎確定ROM ID
總線上的每個1-Wire設備都必須進行識別。存儲在每個1-Wire器件中的唯一64位ROM ID用于選擇各個器件,并根據家族碼識別器件類型。為降低例程的復雜度,采用8位家族碼識別DS28EA00和DS2431。注意:如果1-Wire總線上連接了不止一種器件類型(例如,具有相同的家族碼),則后續的方法無法對器件進行識別。不對總線上的多個1-Wire器件進行識別,則無法對特定的1-Wire器件發送功能命令。如果使用了兩個或更多的類似器件,則必須通過查找表才能正確訪問特定器件。
調用OWSearch函數可以識別總線上所有的1-Wire器件,該函數將8字節ROM ID排成一列。這期間無需調用OWReset函數,因為該函數已經包含在OWSearch函數中。OWSearch函數例外的包含了OWReset函數,是因為其搜索算法具有迭代過程。OWSearch函數的返回值為搜索到的1-Wire器件個數,并將每個64位ROM ID寫入一個名為ROMCodes的二維數組。
下列例程僅演示了調用一次OWSearch的情況,因此后續連接至該1-Wire總線的器件將無法通過該代碼進行識別。OWSearch函數成功執行后將返回搜索到的器件個數。如果搜索失敗,ErrorStatus變量將返回錯誤值,其中包括產生OWReset的故障條件。搜索成功后,對ROMCodes數組進行了遍歷,并保存每個器件的數組索引。這種器件索引方式是通過比較搜索到的每個器件的家族碼實現的。隨后調用數組索引,可以實現與搜索到的特定1-Wire器件進行通信。這相當于創建了一個簡單的鏈表(注:可以通過指針進行操作)。
//---------------------------------------------------------------------------------------------------- //Start of DS1WM search ROM accelerator example //Devices on the 1-Wire IO are: //DS28EA00 Family Code = 42h (6900000004E8C842) //DS2431 Famliy Code = 2Dh (5A0000000FDE052D) //Find all devices on 1-Wire line and populate ROMCodes array Result = OWSearch(ROMCodes); //Returns number of devices found if successful //Set number of 1-Wire devices found if(Result) NumberOfDevices = Result; if(!Result){ switch(ErrorStatus){ case -1: //DS1WM did not recognize 1-Wire Reset (PD=0) //To d add your error code here break; case -2: //No device found (PDR=1) //To d add your error code here break; case -7: //1-Wire IO is shorted (OW_SHORT=1) //To d add your error code here break; case -8: //1-Wire IO is shorted (OW_LOW=1) //To d add your error code here break; case -9: //Invalid CRC for device //To d add your error code here break; case -10: //ROMCodes array too small (Edit MaxNumberDevices in DS1WM.h) //To d add your error code here break; } } //Note: This function is intended to be used when there is only one device with the same //Family Code present on the line for(i=0;i利用DS1WM API函數控制DS28EA00
該示例利用之前搜索到的ROM ID與DS28EA00進行通信。OWReset之后發送Match ROM命令。ROM碼數組連同被訪問的器件索引一起,傳遞到Match ROM函數。1-Wire總線上的器件會在Match ROM命令0x55h之后收到一個64位ROM碼,可以使總線主機在多點總線上尋址到特定的DS28EA00。只有與64位ROM序列完全匹配的DS28EA00才能響應接下來的命令,其它的從器件將等待下一個復位脈沖。
OWWriteByte和OWReadByte API函數用來產生存儲器命令(例如,Write/Copy/Read Scratchpad命令)。DS1WM通過發送Write Scratchpad命令(0x4Eh)以及隨后的高溫、低溫和配置寄存器設置值,來設定溫度報警以及分辨率。上述操作完成后,發送OWReset以及Match ROM命令、ROM ID和Copy Scratchpad命令(0x48h) (將暫存器的內容復制到寄存器存儲器),完成溫度分辨率設置。必須為CPU主機增加10ms的延時,以完成復制操作。考慮到微處理器延時子程序的差異,API僅提供了注釋偽碼。
復制操作完成后,再次執行OWReset,然后發送Match ROM、ROM ID和轉換溫度命令(0x44h)。需要增加100ms的延時,以完成溫度轉換。最后,發送OWReset和Match ROM、ROM ID和Read Scratchpad命令(0xBEh),讀取兩字節溫度數據。需要注意的是,選擇DS28EA00時,必須始終遵循OWReset之后發送Match ROM命令和ROM ID的命令格式。當總線上僅有一個器件時,才能夠使用Skip ROM命令(即無需Search ROM)。//---------------------------------------------------------------------------------------------------- //Start of DS28EA00 example Result = OWReset(); if(!Result){ switch(ErrorStatus){ case -1: //DS1WM did not recognize 1-Wire reset(PD=0) //To d add your error code here break; case -2: //No device found(PDR=1) //To d add your error code here break; case -7: //1-Wire IO is shorted(OW_SHORT=1) //To d add your error code here break; case -8: //1-Wire IO is shorted(OW_LOW=1) //To d add your error code here break; } } //Set temperature resolution Result = MatchROM(ROMCodes,DS28EA00); //Select device Result = OWWriteByte(0x4E); //Issue Write Scratchpad command Result = OWWriteByte(0x00); //TH register data Result = OWWriteByte(0x00); //TL degister data Result = OWWriteByte(0x1F); //Config. reg. data (set 9-bit temp. resolution) OWReset(); //Error code removed for conciseness MatchROM(ROMCodes,DS28EA00); //Select device OWWriteByte(0x48); //Issue Copy Scratchpad command //To d add microprocessor-specific code delay to allow copy to complete //Delay(10MS); //Psuedo code OWReset(); //1-Wire reset MatchROM(ROMCodes,DS28EA00); //Select device OWWriteByte(0x44); //Issue Convert Temperature command //To d add microprocessor-specific code delay to allow temperature conversion to complete //Delay(100MS); //Psuedo code //Read temperature results from scratchpad OWReset(); //1-Wire reset MatchROM(ROMCodes,DS28EA00); //Select device OWWriteByte(0xBE); //Issue Read Scratchpad command TempLSB = OWReadByte(); //Read byte TempMSB = OWReadByte(); //Read byte //End of DS28EA00 example //----------------------------------------------------------------------------------------------------利用DS1WM API函數控制高速模式下的DS2431
該示例利用之前搜索到的ROM ID與DS2431進行通信。OWReset之后發送Overdrive Skip ROM命令(0x3Ch),將所有支持高速模式的1-Wire器件置于高速模式。調用OverdriveEnable函數激活DS1WM高速時序。此時所有1-Wire器件工作在高速模式。標準速率模式和高速模式下的1-Wire時序請參見應用筆記126:“用軟件實現1-Wire?通信”。
使用目標地址TA1和TA2變量
在第一個示例方法中,變量TA1和TA2設置為DS2431期望的存儲器地址。發送OWReset,之后是Match ROM、DS2431 ROM ID、Write Scratchpad命令(0x0Fh)、目標地址1 & 2以及要寫入DS2431 64位暫存器的8字節數據。推薦進行回讀及CRC16校驗操作。關于CRC16的詳細討論,請參考應用筆記27:“理解和運用Maxim iButton?產品中的循環冗余校驗(CRC)”。
OWWriteBytes和OWReadBytes
在第二個示例方法中,調用了兩個新的API函數:OWWriteBytes和OWReadBytes。這兩個API函數簡化了大量數據至暫存器的讀寫操作。
寫暫存器的方法是:設置目標地址1 & 2、將數據寫入WriteBytes數組、執行OWReset、然后發送Match ROM、DS2431 ROM ID、Write Scratchpad命令(0x0Fh)、目標地址1 & 2、利用OWWriteBytes函數寫入保存在WriteBytes的所有10個字節、回讀CRC16并對CRC16進行校驗。
讀暫存器的方法是:執行OWReset、發送Match ROM、DS2431 ROM ID、Read Scratchpad命令(0xAAh)、利用OWReadBytes函數讀取所有13個字節(TA1、TA2、ES、CRC16 & 8字節數據)并保存到ReadBytes。
調用API函數OverdriveDisable,并隨后發送標準OWReset,可以退出高速模數,使所有器件返回至標準速率。//---------------------------------------------------------------------------------------------------- //Start of DS2431 example Result = OWReset(); //Error code removed for conciseness Result = OWWriteByte(0x3C); //Overdrive Skip ROM (all devices are now in overdrive) OverdriveEnable(); //Enable Overdrive Mode //Write scratchpad with data //First method TA1 = 0x00; TA2 = 0x00; Result = OWReset(); //1-Wire reset Result = MatchROM(ROMCodes,DS2431); //Select device Result = OWWriteByte(0x0F); //Issue Write Scratchpad command Result = OWWriteByte(TA1); //Send target address 1 (TA1) Result = OWWriteByte(TA2); //Send target address 2 (TA2) //Write 8 Bytes of Data Result = OWWriteByte(0x11); //Send Data Byte for all Result = OWWriteByte(0x22); Result = OWWriteByte(0x33); Result = OWWriteByte(0x44); Result = OWWriteByte(0x55); Result = OWWriteByte(0x66); Result = OWWriteByte(0x77); Result = OWWriteByte(0x88); //It is recommended that the CRC16 be read back and verified //CRC16 code was left out for conciseness Result = OWReset(); //1-Wire Reset Result = MatchROM(ROMCodes,DS2431); //Select device Result = OWWriteByte(0xAA); //Issue Read Scratchpad command Result = OWReadByte(); //Read TA1 if(Result != TA1){ //To d Add your error code here } Result = OWReadByte(); //Read TA2 if(Result != TA2){ //To d Add your error code here } ES = OWReadByte(); //Read ES //To d add your error code after reads Result = OWReadByte(); //Read Data Byte (0x11) Result = OWReadByte(); //Read Data Byte (0x22) Result = OWReadByte(); //Read Data Byte (0x33) Result = OWReadByte(); //Read Data Byte (0x44) Result = OWReadByte(); //Read Data Byte (0x55) Result = OWReadByte(); //Read Data Byte (0x66) Result = OWReadByte(); //Read Data Byte (0x77) Result = OWReadByte(); //Read Data Byte (0x88) //It is recommended that the CRC16 be read back and verified //CRC16 code was left out for conciseness //Second method TA1 = 0x00; TA2 = 0x00; WriteBytes[0] = TA1; WriteBytes[1] = TA2; for(i=2;i<10;i++){ WriteBytes[i] = i; } Result = OWReset(); //1-Wire reset Result = MatchROM(ROMCodes,DS2431); //Select device Result = OWWriteByte(0x0F); //Issue Write Scratchpad command //Write 10 bytes of data (TA1, TA2 & 8 bytes of data) OWWriteBytes(WriteBytes,10); //Write data bytes //It is recommended that the CRC16 be read back and verified //CRC16 code was left out for conciseness Result = OWReset(); //1-Wire reset Result = MatchROM(ROMCodes,DS2431); //Select device Result = OWWriteByte(0xAA); //Issue Read Scratchpad command //Read 13 bytes of data (TA1, TA2, ES, CRC16 & 8 bytes of data) OWReadBytes(ReadBytes,13); //Read data bytes //It is recommended that the CRC16 be read back and verified //CRC16 code was left out for conciseness //Exit overdrive OverdriveDisable(); Result = OWReset(); //Std. reset issued (all devices are now in standard speed) //End of DS2431 example //----------------------------------------------------------------------------------------------------結論
本應用筆記給出了使用API函數控制DS1WM的示例,無需主機CPU產生1-Wire時序。用戶現在應該對選擇和訪問總線上多個1-Wire器件的通用API函數有了一定的了解。本文給出了DS28EA00和DS2431總線示例器件的控制和訪問示例,此外還演示了高速模式以及單字節/多字節數據的讀寫操作。
評論
查看更多