你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32 光敏传感器示例

[复制链接]
STMCU小助手 发布时间:2022-6-15 17:00
01. 光敏传感器简介6 g0 b! Q2 l: y9 i, f2 I  O8 _
光敏传感器是最常见的传感器之一,它的种类繁多,主要有:光电管、光电倍增管、光敏电阻、光敏三极管、太阳能电池、红外线传感器、紫外线传感器、光纤式光电传感器、色彩传感器、CCD 和 CMOS 图像传感器等。光传感器是目前产量最多、应用最广的传感器之一,它在自动控制和非电量电测技术中占有非常重要的地位。: `3 k  e5 }* D4 h3 I  V
4 }/ J) E2 g* ]% g- f6 _
光敏传感器是利用光敏元件将光信号转换为电信号的传感器,它的敏感波长在可见光波长附近,包括红外线波长和紫外线波长。光传感器不只局限于对光的探测,它还可以作为探测元件组成其他传感器,对许多非电量进行检测,只要将这些非电量转换为光信号的变化即可。
! Q% r/ @, [! c+ }" r+ }0 H: u
3 ?# l( m" B6 S% \7 c探索者 STM32F4 开发板板载了一个光敏二极管(光敏电阻),作为光敏传感器,它对光的变化非常敏感。光敏二极管也叫光电二极管。光敏二极管与半导体二极管在结构上是类似的,其管芯是一个具有光敏特征的 PN 结,具有单向导电性,因此工作时需加上反向电压。无光照时,有很小的饱和反向漏电流,即暗电流,此时光敏二极管截止。当受到光照时,饱和反向漏电流大大增加,形成光电流,它随入射光强度的变化而变化。当光线照射 PN 结时,可以使 PN 结中产生电子一空穴对,使少数载流子的密度增加。这些载流子在反向电压下漂移,使反向电流增加。因此可以利用光照强弱来改变电路中的电流。
4 f: M# Y) K5 X, \5 E
, F, x& R9 {3 L  e8 Z利用这个电流变化,我们串接一个电阻,就可以转换成电压的变化,从而通过 ADC 读取电压值,判断外部光线的强弱。
, V" n* m; D1 z" g+ Z& w1 X+ C; y0 |/ H) G
02. 硬件模块
: ~" X- i7 ~$ d( o用到的硬件资源有:" d. S: w/ Z' P  o$ x9 A, G
1) 指示灯 DS0+ ]$ G  f+ n# e; B. Z- r6 z* ?, B3 g
2) TFTLCD 模块
7 R7 S( ?' v6 N$ g3 F. [" Z: i8 q3) ADC; |0 w  C- `, Y8 _
4) 光敏传感器& E1 O( }( h  R/ T) ?8 e

) `( i' n5 W7 L1 ? O[EGGKG5))YC)5L(YW12KXX.png ! X. k( Q; y( v' Q
# g' N5 U! S- T0 N! n
LS1 是光敏二极管(实物在开发板摄像头接口右侧),R58 为其提供反向电压,当环境光线变化时,LS1 两端的电压也会随之改变,从而通过 ADC3_IN5 通道,读取LIGHT_SENSOR(PF7)上面的电压,即可得到环境光线的强弱。光线越强,电压越低,光线越暗,电压越高。3 c7 u- H" Y6 o/ `

  B  Q. u0 t1 B- d- P' ^+ d03. 程序设计# R2 v7 I2 R( W$ M: g" H
