|
本实验所要实现的功能是:系统开启时首先检测 DS18B20 温度传感器是否存在,若存在输出相应的提示信息,然后间隔 500ms 读取一次 DS18B20 的温度,并通过串口打印输出,最后让 D1 指示灯不断闪烁,提示系统正常运行。程序框架如下: (1)初始化 DS18B20 (2)编写读取温度函数 (3)编写主函数 因为 DS18B20 是单总线通信,所以需要使用 STM32F1 的 PG11 管脚模拟单总线时序,单总线相关时序在前面已经介绍。下面我们打开“DS18B20 温度传感器实验”工程,在 APP 工程组中添加ds18b20.c 文件(里面包含了 DS18B20 驱动程序),同时还要包含对应的头文件路径。 要使用 PG11 管脚模拟单总线时序,就必须使能端口时钟及初始化 GPIO。初始化代码如下: - /****************************************************************
1 z0 G0 O$ D& `! D3 [3 o( a - * 函 数 名 : DS18B20_Init
8 H5 P( Q; o3 n8 m0 t" z R5 X6 z - * 函数功能 : 初始化 DS18B20 的 IO 口 DQ 同时检测DS的存在, [+ B/ X+ G! N A, I" N
- * 输 入 : 无$ W' l$ {# ~8 `* ], }
- * 输 出 : 1:不存在,0:存在8 L! S. J4 x5 v6 m$ Q! _
- *****************************************************************/
: K6 V6 e: k7 T* s3 B - u8 DS18B20_Init(void)
2 \' e+ @+ [: N: T - {5 k. y8 H- Y8 Z5 \
- GPIO_InitTypeDef GPIO_InitStructure;
, a. S% ?0 C4 N - RCC_APB2PeriphClockCmd(DS18B20_PORT_RCC,ENABLE);
i; ?2 M8 q. n$ m/ a) B" v3 l - GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;
, V2 L& D/ O* ~# h - GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
: J$ R1 x" O% U- G" ^# U, K/ [ - GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; K/ I6 y3 N( Q/ _ T1 h7 m# c
- GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);- \& _+ A5 H2 X
- DS18B20_Reset(); h8 T! u Z2 w0 r
- return DS18B20_Check();
% V& d% b' `% b3 L - }
复制代码
1 H% J* j, P3 L3 J! A( k) J, V
该函数带有一个返回值,如果返回值为 1 表示 DS18B20 初始化失败,返回值为 0表示初始化成功。函数返回值其实就是通过调用 DS18B20_Check函数获得,此函数用来检测DS18B20是否存在。初始化函数内还调用了DS18B20_Reset函数,这两个函数其实就是根据前面介绍的初始化时序编写,对应的代码如下: - /****************************************************************; o+ }0 M2 t; B
- * 函 数 名 : DS18B20_Reset- N& ^ S& H# ?4 w& i) p
- * 函数功能 : 复位 DS18B20
9 H: }+ o0 c, i" K' D9 G - * 输 入 : 无
" H- R3 ?) M f& s& _4 s - * 输 出 : 无, p0 E# {6 W* a4 v* Y
- *****************************************************************/& U" s/ K2 R P ~0 |" g9 D
- void DS18B20_Reset(void)
6 n6 W1 _; e# O - {* ^ \6 w1 ~2 l- h4 W$ \
- DS18B20_IO_OUT(); //SET PG11 OUTPUT8 C. U% s' v& W; c4 t
- DS18B20_DQ_OUT=0; //拉低 DQ
* [! h' S& i3 R h7 P2 o - delay_us(750); //拉低 750us, }; ^# q m/ l4 i i& e7 ]
- DS18B20_DQ_OUT=1; //DQ=1+ u) B/ G( g' C% ]
- delay_us(15); //15US+ s6 l/ s/ @7 g: O! U& K
- }
复制代码- /****************************************************************4 d& A0 f% O8 l6 r$ @, }- i
- * 函 数 名 : DS18B20_Check
! C% Y* k7 Q- m( V. X: u* y8 r9 G - * 函数功能 : 检测 DS18B20 是否存在
* R. j% R& `+ a( O# m% P! t - * 输 入 : 无
8 h) ]9 |5 U+ H - * 输 出 : 1:未检测到 DS18B20 的存在,0:存在/ r' v5 Y) z+ o8 d* \. B6 q+ V, }! V
- *****************************************************************/
P* J( Z9 R, m" Q4 M3 f- @ - u8 DS18B20_Check(void)2 @" q- c6 [9 l% y" l/ P, ~
- {
& @$ V: M! {6 Z# M4 S! n - u8 retry=0;* Q/ n9 Y( c) |! ?# W3 e8 }
- DS18B20_IO_IN();//SET PG11 INPUT
' `5 N6 P; u+ j* w - while (DS18B20_DQ_IN&&retry<200)& @7 F' w+ @1 y1 _ R! y$ M. y8 E5 x
- {
* d7 C T5 N- @: z: P: L8 o - retry++;
" f2 O7 m8 m5 a7 | - delay_us(1);
, ^( x9 Z! p* W3 ~2 T - };, [" D6 x+ }( @( P
- if(retry>=200)return 1;4 _7 f3 n# c/ u# M
- else retry=0;) }$ ~0 J; q" L( t+ `
- while (!DS18B20_DQ_IN&&retry<240)
0 g7 u7 d$ x! j0 x0 ~' e+ T( J0 c1 u - {8 a0 M9 \# s) a( {5 j6 Y
- retry++;
6 X2 r* _( b: d5 x - delay_us(1);3 Q K- V* G, R. W
- };
& M- _% C8 O' i$ F5 Q8 H - if(retry>=240)return 1;
8 w5 e0 N+ U/ [, M - return 0;
& Z# B7 O q; |) f6 n: u - }
复制代码
j: Y; O/ x5 p( {: z' J
由于采用单总线,所以数据的写入和读取都是在 PG11 引脚上完成,所以当写入数据的时候需要配置此引脚为输出模式, 当读取数据的时候需要配置此引脚为输入模式,因此会有以下两个函数: - /****************************************************************
! k9 d5 E; g/ r - * 函 数 名 : DS18B20_IO_IN1 W/ p5 L# X. X
- * 函数功能 : DS18B20_IO 输入配置
) f7 z) k L8 J - * 输 入 : 无
; D' n1 p2 R1 p - * 输 出 : 无
0 m# ^' U5 H2 t8 M" I - *****************************************************************/
) ]; [: P- n; H/ J# p - void DS18B20_IO_IN(void)
; A8 x6 `8 d% F$ ^4 }# z0 L - {
, k( u$ P1 C' J' n5 \ ^, {+ |- Q; n - GPIO_InitTypeDef GPIO_InitStructure;
, | U9 C/ v i2 { - GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;/ T# i! B. n6 {6 ]" b$ O+ ?
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
* I. q# }9 B5 f- l" { - GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);8 \0 b s0 C/ S% Q7 ?
- }
复制代码- /****************************************************************
' r8 F; d) A) g, k1 L - * 函 数 名 : DS18B20_IO_OUT3 ^6 ^+ G+ V! ~. U. L, Y
- * 函数功能 : DS18B20_IO 输出配置
8 ?2 s3 g- P$ y6 u" u; m* I - * 输 入 : 无" L% z! W5 ? u8 ~0 F( j
- * 输 出 : 无- Y; R; _" S4 h2 W
- *****************************************************************// t$ Y2 a4 w: j( ~: Y
- void DS18B20_IO_OUT(void)1 f+ ^7 l( U) j9 S" B
- {4 `! l* S$ Y; y2 Z& t. G
- GPIO_InitTypeDef GPIO_InitStructure;* K- T/ j( }7 s7 Y' ]) _* |
- GPIO_InitStructure.GPIO_Pin=DS18B20_PIN;
7 S) O/ H0 u/ m& `( u0 ^ - GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
& t- `) ]4 W2 [) G* d - GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;" B! W1 e0 x% c6 q" b* l
- GPIO_Init(DS18B20_PORT,&GPIO_InitStructure);/ n. j- }6 k1 Z/ Y1 Y
- }
复制代码
# P) J- c) ~* h2 O; X 其实也可以直接使用寄存器来配置管脚的模式,可参考 GPIO寄存器部分。
4 x7 y! T, f+ m |