單總線:
單總線是美國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 [記]