单总线协议
⼀、单总线协议(1-wire)
1.定义:主机和从机⽤⼀根总线进⾏通信,是⼀种半双⼯的通信⽅式,单线=时钟线+数据线+控制线( +电源线)。理想状况下⼀条总线上的从器件数量⼏乎不受数量限制。
2.特点:这是由达拉斯半导体公司推出的⼀项通信技术。它采⽤单根信号线,既可传输时钟,⼜能传输数据,⽽且数据传输是双向的。
3.优点:单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等。
⼆、单总线通信过程
所有的单总线器件要求采⽤严格的通信协议, 以保证数据的完整性。该协议定义了⼏种信号类型:复位脉冲、 应答脉冲、 写0、写1、 读0和读1。所有这些信号,除了应答脉冲以外,都由主机发出同步信号。并且发送所有的命令和数据都是字节的低位在前,这⼀点与多数串⾏通信格式不同(多数为字节的⾼位在前)。
(1)初始化序列:复位和应答脉冲
初始化过程 = 复位脉冲 + 从机应答脉冲。
主机通过拉低单总线480 ~ 960 us产⽣复位脉冲,然后释放总线,进⼊接收模式。主机释放总线时,会产⽣低电平跳变为⾼电平的上升沿,单总线器件检测到上升沿之后,延时15 ~ 60 us,单总线器件拉低总线60 ~ 240 us来产⽣应答脉冲。主机接收到从机的应答脉冲说明单总线器件就绪,初始化过程完成。
初始化时序图如下所⽰:
(2)写间隙
写间隙有两种,包括写0的时间隙和写1的时间隙。
当数据线拉低后,在15 ~ 60 us的时间窗⼝内对数据线进⾏采样。如果数据线为低电平,就是写0,如果数据线为⾼电平,就是写1。主机要产⽣⼀个写1时间隙,就必须把数据线拉低,在写时间隙开始后的15 us内允许数据线拉⾼。主机要产⽣⼀个写0时间隙,就必须把数据线拉低并保持60 us。
写时间隙时序图如下所⽰:
(3)读时间隙
当主机把总线拉低是,并保持⾄少1 us后释放总线,必须在15 us内读取数据。
单总线器件仅在主机发出读时隙时,才向主机传输数, 所以, 在主机发出读数据命令后,必须马上产⽣读时隙,以便从机能够传输数据。所有读时隙⾄少需要 60us, 且在两次独⽴的读时隙之间⾄少需
要 1us的恢复时间,每个读时隙都由主机发起, ⾄少拉低总线 1us (图5所⽰)。在主机发起读时隙之后,单总线器件才开始在总线上发送 0 或1。 若从机发送1,则保持总线为⾼电平;若发送 0, 则拉低总线。当发送 0 时,从机在该时隙结束后释放总线 。由上拉电阻将总线拉回⾄空闲⾼电平状态。从机发出的数据在起始时隙之后,保持有效时间 15us ,因⽽,主机在读时隙期间必须释放总线 ,并且在时隙起始后的 15 us 之内采样总线状态。
读时间隙时序图如下所⽰:
三、单总线实例—DS18B20
当主机对多个DS18B20的某⼀设备进⾏操作时,主机⾸先逐个与挂在总线设备挂接,使⽤搜索ROM(FOh)指令,读出其序列号(33H),然后发送匹配指令(55h),紧接着提供64位序列号,之后就是操作该DS18B20了。
如果只有⼀个DS18B20测温,就不需要搜索ROM、读ROM以及匹配ROM操作了,只需要指令跳过ROM(CCh)指令,就可指令温度转换
(44h)和读取温度(BEh)操作了。#include  "ds18b20.h"#include  "delay.h" //  //实验平台:STM32F103          //  //复位DS18B20void  DS18B20_Rst (void )    {                  DS18B20_IO_OUT ();  //SET PG11 OUTPUT    DS18B20_DQ_OUT =0;  //拉低DQ    delay_us (750);    //拉低750us    DS18B20_DQ_OUT =1;  //DQ=1  delay_us (15);      //15US
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
delay_us (15);      //15US }//等待DS18B20的回应//返回1:未检测到DS18B20的存在//返回0:存在u8 DS18B20_Check (void )    {    u8 retry =0; DS18B20_IO_IN (); //SET PG11 INPUT      while  (DS18B20_DQ_IN &&retry <200) {  retry ++;  delay_us (1); };  if (retry >=200)return  1; else  retry =0;    while  (!DS18B20_DQ_IN &&retry <240) {  retry ++;  delay_us (1); }; if (retry >=240)return  1;      return  0;}//从DS18B20读取⼀个位//返回值:1/0u8 DS18B20_Read_Bit (void )  {    u8 data ; DS18B20_IO_OUT (); //SET PG11 OUTPUT    DS18B20_DQ_OUT =0;  delay_us (2);    DS18B20_DQ_OUT =1;  DS18B20_IO_IN (); //SET PG11 INPUT  delay_us (12); if (DS18B20_DQ_IN )data =1;    else  data =0;      delay_us (50);              return  data ;}//从DS18B20读取⼀个字节//返回值:读到的数据u8 DS18B20_Read_Byte (void )    {            u8 i ,j ,dat ;    dat =0; for 
(i =1;i <=8;i ++)  {        j =DS18B20_Read_Bit ();        dat =(j <<7)|(dat >>1);    }              return  dat ;}//写⼀个字节到DS18B20//dat :要写⼊的字节void  DS18B20_Write_Byte (u8 dat )      {                u8 j ;    u8 testb ; DS18B20_IO_OUT (); //SET PG11 OUTPUT;    for  (j =1;j <=8;j ++)  {        testb =dat &0x01;        dat =dat >>1;        if  (testb )        {
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
{            DS18B20_DQ_OUT =0; // Write 1            delay_us (2);                                        DS18B20_DQ_OUT =1;            delay_us (60);                    }        else          {            DS18B20_DQ_OUT =0; // Write 0            delay_us (60);                        DS18B20_DQ_OUT =1;            delay_us (2);                                  }    }}//开始温度转换void  DS18B20_Start (void ) {                            DS18B20_Rst ();    DS18B20_Check ();      DS18B20_Write_Byte (0xcc ); // skip rom    DS18B20_Write_Byte (0x44); // convert } //初始化DS18B20的IO ⼝ DQ 同时检测DS 的存在//返回1:不存在//返回0:存在      u8 DS18B20_Init (void ){  GPIO_InitTypeDef  GPIO_InitStructure ;    RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOG , ENABLE );  //使能PORTG ⼝时钟    GPIO_InitStructure .GPIO_Pin = GPIO_Pin_11;    //PORTG.11 推挽输出  GPIO_InitStructure .GPIO_Mode = GPIO_Mode_Out_PP ;      GPIO_InitStructure .GPIO_Speed = GPIO_Speed_50MHz ;  GPIO_Init (GPIOG , &GPIO_InitStructure );  GPIO_SetBits (GPIOG ,GPIO_Pin_11);    //输出1 DS18B20_Rst (); return  DS18B20_Check ();}  //从ds18b20得到温度值//精度:0.1C //返回值:温度
值 (-550~1250) short  DS18B20_Get_Temp (void ){    u8 temp ;    u8 TL ,TH ; short  tem ;    DS18B20_Start  ();    // ds1820 start convert    DS18B20_Rst ();    DS18B20_Check ();      DS18B20_Write_Byte (0xcc ); // skip rom    DS18B20_Write_Byte (0xbe ); // convert        TL =DS18B20_Read_Byte ();  // LSB      TH =DS18B20_Read_Byte ();  // MSB              if (TH >7)    {        TH =~TH ;        TL =~TL ;        temp =0;    //温度为负      }else  temp =1;    //温度为正
82
83
84
85
86
87
88
89
90通信协议
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
总结
单总线技术以其线路简单、硬件开销少、成本低廉、软件设计简单优势⽽有着⽆可⽐拟的应⽤前景。基于单总线技术能较好地解决传统识别器普遍存在的携带不便、易损坏、易受腐馈、易受电磁⼲扰等不⾜,可应⽤于⾼度安全的门禁、⾝份识别等领域。其通信可靠简单,很容易实现。因此单总线技术有着⼴阔的应⽤前景,是值得产注的⼀个发展领域。    }else  temp =1;    //温度为正          tem =TH ;      //获得⾼⼋位    tem <<=8;        tem +=TL ;    //获得底⼋位    tem =(float )tem *0.625;  //转换    if (temp )return  tem ;  //返回温度值  else  return  -tem ;    }
147
148
149
150
151
152
153
154
155
156
157#ifndef  __DS18B20_H #define  __DS18B20_H #include  "sys.h"  //            ////IO ⽅向设置#define  DS18B20_IO_IN ()  {GPIOG ->CRH &=0XFFFF0FFF ;GPIOG ->CRH |=8<<12;}#define  DS18B20_IO_OUT () {GPIOG ->CRH &=0XFFFF0FFF ;GPIOG ->CRH |=3<<12;}IO 操作函数              #define  DS18B20_DQ_OUT PGout (11) //数据端⼝ PA0 #define  DS18B20_DQ_IN  PGin (11)  //数据端⼝ PA0    u8 DS18B20_Init (void );//初始化DS18B20short  DS18B20_Get_Temp (void );//获取温度void  DS18B20_Start (void );//开始温度转换void  DS18B20_Write_Byte (u8 dat );//写⼊⼀个字节u8
DS18B20_Read_Byte (void );//读出⼀个字节u8 DS18B20_Read_Bit (void );//读出⼀个位u8 DS18B20_Check (void );//检测是否存在DS18B20void  DS18B20_Rst (void );//复位DS18B20    #endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。