|
本实验所要实现的功能是:系统开启时首先检测 DS18B20 温度传感器是否存在,若存在输出相应的提示信息,然后间隔 500ms 读取一次 DS18B20 的温度,并通过串口打印输出,最后让 D1 指示灯不断闪烁,提示系统正常运行。程序框架如下: (1)初始化 DS18B20 (2)编写读取温度函数 (3)编写主函数 因为 DS18B20 是单总线通信,所以需要使用 STM32F1 的 PG11 管脚模拟单总线时序,单总线相关时序在前面已经介绍。下面我们打开“DS18B20 温度传感器实验”工程,在 APP 工程组中添加ds18b20.c 文件(里面包含了 DS18B20 驱动程序),同时还要包含对应的头文件路径。 要使用 PG11 管脚模拟单总线时序,就必须使能端口时钟及初始化 GPIO。初始化代码如下: - /****************************************************************
* [" I5 |6 j5 E- B6 X - * 函 数 名 : DS18B20_Init
, p) o3 I+ S# e$ N - * 函数功能 : 初始化 DS18B20 的 IO 口 DQ 同时检测DS的存在, _ u, d- | [, I( ]6 M6 Z" G1 ^) X6 V
- * 输 入 : 无9 Z/ T/ I. \. @! n1 @
- * 输 出 : 1:不存在,0:存在6 O5 q1 [9 S; L5 H- T& L9 H; s
- *****************************************************************/
4 d6 z3 o1 @2 g1 T% I, _ - u8 DS18B20_Init(void)' J- v7 u) l; I a# |* d
- {
: j+ I, N/ Z* g- i# p" M - GPIO_InitTypeDef GPIO_InitStructure;
- A3 i3 Q0 ?/ O g O' U3 i - RCC_APB2PeriphClockCmd(DS18B20_PORT_RCC,ENABLE);4 m1 d, H/ N$ w, D- ?
- GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;
: a3 d! m! T+ O4 J+ w/ y - GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; {, I: k1 [* {6 e3 ^
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
d, n7 z' o- ]! Y1 h - GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);5 ], I& ~- Y( {6 P& u* G$ ]
- DS18B20_Reset();/ K ?# E" P4 Q; |0 k
- return DS18B20_Check();
/ z" a" g0 T5 J- G; Y - }
复制代码
2 H8 i7 }2 ^5 z8 @/ Y' m
该函数带有一个返回值,如果返回值为 1 表示 DS18B20 初始化失败,返回值为 0表示初始化成功。函数返回值其实就是通过调用 DS18B20_Check函数获得,此函数用来检测DS18B20是否存在。初始化函数内还调用了DS18B20_Reset函数,这两个函数其实就是根据前面介绍的初始化时序编写,对应的代码如下: - /****************************************************************% a4 z) A" `/ X8 d$ q" D, D5 ~4 e
- * 函 数 名 : DS18B20_Reset
, { k0 a. a2 H/ p8 ~+ j% ` - * 函数功能 : 复位 DS18B20
! ^4 U" Y, P! P% A. d - * 输 入 : 无
1 ^. B m% m! f) v - * 输 出 : 无
8 u: Q3 F! q _: }- |" R) { - *****************************************************************/: j% e! q* ~4 f
- void DS18B20_Reset(void). a- ~9 a, }2 M. j1 G
- { C& d( S# }7 O
- DS18B20_IO_OUT(); //SET PG11 OUTPUT* s: c. W: `: O% ^6 t, \3 e) |
- DS18B20_DQ_OUT=0; //拉低 DQ
: o; F6 ^3 E$ J" H: k3 G - delay_us(750); //拉低 750us+ A% M6 ? I% E$ @5 M; K r% D
- DS18B20_DQ_OUT=1; //DQ=1
7 j. d3 F8 R% T - delay_us(15); //15US5 H: n* V/ j: S! }4 }2 ~
- }
复制代码- /****************************************************************- @' e% O( ?5 T' v# g o9 Y, j( |" Q
- * 函 数 名 : DS18B20_Check
$ |2 k5 N3 J/ N/ g4 {) | - * 函数功能 : 检测 DS18B20 是否存在
( v/ w8 n3 O, G) j - * 输 入 : 无3 f3 n0 f$ J& ]& _
- * 输 出 : 1:未检测到 DS18B20 的存在,0:存在6 z0 N4 s4 b0 N0 ]% s# v& Z% R. }
- *****************************************************************/
+ p; b: {# J$ K5 i% U5 O/ j: Q1 U - u8 DS18B20_Check(void)2 U5 K4 j+ l7 O
- {
r% Z. Z5 m; a0 E, n - u8 retry=0;
' N: }: O. y9 s) k9 k - DS18B20_IO_IN();//SET PG11 INPUT7 @% J% l/ B$ o! H3 W) D& o
- while (DS18B20_DQ_IN&&retry<200)
: L. ]9 k+ e- ]% I* O A! F& r - {: X/ C3 \3 m7 _
- retry++;
( O+ z4 o0 v0 K) t - delay_us(1);
q7 `0 g2 t7 l9 [ e - };
! C: ]$ V6 f5 H3 b5 ` - if(retry>=200)return 1;
# p$ m8 L5 B, g r& w- W - else retry=0;! \# [3 d/ h/ V6 ]1 N
- while (!DS18B20_DQ_IN&&retry<240)5 ?2 u) t. j$ {% Z2 |9 ^
- {' i7 w: S' [: }8 n- g
- retry++;
% {! ]0 m* Z4 j. D+ O - delay_us(1);
# I- n( l. b: x2 r( m, L& G - };
& Y* q7 h. G- C. r' ~. X) ? - if(retry>=240)return 1;
# U" [ x! F7 ?4 N3 q - return 0;
' A& H( I K$ y! b) y - }
复制代码
1 o- y7 V/ Y4 B% A9 |
由于采用单总线,所以数据的写入和读取都是在 PG11 引脚上完成,所以当写入数据的时候需要配置此引脚为输出模式, 当读取数据的时候需要配置此引脚为输入模式,因此会有以下两个函数: - /****************************************************************. O5 b2 |# T- A) b) Y8 B, o+ S$ x9 m
- * 函 数 名 : DS18B20_IO_IN
! V w1 P+ { G. _: w - * 函数功能 : DS18B20_IO 输入配置
7 u8 Z9 I' P( t* n Z - * 输 入 : 无8 F3 J1 o/ I, y5 T( N
- * 输 出 : 无! ^ ~- F' c- ~: y1 ]9 W% y1 |8 N
- *****************************************************************/
% L% q0 H3 R1 R/ `1 D- r) Q - void DS18B20_IO_IN(void)
) K+ \2 G3 a* d - {
- h, b8 y/ g2 T# Y z: b - GPIO_InitTypeDef GPIO_InitStructure;
1 x8 l% `' w% S/ w) e* P - GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;$ l5 e- p7 I$ `/ C% |% l. o8 V
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;" {' l' L: k3 J/ h
- GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);# O: _6 K/ C3 P4 R" C( v, R4 s- ^
- }
复制代码- /****************************************************************
& O/ x8 N+ Y! L4 ~, |* u" N - * 函 数 名 : DS18B20_IO_OUT: }+ Z- d& Q, l& g
- * 函数功能 : DS18B20_IO 输出配置
" J3 Q- P$ G& n y* H! m( d - * 输 入 : 无
. a2 F- {4 A s4 ]/ }3 R, M - * 输 出 : 无
! b# e8 O- s8 a2 t - *****************************************************************/
7 e5 x7 A4 q. o8 P/ G - void DS18B20_IO_OUT(void)+ z( @/ U5 n1 ]3 G: e& S5 n
- {
8 B4 _% d! D9 l n - GPIO_InitTypeDef GPIO_InitStructure;
1 x: Q2 Q8 ?6 J - GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;9 o/ @& l: ~$ D4 O: t% Z
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;) h; u( i+ {9 k: D8 y
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;* ~- q. }$ @; M2 S) W
- GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);! k; U- {3 M4 T- a5 N: R
- }
复制代码 : v* r/ N$ \/ `; H0 [+ `- J' r
其实也可以直接使用寄存器来配置管脚的模式,可参考 GPIO寄存器部分。 2 G% |" N S8 V- m' J
|