最近有在使用sht30这个传感器,相比于新手常用的dht11传感器,sht30更精确,自己花了半小时调好了- i) ?3 `9 e" S0 R
所以拿出来分享给大家。 @; d7 y/ _# v% ~
- P2 U7 x# T o. rsht30外观% |# Y" L, A: o4 t' Z @
5 i" m! b4 S; E( h
3 B* F/ z( b5 J4 a/ T
: `* z- Z: c3 S6 i( Y2 y2 W+ ^( X1 c驱动不是自己写的, 是采用CSDN上的一位朋友的 ,这里贴出来的代码不是本文的主旨, 重要是教会大
0 w q0 \4 I; I- I& l2 ?- H Z+ d- `) f1 ]/ D5 L6 K8 d
家如何配置各个端口(因为是模拟iic 所以大多数引脚都模拟为SCLK和DATA)。4 x3 l8 `& t) }& c
8 k. S) O, h( V+ Q# `: A' A串口输出图8 d$ v* ~! B; a: x+ b. q T$ S9 {7 p
: ]) F2 \3 e' G7 o) s; W
( O4 }9 s' H' L$ A% K! h" Z
" ~# G/ ^- d; ?3 |/ g" q7 N' N4 b$ w- ?2 t# m. n Z/ \# X
驱动代码( g. ^" e1 L+ W5 X
3 ~" _5 O u' s! a! _; O& G5 E
) i1 i) Y! ~+ Y q5 Ksht30.c, g d! N9 d0 ~3 T, _
- #include "SHT30.h"
$ D8 n0 h _2 V/ ]$ P( T% K
, }8 |3 g4 q/ O {- #define write 0; N2 Q1 b, d% s7 Q# N* e7 k" n
- #define read 1
4 F& C2 a* V) u+ ~
; p6 @" v# }2 ^- //IIC总线接口定义! z5 b% x+ Y1 _+ p
- #define SCL PAout(5)2 F3 ?- P* j# j4 N j% p
- #define SDA_OUT PAout(6)
2 C+ T1 ^4 _3 ?# a - #define SDA_IN PAin(6)
" Q$ k4 h- q; K7 O ` - #define IIC_INPUT_MODE_SET() {GPIOA->CRL&=0XF0FFFFFF;GPIOA->CRL|=8<<24;}$ `* |; } K9 A5 B6 V
- #define IIC_OUTPUT_MODE_SET() {GPIOA->CRL&=0XF0FFFFFF;GPIOA->CRL|=3<<24;}
9 u+ D% y' P) r* E - u; O9 b5 p$ O: N, N' ]: ]
-
" i: @' u+ N5 \, f1 | - float humiture[4];, r* z9 e* v# w0 H, R
- u8 humiture_buff1[20];8 w8 l4 n D9 x4 U8 f% v
& i) N5 |- [# }5 M+ `7 ?/ N- void SHT30_Init(void)
% g$ o* v! V, B% r - {
( n, Q: H N7 e. }* z - GPIO_InitTypeDef GPIO_InitStructure;
7 M* i' q! }: X( A - //RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟 : R, R Z1 h+ V" P$ @$ ^0 T/ L1 {3 m
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
1 I/ l/ D/ @ ^. W7 O" _ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;
! I2 h* h7 d5 ? - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出, ~! q, t1 H; R4 i
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
2 l) m& n" q5 d6 m% J+ d: l - GPIO_Init(GPIOA, &GPIO_InitStructure);! I; f/ W: g# E9 R0 H5 ?3 N# m; o
- SCL=1;
* }9 u' w$ Z- S( u - SDA_OUT=1;% Y, \+ C2 Q6 e- V0 Q
- } " C. M* N) p& J- v$ p" U
- /*主机发送ACK*/
1 j# ^% }# v5 M# \0 k# @ - void IIC_ACK(void)" _6 B% g" }5 o; @
- {
# w+ v$ e- e5 |/ b' M5 v; F - IIC_OUTPUT_MODE_SET();9 L+ u5 F4 k- A) I
- SCL=0;
7 K( z1 V9 F+ i- z# R# { - delay_us(2); V+ h$ i" J x! y" j6 w* X$ E
- SDA_OUT=0;% q" R# Y% y/ Y- Q0 S" i/ m+ T
- delay_us(2);
/ ~4 i& S$ Y- ]! M Q - SCL=1;: j- A, x$ C$ y6 p0 O. j
- delay_us(2); K9 E& J4 _0 x5 }' H: S. t
- SCL=0;
# L; U# M& {% l" A Q - delay_us(1);
2 B3 `1 t9 q7 P) u, E - }! I7 F0 ?7 P* N. `8 Y# u
- /*主机不发送ACK*/
& s& J. }2 X7 B6 S( z - void IIC_NACK(void)4 ]/ m% C5 A/ I" q" ~
- {; S1 C5 [, T; C# N: T6 C S
- IIC_OUTPUT_MODE_SET();0 l( ^5 @+ r3 _' T
- SCL=0;9 S9 \ H: P& H# b8 v4 R
- delay_us(2); + Y/ X* G6 z, c9 |% g6 Y/ @& c
- SDA_OUT=1;, f" H; o: ]' p6 |- z
- delay_us(2);
. t1 s7 z& n# S4 T8 Q - SCL=1;
- b* \" x8 p& B2 o - delay_us(2);
1 L* P0 j H: n+ Y+ M$ O0 e ?" v" N& i - SCL=0;
$ l% i+ ]4 O0 M! O; I* _ - delay_us(1); 9 j" `. d. j# m, [
- }1 R n6 @. e8 Q" Y2 p( {
- /*主机等待从机的ACK*/
; N6 K0 b! A7 E+ {; g* o( c8 z - u8 IIC_wait_ACK(void)7 f! l) p" z2 e9 E
- {/ V: \% k6 a8 S' W1 B! Q
- u8 t = 200;
7 L* Z; ~% G) ]7 [% z+ V - IIC_OUTPUT_MODE_SET();: X2 b6 m( {) }4 K6 d. _( A9 t
- SDA_OUT=1;//8位发送完后释放数据线,准备接收应答位 + {6 u- j& X8 p! v$ r' W
- delay_us(1);) i! W) O' w# P% Y$ ?, X
- SCL=0;
& ?+ q Q4 |) |: o% f# O - delay_us(1);
) j# f7 S8 }# Z - IIC_INPUT_MODE_SET();7 s2 l" N- Y( n
- delay_us(1); 7 I5 I* }) W3 s) X
- while(SDA_IN)//等待SHT30应答
+ C) o) q3 d I' K - {' `1 ^! t0 }- F5 F
- t--;
$ W7 g. i/ {3 a) n: h - delay_us(1);
, z5 k+ [. Q# }, S) G2 _2 I* ] - if(t==0) a5 i' M4 f$ w. d7 x' A, s
- {
$ }& L; k8 b- \ r; w; d! x2 _7 Z) }! X - SCL=0;
* `7 f2 e& `/ v5 C3 D( G" s. s - return 1;/ v& }6 Z. P, l: x/ I' v8 H- L* `
- }
0 k9 f2 \# u3 W( g - delay_us(1);
; L* Y- V3 F z: y' p4 n$ g3 ?# N - }
4 k! Y) z4 ^/ @5 H- E$ i - delay_us(1); / R) q( b# ]$ \) ?/ g4 n" E0 ^ o! n2 W
- SCL=1;2 T/ z( L P' q( m) r9 g
- delay_us(1);
/ k! v+ R/ X; L - SCL=0; - a+ G1 b v0 i5 A: w2 p1 Y0 [
- delay_us(1);
" `' F6 J1 g! ~; y% N$ J - return 0; - N, \" X" _9 k/ b
- }
$ f$ j. N U7 z - /*******************************************************************/ t9 n+ C# Z% M) m' y9 Q
- 功能:启动I2C总线,即发送I2C起始条件. : u3 s; f7 Y' E1 [6 z$ C9 j; W
- ********************************************************************/
! H6 f4 U* a% U# ~8 Q' a4 i7 ] - void IIC_Start(void)# I! A7 s: j. A+ d8 T" t" F
- {
! ?) U! ?, Z1 Z- Z2 U8 q - IIC_OUTPUT_MODE_SET();
& d$ ^" F. u3 L* n - SDA_OUT=1;
' F7 _! U# ~5 _+ _: F. i x - SCL=1;) ^+ A0 _2 A$ \5 J- K
- delay_us(4); 9 P/ V3 H; u6 f
- SDA_OUT=0; c& q k- p( Q1 A
- delay_us(4);
8 |" o: B$ [- A- y - SCL=0;+ }' P& B* N. J6 S3 C% @. l I
- }
$ M- s4 @3 J- d8 C: [; t9 t, q - 2 J4 |& X* V+ Q1 h- Q: m0 ?, l+ M) U
- /*******************************************************************9 B& q, Z4 A6 n8 i7 g
- 功能:结束I2C总线,即发送I2C结束条件. # c9 e8 C( x& O4 d
- ********************************************************************/7 F- f3 T' A, I9 b+ b( G7 c
- void IIC_Stop(void) t; P5 K: h# a( [/ r$ [+ u
- {
- C$ T' e. O7 A0 K - IIC_OUTPUT_MODE_SET();
, G) e7 M, t! t0 y+ K0 r( L - SCL=0;0 y# U: F4 K" z! F3 A
- SDA_OUT=0;
2 h h) m+ ?* f7 _6 D/ [: C4 K - delay_us(4);
. m# x1 y6 g$ A0 [) y. V. A+ I1 I' { - SCL=1;
. ?" n0 {4 c1 v: w% G3 E - delay_us(4);
' s! W' N! Z9 a: y/ G0 _" X% I - SDA_OUT=1;, S4 {, f& S( v
- delay_us(4);* w! f/ T* l/ A, B0 m
- }/ R$ k( c. O& a( H& ?3 T9 A
- ' |3 I* z: \" h3 b6 n5 \+ v U
- /*******************************************************************. s" F" t% A8 T' T9 T( v
- 字节数据发送函数
5 l a: J0 M, S5 e& ] - 函数原型: void SendByte(UCHAR c);8 i3 S0 u5 m) ^0 P" O7 y& P% V
- 功能:将数据c发送出去,可以是地址,也可以是数据8 g; E: ?) O' k' U
- ********************************************************************/
7 w' U$ C4 p8 `0 T- j: b, \2 b - void IIC_SendByte(u8 byte)2 o7 C# }5 k1 t: t. ~8 {
- {
. d* h( s x `; l3 \) k - u8 BitCnt;) ]- q) T4 v2 G. K5 t
- IIC_OUTPUT_MODE_SET();' K( f' l' n Y: V4 h) `5 E9 V
- SCL=0;
p9 @5 O( ~7 [. I6 t - for(BitCnt=0;BitCnt<8;BitCnt++)//要传送的数据长度为8位7 H, c+ Q# I. R7 n: j1 G
- {& Z# S! e3 ]+ u
- if(byte&0x80) SDA_OUT=1;//判断发送位8 ]' w* b7 T" j, V7 C5 b; M
- else SDA_OUT=0; * `1 B+ Z, G& h: m1 _/ Q
- byte<<=1;
. @) ~+ M/ k8 A6 w0 G - delay_us(2); 8 Q# I6 V5 {9 X4 _) p
- SCL=1;( u b3 g1 \# v% ]2 P
- delay_us(2);
' w0 I) s, @6 }% b1 F5 q2 { - SCL=0;
9 E# z$ Y2 m/ d, c - delay_us(2);% @. c* x) \' R. _8 o9 L: w4 r
- }# r, \! g5 } M% p6 P
- }
. z k8 y$ Z/ o( h8 x, w1 r - /*******************************************************************; ]9 V3 c- z* Z. j" F7 u+ j9 h
- 字节数据接收函数
7 e2 R$ |" b2 ^' d& { - 函数原型: UCHAR RcvByte();
# D$ X1 Z' I- w& C/ h" u# x - 功能: 用来接收从器件传来的数据 6 a" @/ t6 r4 s. f* Z
- ********************************************************************/ 1 c0 _; R3 x( y9 G9 m+ W
- u8 IIC_RcvByte(void)
/ a9 E1 B) a7 \* { - {1 d2 t( Z& q( |: _. h, e
- u8 retc;
1 f) Y* l k5 O9 g4 Q7 A4 o - u8 BitCnt;( _4 N" S) k/ K
- retc=0;
& j, V p/ o8 B# j5 f - IIC_INPUT_MODE_SET();//置数据线为输入方式) `# t7 |, x$ a+ i& B. I5 B
- delay_us(1); : B: ~/ z+ N: W' f9 Z0 ~
- for(BitCnt=0;BitCnt<8;BitCnt++)
3 j; F z& Q, F& X1 `# |% G - { 1 l t2 {1 p% x7 x+ L
- SCL=0;//置时钟线为低,准备接收数据位8 O1 |) ?9 ~0 ?! ^ W3 N
- delay_us(2); 8 r. e: y- P6 w# ^' f% R
- SCL=1;//置时钟线为高使数据线上数据有效 2 e( U- T4 P- V' ~6 N
- retc=retc<<1;
9 x5 [: Q9 m1 ?8 N" _! J7 a; i - if(SDA_IN) retc |=1;//读数据位,接收的数据位放入retc中 5 W, C5 {) V2 h5 m. j, v3 j( a
- delay_us(1);$ a, d3 `& C+ P% U
- }
) \* P, l( c3 H6 o - SCL=0; / M3 ?4 ? X p; F, Q( @8 r
- return(retc);
. n- j" p8 W# b I% Z1 r6 ] - }; X w. M' P) u, p
- /*******************************************************************" C4 U; x6 r3 f6 p n( p
- 温湿度获取函数 / E o# L8 t0 x4 y A
- 函数原型: SHT30_read_result(u8 addr);
) l1 m @8 a& }! e - 功能: 用来接收从器件采集并合成温湿度
3 o7 |- f ]$ ^% w' R - ********************************************************************/ # V1 P8 L* s! [- {) `7 c
- void SHT30_read_result(u8 addr)- G, T0 r3 f9 _6 ^( d1 C5 M
- {; x( m9 E; ~6 N7 h8 n9 z8 w
- u16 tem,hum;( m; m4 f: i- {. \4 g0 N
- u16 buff[6];! h2 {$ i _% J E# ^
- float Temperature=0;
, N& [. t d+ u - float Humidity=0;
1 D; h1 M `0 ]6 H9 P3 a1 X# C - 3 e, p$ s+ V8 r) Q, P; J
- IIC_Start();7 l: L" u: c, ~( {
- IIC_SendByte(addr<<1 | write);//写7位I2C设备地址加0作为写取位,1为读取位. x; `, S7 Q% T% L$ a) z/ ]2 P5 j4 b
- IIC_wait_ACK();
3 Y2 Q* ^% ?) s* f8 | - IIC_SendByte(0x2C);0 U9 Y0 D3 q; H- ^: b$ Q6 g6 H
- IIC_wait_ACK();
3 ` h6 w# N0 o: x) q - IIC_SendByte(0x06);. H1 A* k) w1 H5 O
- IIC_wait_ACK();4 S4 E; Y5 f* s' G" V
- IIC_Stop();0 P. p" m1 e# V- F( S' p
- delay_ms(50);
' y: ]7 p. o; L1 e3 t1 s - IIC_Start();
8 ]1 r0 i( T2 y& q - IIC_SendByte(addr<<1 | read);//写7位I2C设备地址加0作为写取位,1为读取位% s* M3 A2 R, S7 K9 Y* j
- if(IIC_wait_ACK()==0)
3 N* Z9 ~& x+ l& h* _5 i - {- o; q. @$ q0 {0 k
- buff[0]=IIC_RcvByte();4 D$ n) u7 k: i# V9 Q8 L3 x
- IIC_ACK();
9 w! C# g( U2 I& V4 B! `7 Z4 @ - buff[1]=IIC_RcvByte();0 Z# n- y* ^; B9 t( r- j
- IIC_ACK();/ u) I; o5 e, i
- buff[2]=IIC_RcvByte();+ q/ K# ~0 I" _3 [: ]& C: r) H
- IIC_ACK();
# v- y- L8 l. B+ S - buff[3]=IIC_RcvByte();
$ ~8 R# B+ n/ }* R3 h1 k5 G - IIC_ACK();" x& w% k N- S$ n3 `" f, Q, [
- buff[4]=IIC_RcvByte();1 u6 g! \- m+ S# Q$ r1 K
- IIC_ACK();# B0 C$ b& O6 j) s& ~+ ? ^# A
- buff[5]=IIC_RcvByte();3 }4 z; E2 e* ]' o& o$ F. U6 o
- IIC_NACK();
! n3 \. f8 g# R& n N( q$ p# L - IIC_Stop();
" G* \$ ^: a2 F* b' n - }" h" ]1 l/ }5 |& g" c
-
) C2 ~. I; x2 { - tem = ((buff[0]<<8) | buff[1]);//温度拼接
9 D8 i5 E, g3 X. B: Q# a - hum = ((buff[3]<<8) | buff[4]);//湿度拼接
3 c5 j9 }3 E2 Y# T - 8 F1 ^3 L5 u" f1 T2 Z
- /*转换实际温度*// c$ p' s7 B9 E) R3 T# z
- Temperature= (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)& T; @# l+ B( s6 O4 _" J
- Humidity= (100.0*(float)hum/65535.0);// RH = hum*100 / (2^16-1)' S. ?8 }% J/ W* b- h
- " c7 v% K( V! ]6 w" t/ z2 k
- if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))//过滤错误数据
5 u2 z) q3 [2 l" V, m- y - {1 H6 z6 J6 I6 m3 m! s1 j
- // humiture[0]=Temperature;& _# x1 r7 O4 H6 W! |
- // humiture[2]=Humidity;+ }- J" l- {( \, Y3 g3 q1 }/ ]
- sprintf(humiture_buff1,"%6.2f*C %6.2f%%",Temperature,Humidity);//111.01*C 100.01%(保留2位小数)9 E3 J* U( @* Z
- }
5 V- X; N+ E* g" |) }1 R; q$ Y - printf("温湿度:%s\n",humiture_buff1);
* z3 d q, T* d2 ~ - hum=0;& L% p, O4 h! _" s8 d0 R
- tem=0;% O+ e* x( ]( ^' j; Q
- }9 I% `! f& T, j }; e @
, f! a9 _3 A, S
复制代码 " E2 v d9 Y: w
; ~& b# T- d9 g& L8 M* v9 y
sht30.h. P$ }4 q& x4 J) b0 [9 t7 Y
- #ifndef SHT30_H5 T) |% V7 e2 m5 c
- #define SHT30_H9 B/ k! c0 v/ D
- #include "delay.h"
/ {# v; @$ r* N9 d - #include "sys.h"* R$ f. o8 T) |5 N% d g
- #include "stdio.h"- P9 @5 m4 X# k: t1 O) T; C. a
- #include "usart.h", x) ~! {, [9 z
- #include "string.h"
' N) h2 n& y- h7 A1 ~4 x - ; |3 ]: N8 M! ]! c" Q5 [
- extern u8 humiture_buff1[20];3 ^! }9 E4 U2 d
- 8 M; ~7 q) ~# I1 a1 y7 v& \
- void SHT30_Init(void);. V9 l0 ?) p* _0 {( S% L
- void IIC_ACK(void);6 B; a) o% M7 t' D: J3 `+ d) _
- void IIC_NACK(void);
; }: T: Z# l! U6 R: C& g' L+ Y2 t& x - u8 IIC_wait_ACK(void);
& S5 u% `$ ~0 i* |2 {3 _ - void IIC_Start(void);
, l N' l: Q+ g; c - void IIC_Stop(void);$ i! N" O5 l$ j- g9 `
- void IIC_SendByte(u8 byte);% R5 f' l% L0 J( p Y0 Q
- u8 IIC_RcvByte(void);6 p8 J4 J3 Z/ a: E; o/ x5 s' p
- void SHT30_read_result(u8 addr);
( r0 d- U( s4 t* u7 y1 D - , E1 Z n4 g" G2 f" p W
- #endif$ z0 r% g& E [4 t
- , A6 v4 M) q3 N8 U* N
复制代码 3 j7 X9 {) m) b3 M o$ a+ |
9 Z* n y0 i( y) z1 @主函数(while循环可以写个测试的printf)% y' Z, O0 d9 z* w8 I: \, h+ s* h. ~8 G
- #include "delay.h"- {9 t6 `/ G. O U3 x, C
- #include "sys.h"
, l! i% b! \0 y! @7 q# Q - #include "usart.h"3 ~+ N' }9 P/ d) Y }
- #include "SHT30.h"
2 J' t8 ~% R. i4 V* Y7 T. Y4 }" D -
2 Z3 K! \" f4 g& A
3 I+ f! m4 r$ l) ^# e) j$ J3 }- int main(void)
" o! ?$ z- u. Z) G+ Q4 v - {
3 ~/ p( b( z8 J$ `) w: o - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2* G. v9 _! r3 {" ^ u+ x* Y2 H' {8 v
- delay_init(); //延时函数初始化 V1 M1 W5 N/ |6 y4 ?# P+ q
- uart_init(9600); //串口初始化为9600+ m# j! @* F" _8 S6 P' n0 Y
- SHT30_Init();
* c3 v; g2 z2 N, E: k - while(1)
' P& C5 a# ?7 k% C$ q2 q - {
' P' y/ i! l; n/ K4 p6 ^- \ - //printf("123456");" p) B1 K) M- a: F
- SHT30_read_result(0x44);
; I/ E/ j4 I$ o4 Q2 d. } - delay_ms(300); 7 E8 C9 l# c1 r2 W% c
-
! A/ p9 _, R9 V! Z: d - }6 ? [# E7 B \
- }6 O" M4 I$ C( X" N2 x+ M
复制代码 3 U8 o% Q; Z# u! U/ J+ w
9 ~5 u& I$ P- ?0 ~- ^代码实测能用 ,直接复制即可, 但是如果想改端口继续往下看。
8 M4 q2 A- T6 a- z( @
0 g% K2 a1 h# V: R5 ^
4 R; ]+ z5 \: u' K4 y+ i9 F# ?! R3 B" U( G6 \, w1 {0 q
* ^# w5 L$ E0 d n4 m; n4 I上图红色框选的是换端口所有需要改变的地方 这里漏框了上面的几个宏定义, 上面几个也要改。! i- z( J: L- ?# L! M' |! q- v
3 q1 U) Q4 `- F& n# Q: B
/ K, O7 l! P! Y Y
Y& Y& H" u5 m7 O
GPIOA->CRL&=0XF0FFFFFF;理解为 清零了32位数据中的4位
7 |- L; C8 M" I* q8 X4 }5 QGPIOA->CRL|=8<<24;理解为置位了32位中的(24,25,26,27)的值
1 M' b6 x4 v, Y/ `, k+ u# @$ _1 s% ~4 y+ G D
7 P) F% F" G9 Q2 I$ H1 [" U2 p5 k( u7 h" l% H3 w
( v: z2 m& a& H1 M
7 {! P, h! Y3 m* b5 n
9 Z. d' l. l0 |' m5 B/ S/ o H
0 M( S1 k' R3 e i! H1 b上面两副图来自stm32中文手册 ,意思很明了, 有两个寄存器用来配置io口模式,CRL配置GPIO0-7, CRH配置GPIO8-15,第三副图是教你具体怎么配置,按照手册就可以选择配置你想用的端口了。
! n/ H/ Z v( G' ^$ p1 T————————————————" d2 ^- D; z) v+ c* ^+ {7 q
版权声明:文某91 O; H9 g9 ]; b
如有侵权请联系删除
9 ?$ D$ l3 ~" [# \" K7 q9 F5 N% U/ ?# C: u3 P' J
) I5 R5 B" [4 T- p+ h; o
% z7 ?6 n# C7 f3 {" ` |