adc.h文件/ @/ k( i8 S# J2 ?! g2 q

' ?: H4 l. s: g" n1 W
  1. //-----------------------------------
    2 ~# P. H0 h8 p5 z- h* U2 N5 U
  2. //ADC3通道初始化+ A7 x, |% Q: l' U: T3 x
  3. void ADC3_Init(void);; e5 r* k( B& q% `7 L. [
  4. //获取ADC3某个通道的值. Z1 p$ f( J" z$ K8 C
  5. u16 Get_Adc3(u8 ch);
    6 {& Z9 z+ y$ B" \! L9 |- I
  6. //获取某个通道给定次数采样的平均值
    # P) l" S. ^* l9 H$ ~
  7. u16 Get_Adc3_Average(u8 ch, u8 times);
复制代码

7 V( e8 Z5 q* I. z' X4 Xadc.c文件
+ ?" Y! ^5 t( d) m0 }4 _- j, v/ Q5 a/ T9 r+ w+ N4 [- \
  1. //-------------------------ADC3------------------------
    : M3 J! a; L0 ]& Y% i
  2. //ADC3通道初始化" ]. W$ ?# |1 n1 }4 Y" L
  3. void ADC3_Init(void)8 h2 r: T; k+ [/ p
  4. {
    + ~' X1 q/ P/ J# O# p9 y1 r0 [! x
  5.         GPIO_InitTypeDef GPIO_InitStructure;  j& p3 J! t9 z2 j8 P! v. }, _
  6.         ADC_CommonInitTypeDef ADC_CommonInitStructure;) P3 c3 Z8 s! H3 u/ I
  7.         ADC_InitTypeDef ADC_InitStructure;
    ( e  r* p% g, [0 C+ M
  8.         4 ?6 j7 j% `# Q% Y) C+ r
  9.         //开启GPIO时钟 PA5
    4 {) ^& R6 D; z/ a7 `
  10.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
    . H! w; q& B3 o: y3 `2 B
  11.           P; S5 E4 C. C- a$ s1 x
  12.         //开启ADC1时钟
    : ]5 `  z+ Q7 e  k% W- p" Z9 Y, r
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);        
    " ^0 Q5 p* t- n6 d# A+ e  g
  14.         
    * j+ o7 K7 l9 B+ q) z/ n0 g
  15.         //GPIO初始化 初始化为模拟功能
    8 H2 _0 x1 i- e" e
  16.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;, O" d8 U, Q! w* }2 r2 F8 W
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    6 L  c4 F; d& n! n
  18.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    . }. x+ P& x# u0 w
  19.         GPIO_Init(GPIOF, &GPIO_InitStructure);
    ! W+ ?3 h( a) b7 S/ h
  20.         7 ^( i$ c; B5 r
  21.         RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE);          //ADC1复位
    . P+ q, i% m9 p- Z! t# U
  22.         RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE);        //复位结束        
    0 {7 H5 K# i3 b3 g
  23.         
    " t2 O# \8 ]! l; ^4 u; j
  24.         
    : d" I$ d$ J3 W5 P& Z$ `
  25.         //初始化ADC_CCR寄存器
    7 Z3 I4 x" ^0 B( K, @' j* u1 n

  26. ' v" M% u$ G0 ~' i9 Y6 W# z
  27.         ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;7 D" y# G) y9 l0 b# o
  28.         ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    $ I* P3 S% W9 U
  29.         ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    - a2 {0 p; y; R8 D1 Z
  30.         ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;; y5 O0 N0 T1 t! Q/ H5 B
  31.         ADC_CommonInit(&ADC_CommonInitStructure);
    7 D4 N6 H% z4 ~& m5 ]/ p
  32.         
    1 W  x4 n# H9 m8 g' [

  33. ! [; f3 z8 d% R& x. ]( Y
  34.         //初始化ADC1
    0 B$ P! T0 _) K2 `8 v4 u' l3 Y
  35.         ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    9 _2 o. U. M) B/ i! q- `) w6 c, |# ]
  36.         ADC_InitStructure.ADC_ScanConvMode = DISABLE;8 s  q7 R; q9 J
  37.         ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    9 g! |& D# c  K
  38.         ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;8 L4 g0 K2 r- z3 K3 D; p* [4 p
  39.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ! V+ P+ q6 r9 P4 f$ v
  40.         ADC_InitStructure.ADC_NbrOfConversion = 1;
    ( ?0 i9 w  s3 O5 i7 D; S8 V
  41. $ N6 ?% L. v0 p& w# J0 n
  42.         ADC_Init(ADC3, &ADC_InitStructure);
    & I, y2 }5 O% V% {& x! O
  43. 3 K4 f0 q  |# e
  44. 2 n; n0 _2 ]2 t+ \8 L7 b* B% o
  45.         //设置ADC规则组通道 一个序列 采样时间
    5 [% j1 v# L6 c, m+ c6 G+ U
  46.         //ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_480Cycles);
    ; T7 A2 f6 C5 W
  47. 0 {. N. N; X+ {9 o$ P
  48. 0 M! {  |0 b6 v3 |" v
  49.         //使能ADC
    - T8 X7 B# j! s
  50.         ADC_Cmd(ADC3, ENABLE);
    % R% f) g* y8 E. C. }
  51.         8 @& F4 ]! u+ a+ ]. D1 H' a
  52. }
    ! a; p9 _0 h* M8 ]+ T
  53. 5 U& D4 J  e/ k; ?
  54. //获取ADC3某个通道的值$ B$ B. o  Y& U1 v  z5 R6 ]+ ?6 G
  55. u16 Get_Adc3(u8 ch)
    % d% p  \6 u, c9 m" s! p# L! a4 `
  56. {  d% @+ ?: `6 R% i% _
  57.         //设置ADC规则组通道 一个序列 采样时间: R8 e( u9 }. B' b4 A
  58.         ADC_RegularChannelConfig(ADC3, ch, 1, ADC_SampleTime_480Cycles);
    7 U7 d' t6 m& V# h  m9 e3 g
  59.         9 R7 X: @7 p7 t# g
  60.         //开启ADC3的软件转换启动功能# q9 P% ?1 F" U9 K) d
  61.         ADC_SoftwareStartConv(ADC3);
    , `9 J4 \/ [. M! p& `
  62.         * T3 j% m  L; |
  63.         //等待转换结束
    2 U* Y: C9 N2 ^- j5 C
  64.         while(ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET)
    2 E2 D. n4 V4 J* s% U. b+ ]
  65.                 ;
    3 d( O) b, A# A; S& X- b

  66. ! Z6 u6 \# V( q* p
  67.         //读取ADC的值# p2 j$ T! T9 U. g: c0 e  y1 e1 p* C
  68.         return  ADC_GetConversionValue(ADC3);9 h2 r# {( J* c) @# Y+ h, x; ]
  69. 6 o; Z. g) F* k/ o2 ]6 h
  70. }; ^" j( L+ B) T7 ^3 L- m

  71. 4 _8 J2 N) ?: x- J7 q" Q
  72. //获取某个通道给定次数采样的平均值
    : X2 |( E1 i7 Z/ l+ O2 d
  73. u16 Get_Adc3_Average(u8 ch, u8 times)
    3 Y( I: {1 m) T7 q4 a
  74. {, @. p( \0 n' L
  75.         u32 tmp = 0;
    " [! l: Q8 j! p6 Z' d
  76.         u8 i = 0;
    , M' A8 M  U3 d5 v; W
  77.         0 C! Z' P" \7 O0 h* W# D
  78.         for (i = 0; i < times; i++)+ u0 M' j' ]) t  I" ?  J& t
  79.         {
    $ O) g& p4 \2 Q$ x
  80.                 tmp += Get_Adc3(ch);
    ( D7 J& Z0 ?2 `. _+ A
  81.                 delay_ms(5);
    ! {. U5 Y* A, v/ ]
  82.           V' Q# q: c1 ]" R
  83.         }1 o  g3 V) |. q3 M# A2 V
  84.         . n9 z9 [, c& w" \2 H
  85.         //得到平均值9 @; X1 S, a  c0 h* j/ g. V
  86.         tmp /= times;
    . }2 w  u, q6 s- U/ X3 M6 a
  87.         
    : _" I$ G% W7 E1 k/ P& ^* D
  88.         if (tmp > 4000)
    + o9 O0 r8 S4 _+ U. B' E
  89.         {
    : B0 I' w; ^4 O: p/ {. H
  90.                 tmp = 4000;# P5 Y7 K$ t$ J4 V6 M6 g/ }
  91.         }; y1 j* C9 e  E- Z8 ^
  92.         ( g& ]' \3 e6 f0 i+ r0 L: }
  93.         
    " m5 K  s% w6 e& O' F; W
  94.         return (u16)(100 - (tmp / 40));1 D9 w( x4 Q7 H( I
  95. }
复制代码
1 b! I9 b: |1 J: U
main.c文件2 s$ ?: L+ A: P# J, L

2 P0 K1 G) N- J$ n2 B
  1. #include "sys.h"7 r' a' J( m  o2 b
  2. #include "delay.h"2 v/ h7 n3 G8 }% T8 E6 v
  3. #include "usart.h"- N  l  @% N& G/ _% K
  4. #include "led.h"( G/ q& \2 u% y8 h  p' f% {; i& b
  5. #include "beep.h"* i: N  p4 N2 `( A5 |" n) c! u( h( x
  6. #include "key.h"3 ]/ c! M  h! d1 m! F
  7. #include "usmart.h"
    , j! e% B% Y) n) h
  8. #include "lcd.h"! b% e5 o9 S, L1 [
  9. #include "rtc.h"
    / l6 \# v: u" M5 T6 j: H1 L3 C$ ^: U
  10. #include "rng.h"/ Z: f3 k+ M* S
  11. #include "key.h"
    " ?- O9 q: ]2 B" W" M& J8 X0 J
  12. #include "wkup.h"+ ~0 F0 U* ?9 r
  13. #include "adc.h") T) z! C+ @  M9 D' @
  14. ) A" d6 f2 u- l
  15. int main(void). _1 O# ?' q" d$ x8 Q& s: O$ {+ d$ F- z7 T7 n
  16. {
    : R& ~0 L% M  U% |) ]0 X5 _, ]
  17.         //u16 value = 0;
    ' i5 M/ i6 `, Q8 Y7 N' y3 r; m) S
  18.         2 g$ I% W& Z5 Y$ u/ v) }
  19.         u16 temp = 0;
    . M8 W4 G9 k3 L' n; s/ o1 U6 q

  20. % h) j4 V+ y* c* g+ a0 f3 _" S1 C. b
  21.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    * W8 ?8 y" u/ @& ~
  22.         # m2 }& f. U1 |6 {. ^- d
  23.         delay_init(168);- i/ U, W' M4 P% i
  24.         
    2 h! \# N* Q8 ~. F2 D% I! A
  25.         uart_init(115200);$ y  S" P7 P) i* v
  26.         1 W5 c3 l! z+ a+ }5 ^$ O" M0 b
  27.         //usmart_dev.init(84);
      S3 g5 T0 p# n9 c9 j; m8 y$ P
  28. 1 I. @0 u: {. f/ k+ Q0 m  q
  29.         , H* @; L6 Q. f- X
  30.         LED_Init();
      v8 S! v# O7 {0 m5 s) q
  31.         3 V3 b" z  V0 B# F! u6 X5 e1 y+ m' N
  32.         , b" T, n2 c0 Z2 ~
  33.         LCD_Init();3 B; o* w7 |2 [/ N0 m

  34. ' ~* f: H$ _+ J7 _4 M
  35.         ADC3_Init();3 S$ G6 h: r% K( {) G/ k8 L7 {
  36.         
    $ g" f# J9 }3 H  [0 i0 n$ \4 a
  37.                 + B0 g# v+ x* ]
  38.         POINT_COLOR = RED;6 c4 O. W8 o7 ^" F; ~& r
  39.         
    7 ?+ k- V% a, z9 L; ]/ s
  40.         LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");        
    5 s1 q! D' _& x  L- u. i- w7 _- j
  41.         LCD_ShowString(30,70,200,16,16,"LSENS TEST");        
    + }9 i# g. A, j; H% z5 ]
  42.         LCD_ShowString(30,90,200,16,16,"ATOM@tom");- A( M/ V/ c6 Z
  43.         LCD_ShowString(30,110,200,16,16,"2020/09/15");         * D. t! i9 e/ F$ C% ^" I, i* F
  44.         * O& N$ _: s  K9 r# C
  45.         //设置字体为蓝色
    4 ?5 d# n7 j) [; R/ J5 v  {' d
  46.         POINT_COLOR = BLUE;
    ; U- W# }% Z$ [
  47.         LCD_ShowString(30,140,200,16,16,"LSENS VAL:");         # [5 D2 r% Z9 t" K" k
  48.                
    9 A* X0 v* u& e' v  b$ W: A' ~
  49.         while(1)
    0 M- A+ J" @6 s% f
  50.         {/ B. ^5 X- M, f2 p1 `
  51.                 //得到温度值
    1 ]$ Z6 I' ^7 t5 b
  52.                 temp = Get_Adc3_Average(ADC_Channel_5, 10);3 m" P% F1 q8 H) I
  53.                
    ' R, R5 M$ C* u0 N
  54.                   Y/ F$ T8 C1 e! i) |
  55.                 LCD_ShowxNum(30+10*8,130,temp,3,16,0);//显示ADC的值
    , c# [6 o& L# k" C( Q2 a- {$ N5 K
  56. # c( {( e" _1 f2 h
  57.                 printf("Light: %d\r\n", temp);" h! \- E3 ~3 x# ?
  58.                
    0 I) z. b- f7 ~8 L) @0 |
  59.                 LED1 = !LED1;
    9 ^, i$ `  e- p1 G' K5 D
  60.                
    " [8 A2 H# _3 g: s6 l6 b4 }
  61.                 delay_ms(250);3 N: C' y, F8 }5 X- t" M
  62.         }
    ' h- Z  K, P; p2 h
  63. }
复制代码

' N+ b! ?  J" m( O  U. X- _1 f04. 结果验证

! J4 |& k$ V; b9 R; G伴随 DS0 的不停闪烁,提示程序在运行。此时,我们可以通过给 LS1 不同的光照强度,来观察 LSENS_VAL 值的变化,光照越强,该值越大,光照越弱,该值越小。0 K2 e1 M" `! t+ ~

7 V1 ]/ V1 V/ ?+ u& o/ m
3 V; B. s6 r  X3 n4 D7 O; F
赞 收藏 评论0 发布时间:2022-6-15 17:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版