最近有在使用sht30这个传感器,相比于新手常用的dht11传感器,sht30更精确,自己花了半小时调好了
5 |! X1 b. S- {$ ` I所以拿出来分享给大家。4 |0 d$ i9 A3 v# B
) _( e, |9 M' X7 o+ L/ A) Gsht30外观2 |% A+ w1 B3 r+ _9 Y
: M' A6 T/ R7 S0 h: s
! n, W# \. Q2 c6 i* a0 Q" w3 P- i) `- {2 f+ q' y
驱动不是自己写的, 是采用CSDN上的一位朋友的 ,这里贴出来的代码不是本文的主旨, 重要是教会大
' Q: E4 Y8 J b) j G r1 f- x6 K0 o9 \9 Z
家如何配置各个端口(因为是模拟iic 所以大多数引脚都模拟为SCLK和DATA)。
2 V! ]) M; q% E* z% [- g3 [6 x( ~; c( ]3 Y1 B
串口输出图% N1 U8 |5 V$ [4 K( T' m/ k
4 f2 k" X+ W6 a5 Y- h2 z
6 ?/ b9 J9 E5 y0 ~
% P j; y# Z M" w2 Y. E6 x7 h! V: [
驱动代码/ ]2 _9 v) ?5 n& E$ S
- l q1 \+ O( ?, t& X
: k, n9 d) o/ z; K: ?" dsht30.c
) v1 ]6 F* w9 h0 ~0 j, E- #include "SHT30.h"
, [: l8 y6 D0 X9 h$ X
8 G0 A; O6 i' U% r6 Y% a# O- #define write 02 R/ M0 ~8 G) @& q- c
- #define read 1
3 }1 B6 L" z% M. a - " a8 M/ Q* e: @4 ~3 G; E0 p
- //IIC总线接口定义
5 K) R1 q5 I- b9 ~ - #define SCL PAout(5)
0 X. e% k" h* [6 s! m& g& O - #define SDA_OUT PAout(6)
# [8 P7 Y' f7 v6 P - #define SDA_IN PAin(6)' Q0 z- U4 g( u9 {1 q2 v7 _
- #define IIC_INPUT_MODE_SET() {GPIOA->CRL&=0XF0FFFFFF;GPIOA->CRL|=8<<24;}
7 \* p7 B- J" q' y: B" u' j' C - #define IIC_OUTPUT_MODE_SET() {GPIOA->CRL&=0XF0FFFFFF;GPIOA->CRL|=3<<24;}
( Q% \* Q* g- I, P# ` - ( T' h" ?0 z4 X: f
-
" x. R3 p3 A6 X/ |- m+ t - float humiture[4];& \+ |/ @, s7 G& @1 O
- u8 humiture_buff1[20];
8 _* J3 e, |. F3 `1 V7 V
; U5 r- k' {7 a" T" ?- W- void SHT30_Init(void)
8 _2 ]0 T, p; |' n& Z. J; V - {
% }5 f5 o5 @3 F. E+ r9 c2 C - GPIO_InitTypeDef GPIO_InitStructure;" y a$ k" E$ d5 {3 ]0 i+ A
- //RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟
9 z1 C" U w9 n" @! K4 F - RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
# N& E: |8 n- L! U8 u. ^( E- e- V - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;
) t$ s) ]& t% ~, Z - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出3 b9 o* @6 r/ e* j( K3 c. |
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;+ q- E2 O0 z- Q) F4 _
- GPIO_Init(GPIOA, &GPIO_InitStructure);
" ^+ t- G }) K - SCL=1;
+ p2 C: L4 G# r5 L) ]" k& @% ]9 w - SDA_OUT=1;
# y( K! ^9 _) V# ^2 V1 G- P' p2 g; o - }
0 o: E9 @( p5 p- l @: `& `( n - /*主机发送ACK*/# A8 I& g1 c3 S) _2 x# w m
- void IIC_ACK(void)8 c; l; W3 E. X/ @2 \5 r+ O, O
- {1 X; v/ J7 U# I0 K
- IIC_OUTPUT_MODE_SET(); I, ]* W5 [0 S+ U# p6 {( E8 B
- SCL=0;" b$ d7 T9 x B v3 I' b3 c' |* c
- delay_us(2);
1 r' d2 S# p. U0 z! y* H. X - SDA_OUT=0;
; L1 n( Y9 ], M0 E- P2 k, l - delay_us(2);
" m. h! }4 D+ G0 Q: \ - SCL=1;2 m+ F8 c* p! T7 u) h7 d
- delay_us(2);
7 z' _9 G* p% l9 d' P5 h- | - SCL=0; 3 n$ Y G# @3 R0 Z
- delay_us(1); 2 x! G9 i) m3 P1 m
- }, {% w2 u8 k$ s( V/ A! r
- /*主机不发送ACK*/
! `7 V1 k8 r) @8 L - void IIC_NACK(void)
& X. a6 U/ Y! k3 @) D0 a- S - {
" M/ o3 Y- b! p9 i O- j - IIC_OUTPUT_MODE_SET();
* U7 ~+ N' `6 ~! B - SCL=0;# d5 U, {& e1 h, h) d* K" |
- delay_us(2);
. n) e1 {! T( L# y. w+ e+ w - SDA_OUT=1;6 z1 u7 B8 _ K9 J& ?: U
- delay_us(2);
d( s$ B4 K; [! L+ i2 W - SCL=1;
+ h# W" |0 ?* T1 _ - delay_us(2);
; m! w5 h7 q/ a - SCL=0; & l; v A& h; \3 B% b: H2 o
- delay_us(1); 2 E3 O F2 @9 ]- P+ y8 r
- }4 ^9 B" |1 B2 Y/ u' w
- /*主机等待从机的ACK*/. e- m: c8 ?2 L+ d( g1 A0 c
- u8 IIC_wait_ACK(void)
) @8 W6 @2 P3 y1 E# N# Z% _; U' j( t. p - {
; v6 i# y: [1 h. ^/ Q/ J, D - u8 t = 200;9 T$ ]0 o( Q W; F& S5 y
- IIC_OUTPUT_MODE_SET();0 W6 o* }- }7 D+ y# w" p2 B* J
- SDA_OUT=1;//8位发送完后释放数据线,准备接收应答位
: t& ^8 y9 U5 h2 X& @3 U - delay_us(1);
( y5 w- {& S2 e+ X* k - SCL=0;
4 ?/ ^. B' Q& r) V3 U7 G; i' b - delay_us(1);
# O* K3 q: l4 d - IIC_INPUT_MODE_SET();
- ` W9 f0 F+ \; h1 }- m5 K$ s - delay_us(1);
7 \' s2 N1 g. ?8 M - while(SDA_IN)//等待SHT30应答
4 K; R$ n$ f. G( A* K# D - {) s5 Z8 P' r; c
- t--;
9 a) V/ h O, k( j! n, Q - delay_us(1); % f/ g2 p/ t1 O$ A- `' z
- if(t==0)
0 W+ t* Z& C5 n - {9 X2 |6 \; A l/ X3 q
- SCL=0;
$ ~+ {" C6 R2 j- h" Q* ], P A" B8 ` - return 1;
; k9 P8 L, X% b e2 p - }5 [; v0 S5 E! F# U" f4 ?
- delay_us(1); + @* J7 O ?! f4 i! ?" j% l
- }
# d; {- d( e: y% O: R$ l& h3 e - delay_us(1);
% h% J! N, n+ g - SCL=1;. i6 C9 \8 e. e+ v- s
- delay_us(1);# H" k6 F' O: L. p
- SCL=0;
5 x* e$ H5 ]. D; X$ c+ h1 ?7 { - delay_us(1); + V; O/ d# {3 k% p0 L; j
- return 0;
- n$ Y1 V) |! u) m& ~) b - }/ i+ O% a' n. _2 x/ p4 A/ t
- /*******************************************************************! ^$ M8 {9 n& T
- 功能:启动I2C总线,即发送I2C起始条件. 2 Y2 U1 ]1 t6 w3 @* M
- ********************************************************************/* h* d+ L- o% A/ }3 S1 K* t
- void IIC_Start(void)& p5 f( l; j H
- {
( g$ h1 h2 O- l - IIC_OUTPUT_MODE_SET();+ G" g$ e" N' x+ a2 T
- SDA_OUT=1;
. Q6 \5 u5 v$ t* { - SCL=1;6 x ~0 O! r8 E) d1 J4 Z% k# b* u
- delay_us(4);
! x8 a1 w) k( ^. ~ - SDA_OUT=0;
0 ?0 a+ V8 b# V - delay_us(4);
$ v) C0 _. I- r7 I' E! I m - SCL=0;% C$ E$ c, z* ~* m/ m' l1 U
- }/ E3 q( U9 z- T; A8 }7 L8 X
- % \/ [! ^0 @- s. q3 n
- /*******************************************************************: F0 I( z* n% s2 A! r E
- 功能:结束I2C总线,即发送I2C结束条件. - m. ^% z: x9 c9 K: l
- ********************************************************************/
! w+ [& A6 w! f9 E& v: \& J% a - void IIC_Stop(void)* {7 \! V; L6 E2 s) P2 M+ U+ ]
- {* [1 O, k% x) g$ ^: ?" e
- IIC_OUTPUT_MODE_SET();
, G! F+ u3 b3 Q5 W' d% U - SCL=0;1 L5 u- O3 D5 L+ L4 |
- SDA_OUT=0; 7 ~" \' `5 x' e% C
- delay_us(4);
% I" O2 D# q$ S8 Y7 D7 r, ? - SCL=1;
0 j1 p2 n8 f9 c% V2 U; M - delay_us(4);
2 s/ b) ]; Y! B& o - SDA_OUT=1;! L5 v. A2 D: q3 o2 i/ s
- delay_us(4);
! p+ @+ ~0 S, n" }$ @' H4 ? l0 P8 ? - }: W- \* |6 s3 S
-
0 j/ l+ L' n, w7 N" v' ~+ ~$ `5 j" E - /*******************************************************************: V. u- [; i V0 j0 w9 t8 {7 t1 [
- 字节数据发送函数 - o( {" o: o$ M0 M& g8 k
- 函数原型: void SendByte(UCHAR c);
, z7 L+ _! [1 c: k4 e' L7 | - 功能:将数据c发送出去,可以是地址,也可以是数据
2 s6 m# b0 h+ u" F. ?4 h% w - ********************************************************************/
1 Z, `$ t/ P9 E4 D5 y6 @ - void IIC_SendByte(u8 byte)
6 M) s& e7 k) }. k. l7 }$ v) h - {
9 Q8 v2 X7 y' h, a# z) m/ t - u8 BitCnt;) J3 V( h: B5 |/ A# _. m
- IIC_OUTPUT_MODE_SET();( M7 g4 V3 x% a1 T* `
- SCL=0;) Z+ \6 Y( y- a0 F5 Z+ s
- for(BitCnt=0;BitCnt<8;BitCnt++)//要传送的数据长度为8位" u* e: M3 e- q
- {+ `5 x$ |5 K; v, _" C3 X' [: Y
- if(byte&0x80) SDA_OUT=1;//判断发送位
% L* F* O! K9 Z - else SDA_OUT=0;
! c6 |3 s# Y' I& T - byte<<=1;( q- W: B' B9 _/ P
- delay_us(2); ) ]: [# P, M: Y2 k- w
- SCL=1;
8 ^4 _6 [' m; ^& I; q& \% p2 R - delay_us(2);
+ z+ B/ h1 Y8 z5 a( G% s - SCL=0;" _$ z: R3 V6 m, Y0 ^, e
- delay_us(2);
% ~* R$ ^) D+ g0 v* |/ |. I - }. k1 R! ~/ q U
- }
& l' d9 `5 w4 p2 M9 P% P5 \$ I7 ? - /*******************************************************************
' N( t) f5 K$ K2 H6 y0 B& z' D1 \ - 字节数据接收函数 $ X5 l% N( `. p6 c9 d0 N! o
- 函数原型: UCHAR RcvByte();
( |$ `( c" N6 v2 |9 n0 Y6 ?& ? - 功能: 用来接收从器件传来的数据
2 v2 j; \; I# h9 a4 ~/ D5 a - ********************************************************************/
1 Z8 @. P) ?6 Q - u8 IIC_RcvByte(void)
8 d) `. U% z) W - {
9 s* Y0 n0 o4 L% A5 H - u8 retc;+ x# s6 Q1 ^% J' [, D
- u8 BitCnt;
- i9 H3 T. g6 \, d F0 {+ Z# ~# U - retc=0; 3 j7 M: p( ` Y" A( K' M6 ~
- IIC_INPUT_MODE_SET();//置数据线为输入方式
4 A/ h! A% W( c: v, ?. i( r. ] - delay_us(1); ) C3 U6 P% x" {( b% ?5 i# q* Q# y7 J2 e
- for(BitCnt=0;BitCnt<8;BitCnt++). W( M4 i1 l- H
- {
2 X, Y* D' k/ \7 d( N0 Z - SCL=0;//置时钟线为低,准备接收数据位
4 i5 R2 B, z8 X5 r5 T: P3 T- p - delay_us(2); 6 |6 D/ e& a8 A, b, w
- SCL=1;//置时钟线为高使数据线上数据有效 - D3 `5 m! c. {6 h
- retc=retc<<1;
0 S$ H6 j) M3 r2 d1 U" b5 O - if(SDA_IN) retc |=1;//读数据位,接收的数据位放入retc中
. N! Q' B, A1 Z% z4 e3 V n - delay_us(1);3 ? s% V' g! [) f3 i4 W! n* _( O
- }( e0 o4 [6 o: g7 M& \! K
- SCL=0; % o7 Q# g3 j2 c1 M/ ~2 K; i
- return(retc);- a7 a( X! D/ Y! ?) i
- }
' ~. T; E2 [% M4 ~ - /*******************************************************************
; Q2 Y8 ~8 i& D1 V - 温湿度获取函数 ' A F0 g- v* c0 ^7 S0 G: w4 d- d- k! W
- 函数原型: SHT30_read_result(u8 addr);
5 f0 }- A) H# L% T/ {( T - 功能: 用来接收从器件采集并合成温湿度
6 i# d7 ^1 o) d# r$ V - ********************************************************************/ - d# W8 ^- @% D/ ^
- void SHT30_read_result(u8 addr)
% Z4 a6 E* u1 p - {
/ H1 x0 K* d6 Y( ^& U3 f* h - u16 tem,hum;; R8 E6 K; R. Q3 M3 \3 t0 m3 M
- u16 buff[6];) e( \' }" t% U
- float Temperature=0;
7 K2 S1 h: w& J# m - float Humidity=0;1 l- x/ {6 _! W- e9 l) P- z
- . D/ C" D) O8 C- \. O
- IIC_Start();0 e0 ~4 r& W0 a* M% h( g- v
- IIC_SendByte(addr<<1 | write);//写7位I2C设备地址加0作为写取位,1为读取位
% V+ d" n/ o; k5 ] - IIC_wait_ACK();3 G; [, d0 x: X- ]6 j1 X$ Q
- IIC_SendByte(0x2C);
4 o. y. ]2 V* u$ _+ d5 } - IIC_wait_ACK();
) b Q6 Q& _) A# W# i) s* X* j) a - IIC_SendByte(0x06);
" }5 t* u9 g# s0 r% N) X - IIC_wait_ACK();4 ]# @, c p2 G7 W$ g) |$ a2 c) z
- IIC_Stop();
9 {( H8 v5 D) s8 V3 _ - delay_ms(50);
" k, X Y- d6 J' P7 j& s - IIC_Start();
. H5 v/ P& ?2 q - IIC_SendByte(addr<<1 | read);//写7位I2C设备地址加0作为写取位,1为读取位* W% B- Y+ e5 y/ z# \! m
- if(IIC_wait_ACK()==0)3 N3 ~( [, G9 \
- {+ t2 b) r# L: Z( E
- buff[0]=IIC_RcvByte();$ A8 w2 i/ s' J& c
- IIC_ACK();
C. R# d, k6 h% f - buff[1]=IIC_RcvByte();
2 d' D9 G, K c" y+ D - IIC_ACK();
/ T4 B- @6 P0 @$ X3 I3 t+ F - buff[2]=IIC_RcvByte();: o5 k+ C8 h- l. N$ E) m" U0 L) q
- IIC_ACK();; |5 {$ @1 W5 [ M |+ N& I% g
- buff[3]=IIC_RcvByte();1 k& U6 L0 ?+ @
- IIC_ACK();
6 k. w0 r j; `' |7 f" J' y - buff[4]=IIC_RcvByte();7 A# R) ~1 f! i! x2 x/ q5 z
- IIC_ACK();
8 o* D E4 S/ A" V0 ~8 ]/ h8 G - buff[5]=IIC_RcvByte();' A2 Y% P0 M C6 C% a) [
- IIC_NACK();6 Z* h8 \8 Y* x/ _+ N
- IIC_Stop();2 c* ?% |1 y9 s, D
- }& [ m+ l& J Q! N
- $ K1 h' o/ X% L* {& Y
- tem = ((buff[0]<<8) | buff[1]);//温度拼接' Q/ \( [0 q" i0 g/ z9 B4 [
- hum = ((buff[3]<<8) | buff[4]);//湿度拼接
9 A: e6 v+ P. b; Y" h" [* v" N - * V( a/ U. N5 X% B d
- /*转换实际温度*/
7 d- r- l. E! ?: x! `+ K - Temperature= (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)
2 @) l d% I0 u7 y+ D$ [ - Humidity= (100.0*(float)hum/65535.0);// RH = hum*100 / (2^16-1)
# B& P# b& Q* A -
, P5 K' ]% w7 d - if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))//过滤错误数据
@% L- L3 a& U7 ^: J" ? - {
B2 K: F9 X- K5 @2 y, Z - // humiture[0]=Temperature;: h3 W6 ~& n, j- d" J7 G/ @
- // humiture[2]=Humidity;8 k& r! ^5 ?2 K) B$ ?
- sprintf(humiture_buff1,"%6.2f*C %6.2f%%",Temperature,Humidity);//111.01*C 100.01%(保留2位小数)- m# C C( P( q' w
- }, T; T' h2 Q9 Z' A$ M M* o
- printf("温湿度:%s\n",humiture_buff1);
* B4 o% c( F U1 e! y( H2 c - hum=0;) _6 O# O j0 b# ?# j9 T- s5 m
- tem=0;/ Y; V9 z( ^' K) J& M2 [. ^; B
- }4 S2 H i& R; A) H* @
- 6 B% B) Z2 A3 g& G2 {1 s
复制代码
( J( h7 o% r _7 a9 l- Y e2 N5 s% `# e6 R& Y. E9 u
sht30.h) B) N+ ]% t9 }
- #ifndef SHT30_H
' ^0 x# H& [+ r5 z3 x- C - #define SHT30_H
0 q6 e, y* s7 g7 ?1 F - #include "delay.h"* P) L2 z& K1 O/ b
- #include "sys.h"
( r( u. B6 [) k0 O0 G8 m - #include "stdio.h"
0 |1 p! i5 o- V+ b' L) o# ] - #include "usart.h"
z7 h! o" M- q% c* u# j5 b7 D - #include "string.h", D7 O/ s$ u0 K2 |# q4 S; Y$ c/ T
-
$ \3 P" v$ h& P1 _; [% ^) u - extern u8 humiture_buff1[20];9 d; ^0 u. t! }7 P% X
* W8 h8 I% E% K1 o- void SHT30_Init(void);' t: H- x7 ^# s: v, m2 D" d1 k
- void IIC_ACK(void);
" `7 h, ~( j. C5 P) n3 } - void IIC_NACK(void);( R4 L: f! q$ a; T: Z' W, x& @9 P
- u8 IIC_wait_ACK(void);
9 m1 D& ?& @8 ]- k( t) O; v - void IIC_Start(void);
9 n& N" G, [' w - void IIC_Stop(void);$ B5 W& y9 f" |& o, W* N' C) p
- void IIC_SendByte(u8 byte);
5 v1 _6 ^/ @6 C6 h" u - u8 IIC_RcvByte(void);
- h# [+ {: V7 @4 { e7 j - void SHT30_read_result(u8 addr);1 e& R' T$ e B, f$ Q$ @
- ! V, W$ n8 ?! E) z, H; Y9 p
- #endif f2 |' m, p$ x [3 R
3 e: x1 I: r& H0 K) y8 s: K
复制代码
0 a7 N# R* s! d% o- x6 q
% X+ y% r: A. n4 N主函数(while循环可以写个测试的printf)# a0 f. K2 |4 G/ f
- #include "delay.h"
$ j8 h6 b4 X& j! [ - #include "sys.h"
' q" ^; p+ a6 @2 Q3 i% O - #include "usart.h"
9 L) |/ _9 w+ U& S* F9 o" h - #include "SHT30.h"
, k1 E4 w6 m3 u- T -
. Q: H% F- N& R
# s" w5 d x. |% V# f1 Q- int main(void)
9 H3 Z: @- U7 V - { ( O \1 O( z& E0 C
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
% ]1 T* u1 w. U - delay_init(); //延时函数初始化 6 D9 V- Y; i; T5 b4 d: \
- uart_init(9600); //串口初始化为9600- [( U' C) t3 j: n
- SHT30_Init();7 A& h' k' W! a c2 q) F6 ^8 ^
- while(1)
. F* N* w2 _% _+ Z, D, k% T+ B - {
' S) u* F6 z$ _( F( s: _' Y: W' c) C1 \% p - //printf("123456");
: e+ ]& x3 Q0 l' N - SHT30_read_result(0x44);6 J/ g* S2 v1 n. t! a1 z n0 U
- delay_ms(300); 5 }; }5 S t! l
- 2 C' p/ W6 S3 [2 `
- }
, M& N# U5 ~1 e& a8 h* ]0 g+ w; J2 F - }- @ G& L0 {6 L0 ]
复制代码
3 f/ ?% Q" `, Y7 J V: J% \6 A0 U0 Z/ \1 m. [4 p3 B2 C* w- o
代码实测能用 ,直接复制即可, 但是如果想改端口继续往下看。
8 Q, F$ t6 B" H% J
. i3 ^6 c) a3 U( K- _
0 L7 j# p+ r5 _
* z* C! f1 ^# O; G# u; t# w0 N0 a
上图红色框选的是换端口所有需要改变的地方 这里漏框了上面的几个宏定义, 上面几个也要改。6 F: Z& t; ^' ]% R) a; d3 d
+ G, L l. J$ G" v4 z
" D7 _/ y |* C7 h; J: a" ?4 f i4 |
% ^0 q: H5 w% h5 {1 Y0 HGPIOA->CRL&=0XF0FFFFFF;理解为 清零了32位数据中的4位# R# u5 l! B/ E
GPIOA->CRL|=8<<24;理解为置位了32位中的(24,25,26,27)的值
; `1 M5 n" `: I5 f q. \* e6 @: v. e% W2 c5 B
# S: A; m" ], A9 H6 M! Y) L
4 C! {2 S& s7 ]" w* U- \
3 J$ L/ [( s) |! {
8 F `$ ~1 r! q5 a6 I. l
7 y4 }8 ^1 v5 |* S+ t3 z C5 a
8 ~8 f, l g0 Z( C! V1 M
上面两副图来自stm32中文手册 ,意思很明了, 有两个寄存器用来配置io口模式,CRL配置GPIO0-7, CRH配置GPIO8-15,第三副图是教你具体怎么配置,按照手册就可以选择配置你想用的端口了。* f+ T u; S8 u. ?& L; Y
————————————————8 j1 `3 ^; e& |7 |
版权声明:文某9
' H5 ^& I" m7 N( J/ c如有侵权请联系删除% |1 ~" N/ H9 d/ ?* `
: Q. @- j8 ]8 v+ C
5 @9 x5 V" F: g
0 D. E$ h9 j6 p9 h3 s ]. L, v
|