使用8086汇编驱动SHT11传感器
前言:使用Proteus 7.8仿真软件实现8086接入SHT11温湿度传感器(实现读取温度数据部分功能),并学习如何在没有集成硬件控制下串行总线的驱动方式,汇编的精髓就是寄存器的操作、各种寻址方式、位操作、对内存和栈的理解。
本文参考博客:
https://www.cnblogs.com/zhaoming510/p/3935248.html
关于串行总线通信协议,推荐比较好的帖子:
http://m.elecfans.com/article/574049.html
一、电路连接:
首先按照如图所示的电路实现8086最小系统和SHT11驱动与显示电路(一片8255a):
二、数据手册关键信息提取:
说明一下,从SHT11读取的信息并不能直接得到温度信息,还要经过公式转换,校验的工作也比较复杂,所以这里就省略了。
1、SHT11电路连接:SHT11接口类似与IIC,硬件是可以兼容的,但是协议不兼容
2、SHT11启动时序:SHT11启动时序比IIC的START信号要复杂的多了
3、SHT11命令集:这里我们只要温度测量的命令也就是00011
4、直接复位的时序,每次读取完数据还要读CRC-8 Checksum,这个就有点麻烦了,仿真软件基本可以确保数据有效性,但实际中校验还是有必要的。
5、手册中推荐的工作时序:我们直接用上图的重启时序跳过Checksum,注意这里有主机要接受ACK信号,程序里没有体现出来,但这里处理一下比较好
三、编写代码:
经验总结:
1、结合时序图,可以先写小段程序验证一下,看是否能够得到想要的波形,这里需要用到虚拟示波器。
2、实现数据到波形或者波形到数据需要灵活运用位操作。
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 ; 3 ;;;;程序功能 :8086 驱动SHT11温湿传感器 (用I/O口对串行总线时序进行模拟) 4 ; 5 ;;;;传感器接入 :SCK 时钟信号(8255A PC0) DATA 数据信号(接8255A PC4) (与IIC总线时序的SCL、SDL不兼容) 6 ; 7 ;;;;运行模式 :12BIT数据读取(忽略CRC-8校验和、通讯复位命令截断) 8 ; 9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 10 11 IOY0 EQU 0C400H ;片选IOY0对应的端口始地址 0000 11000 1000 0000 0000 (A15,A14,A10=1) 12 IOY1 EQU 0C440H 13 14 IOA EQU IOY0+00H*4 ;8255的A口地址 15 IOB EQU IOY0+01H*4 ;8255的B口地址 16 IOC EQU IOY0+02H*4 ;8255的C口地址 17 CTRL EQU IOY0+03H*4 ;8255的控制寄存器地址 18 19 RH EQU 00000101B ;SHT11命令字 20 21 CODE SEGMENT 22 ASSUME CS:CODE,DS:CODE ;代码段定义 23 24 START: MOV AX,CODE 25 MOV DS,AX 26 LEA SP,SEGTAB ;取出偏移地址放入栈顶指针寄存器(使用栈) 27 28 MOV SI,5000H ;在缓存区(内存) 用于保存待显示在数码管上的信息 29 MOV WORD PTR [SI], 0AH 30 MOV WORD PTR [SI+2],0AH 31 MOV WORD PTR [SI+4],0AH 32 MOV WORD PTR [SI+6],0AH 33 34 MOV AL,10000000B ;C口输出 35 MOV DX,CTRL 36 OUT DX,AL 37 DISP: 38 CALL DALLY ;显示信息 39 40 CALL INIT_SHT11 ;SHT11启动时序 41 42 CALL WRITE_CW ;写入命令字 43 CALL ACK_CW ;传感器(SHT11)应答 44 45 CALL DALLY 46 47 CALL WAIT_DATA ;等待数据产生 48 CALL READ_DATA_H ;读取高4(8)位 49 CALL ACK_READ ;CPU(8086)应答 50 CALL READ_DATA_L ;读取低8位 51 52 CALL DALLY 53 54 CALL RESTART_SHT11 ;发送重连信号 56 CALL SEG_LED_DATA ;数据处理 57 58 JMP DISP 59 60 DALLY PROC NEAR ;软件延时子程序 61 CALL CLEAR 62 CALL DIS 63 PUSH CX 64 MOV CX,000FH 65 D1: MOV AX,000FH 66 D2: DEC AX 67 JNZ D2 68 LOOP D1 69 POP CX 70 RET 71 DALLY ENDP 72 73 CLEAR PROC NEAR ;清除数码管显示子程序 74 MOV DX,IOB ;段位置0即可清除数码管显示 75 MOV AL,00H 76 OUT DX,AL 77 RET 78 CLEAR ENDP 79 80 DIS PROC NEAR ;显示键值子程序 81 PUSH AX 82 PUSH SI 83 MOV SI,5006H 84 MOV DL,0F7H 85 MOV AL,DL 86 AGAIN: PUSH DX 87 MOV DX,IOA 88 OUT DX,AL ;设置X1~X4,选通一个数码管 89 MOV AL,[SI] ;取出缓冲区中存放键值 90 MOV BX,OFFSET SEGTAB 91 AND AX,00FFH 92 ADD BX,AX 93 MOV AL,[BX] 94 MOV DX,IOB 95 OUT DX,AL ;写入数码管A~DP 96 CALL DALLY1 97 DEC SI 98 DEC SI ;取下一个键值 99 POP DX 100 MOV AL,DL 101 TEST AL,01H ;判断是否显示完? 102 JZ OUT1 ;显示完,返回 103 ROR AL,1 104 MOV DL,AL 105 JMP AGAIN ;未显示完,跳回继续 106 OUT1: POP SI 107 POP AX 108 RET 109 DIS ENDP 110 111 DALLY1 PROC NEAR ;软件延时子程序 112 PUSH CX 113 MOV CX,002FH 114 D3: MOV AX,002FH 115 D4: DEC AX 116 JNZ D4 117 LOOP D3 118 POP CX 119 RET 120 DALLY1 ENDP 121 122 123 INIT_SHT11 PROC NEAR ;启动时序生成 124 125 MOV DX,IOC 126 MOV AL,11H 127 OUT DX,AL 128 129 MOV AL,01H 130 OUT DX,AL 131 132 MOV AL,00H 133 OUT DX,AL 134 135 MOV AL,01H 136 OUT DX,AL 137 138 MOV AL,11H 139 OUT DX,AL 140 141 MOV AL,10H 142 OUT DX,AL 143 144 RET 145 146 INIT_SHT11 ENDP 147 148 WRITE_CW PROC NEAR ;(手动加精)发送控制字 149 150 MOV CX,08 151 MOV DX,IOC 152 MOV BL,RH 153 LP0: 154 SHL BL,1 155 MOV AL,00H 156 JNC EXIT0 157 MOV AL,10H 158 EXIT0: 159 OUT DX,AL 160 161 AND AL,10H 162 OUT DX,AL ;写完1位数据将时钟线拉低,等待发送 163 164 OR AL,01H 165 OUT DX,AL ;时钟线上升沿,发送1位数据 166 ;等待1位数据发送完成 167 LOOP LP0 168 169 RET 170 171 WRITE_CW ENDP 172 173 ACK_CW PROC NEAR ;写入控制字后SHT11发送应答型号 174 ;C口高四位输入,C口低四位输出 175 MOV AL,10001000B 176 MOV DX,CTRL 177 OUT DX,AL 178 179 MOV DX,IOC 180 181 MOV AL,10H 182 OUT DX,AL ;8位数据发送完成,DATA线拉高 183 184 MOV AL,11H ;时钟线拉高 185 OUT DX,AL 186 187 MOV AL,10H 188 OUT DX,AL ;数据线拉高,时钟线拉低,等待转换完成 189 190 RET 191 192 ACK_CW ENDP 193 194 WAIT_DATA PROC NEAR 195 196 MOV DX,IOC 197 R: 198 IN AL,DX 199 TEST AL,10H ;等待数据线被拉低 200 JNZ R 201 202 RET 203 204 WAIT_DATA ENDP 205 206 READ_DATA_H PROC NEAR ;读取高4(8)位 207 208 MOV CX,08 209 MOV DX,IOC 210 LP1: 211 MOV AL,01H 212 OUT DX,AL ;时钟上升沿后,读取数据线 213 214 IN AL,DX 215 TEST AL,10H ;数据有效位C4 216 MOV AL,0 217 JZ EXIT1 218 INC AL 219 EXIT1: 220 DEC CL 221 SHL AL,CL 222 ADD DATA_H,AL 223 INC CL 224 225 MOV AL,00H ;时钟下降沿 226 OUT DX,AL 227 OUT DX,AL 228 OUT DX,AL ;维持低电平 229 230 LOOP LP1 231 232 RET 233 234 READ_DATA_H ENDP 235 236 237 ACK_READ PROC NEAR ;CPU(8086)应答 238 239 MOV AL,10000000B ;C口输出 240 MOV DX,CTRL 241 OUT DX,AL 242 243 MOV DX,IOC 244 245 MOV AL,00H 246 OUT DX,AL 247 248 MOV AL,01H ;数据线拉低,时钟线拉高才生应答信号 249 OUT DX,AL 250 OUT DX,AL 251 OUT DX,AL 252 253 MOV AL,00H 254 OUT DX,AL 255 256 MOV AL,10001000B ;C口高四位输入,C口低四位输出 257 MOV DX,CTRL 258 OUT DX,AL 259 RET 260 261 ACK_READ ENDP 262 263 READ_DATA_L PROC NEAR ;读取低8位 264 265 MOV CX,08 266 MOV DX,IOC 267 LP2: 268 MOV AL,01H 269 OUT DX,AL 270 271 IN AL,DX 272 TEST AL,10H 273 MOV AL,0 274 JZ EXIT2 275 INC AL 276 EXIT2: 277 DEC CL 278 SHL AL,CL 279 ADD DATA_L,AL 280 INC CL 281 282 MOV AL,00H 283 OUT DX,AL 284 OUT DX,AL 285 OUT DX,AL 286 LOOP LP2 287 288 RET 289 290 READ_DATA_L ENDP 291 292 RESTART_SHT11 PROC NEAR 293 294 MOV AL,10000000B ;C口输出 295 MOV DX,CTRL 296 OUT DX,AL 297 298 MOV DX,IOC 299 MOV CX,9 300 LP3: 301 MOV AL,10H 302 OUT DX,AL 303 304 MOV AL,11H 305 OUT DX,AL ;数据线保持高电平,时钟9次触发以复位串口 306 307 LOOP LP3 308 309 RET 310 311 RESTART_SHT11 ENDP 312 313 SEG_LED_DATA PROC NEAR 314 315 MOV AH,DATA_H 316 MOV AL,DATA_L 317 318 MOV CX,4 319 MOV BX,10 320 MOV SI,5006H 321 LP4: 322 XOR DX,DX 323 DIV BX 324 325 MOV [SI],DL 326 DEC SI 327 DEC SI 328 329 LOOP LP4 330 331 MOV DATA_H,0 332 MOV DATA_L,0 333 334 RET 335 336 SEG_LED_DATA ENDP 337 338 DW 256 DUP(?) 339 SEGTAB DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H 340 341 DATA_H DB 00H 342 DATA_L DB 00H 343 DATA_T DB 01H 344 DATA_S DW 0000H 345 346 CODE ENDS 347 END START
运行效果:
由于8086不支持浮点运算,对应的数据可以通过手册的公式和表格另行计算: