带有存储器功能的数字温度计
DS1624基本原理
DS1624是美国DALLAS公司生产的一款集成了测量系统和存储器功能的芯片,数字接口电路简单且兼容I2C总线。一片控制器最多可控制8片DS1624。该芯片的数字温度输出精度为0.03125℃,达到13位,能在最低2.7V电压下工作,适用于低功耗系统。
DS1624基本特性
1.无需外围元件即可测量温度
2.测量范围为-55℃~+125℃,精度为0.03125℃
3.测量温度的结果以13位数字量(两字节传输)给出
4.测量温度的典型转换时间为1秒
5.集成了256字节的E2PROM非易性存储器
6.数据的读出和写入通过一个2-线(I2C)串行接口完成
7.采用8脚DIP或SOIC封装
引脚描述及功能方框图
DS1624工作原理
温度测量
DS1624采用独特的在线温度测量技术来测量温度。它利用对温度敏感振荡器和对温度不敏感振荡器时钟脉冲计数值的比较来计算温度。初始时,计数器值相当于-55℃,如果在计数周期结束前计数器归零,则温度寄存器中的数字会增加,表示温度高于-55℃。
同时,计数器会重新预置一个值,并开始新的计数,直到再次归零。
通过调整每1℃内计数器的计数,斜坡累加电路可以补偿振荡器的非线性误差,提高精度。为了实现0.03125℃的精度,DS1624会输出13位的温度数据,以及发出读取请求后的两位补偿值。这些数据可以通过2线制串行口按顺序输出,最高位在前,最低位在后。
温度与输出数据关系表
温度 |
数字量输出(二进制) |
数字量输出(十六进制) |
+125℃ |
0111,1101,0000,0000 |
7D00H |
+25.0625℃ |
0001,1001,0001,0000 |
1910H |
+0.5℃ |
0000,0000,1000,0000 |
0080H |
+0℃ |
0000,0000,0000,0000 |
0000H |
-0.5℃ |
1111,1111,1000,0000 |
FF80H |
-25.0625℃ |
1110,0110,1111,0000 |
E6F0H |
-55℃ |
1100,1001,0000,0000 |
C900H |
由于数据在总线上传输时MSB在前,所以DS1624读出的数据可以是一个字节(分辨率为1℃),也可以是两个字节,第二个字节包含的最低位为0.03125℃。
DS1624工作方式
DS1621的工作方式是由片上的配置/状态寄存器来决定的,如表,该寄存器的定义如下:
DS1624芯片有两个重要的控制位:DONE和1SHOT。DONE用于指示转换是否完成,当温度转换结束时,DONE置1;在转换进行中,DONE为0。1SHOT用于选择温度转换模式。当1SHOT为1时,为单次转换模式,即在接收到启动温度转换命令后,DS1624进行一次温度转换。当1SHOT为0时,为连续转换模式,DS1624将持续进行温度转换,并将最近一次的结果保存在温度寄存器中。这两个控制位都是非易失性的,能够保持设置的状态。
片内256字节存储器操作
DS1624的存储器编程有两种模式:字节编程模式和页编程模式。
在字节编程模式下,主控制器向DS1624发送地址和一个字节的数据。通过发送开始信号(START)后,主器件发送写控制字节(1001A2A1A00,其中R/W控制位为低电平“0”)来寻址接收器,DS1624收到后进行应答。接着主器件发送访问存储器指令(17H),DS1624再次应答。接下来,主器件发送下一个字节的字地址,该字地址将被写入DS1624的地址指针。在DS1624再次应答后,主器件发送数据字节并写入目标存储地址。DS1624再次应答后,主器件产生停止条件(STOP),触发内部写周期。在内部写周期中,DS1624不会产生应答信号。
在页编程模式中,与字节编程方式类似,首先发送控制字节、访问存储器指令(17H)和字地址给DS1624。然后,连续发送N个数据字节,其中每8个字节为一页。主器件将不超过一页字节的数据字节发送到DS1624,并暂存在片内页面缓存器中。在发送停止信号后,数据字节将被写入存储器。每接收到一个字节后,低位顺序地址指针在内部递增。高位顺序字地址保持不变。如果主器件在发送多于一页字节的数据之前产生停止条件,地址计数器将循环,并且先接收到的数据将被覆盖。与字节编程操作类似,一旦接收到停止条件,内部写周期将开始。
存储器的读操作
在这种模式下,主控制器可以从DS1624的EEPROM中读取数据。首先发送开始信号(START)后,主器件发送写控制字节(1001A2A1A00),DS1624收到后进行应答。然后主器件发送访问存储器指令(17H),DS1624再次应答。接下来,主器件发送字地址,并将其写入DS1624的地址指针。DS1624再次应答后,主器件不发送停止条件,而是重新发送开始信号(START),接着发送读控制字节(1001A2A1A01)。主器件接收到DS1624的应答之后,开始接收DS1624送出的数据。每接收到一个字节的数据后,主器件都要发送一个应答信号给DS1624。直到主器件发送非应答信号或停止条件,DS1624的数据发送过程才结束。
DS1624的指令集
- 访问存储器指令[17H]:该指令用于访问DS1624的EEPROM存储器,发送该指令后,下一个字节就是要访问的存储器的字地址数据。
- 访问设置寄存器指令[ACH]:当R/W位置0时,该指令用于向设置寄存器写入数据。发送该指令后,接下来的一个字节将被写入设置寄存器。当R/W位置1时,该指令用于从设置寄存器中读取数据。
- 读温度值指令[AAH]:该指令用于读取最后一次测温的结果。DS1624会产生两个字节的数据,即为寄存器内的结果。
- 开始测温指令[EEH]:该命令将启动一次温度测量,不需要再输入数据。在单次测量模式下,可在进行转换的同时使DS1624保持闲置状态。在连续模式下,将启动连续测量。
- 停止测温指令[22H]:该命令用于停止温度测量,不需要再输入数据。这个命令可以用来停止连续测温模式。发出请求后,当前温度测量结束,DS1624将保持闲置状态,直到下一个开始测温的请求发出才会继续进行连续测量。
主机对DS1624写操作通信格式
I2C通信开始 |
主器件发送控制字节(DS1624地址和写操作) |
DS1624应答 |
主器件发送访问DS1624的指令 |
DS1624应答 |
主器件发送的数据字节 |
DS1624应答 |
I2C通信停止 |
|
|
|
|
|
|
|
|
主机对DS1624读操作通信格式
I2C通信开始 |
主器件发送控制字节(DS1624地址和写操作) |
DS1624应答 |
主器件发送访问DS1624的指令 |
DS1624应答 |
I2C通信开始 |
主器件发送控制字节(DS1624地址和读操作) |
DS1624应答 |
数据字节0 |
主机应答 |
数据字节1 |
主机非应答 |
I2C通信停止 |
|
|
|
|
|
|
|
|
|
|
|
|
|
实验任务
用一片DS1624完成本地数字温度的测量,并通过8位数码管显示出测量的温度值。
电路原理图
程序设计内容
(1)由于DS1624是I2C总线结构的串行数据传送,它只需要SDA和SCL两根线完成数据的传送过程。因此,我们在进行程序设计的时候,也得按着I2C协议来对DS1624芯片数据访问。有关I2C协议参看有关资料,这里不详述。对于AT89S51单片机本身没有I2C硬件资源,所以必须用软件来模拟I2C协议过程。
(2)要从DS1624中读取温度值,首先启动DS1624的内部温度A/D开始转换,对应着有相应的命令用来启动开始温度转换,有关DS1624的指令集参考前面的叙述。一般情况下,DS1624经过一次温度的变换,需要经过1秒钟左右的时间,所以等待1秒钟后,即可读取内部的温度值,对于读取的温度值,仍然通过DS1624的指令集来完成温度的读取。但所有有数据的传送过程必须遵循I2C协议。
C语言源程序
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 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 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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
| #include <AT89X52.H> #include <INTRINS.H> unsigned char code displaybit[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f}; unsigned char code displaycode[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71,0x00}; unsigned char code dotcode[32]={0,3,6,9,12,16,19,22, 25,28,31,34,38,41,44,48, 50,53,56,59,63,66,69,72, 75,78,81,84,88,91,94,97}; sbit SDA=P1^6; sbit SCL=P1^7; unsigned char displaybuffer[8]={0,1,2,3,4,5,6,7}; unsigned char eepromdata[8]; unsigned char temperdata[2]; unsigned char timecount; unsigned char displaycount; bit secondflag=0; unsigned char secondcount=0; unsigned char retn; unsigned int result; unsigned char x; unsigned int k; unsigned int ks; void delay(void); void delay10ms(void); void i_start(void); void i_stop(void); void i_init(void); void i_ack(void); bit i_clock(void); bit i_send(unsigned char i_data); unsigned char i_receive(void); bit start_temperature_T(void); bit read_temperature_T(unsigned char *p); void delay(void) { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } void delay10ms(void) { unsigned int i; for(i=0;i<1000;i++) { delay(); } } void i_start(void) { SCL=1; delay(); SDA=0; delay(); SCL=0; delay(); } void i_stop(void) { SDA=0; delay(); SCL=1; delay(); SDA=1; delay(); SCL=0; delay(); } void i_init(void) { SCL=0; i_stop(); } void i_ack(void) { SDA=0; i_clock(); SDA=1; } bit i_clock(void) { bit sample; SCL=1; delay(); sample=SDA; _nop_(); _nop_(); SCL=0; delay(); return(sample); } bit i_send(unsigned char i_data) { unsigned char i; for(i=0;i<8;i++) { SDA=(bit)(i_data & 0x80); i_data=i_data<<1; i_clock(); } SDA=1; return(~i_clock()); } unsigned char i_receive(void) { unsigned char i_data=0; unsigned char i; for(i=0;i<8;i++) { i_data*=2; if(i_clock()) i_data++; } return(i_data); } bit start_temperature_T(void) { i_start(); if(i_send(0x90)) { if(i_send(0xee)) { i_stop(); delay(); return(1); } else { i_stop(); delay(); return(0); } } else { i_stop(); delay(); return(0); } } bit read_temperature_T(unsigned char *p) { i_start(); if(i_send(0x90)) { if(i_send(0xaa)) { i_start(); if(i_send(0x91)) { *(p+1)=i_receive(); i_ack(); *p=i_receive(); i_stop(); delay(); return(1); } else { i_stop(); delay(); return(0); } } else { i_stop(); delay(); return(0); } } else { i_stop(); delay(); return(0); } } void main(void) { P1=0xff; timecount=0; displaycount=0; TMOD=0x21; TH1=0x06; TL1=0x06; TR1=1; ET1=1; ET0=1; EA=1; if(start_temperature_T()) { secondflag=0; secondcount=0; TH0=55536/256; TL0=55536%256; TR0=1; } while(1) { if(secondflag==1) { secondflag=0; TR0=0; if(read_temperature_T(temperdata)) { for(x=0;x<8;x++) { displaybuffer[x]=16; } x=2; result=temperdata[1]; while(result/10) { displaybuffer[x]=result%10; result=result/10; x++; } displaybuffer[x]=result; result=temperdata[0]; result=result>>3; displaybuffer[0]=(dotcode[result])%10; displaybuffer[1]=(dotcode[result])/10; if(start_temperature_T()) { secondflag=0; secondcount=0; TH0=55536/256; TL0=55536%256; TR0=1; } } } } } void t0(void) interrupt 1 using 0 { secondcount++; if(secondcount==100) { secondcount=0; secondflag=1; } TH0=55536/256; TL0=55536%256; } void t1(void) interrupt 3 using 0 { timecount++; if(timecount==4) { timecount=0; if (displaycount==5) { P0=(displaycode[displaybuffer[7-displaycount]] | 0x80); } else { P0=displaycode[displaybuffer[7-displaycount]]; } P2=displaybit[displaycount]; displaycount++; if(displaycount==8) { displaycount=0; } } }
|