- #ifndef __LIGHT_H
) g4 C9 R% H" V5 J" Z6 \5 ]; H - #define __LIGHT_H
5 d/ b. E! F; `1 Z. K9 r - # W5 [, b4 }* F* E: Q' m4 Z* K
- #include "system.h"
$ n9 |+ F, d* r: j& Z6 z - #include "delay.h"
4 j" q. G) A8 ]2 y) P4 }2 U - " \# N8 l( W) h' e' w& {; f& s
- //IO方向设置9 o( w5 W8 s% ~' [- j4 n* T
- #define SDA_IN() {IIC_SDA_GPIO_Port->CRH&=0XFFFFFF0F;IIC_SDA_GPIO_Port->CRH|=(u32)8<<4;}
% g1 f6 w' T! _4 S$ X - #define SDA_OUT() {IIC_SDA_GPIO_Port->CRH&=0XFFFFFF0F;IIC_SDA_GPIO_Port->CRH|=(u32)3<<4;}" u% z0 k8 |5 _" n# l, z; C
* \& N% W% A! o9 r+ r6 }# s+ k- #define IIC_SCL PCout(8) //SCL5 _( t- B8 U. R" [2 U3 A
- #define IIC_SDA PCout(9) //SDA + [- G4 }3 o. A
- #define READ_SDA PCin(9) //输入SDA6 o9 x# R4 I# U" T- x5 M0 U( E1 q
- #define ADDR 0x23 //0100011
. Y# M, }2 [. }1 v) n; X - . D2 p' H: V8 H3 K7 ^) c+ b! f
- #define BHAddWrite 0x46 // 从机地址+最后写方向位
" q4 C& ~+ P |$ N' Z - #define BHAddRead 0x47 // 从机地址+最后读方向位7 k Y$ v) B$ Y+ X
- #define BHPowDown 0x00 // 关闭模块' F V E, z5 c* g: U
- #define BHPowOn 0x01 // 打开模块等待测量指令
' r+ Y4 w" l; m, ^ - #define BHReset 0x07 // 重置数据寄存器值在PowerOn模式下有效" y( |; q- f1 U; O2 u! m# m# F
- #define BHModeH1 0x10 // 高分辨率 单位1lx 测量时间120ms9 h* K; i- s* u8 I
- #define BHModeH2 0x11 // 高分辨率模式2 单位0.5lx 测量时间120ms" P7 u$ |: P* e% Z' g; g: B
- #define BHModeL 0x13 // 低分辨率 单位4lx 测量时间16ms
9 u! \6 H1 x# _+ T7 J - #define BHSigModeH 0x20 // 一次高分辨率 测量 测量后模块转到 PowerDown模式6 U' w7 a: v% s. ~: N) R: q
- #define BHSigModeH2 0x21 // 同上类似: T0 x6 p9 ?* `; ?8 J! t
- #define BHSigModeL 0x23 // 上类似
( ^6 D; x" q/ d& T2 Z - % `. b, k& N! C! F
- void Single_Write_BH1750(u8 REG_Address);
' n. d7 N1 s, u0 e! c7 T/ H - void Light_Init(void);
. w7 L( o& v9 J8 U/ Z, h! x - void bh_data_send(u8 command);
9 {3 ?/ y$ D3 A8 e4 d2 }" D - u16 bh_data_read(void);
% s2 m4 q2 C- q! e3 a! e" ? - , r r* a- e% h4 l
- //IIC所有操作函数
7 Q( T% |& ?0 i7 G - void IIC_Init(void); //初始化IIC的IO口
; w$ L6 h4 {4 ^ - void IIC_Start(void); //发送IIC开始信号
# O. r1 ~. N# {# ]/ z - void IIC_Stop(void); //发送IIC停止信号+ D/ K& C4 f2 i
- void IIC_Send_Byte(u8 txd); //IIC发送一个字节4 Q; t3 W2 W: m* P
- u8 IIC_Read_Byte(u8 ack); //IIC读取一个字节
0 S# m4 h7 z5 @1 B# `7 R - u8 IIC_Wait_Ack(void); //IIC等待ACK信号) B+ K* V- ~2 A& D# G% k
- void IIC_Ack(void); //IIC发送ACK信号9 [: \2 y# J. Z# K4 r
- void IIC_NAck(void); //IIC不发送ACK信号
2 U/ z! C; N9 }2 o
& I) E: j* Q1 q- void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);0 I2 h7 R% Q* q) F" z/ P) F* X! B& J
- u8 IIC_Read_One_Byte(u8 daddr,u8 addr);5 ~3 {4 @. z' l8 P# b8 F6 s5 d1 x
! f$ k U7 z/ {0 I; i; S* Z# j) Z- #endif
复制代码- #include "bh1750.h"( R* R+ k& ~0 m+ A. ?4 X* s6 X. ~
- i) L1 B' a+ f" p$ M# [, @. O, O6 k- void Single_Write_BH1750(u8 REG_Address)9 D% V, \7 m9 y% M
- {
]1 y8 a6 [0 i - IIC_Start(); // 起始信号
2 t% ~0 L7 q* `! u7 M - IIC_Send_Byte(BHAddWrite); // 发送设备地址+写信号2 {& z: J9 e& r* c) R
- IIC_Send_Byte(REG_Address); // 内部寄存器地址,
% s+ s* J8 o$ h" h5 m - // BH1750_SendByte(REG_data); // 内部寄存器数据,/ D, J5 i \9 u: V- n5 ^1 K( N
- IIC_Stop(); // 发送停止信号
# {) Y! ^6 W/ D$ J6 R2 J/ i - }4 z$ |) E# Z% V9 G9 Y5 j$ f5 _& X
. X- M/ a3 K# u7 g p# r! l+ I- void Light_Init(void)) O0 ^# B; `' b& x( ?
- {
0 w" l8 f ]2 i$ \) K9 ? - GPIO_InitTypeDef GPIO_InitStruct = {0};
% w# F% h* r# J6 D( ?
: ?) {; ]. B& t& s7 j& q6 _: \- m- // 使能GPIOD时钟( E8 p8 Q2 b+ D
- __HAL_RCC_GPIOD_CLK_ENABLE();
4 Z* c* u% [0 X/ H3 C6 X
+ w9 e- ^7 B8 [6 o9 X* N/ r! }' v- // PD6和7引脚置高
/ C% C) |/ l2 R6 D - HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET);% P4 b5 B% B$ `! r9 v+ ?% x
- ! o9 Z- b5 V- r1 s; T. ~! W8 Y" o+ l
- // 初始化引脚
, _1 ^( [& ~. \( y+ b7 `; _$ M0 W - GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;* n8 s m6 i& [% k5 L m
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
) @* H7 } g- s8 t' f- m - GPIO_InitStruct.Pull = GPIO_NOPULL;
7 Q# ^* q; b' c7 T! M( j - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
" Q4 S3 } Z% W. I - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
. P4 S" \5 L( j. H) I1 C
0 D# E, f* H, A X/ p- Single_Write_BH1750(0x01);
$ k/ z& i5 y- E ^6 w I5 u - bh_data_send(BHPowOn);
7 b) f! v. j- Y# v9 R+ F - bh_data_send(BHReset);: x. h; k: e: m8 C% i- }' ~
- bh_data_send(BHModeL); //选择的是分辨率是4lx,测量时间是16ms的9 a! a' _% V7 ]: C2 r
- delay_ms(180);0 y+ F) p+ U5 _' {" Y5 Q6 D
- }# J$ s0 A, }% L$ H! e# j6 s' d. K" }2 }
- , Y, f+ P# i* @2 z$ w
- //产生IIC起始信号
5 f; U- m, ~1 y9 P5 j4 ~. ~) D - void IIC_Start(void)- U1 H% Z1 W- f" e! G
- {) l- p) G; v. P: ?7 n
- SDA_OUT(); //sda线输出
( @9 Q. d5 ` W: [ - IIC_SDA=1;: J6 \3 z" J I, u' N7 {; }
- IIC_SCL=1;- X" j ]! x0 |( \7 `
- delay_us(4);
! }% F: m/ z4 X: e7 N# J9 F# f - IIC_SDA=0;//START:when CLK is high,DATA change form high to low! f" Y( x1 t- t: s* ?
- delay_us(4);5 p) i/ o- W/ B: |4 N& G
- IIC_SCL=0;//钳住I2C总线,准备发送或接收数据: I4 q" Z/ Y1 o1 a7 z
- }/ Q, x$ ~$ x' `. l0 K
1 H) z$ O L9 u; T- //产生IIC停止信号" O' U, Q. _3 G
- void IIC_Stop(void)1 z: J3 }' d# `) ]) v: z9 }& |
- {
- b; j J. a8 O4 H4 }; V$ ~ - SDA_OUT();//sda线输出
H0 o: ?# E6 _' E - IIC_SCL=0;3 B$ ^+ m. Z- ~7 c: d+ @+ g( c
- IIC_SDA=0;//STOP:when CLK is high DATA change form low to high4 h; i+ d# M3 ?! M% Q+ r' x
- delay_us(4);& f; y/ o/ {/ X: o4 f
- IIC_SCL=1;, e# m$ y9 u& v; ?" u
- IIC_SDA=1;//发送I2C总线结束信号" s7 g" K" m6 n7 r
- delay_us(4);
7 \7 D) Y/ x/ d - }
; K9 a3 {2 B, A2 ^+ c
+ T1 V2 Q a* v/ b- //等待应答信号到来 `' f' b( I" N4 e* |2 R
- //返回值:1,接收应答失败
+ T4 e! I% Y' d - // 0,接收应答成功
1 a6 ?1 Z3 l& |2 H- @, d, u0 ^6 s - u8 IIC_Wait_Ack(void); A$ t- I* n* l9 ~
- {
( e' L' D) V" y/ p - u8 ucErrTime=0;9 T8 T! Y2 y1 j) e( O0 B( e
- SDA_IN(); //SDA设置为输入
5 A \- J2 W9 R - IIC_SDA=1;
, d6 ?* O! c4 l9 n* _ - delay_us(1);
* }- u' _* p9 L - IIC_SCL=1;
8 L5 T8 _; O# g( _9 e4 ^ - delay_us(1);
1 ~6 e/ R6 N6 D% _* f+ I |& Z - while(READ_SDA)& J% i% z! c, P8 e
- {
8 b9 r; K+ g: C - ucErrTime++;
: P3 ]9 O% `$ j. `* ` - if(ucErrTime>250)
8 F0 W: U1 k& {/ m% ], | - {
5 a' w" r+ Y" q4 Q, n1 c - IIC_Stop();
& S) ~' l" k! [ p1 z r) W Q) z- J - return 1;
* j) q. |. O* \. l5 u) U - }5 r% } W' j* Z) ~) x* k/ k
- }% D# E2 |& }* ?; ^7 V0 c2 x
- IIC_SCL=0;//时钟输出03 N% B* z$ i) h2 z1 k
- return 0;
) X9 ?. I+ R4 q) c+ b+ \ - }
]$ V2 N. R2 \' z' ]9 E. D+ q
' q2 C, y9 o& M7 a9 S5 F- //产生ACK应答
( m3 I4 }5 \0 \7 ]0 n! J - void IIC_Ack(void)
' Y: P# X4 x( T! `( c* q - {- |9 P$ U1 b$ v( x
- IIC_SCL=0;4 _& Z& O* `# h- b4 C# Z% p( D
- SDA_OUT();' T5 m8 }9 Q4 g. g7 a
- IIC_SDA=0; q) b4 E+ R& D
- delay_us(2);
9 L M3 i, j7 q- D - IIC_SCL=1;
8 @6 N$ j! L: }: Z - delay_us(2);
" W- Q8 Z! L" b8 u - IIC_SCL=0;
' [9 l* ?& d3 p8 Y' } - }
& e9 O: ]8 o% [' i s - , P1 `. B! ^: f
- //不产生ACK应答
3 d" Z: ~. O8 @- A/ y - void IIC_NAck(void)
, q) T/ O, V, d8 ~: E9 ~4 t - {# D# \0 u) R- N5 s& i# M
- IIC_SCL=0;0 N; ^2 ^4 V! j9 P3 a: p1 d8 q
- SDA_OUT();
1 K2 e! o7 i0 u- h! v - IIC_SDA=1;) V2 O, F9 |3 z; {
- delay_us(2);( l% q) F C. T# [
- IIC_SCL=1;
) j8 r9 g5 E- a. I; r, a - delay_us(2);
$ \9 `9 S; m6 q1 y - IIC_SCL=0;
5 L7 J3 S5 Q5 R' K3 ]6 M2 l+ ~ - }* Z/ C- v, D* _$ y# o/ _
- - N8 N) x7 J+ s% \' E# u2 N
- //IIC发送一个字节+ W j" L _) d# ]7 ]. M" b
- //返回从机有无应答! A$ U& k7 A0 c: N4 a9 J
- //1,有应答
1 A6 s9 y$ W0 y* L - //0,无应答# J! a( [. @$ b' I, [% R
- void IIC_Send_Byte(u8 txd)
! c! w' q: x9 O3 p3 c# Q5 x, O/ E - {0 P6 n% u* q& l2 [" j: h' M% U" L" e- {
- u8 t;
& j1 J ~6 a) U- { - SDA_OUT();
" B( W& z$ w9 m( Z - IIC_SCL=0;//拉低时钟开始数据传输2 L' c% i* d( w: V; b9 x/ x6 \
- for(t=0; t<8; t++): S6 x' t5 F, O/ V- ?/ p F2 V
- {" E2 r" X+ r" L* `
- //IIC_SDA=(txd&0x80)>>7;. x) p! ~) r2 v2 n! S- N; c5 g
- if((txd&0x80)>>7)
( ]. O( {; M9 y+ a- D4 W - IIC_SDA=1;# f' z+ t2 S8 m+ N$ O" a- u h- }* H
- else
& ?( `) S0 }" t - IIC_SDA=0;
$ s9 r8 ^6 \- Q0 N* X - txd<<=1;: R9 ?6 O( T. B7 B2 X! l
- delay_us(2); //对TEA5767这三个延时都是必须的
5 [# h5 @( \/ d. y' G' [: d* U0 O - IIC_SCL=1;' U) `% _! V' S3 L4 ~
- delay_us(2);
% h/ o2 V1 s$ B2 u3 u) @ - IIC_SCL=0;
. d1 b0 }5 L+ D7 D$ h9 [ - delay_us(2);1 q6 g) X4 N' L" q
- }$ b7 I S k% U$ A2 s+ H1 r' s5 m" r
- }5 `! \0 r0 |6 u: v
- : b/ |* a% m1 @% u5 M; `
- //读1个字节,ack=1时,发送ACK,ack=0,发送nACK9 K$ L7 U7 t9 l8 \. {
- u8 IIC_Read_Byte(unsigned char ack)6 E0 w0 r* {9 e' G3 W9 {- w; [$ M
- {7 b7 X! R+ z4 l2 Z
- unsigned char i,receive=0;
% ?& G8 l' H% q- @& b3 @ - SDA_IN();//SDA设置为输入
+ c* o. T; k4 @ - for(i=0; i<8; i++ )
0 z4 c+ T% c: b% {' r, |5 J9 m7 k - {
3 y+ e3 t9 @( u% @0 s' j- S - IIC_SCL=0;
$ f8 H' \" p2 J" b, E: \' r5 D+ Q - delay_us(2);
2 M. [0 Q8 u! |5 | - IIC_SCL=1;+ x4 A( v$ `8 @
- receive<<=1;9 y7 v2 c2 r! P( N& w" j2 M
- if(READ_SDA)receive++;
' ?; ^6 G! S- _0 c1 H- H - delay_us(1);
# w% U6 F3 Q2 J# s - }9 I) @' F& y+ N( F
- if (!ack)
7 ~" _ O; F- r( {! O) _% m - IIC_NAck();//发送nACK9 [9 f6 {. I1 v' U/ e2 V; O
- else& B; u( C c0 [. Q7 ?
- IIC_Ack(); //发送ACK1 B: n7 N% D; I3 f- j
- return receive;
5 H, B( ?# B2 `" ^7 ` - }
3 ^1 f6 G; a; |( ]- ~6 y - & P' t) G4 O$ P; X1 w% q. I
- void bh_data_send(u8 command)
% Z. t2 I5 ?; o; p8 g" B - {# Z9 j. x/ T- j9 q+ Y, R6 o+ j( ~2 u
- do0 h5 e1 y8 s1 C1 J
- {, S/ q% s- f/ N! I: A
- IIC_Start(); //iic起始信号% |& v3 @6 W6 s& d& U- w
- IIC_Send_Byte(BHAddWrite); //发送器件地址% G- k3 q( s. L5 ]. w9 W2 H( ^
- }
* n8 `# ^' [* ?3 F+ ^. r - while(IIC_Wait_Ack()); //等待从机应答
" u# }9 V* K2 r; ~ - IIC_Send_Byte(command); //发送指令
7 C6 C9 j+ k# Q) v& l5 k& f. V/ M - IIC_Wait_Ack(); //等待从机应答" h9 k/ j) | b0 X" N4 `
- IIC_Stop(); //iic停止信号& ^8 `9 ~( S& ?& ?& o2 L
- }
% Q# c3 H$ C6 H3 e3 a8 h - 9 G; f* ~0 l7 O6 b
- u16 bh_data_read(void)- w, W! b3 Y7 a9 l# D
- {
4 m; B& N7 |6 z" G8 j) U- C7 z& W - u16 buf;1 t# O1 M6 ?: r0 S$ p P! Q4 H) a
- IIC_Start(); //iic起始信号6 R. ^ Z8 g4 h& P
- IIC_Send_Byte(BHAddRead); //发送器件地址+读标志位
* p( c, M) Z7 u' Z& x - IIC_Wait_Ack(); //等待从机应答# v" Y& w, b4 f' I+ Y9 \: l4 S
- buf=IIC_Read_Byte(1); //读取数据, i6 J' k _1 P2 m& o" s
- buf=buf<<8; //读取并保存高八位数据6 [$ d# `* m$ @* \/ [8 a: \8 g
- buf+=0x00ff&IIC_Read_Byte(0); //读取并保存第八位数据: q8 k* o' S' Q+ P
- IIC_Stop(); //发送停止信号" U5 i! U! ~7 k! J- f& L
- return buf;
0 y- N" N: i2 W% E - }
) |2 ?9 R' N8 o8 J6 g, i N' I2 t
& m, ]+ ]; \- i; o* V# \
) E) W2 X) e* N% N2 D+ r
复制代码
Z# r% x" q' Y" e6 B |