单总线解析与DS2401驱动程序设计
1 单总线协议(1-wire)
定义:主机和从机通过1根线进行通信,在一条总线上可挂接的从器件数量几乎不受限制。特点:这是由达拉斯半导体公司推出的一项通信技术。它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向的。优点:单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等。
注意:总线上拉电阻选择
2 单总线通信过程
2.1 初始化
初始化过程 = 复位脉冲 + 从机应答脉冲。
主机通过拉低单总线480 ~ 960 us产生复位脉冲,然后释放总线,进入接收模式。主机释放总线时,会产生低电平跳变为高电平的上升沿,单总线器件检测到上升沿之后,延时15 ~ 60 us,单总线器件拉低总线60 ~ 240 us来产生应答脉冲。主机接收到从机的应答脉冲说明单总线器件就绪,初始化过程完成。
2.2 写间隙
写间隙有两种,包括写0的时间隙和写1的时间隙。
当数据线拉低后,在15 ~ 60 us的时间窗口内对数据线进行采样。如果数据线为低电平,就是写0,如果数据线为高电平,就是写1。主机要产生一个写1时间隙,就必须把数据线拉低,在写时间隙开始后的15 us内允许数据线拉高。主机要产生一个写0时间隙,就必须把数据线拉低并保持60 us。
2.3 读时间隙
当主机把总线拉低是,并保持至少1 us后释放总线,必须在15 us内读取数据。
3 DS2401简介
DS2401 增强型硅序列号是一款低成本的电子注册码,以最少的电接口(通常只需一个微处理器端口)提供绝对、唯一的识别功能。内含一个工厂刻入的 64 位 ROM,其中包括: 48 位唯一序列码、 8 位 CRC 校验码和 8 位家族码 (01h)。数据采用 1-Wire 协议,仅通过一个信号引线和一个地回路串行传输。用于读取和写入器件的电源可以由数据线本身产生,无需外部供电。
3.1 复位脉冲和在线应答脉冲的复位过程
从下图看知道复位信号是单片机下拉总线480us~960us,然后释放总线,也就是改单片机IO口为输入状态。60us后读取总线时间,读取总线电平必须在释放总线后60us但是不能超过240us时间。如果读取到低电平,那么表示复位成功。
3.2 写 0(Write 0)
主机拉低总线后,需要保持60us以上,但是不能超过120us.
3.3 写 1(Write 1)
主机要产生一个写1时间隙,就必须把数据线拉低,在写时间隙开始后的15 us内允许数据线拉高,15us后从机就开始读取总线的电平,期间不可以改变总线状态。
3.4 读数据(Read Data)
当主机把总线拉低是,并保持至少1 us后释放总线,必须在15 us内读取数据。
4 DS2401驱动程序设计
DS2401 内建 ROM 仅由单根数据线访问。依据 Dallas 的 1-Wire 协议,可以从中提取 48 位序列码, 8 位家族码和 8 位 CRC 校验码。 1-Wire 通信协议规定总线的收发按照特殊时隙下的总线状态进行、由主机发出的同步脉冲下降沿初始化。所有数据读写都按照低位在前的原则。
8 位 CRC 校验码算法设计
1. static unsigned char CRC8Calculate(void *pBuf ,unsigned pBufSize)
2. {
3. unsigned char retCRCValue=0x00;
4. unsigned char *pData;
5. int i=0;
6. unsigned char pDataBuf=0;
7. // retCRCValue=0x01;
8. pData=(unsigned char *)pBuf;
9. // pDataBuf=pData[0];
10. // cout<<hex<<pDataBuf<<endl;
11.
12. while(pBufSize--)
13. {
14. pDataBuf=*pData++;
15. for(i=0;i<8;i++)
16. {
17. if((retCRCValue^(pDataBuf))&0x01)
18. {
19. retCRCValue^=0x18;
20. retCRCValue>>=1;
21. retCRCValue|=0x80;
22. // printf("i=%d;retCRCValue=%x\n",i,retCRCValue);
23. }
24. else
25. {
26. retCRCValue>>=1;
27. // printf("i=%d;retCRCValue=%x\n",i,retCRCValue);
28. }
29. pDataBuf>>=1;
30. }
31.
32. }
33. return retCRCValue;
34. }
1. //the cyclic redundancy check
2. void crc(unsigned char byte)
3. {
4. unsigned char crc,bit0,cbit,r;
5. int i;
6. crc=peekb(0x60);
7. for(i=0;i<=7;i++)
8. {
9. cbit=crc&0x01;
10. bit0=byte&0x01;
11. crc=crc>>1;
12. r=cbit^bit0;
13. if(r==1)
14. {
15. crc=crc^0x8c;
16. }
17. byte=byte>>1;
18. }
19. pokeb(0x60,crc);
20. }
21. //end of crc
接口设计:
1. //******************************DS2401初始化*************************
2.
3. unsigned char DS2401Init(void)
4. {
5. unsigned char result;
6. DelayNus(G);
7. DS2401IO = 0; // Drives DQ low
8. DelayNus(H);
9. DS2401IO = 1; // Releases the bus
10. DelayNus(I);
11. if(DS2401IO==0)
12. result = 1;
13. else
14. result = 0;
15. DelayNus(J); // Complete the reset sequence recovery
16. return result; // Return sample presence pulse result
17. //1代表初始化成功,0代表失败
18. }
19.
20. //******************************发送读写命令*************************
21. void SendOrderToDS2401(unsigned char order)
22. {
23. unsigned char Temp = 8;
24. while(Temp)
25. {
26. if(order&0x80)
27. {
28. DS2401IO = 0;
29. DelayNus(4);//拉低10us
30. DS2401IO = 1;//拉高
31. DelayNus(200);
32. }
33. else
34. {
35. DS2401IO = 0;
36. DelayNus(100);//拉低100us
37. DS2401IO = 1;//拉高
38. DelayNus(200);
39. }
40. Temp--;
41. order<<=1;
42. }
43.
44. }
45.
46. //*****************************对2401写一位数据**********************
47. void DS2401WriteBit(bit b)
48. {
49. if (b)
50. {
51. // Write '1' bit
52. DS2401IO = 0; // Drives DQ low
53. DelayNus(A);
54. DS2401IO = 1; // Releases the bus
55. DelayNus(B); // Complete the time slot and 10us recovery
56. }
57. else
58. {
59. // Write '0' bit
60. DS2401IO = 0; // Drives DQ low
61. DelayNus(C);
62. DS2401IO = 1; // Releases the bus
63. DelayNus(D);
64. }
65. }
66.
67. //*****************************对2401读一位数据**********************
68.
69. unsigned char DS2401ReadBit(void)
70. {
71. unsigned char result;
72. DS2401IO = 0; // Drives DQ low
73. DelayNus(A);
74. DS2401IO = 1; // Releases the bus
75. DelayNus(E);
76. result = DS2401IO ;; // Sample the bit value from the slave
77. DelayNus(F); // Complete the time slot and 10us recovery
78. return result;
79. }
80. //*****************************对2401写一个字节数据**********************
81.
82. void OWWriteByte(int value)
83. {
84. unsigned char loop;
85. for (loop = 0; loop < 8; loop++)
86. {
87. DS2401WriteBit(value & 0x01);
88. value >>= 1;
89. }
90. }
91. //*****************************对2401读一个字节数据**********************
92.
93. unsigned char OWReadByte(void)
94. {
95. unsigned char loop, result=0;
96. for (loop = 0; loop < 8; loop++)
97. {
98. result >>= 1;
99. if (DS2401ReadBit())
100. result |= 0x80;
101. }
102. return result;
103. }
104.
105. //******************************读DS2401 ID 号*************************
106. void ReadDS2401ID(void)
107. {
108.
109. unsigned char Temp=0;
110. while(1)
111. {
112. if(DS2401Init())
113. {
114. DS2401WorkOK = 1;//表示DS2401初始化成功
115. break;
116. }
117. else Temp++;
118. if(Temp>=10)
119. {
120. DS2401WorkOK=0;//初始化10次失败的化,表示DS2401工作不正常
121. break;
122. }
123. }
124. if(DS2401WorkOK)
125. {
126. OWWriteByte(0x33);//发送读命令码
127. for (Temp=0;Temp<8;Temp++)
128. {
129. IDCode[Temp] = OWReadByte();//读一个字节,总共8个
130. }
131. }
132.
133. }