本实验所要实现的功能是:系统开启时首先检测 DS18B20 温度传感器是否存在,若存在输出相应的提示信息,然后间隔 500ms 读取一次 DS18B20 的温度,并通过串口打印输出,最后让 D1 指示灯不断闪烁,提示系统正常运行。程序框架如下: (1)初始化 DS18B20 (2)编写读取温度函数 (3)编写主函数 因为 DS18B20 是单总线通信,所以需要使用 STM32F1 的 PG11 管脚模拟单总线时序,单总线相关时序在前面已经介绍。下面我们打开“DS18B20 温度传感器实验”工程,在 APP 工程组中添加ds18b20.c 文件(里面包含了 DS18B20 驱动程序),同时还要包含对应的头文件路径。 要使用 PG11 管脚模拟单总线时序,就必须使能端口时钟及初始化 GPIO。初始化代码如下: - /****************************************************************, q: o, z2 G. c3 I) H% V7 O9 v
- * 函 数 名 : DS18B20_Init
! C' ]: H: [$ }' c! p6 ]4 N _8 ^ - * 函数功能 : 初始化 DS18B20 的 IO 口 DQ 同时检测DS的存在
; |( k1 n" }( ~ Z- ?. } - * 输 入 : 无) a4 U' P: v8 ^+ m# [4 c5 J3 z
- * 输 出 : 1:不存在,0:存在; p: C! O2 `2 O$ Q7 L }
- *****************************************************************/
1 E' {* Q! W9 P- f - u8 DS18B20_Init(void)% |/ Q4 T. c G
- {" j2 D" V6 R$ c; f; [3 \/ ?
- GPIO_InitTypeDef GPIO_InitStructure;8 `! c; S- u; v: e6 \- \
- RCC_APB2PeriphClockCmd(DS18B20_PORT_RCC,ENABLE);5 l' J6 y }1 v5 W+ V) Q% B3 ?
- GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;
/ l$ X6 d3 g1 v: L- N5 A- x - GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
$ V2 ~: n) x( r' `$ Q - GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;! d2 u$ ^( o. [, e, y& t* K
- GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);. O; L3 F2 k5 |* m _* S
- DS18B20_Reset();
) C4 c. N5 {! f$ u: c# A4 N2 }3 k5 | - return DS18B20_Check();
1 P' H& ^# ]; \" i3 W. y/ W4 ]/ x J - }
复制代码
, {3 R4 t8 k3 i5 {6 L* z) r( _" P
该函数带有一个返回值,如果返回值为 1 表示 DS18B20 初始化失败,返回值为 0表示初始化成功。函数返回值其实就是通过调用 DS18B20_Check函数获得,此函数用来检测DS18B20是否存在。初始化函数内还调用了DS18B20_Reset函数,这两个函数其实就是根据前面介绍的初始化时序编写,对应的代码如下: - /****************************************************************& G q, n* m1 D3 w' P5 J
- * 函 数 名 : DS18B20_Reset3 ?" \6 l+ ]1 s0 u$ j X
- * 函数功能 : 复位 DS18B20% [' Q+ [2 Z. H
- * 输 入 : 无4 ` y' q3 N7 y4 Y( ?
- * 输 出 : 无5 V, M+ X/ j! ?( h0 Q! _6 |
- *****************************************************************/
3 u9 z6 r2 y- ?0 [9 t - void DS18B20_Reset(void)
* K! A6 u6 h2 G7 F% ?- m0 n - {. @6 }0 c( F3 h# X- L8 I2 E8 b
- DS18B20_IO_OUT(); //SET PG11 OUTPUT
M- X, E+ G$ j- M - DS18B20_DQ_OUT=0; //拉低 DQ
1 r; j5 y7 W! k8 B ? - delay_us(750); //拉低 750us
' V0 ]4 v, Q- T6 t! Y - DS18B20_DQ_OUT=1; //DQ=1
0 v3 W ]7 \) F# w5 J - delay_us(15); //15US
; h& ]/ `0 y2 X% i - }
复制代码- /****************************************************************
G8 \' Y/ E, E. H; \; d6 u - * 函 数 名 : DS18B20_Check
# g+ |/ z7 W( ]* I. M - * 函数功能 : 检测 DS18B20 是否存在
2 C \2 e4 x% ?' \ - * 输 入 : 无
1 O( k6 a2 x# s' U4 l3 l, | - * 输 出 : 1:未检测到 DS18B20 的存在,0:存在
2 k9 A* l/ Y* u b \ - *****************************************************************/ _( W8 V. d$ l& j7 {
- u8 DS18B20_Check(void)8 w0 ]; ?9 n6 q5 g4 l: l
- {: q& ~8 Q- B! a9 q% b8 n* |4 J
- u8 retry=0;3 z$ |" c" L+ p1 G8 t
- DS18B20_IO_IN();//SET PG11 INPUT
3 P3 @; W4 U; ~$ k - while (DS18B20_DQ_IN&&retry<200)
2 r7 T% L& O( e3 ^' M6 \0 u1 { - {
3 h: A' R9 M, w- |! c - retry++;+ o1 d+ \& ]" l& ~; f
- delay_us(1);
/ X: L3 z5 R: I - };
/ J* Z @" X# s0 ?# d: j - if(retry>=200)return 1;' H1 z9 I0 Y5 l
- else retry=0;
# Q1 v6 j( {! L. I, c - while (!DS18B20_DQ_IN&&retry<240)
4 q1 ^) u) s6 R% z) o2 b9 D1 ^ - {
# y- o( ?) z c8 {1 ~ - retry++;
1 K, M! j* h' A( x5 u7 M/ v/ y u - delay_us(1);
2 K) }* ?# W. C* X, I8 G2 J. ?) X5 ~ - };
3 z# L6 E% p" e; d* U. V3 _2 j( J) z - if(retry>=240)return 1;
0 O" T% J" [- _# e" g6 t - return 0;
( S, _, U4 y( y! I/ Z - }
复制代码
! o3 E# P }+ l
由于采用单总线,所以数据的写入和读取都是在 PG11 引脚上完成,所以当写入数据的时候需要配置此引脚为输出模式, 当读取数据的时候需要配置此引脚为输入模式,因此会有以下两个函数: - /****************************************************************
$ J+ k) p9 ?3 }! D- s - * 函 数 名 : DS18B20_IO_IN
* ]0 o! u1 e5 I) w6 a - * 函数功能 : DS18B20_IO 输入配置: Y& w) C3 P; V' D
- * 输 入 : 无
9 R( m& e3 Y, n6 W$ f- W - * 输 出 : 无1 H9 l4 h1 W, p* |+ a
- *****************************************************************/
2 n3 [! l2 Q* a; ^ - void DS18B20_IO_IN(void)8 n( Y) f8 Y, ?% ~6 X- X
- {
+ p6 {5 K7 {: m' @6 j, ]8 c# c( a - GPIO_InitTypeDef GPIO_InitStructure;
: z5 A# o9 Y) J' _% _- m* D - GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;6 r7 p% ` g7 `' O/ z
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
2 s! K6 H, F. Y& d3 ~' r. R4 B( z - GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);" q( ~. h+ ?8 V: f1 J& A
- }
复制代码- /****************************************************************
3 J$ z+ A+ Q* D8 m2 e' I - * 函 数 名 : DS18B20_IO_OUT2 {8 p: D/ C. A
- * 函数功能 : DS18B20_IO 输出配置/ G) F: w8 q6 C& D6 v
- * 输 入 : 无7 e' H; O6 | @* s) ]
- * 输 出 : 无) |6 a0 w7 t) X( q
- *****************************************************************/
, N$ A: k$ O& j! O - void DS18B20_IO_OUT(void). E* ], r5 d/ D+ l2 i
- {
' B( S, d% M% K# i9 g! H - GPIO_InitTypeDef GPIO_InitStructure;
( z" b. a& ?- N) ^8 b# \( w - GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;
4 c! e( _, V m# m d. X6 ?; _ - GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
6 o3 K3 M# \0 t. R7 i- N# x3 c - GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
3 A' V6 R, \& a: m* z; t - GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);) p! d; z# z; V. Y% b
- }
复制代码
) v% u' F8 `! C) ?+ d1 g1 Y 其实也可以直接使用寄存器来配置管脚的模式,可参考 GPIO寄存器部分。 6 c$ X- A; c- P/ ]+ p
|