one-wire(單總線)組件


單總線:

  單總線是美國DALLAS公司推出的外圍串行擴展總線技術。與SPI、I²C串行數據通信方式不同.它采用單根信號線,既傳輸時鍾又傳輸數據,而且數據傳輸是雙向的,具有節省I/O口線、資源結構簡單、成本低廉、便於總線擴展和維護等諸多優點。

原理

  單總線器件內部設置有寄生供電電路(Parasite Power Circuit)。當單總線處於高電平時,一方面通過二極管VD向芯片供電,另方面對內部電容C(約800pF)充電;當單總線處於低電平時,二極管截止,內部電容c向芯片供電。由於電容c的容量有限,因此要求單總線能間隔地提供高電平以能不斷地向內部電容C充電、維持器件的正常工作。這就是通過網絡線路“竊取”電能的“寄生電源”的工作原理。要注意的是,為了確保總線上的某些器件在工作時(如溫度傳感器進行溫度轉換、E2PROM寫人數據時)有足夠的電流供給,除了上拉電阻之外,還需要在總線上使用MOSFET(場效應晶體管)提供強上拉供電。單總線的數據傳輸速率一般為16.3Kbit/s,最大可達142 Kbit/s,通常情況下采用100Kbit/s以下的速率傳輸數據。主設備I/O口可直接驅動200m范圍內的從設備,經過擴展后可達1km范圍。

結構

  單總線主機或從機設備通過一個漏極開路或三態端口連接至該數據線,這樣允許設備在不發送數據時釋放數據總線,以允許設備在不發送數據時能夠釋放總線,而讓其他設備使用總線,其內部等效電路如圖9—20所示。
單總線要求外接一個約5 k的上拉電阻.這樣,當單總線在閑置時,狀態為高電平。如果傳輸過程需要暫時掛起,且要求傳輸過程還能夠繼續,則總線必須處於空閑狀態。
傳輸之間的恢復時間沒有限制,只要總線在恢復期間處於空閑狀態(高電平)。如果總線保持低電平超過480 us,總線上的所有器件將復位。另外,在寄生方式供電時,為了保證單總線器件在某些工作狀態下(如:溫度轉換器件、EEPROM寫入等)具有足夠的電源電流,必須在總線上提供強上拉。

命令序列

  1一wire協議定義了復位脈沖、應答脈沖、寫0、讀0和讀1時序等幾種信號類型。所有的單總線命令序列(初始化ROM命令,功能命令)都是由這些基本的信號類型組成。在這些信號中,除了應答脈沖外,其他均由主機發出同步信號、命令和數據,都是字節的低位在前。典型的單總線命令序列如下:
第一步:初始化。
第二步:ROM命令.跟隨需要交換的數據。
第三步:功能命令,跟隨需要交換的數據。
每次訪問單總線器件.都必須遵守這個命令序列.如果序列出現混亂,則單總線器件不會響應主機。但是這個准則對於搜索ROM命令和報警搜索命令例外,在執行兩者中任何一條命令后,主機不能執行其他功能命令,必須返回至第一步。
(1)初始化
單總線上的所有傳輸都是從初始化開始的,初始化過程由主機發出的復位脈沖和從機響應的應答脈沖組成.應答脈沖使主機知道總線上有從機設備,且准備就緒。
(2)ROM命令
當主機檢測到應答脈沖后,就發出ROM命令,這些命令與各個從機設備的唯一64位ROM代碼相關,允許主機在單總線上連接多個從設備時,指定操作某個從設備。使得主機可以操作某個從機設備。這些命令能使主機檢測到總線上有多少個從機設備以及設備類型,或者有沒有設備處於報警狀態。從機設備支持5種ROM命令,每種命令長度為8位。豐機在發出功能命今之前.必須發出ROM命今.
(3)功能命令
主機發出ROM命令,訪問指定的從機,接着發出某個功能命令。這些命令允許主機寫入或讀出從機暫存器、啟動工作以及判斷從機的供電方式。

one_wire.c

  1 /**
  2  * @file one_wire.c
  3  * @brief
  4  * @version 0.1
  5  * @date 2019-06-28
  6  *
  7  * !!!注意單總線GPIO腳必須有上拉,讀寫數據均為低位在前高位在后。
  8  *
  9  * @copyright Copyright (c) 2019
 10  *
 11  */
 12 /*-----------------------------------------------------------------------------
 13                             include
 14 -----------------------------------------------------------------------------*/
 15 #include "one_wire.h"
 16 #include "freertos\FreeRTOS.h"
 17 #include "freertos\task.h"
 18 #include "freertos\semphr.h"
 19 
 20 /*-----------------------------------------------------------------------------
 21                             define
 22 -----------------------------------------------------------------------------*/
 23 /* 用到的硬件TIMER定義 */
 24 #define ONE_WIRE_TIMER (TIMER0)
 25 #define ONE_WIRE_TIMER_IRQ (TIMER0_IRQn)
 26 #define ONE_WIRE_TIMER_US (get_apb_clk()/1000000)
 27 /* 發送復位信號延時定義 */
 28 #define ONE_WIRE_SEND_RESET_TIMER_US (480)/* 發送復位時間 */
 29 #define ONE_WIRE_READ_RESPOND_TIMER_US (70)/* 讀取響應時間 */
 30 #define ONE_WIRE_RESPOND_CONTINUE_TIMER_US (480)/* 響應持續時間 */
 31 /* 寫數據信號延時定義 */
 32 #define ONE_WIRE_WRITE_PREPARE_TIMER_US (15)/* 寫數據准備時間 */
 33 #define ONE_WIRE_WRITE_TIMER_US (30)/* 寫數據時間 */
 34 #define ONE_WIRE_WRITE_CONTINUE_TIMER_US (65)/* 寫數據持續時間 */
 35 /* 讀數據信號延時定義 */
 36 #define ONE_WIRE_READ_PREPARE_TIMER_US (3)/* 讀數據准備時間 */
 37 #define ONE_WIRE_READ_TIMER_US (13)/* 讀數據時間 */
 38 #define ONE_WIRE_READ_CONTINUE_TIMER_US (63)/* 讀數據持續時間 */
 39 
 40 /*-----------------------------------------------------------------------------
 41                             extern
 42 -----------------------------------------------------------------------------*/
 43 
 44 /*-----------------------------------------------------------------------------
 45                         struct / enum / union
 46 -----------------------------------------------------------------------------*/
 47 /* 整體狀態類型 */
 48 typedef enum
 49 {
 50     ONE_WIRE_RESET_STATE = 0,
 51     ONE_WIRE_WRITE_STATE = 1,
 52     ONE_WIRE_READ_STATE = 2,
 53 }one_wire_state_t;
 54 
 55 /* 復位狀態類型 */
 56 typedef enum
 57 {
 58     ONE_WIRE_RESET_PREPARE_STATE = 0,
 59     ONE_WIRE_RESET_TIME_STATE = 1,
 60     ONE_WIRE_RESET_CONTINUE_STATE = 2,
 61     ONE_WIRE_RESET_END_STATE = 3,
 62 }one_wire_reset_state_t;
 63 
 64 /* 寫狀態類型 */
 65 typedef enum
 66 {
 67     ONE_WIRE_WRITE_PREPARE_STATE = 0,
 68     ONE_WIRE_WRITE_TIME_STATE = 1,
 69     ONE_WIRE_WRITE_CONTINUE_STATE = 2,
 70     ONE_WIRE_WRITE_END_STATE = 3,
 71 }one_wire_write_state_t;
 72 
 73 /* 讀狀態類型 */
 74 typedef enum
 75 {
 76     ONE_WIRE_READ_PREPARE_STATE = 0,
 77     ONE_WIRE_READ_TIME_STATE = 1,
 78     ONE_WIRE_READ_CONTINUE_STATE = 2,
 79     ONE_WIRE_READ_END_STATE = 3,
 80 }one_wire_read_state_t;
 81 
 82 /*-----------------------------------------------------------------------------
 83                             global
 84 -----------------------------------------------------------------------------*/
 85 static one_wire_config one_wire = { GPIO0,
 86                                     gpio_pin_0,
 87                                     UART1_TX_PAD,
 88                                     THIRD_FUNCTION };/*!< 默認GPIO配置 */
 89 
 90 static one_wire_state_t one_wire_state;/*!< 整體狀態 */
 91 static one_wire_reset_state_t one_wire_reset_state;/*!< 復位狀態 */
 92 static one_wire_write_state_t one_wire_write_state;/*!< 寫數據狀態 */
 93 static one_wire_read_state_t one_wire_read_state;/*!< 讀數據狀態 */
 94 
 95 SemaphoreHandle_t one_wire_lock;/*!< 互斥信號量 */
 96 
 97 static uint8_t one_wire_data;/*!< 讀寫數據臨時變量 */
 98 
 99 /*-----------------------------------------------------------------------------
100                             declare
101 -----------------------------------------------------------------------------*/
102 
103 /*-----------------------------------------------------------------------------
104                             function
105 -----------------------------------------------------------------------------*/
106 /**
107  * @brief 毫秒級延時
108  *
109  * @param us 毫秒數
110  */
111 static void one_wire_delay_us(uint32_t us)
112 {
113     /* 毫秒級延時 */
114     timer_set_count(ONE_WIRE_TIMER,us * ONE_WIRE_TIMER_US);
115     timer_start(ONE_WIRE_TIMER);
116 }
117 
118 /**
119  * @brief 初始化
120  *
121  */
122 int8_t one_wire_init(one_wire_config* config)
123 {
124     if(NULL != config)
125     {
126         /* 保存配置信息 */
127         one_wire.one_wire_gpio_group = config->one_wire_gpio_group;
128         one_wire.one_wire_gpio_pin = config->one_wire_gpio_pin;
129         one_wire.one_wire_gpio_pad = config->one_wire_gpio_pad;
130         one_wire.one_wire_gpio_func = config->one_wire_gpio_func;
131     }
132     /* 初始化GPIO */
133     Scu_SetDeviceGate((unsigned int)one_wire.one_wire_gpio_group,ENABLE);
134     Scu_Setdevice_Reset((unsigned int)one_wire.one_wire_gpio_group);
135     Scu_Setdevice_ResetRelease((unsigned int)one_wire.one_wire_gpio_group);
136     Scu_SetIOReuse(one_wire.one_wire_gpio_pad,one_wire.one_wire_gpio_func);
137     /* 初始化TIMER */
138     Scu_SetDeviceGate(ONE_WIRE_TIMER,ENABLE);
139     Scu_Setdevice_Reset(ONE_WIRE_TIMER);
140     Scu_Setdevice_ResetRelease(ONE_WIRE_TIMER);
141     __NVIC_SetVector(ONE_WIRE_TIMER_IRQ,(uint32_t)one_wire_timer_handler);
142     NVIC_EnableIRQ(ONE_WIRE_TIMER_IRQ);
143     timer_init_t init;
144     init.mode = timer_count_mode_single;
145     init.div = timer_clk_div_0;
146     init.width = timer_iqr_width_2;
147     init.count = 0xFFFFFFFF;
148     timer_init(ONE_WIRE_TIMER,init);
149     one_wire_lock = xSemaphoreCreateCounting(1,0);
150     if(NULL == one_wire_lock)
151     {
152         return RETURN_ERR;
153     }
154     return RETURN_OK;
155 }
156 
157 /**
158  * @brief 發送復位信號
159  *
160  */
161 void one_wire_reset(void)
162 {
163     one_wire_state = ONE_WIRE_RESET_STATE;
164     one_wire_reset_state = ONE_WIRE_RESET_PREPARE_STATE;
165     one_wire_delay_us(1);
166     xSemaphoreTake(one_wire_lock,portMAX_DELAY);
167 }
168 
169 /**
170  * @brief 寫一個byte
171  *
172  * @param data 數據
173  */
174 static void one_wire_write_byte(uint8_t data)
175 {
176     one_wire_state = ONE_WIRE_WRITE_STATE;
177     one_wire_write_state = ONE_WIRE_WRITE_PREPARE_STATE;
178     one_wire_data = data;
179     one_wire_delay_us(1);
180     xSemaphoreTake(one_wire_lock,portMAX_DELAY);
181 }
182 
183 /**
184  * @brief 讀一個byte
185  *
186  * @return uint8_t data
187  */
188 static uint8_t one_wire_read_byte(void)
189 {
190     one_wire_state = ONE_WIRE_READ_STATE;
191     one_wire_read_state = ONE_WIRE_READ_PREPARE_STATE;
192     one_wire_delay_us(1);
193     xSemaphoreTake(one_wire_lock,portMAX_DELAY);
194     return one_wire_data;
195 }
196 
197 /**
198  * @brief 寫數據
199  *
200  * @param data 數據
201  * @param len 長度
202  */
203 void one_wire_write(uint8_t *data,uint32_t len)
204 {
205     for (int i = 0; i < len; i++)
206     {
207         one_wire_write_byte(data[i]);
208     }
209 }
210 
211 /**
212  * @brief 讀數據
213  *
214  * @param data 數據
215  * @param len 長度
216  */
217 void one_wire_read(uint8_t *data,uint32_t len)
218 {
219     memset(data,0,len);
220     for (int i = 0; i < len; i++)
221     {
222         data[i] = one_wire_read_byte();
223     }
224 }
225 
226 /**
227  * @brief TIMER中斷處理函數
228  *
229  */
230 void one_wire_timer_handler(void)
231 {
232     static uint8_t count = 0;
233     switch (one_wire_state)
234     {
235     /* 發送復位信號流程 */
236     case ONE_WIRE_RESET_STATE:
237         switch (one_wire_reset_state)
238         {
239         case ONE_WIRE_RESET_PREPARE_STATE:
240             gpio_set_output_mode(one_wire.one_wire_gpio_group,one_wire.one_wire_gpio_pin);
241             gpio_set_output_low_level(one_wire.one_wire_gpio_group,one_wire.one_wire_gpio_pin);
242             one_wire_delay_us(ONE_WIRE_SEND_RESET_TIMER_US);
243             one_wire_reset_state = ONE_WIRE_RESET_TIME_STATE;
244             break;
245         case ONE_WIRE_RESET_TIME_STATE:
246             gpio_set_input_mode(one_wire.one_wire_gpio_group,one_wire.one_wire_gpio_pin);
247             one_wire_delay_us(ONE_WIRE_READ_RESPOND_TIMER_US);
248             one_wire_reset_state = ONE_WIRE_RESET_CONTINUE_STATE;
249             break;
250         case ONE_WIRE_RESET_CONTINUE_STATE:
251             if(gpio_get_input_level_single(one_wire.one_wire_gpio_group,one_wire.one_wire_gpio_pin))
252             {
253                 mprintf("從機未響應 %s %d\n",__FILE__,__LINE__);
254                 return;
255             }
256             one_wire_delay_us(ONE_WIRE_RESPOND_CONTINUE_TIMER_US - ONE_WIRE_READ_RESPOND_TIMER_US);
257             one_wire_reset_state = ONE_WIRE_RESET_END_STATE;
258             break;
259         case ONE_WIRE_RESET_END_STATE:
260             xSemaphoreGiveFromISR(one_wire_lock,NULL);
261             break;
262         default:
263             break;
264         }
265         break;
266     /* 發送寫數據信號流程 */
267     case ONE_WIRE_WRITE_STATE:
268         switch (one_wire_write_state)
269         {
270         case ONE_WIRE_WRITE_PREPARE_STATE:
271             gpio_set_output_mode(one_wire.one_wire_gpio_group,one_wire.one_wire_gpio_pin);
272             gpio_set_output_low_level(one_wire.one_wire_gpio_group,one_wire.one_wire_gpio_pin);
273             one_wire_delay_us(ONE_WIRE_WRITE_PREPARE_TIMER_US);
274             one_wire_write_state = ONE_WIRE_WRITE_TIME_STATE;
275             break;
276         case ONE_WIRE_WRITE_TIME_STATE:
277             if(one_wire_data)
278             {
279                 gpio_set_input_mode(one_wire.one_wire_gpio_group,one_wire.one_wire_gpio_pin);
280             }
281             one_wire_delay_us(ONE_WIRE_WRITE_TIMER_US - ONE_WIRE_WRITE_PREPARE_TIMER_US);
282             one_wire_write_state = ONE_WIRE_WRITE_CONTINUE_STATE;
283             break;
284         case ONE_WIRE_WRITE_CONTINUE_STATE:
285             one_wire_delay_us(ONE_WIRE_WRITE_CONTINUE_TIMER_US - ONE_WIRE_WRITE_TIMER_US - ONE_WIRE_WRITE_PREPARE_TIMER_US);
286             count++;
287             if(8 != count)
288             {
289                 one_wire_write_state = ONE_WIRE_WRITE_PREPARE_STATE;
290             }
291             else
292             {
293                 one_wire_write_state = ONE_WIRE_WRITE_END_STATE;
294                 count = 0;
295             }
296             break;
297         case ONE_WIRE_WRITE_END_STATE:
298             xSemaphoreGiveFromISR(one_wire_lock,NULL);
299             break;
300         default:
301             break;
302         }
303         break;
304     /* 發送讀數據信號流程 */
305     case ONE_WIRE_READ_STATE:
306         switch (one_wire_read_state)
307         {
308         case ONE_WIRE_READ_PREPARE_STATE:
309             one_wire_data = 0;
310             gpio_set_output_mode(one_wire.one_wire_gpio_group,one_wire.one_wire_gpio_pin);
311             gpio_set_output_low_level(one_wire.one_wire_gpio_group,one_wire.one_wire_gpio_pin);
312             one_wire_delay_us(ONE_WIRE_READ_PREPARE_TIMER_US);
313             one_wire_read_state = ONE_WIRE_READ_TIME_STATE;
314             break;
315         case ONE_WIRE_READ_TIME_STATE:
316             one_wire_delay_us(ONE_WIRE_READ_TIMER_US - ONE_WIRE_READ_PREPARE_TIMER_US);
317             one_wire_read_state = ONE_WIRE_READ_CONTINUE_STATE;
318             break;
319         case ONE_WIRE_READ_CONTINUE_STATE:
320             one_wire_data |= gpio_get_input_level_single(one_wire.one_wire_gpio_group,one_wire.one_wire_gpio_pin) << count;
321             one_wire_delay_us(ONE_WIRE_READ_CONTINUE_TIMER_US - ONE_WIRE_READ_TIMER_US - ONE_WIRE_READ_PREPARE_TIMER_US);
322             count++;
323             if(8 != count)
324             {
325                 one_wire_read_state = ONE_WIRE_READ_PREPARE_STATE;
326             }
327             else
328             {
329                 one_wire_read_state = ONE_WIRE_READ_END_STATE;
330                 count = 0;
331             }
332             break;
333         case ONE_WIRE_READ_END_STATE:
334             xSemaphoreGiveFromISR(one_wire_lock,NULL);
335             break;
336         default:
337             break;
338         }
339         break;
340     default:
341         break;
342     }
343 }

one_wire.h

/**
 * @file one_wire.h
 * @brief DHT11傳感器的頭文件
 * @version 0.1
 * @date 2019-07-02
 *
 * @copyright Copyright (c) 2019
 *
 */

#ifndef __ONE_WIRE_H__
#define __ONE_WIRE_H__

/**
 * @ingroup components
 * @defgroup one_wire 單總線
 * @brief 單總線組件
 * @{
 */

#ifdef __cplusplus
extern "C" {
#endif

/*-----------------------------------------------------------------------------
                            include
-----------------------------------------------------------------------------*/
#include "stdint.h"
#include "string.h"
#include "ci110x_timer.h"
#include "ci110x_gpio.h"
#include "ci110x_scu.h"
#include "ci_log.h"

/*-----------------------------------------------------------------------------
                            define
-----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
                            extern
-----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
                        struct / enum / union
-----------------------------------------------------------------------------*/
/* 單總線配置結構體 */
typedef struct
{
    gpio_base_t one_wire_gpio_group;/*!< GPIO組 */
    gpio_pin_t one_wire_gpio_pin;/*!< GPIO_PINX */
    PinPad_Name one_wire_gpio_pad;/*!< PAD名稱 */
    IOResue_FUNCTION one_wire_gpio_func;/*!< 第幾功能是GPIO */
}one_wire_config;

/*-----------------------------------------------------------------------------
                            global
-----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
                        function declare
-----------------------------------------------------------------------------*/
int8_t one_wire_init(one_wire_config* config);
void one_wire_reset(void);
void one_wire_write(uint8_t *data,uint32_t len);
void one_wire_read(uint8_t *data,uint32_t len);
void one_wire_timer_handler(void);

#ifdef __cplusplus
}
#endif

/**
 * @}
 */

#endif

/*-----------------------------------------------------------------------------
                            end of the file
-----------------------------------------------------------------------------*/

                                                                    ------脫命散人 2019.9.2 [記]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM