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 "freertosFreeRTOS.h"
 17 #include "freertos	ask.h"
 18 #include "freertossemphr.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
",__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 [记]

原文地址:https://www.cnblogs.com/wangyanwen/p/11445326.html