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

物联网之STM32开发六(ADC模数转换)

[复制链接]
STMCU-管管 发布时间:2020-9-28 10:09
STM32-ADC模数转换内容概要:

STM32-ADC模数转换概述

STM32-单通道采集实例

STM32-多通道采集实例


6 g" [- L8 N+ s/ [, X% S

STM32-ADC模数转换概述3 X2 Z$ r* p2 ^2 n' c4 Q' B9 E! a

内容概要:

ADC简介

STM32F0-ADC时钟

STM32F0-ADC转化模式

STM32F0-ADC转化时间

STM32F0-ADC模拟看门狗

) [0 k# M6 g: o- G& y5 k

& B# K. Q( i8 c

ADC简介:

ADC的作用:采集传感器的数据,测量输入电压,检查电池电量剩余,监测温湿度等。


3 E% |, |3 M" Y

ADC的性能指标:

    量程:能测量的电压范围

    分辨率:ADC的分辨率通常以输出二进制数的位数表示,位数越多,分辨率越高,一般来说分辨率越高,转化时间越长。

    转化时间:模拟输入电压在允许的最大变化范围内,从转换开始到获得稳定的数字量输出所需要的时间称为转换时间


! d$ Y( ]: `$ s; A( y4 C( t

1_meitu_1.jpg

' T; i$ C6 N  k; d6 p3 W" X

STM32F0-ADC特性:

5 ^+ Z3 j% M4 {) ?1 ~& ]/ ]9 W

2_meitu_2.jpg

( Z% ^/ }' P- S( F$ m

12位精度下转换速度可高达1MHz


/ p& P8 k+ n7 ^0 C* _6 L* T

可配置的转换精度:6位,8位,10位,12位

转换电压范围:0 ~ 3.6V,V SSA ~ V DDA

供电范围:2.4V ~ 3.6V

19个转换通道: 16个外部通道、 3个内部通道

8 \/ V- l1 K1 w" B& X

采样时间可配置


1 |" x& Q9 O- M2 C* ~# D

ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中

5 v; B" D4 |6 `/ G( `

STM32F0-ADC时钟:

& U" m! Y. |1 Q7 u, V

APB时钟的2或4分频,最高14MHz

优点:不会有时钟域之间的同步带来的抖动,触发事件和转换的起始时刻之间的延迟是确定 的,从 而保证转换之间的时间间隔是固定的

缺点: ADC的转换时间和系统时钟频率相关,受系统频率的影响较大


) s+ B) M4 A! |8 C9 c


+ W( t; Y+ {2 U! T

片上14MHZ HSI RC振荡器

优点:无论MCU的运行频率,都可以保证最高的ADC工作频率可以使用自动节电模式(自动开启或关闭14MHz的内部振荡器)

缺点:触发信号的同步会带来抖动,触发事件和转换的起始时刻之间的延迟不确定


, r3 Q/ O% Z6 E2 ^. s

# H/ E9 l0 L- V7 q$ _' j

3_meitu_1.jpg

: y- ?9 p+ Z0 y2 E2 R% ~

STM32F0-ADC通道的选择:

4_meitu_2.jpg


& S1 y3 M$ T: N* \; T/ G9 a* m8 W8 P6 X

19路复用通道:

    ●16 个从 GPIO 引脚引入的模拟输入 (ADC_IN0...ADC_IN15)

    ●3 个内部模拟输入 ( 温度传感、内部参考电压、 VBAT 通道 )

ADC 可以转换一个单一通道或自动扫描一个序列通道。被转换的通道序列必须在通道选择寄存器 ADC_CHSELR 中编程选择:每个模拟输入通道有专门的一位选择位 (CHSEL0...CHSEL18).


+ E4 I" T0 V; g


5 E9 ~' H( [) d1 t8 w5 B- N

STM32F0-ADC转化模式:

5_meitu_3.jpg


! j( }" e/ o9 `6 T, H& c
- z: C9 X" G+ ~( Z

注:  ADC 通知应用每次转换结束 (EOC) 事件

         ADC 通知应用每次序列转换结束 (EOS) 事件。

         这些标志位都是在ADC 中断和状态寄存器(ADC_ISR)中  ADC_CFGR1可配置COUNT位 。

         每次有一个通道在转化结束之后( (EOC) 事件),必须先读取出数据寄存器中采集的数据,然后才能采集下一个通道。


3 i2 a, \& C; D5 ^) S3 X! }7 @

6 G0 r8 i* M% r

6_meitu_4.jpg

9 |  v6 q8 c. i3 ~* i

7_meitu_5.jpg


4 q. ~; \2 T4 v. w* [3 E9 D7 a: ]5 ?, P+ k

STM32F0-ADC转化时间:

可编程采样时间 (SMP):

      T Sampling 可配置:     SMP[2:0]@ADC_SMPR

      需要和外部电路的输入阻抗匹配,采样时间适用于所有通道


4 z" O  I. P9 P0 M+ m9 E$ X

转化的时间:

T conversion 取决于转换精度: RES[1:0]@ADC_CFGR1

: E* w7 F9 y' J7 S4 e: b8 Q7 v

8_meitu_6.jpg


1 O# u1 I6 S7 \( u
$ c3 x' k/ o0 i  _

每个通道总的转换时间等于:  T Sampling + T conversion (采样时间 + 转化时间)

转换时间快速预览表:不需要高转换精度的应用,可以通过降低精确度来提高转换速度    假设ADC模块工作在14MHz的最高工作频率下


6 r& X) ]. Z0 Y# J7 k

& x# v6 [! ?( p4 |" i( E, N6 i3 H5 j: ^

9_meitu_7.jpg

% ]: R: l% ^. E; B
# {3 T# T  r& w

STM32F0-ADC触发方式:

软件触发:软件设置ADC_CR的ADSTART=1 时,触发选择有效。

外部事件触发:外部事件 ( 例如:定时器TRGO、输入引脚 ) 触发,可以设置触发源以及触发极性


1 {, j# F" N4 f# o4 u, r9 A


7 b" v2 W" ~+ t* h) A

10_meitu_8.jpg

" w! e: l( U7 v2 E0 I

( {! w- N& M4 ~2 I' ]: c; q

11_meitu_9.jpg


7 M9 j0 m/ `4 a0 L* `: @5 d' ^1 o6 D! \

STM32F0-ADC模拟看门狗:

/ g" P% e& [3 ]4 z' P0 y

12_meitu_10.jpg

1 m9 x8 H' Z( J6 |# D0 `! K8 D

检测待转换的模拟电压:(简单的来说就是检测到电压值不在预设的范围之内,则产生中断,在中断中设置报警等处理措施)

    电压超出检测范围就置位AWD@ADC_ISR,并条件性地产生中断      

    检测范围由上下门限寄存器指定、 12位的ADC_HTR和ADC_LTR有效值


) Q- ]5 ]) k  a3 p* V) o: g& v

模拟看门狗的使能控制:

    AWDEN@ADC_CFGR1      

    检测所有通道还是单个通道由AWDSEL@ADC_CFGR1决定      

    检测哪个单个通道由AWDCH[4:0]@ADC_CFGR1决定


/ l' O; ]- `: @( C7 h9 [/ z3 _  q

% l3 w  s7 o& A' J  l' {

STM32-单通道采集实例
# T) C/ m* P+ s3 m/ D

实验要求:利用ADC采集光照传感器的数据,并在中断中获取采集的结果


7 Z. [( ~" Y% D$ b, u6 W: I- v% W

: U' N) V, j' H

13_meitu_11.jpg


2 n) k$ v0 Y2 F2 ^
% T7 D1 J' `0 q% k

注:光敏电阻光强越强则阻值越小

# w+ ~' ?* B# w0 o

过程如下:

+ f4 C, y- f3 d" W

* c( X% C4 i0 f

14_meitu_12.jpg

3 e: n- q! {. E, h& Y
, D; j+ Q6 W& I% t- Z% I1 F

15_meitu_13.jpg


& C) G1 U3 c( H- v* T6 a# a  o; ?5 B% ^3 Y- N8 t5 Z- n

16_meitu_14.jpg


1 z9 _" f9 G0 h$ w1 \
0 y0 ?) a$ b0 W. K: {2 u/ o- ^# t

17_meitu_15.jpg

$ [7 n, W6 z8 k( s2 w+ a
$ p* N. R2 ?0 B7 U

18_meitu_16.jpg


; ^1 H% o, X& n/ i$ }. k6 K
5 F" R% f) x  u' p

19_meitu_17.jpg


. S$ S' k8 E' o- h
& s- r: M3 g" |7 S5 A

20_meitu_18.jpg


! h; {" ^9 y6 f: I1 |5 r  ]) }4 W# h8 M* x

21_meitu_19.jpg

7 t5 t# B4 @! c% ]- I

22_meitu_20.jpg

. t" O& Y1 h" ^+ D& e
: |2 o) R# h% _8 y0 M4 K& V

main.c中启动ADC并使能中断

23_meitu_21.jpg

) F1 _4 t9 R  M; [5 t

/ z$ Z$ i5 Y6 Z8 ]( O5 QHAL_ADC_Start_IT(&hadc);//启动ADC转化并使能中断

追加到回调函数(可以在向量表中开始追加,也可以在中断程序文件中(.._it.c表示的就是中断程序文件)追加)

main.c中重新编写fputc函数,adc.c中重新编写回调函数:

5 a+ A# S7 h' z# K7 _# Z


  1. 4 z; N: l4 K; k
  2. int fputc(int ch,FILE *f){       
    , w, }0 ~: G6 I- i) G1 o$ Q# h
  3.     while((USART1->ISR&(1<<7)) == 0);        - u( u) b6 {8 A! z1 _5 C7 [  c
  4.     USART1->TDR=(uint8_t)ch;$ u1 H) E2 X' @3 j  t9 {" r: b9 n
  5.     return ch;
    5 F1 I6 b+ i6 f# I9 s9 \
  6. }
复制代码
  1. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
    " w! H& l* [# K! K! f/ m( f, I
  2. {
    " e' T0 W: }0 D
  3.         uint32_t light_value;7 p1 B' E1 _+ L- v
  4.         light_value = HAL_ADC_GetValue(hadc);  //获取ADC中数据寄存器采集的值0 B$ k3 g1 M5 N9 I8 W5 O
  5.         printf("light_value = %d\n",light_value);9 d8 P$ l6 U2 K1 g, R/ e
  6. }
复制代码
* e9 Y! n4 K: \9 f* o8 L% N

测试结果:

( V" [( p- r7 B3 w8 ~3 \


& D9 l- J- l" O$ m* _" M

28.png

$ N+ A  B; K0 t/ w. c3 X
. N, k$ ?$ U/ ~" q! l
STM32-多通道采集实例

实验要求:利用ADC采集按键以及光照传感器的数据,并在按键中断处理程序中打印采集的结果

原理图分析:

29_meitu_27.jpg

+ z( e1 z8 K( ]+ G
$ h* p1 e7 E. j7 M; h

实验过程:

30_meitu_28.jpg


1 Y! Y1 h& O8 x1 f) |, c1 |: w; h
4 E! c$ d+ Q1 R$ Y6 N

31_meitu_29.jpg


1 I/ j0 o# r+ Z4 |- Y" x' n
* D' N& C- ~1 w( r" B2 o

32_meitu_30.jpg


% S4 u6 ]6 u2 d1 P$ Q
1 E( [) X! F5 I" Q' K. z- a0 W) l

配置ADC功能,因为是由按键中断进行采集,所以配置可以随便选择

33_meitu_31.jpg

9 m$ z9 Q* P7 U$ G  d9 X

打开按键中断:

34_meitu_32.jpg

2 Y8 W9 f% i9 Q" V
; ^2 Z3 ~1 N, A, G& d. V

导出工程:

35_meitu_33.jpg


5 ?( h; n- V5 r: k
% p" l7 F$ u' H

36_meitu_34.jpg


6 A& |4 ~  j! d1 G+ A4 }. l  F  h% _; C2 V  b: Q: q& [: j

追加到按键中断回调函数

37_meitu_35.jpg


' u+ }3 z( F+ a1 t7 w

38_meitu_36.jpg

  }2 K1 B+ w& L
8 Q" `+ h/ X" d- K- Q

gpio.c中重新编写fputc 和 回调函数,添加必要的头文件:


8 Y% w7 w  Q! L


* ~# z; y7 M2 d4 s* D( o) Q

39_meitu_37.jpg


. I6 |. v8 z. x) V' [4 ^+ r6 M
  1. #include "adc.h"
    " X* k* e) C, _& L& }
  2. #include "usart.h"
    7 m# s: Y4 v/ {

  3. , ?( \6 M9 I5 _# Z9 N
  4. int fputc(int ch,FILE *f){        1 k( ]% X% D- i( O# D. N0 L
  5.     while((USART1->ISR&(1<<7)) == 0);        6 Y, b; ]# ]) ^; T+ c
  6.     USART1->TDR=(uint8_t)ch;9 N6 [9 L6 l0 u, [/ A8 c
  7.     return ch;2 c1 H$ R6 y4 ^* F1 a4 P& p* n( Z
  8. } - M) S, G; N3 r
  9. 0 c7 }& x5 C* Q  f) W! u% _
  10. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    5 q0 w" k7 k  h9 m5 t" P2 X
  11. {1 _' K' @8 H# W/ T, K
  12.         uint32_t temp = 0;- m6 h( Z6 Z2 N! I7 r  N
  13.         if(GPIO_Pin == GPIO_PIN_8), F/ N4 E# O6 q* v0 i
  14.         {
    8 u) X6 Y/ P1 I0 p$ G
  15.                 HAL_ADC_Start(&hadc);   //启动ADC
    3 M, ?! ?" D9 P7 `+ J0 u
  16.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束2 }+ S* q) c& D5 u- d0 k
  17.                 temp = HAL_ADC_GetValue(&hadc);; ^6 O% k7 p. A% U3 u7 t
  18.                 printf("key adc value = %d\n", temp);8 }0 B, e- V. {" l6 C/ K
  19.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束
    - E5 I+ T7 U5 p
  20.                 temp = HAL_ADC_GetValue(&hadc);3 e) S1 H# b& V; X, k. J5 T
  21.                 printf("light adc value = %d\n", temp);+ B' K1 _! `& f
  22.                 HAL_ADC_Stop(&hadc);  //关闭ADC7 D+ g9 U( N' h+ O8 Y: R+ k: q8 X
  23.         }
    / o6 r$ `2 X6 e
  24. }
复制代码

2 ~" i% {6 Q2 g8 m4 q0 w4 }+ Z1 R8 E7 S& W0 ^: j% [% K

4 [& h, s/ x6 G2 ^" T/ V% C* Q1 ]* ^4 j0 c6 H

测试结果:


7 V/ G$ `% Y- V( r6 h


/ \' D" [; A; u

利用中断和ADC识别五向键,即五向键任一按键拨动时能通过串口打印出是那个按键, F  `6 X6 b+ a8 A2 w; F
2 [: x* Z; x) I. M

41_meitu_39.jpg


- F/ ]- b/ T2 P( L; t; C
" j+ K2 K, s" }- a; R# y4 w

42_meitu_40.jpg


8 _, y2 g! F; w" B" x' w
  k4 J+ a% v6 o/ i* _; x
9 j( Z. U" P" W& @. j; s3 P( h

43_meitu_41.jpg


8 X- O, b7 U/ d! ?, E* [/ `; Y8 E8 H, N

44_meitu_1.jpg

% g: O1 x  J# V) s1 G( @

/ T1 p8 H' [+ D$ u4 e' h

45_meitu_2.jpg

  g1 ^9 w8 @) u% b& g3 i' I
" ]3 T8 g7 W0 ]) l6 a

46_meitu_3.jpg


' I+ d+ B/ S3 B! y; s- w

  1. 4 y0 x% ]+ ]3 b7 Q; x
  2. #include "adc.h"+ b) ]4 @5 @& b
  3. #include "usart.h"8 g( }9 g0 w4 S

  4. : _& g, S/ Y9 f! H4 u
  5. int fputc(int ch,FILE *f){        ! `. `# t9 |2 t) Z1 ~
  6.     while((USART1->ISR&(1<<7)) == 0);       
    , z  A7 w+ n7 j+ \& I$ h3 G& s
  7.     USART1->TDR=(uint8_t)ch;- U$ a; E, a, ^2 {
  8.     return ch;, M  b8 e  Y9 Q' F# ?% ?/ _
  9. }- c) r: D, Z' r$ u2 z0 ?
  10. 4 u$ z: G4 B! d# B$ I
  11. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    6 E2 r9 {7 Z. O$ P1 M1 t1 A$ [
  12. {
    0 v# ]" l* g9 ~
  13.         if(GPIO_Pin == GPIO_PIN_8); e$ V' ~3 ?( X5 \* Z: w" I) ~4 i- g
  14.         {
    - M6 s) n/ H* |. V
  15.                 uint32_t data = 0;, q6 g% z9 _% H. g
  16.                 HAL_ADC_Start(&hadc);
    3 q1 U6 ~2 l. p$ F) ?' e0 s7 f
  17.                 while(!(hadc.Instance->ISR & (1<<2)));
    * e+ n7 Q! e! e, Z" ~: U
  18.                 data = HAL_ADC_GetValue(&hadc);* L! ^) o' l7 a: [
  19.                 printf("key value = %d    ", data);. n7 ]( ~: Z6 z# t
  20.                 if(data > 0 && data < 500)- e% ?9 @0 r, f' T% i: B, H
  21.                 {3 D; i' U& M) v0 [' x
  22.                         printf("下边的按键被按下\n");3 S% l& M* W5 X  K! J" ]
  23.                 }' i' V, P1 ^3 M- O: G+ N/ l
  24.                 else if(data < 1600)
    & a) N& v' \2 H$ [9 D
  25.                 {2 L# O9 H# B- r7 G) y0 ?4 d
  26.                         printf("左边的按键被按下\n");
    ! W5 W+ J& \& P9 k9 c
  27.                 }
    " k% m8 |7 R' N- Z+ C% O2 O. S
  28.                 else if(data < 2200)
    ! b/ v8 r' y, N; p8 W
  29.                 {1 J1 b: ?: G1 {
  30.                         printf("上边的按键被按下\n");. B9 m1 q0 s3 u4 s! d2 I6 {
  31.                 }
    * R/ u4 I# J* s* ?6 M1 t
  32.                 else if(data < 2700)' H! x" Q! i8 s% C! f
  33.                 {
    2 L! E# h- ^( \
  34.                         printf("中间的按键被按下\n");
    6 ?( ]+ B; i9 l0 r1 U# ]' H2 E3 s
  35.                 }) E  G& A. _3 X! ~6 i( r
  36.                 else if(data < 3100)$ L$ d: [8 F- f) a2 o% t3 D9 {9 b
  37.                 {$ F9 ~( j8 d; \7 G5 ~' k6 p
  38.                         printf("右边的按键被按下\n");
    / N& s7 e  h, `; A9 R' c% w
  39.                 }
    ! N$ H  N1 m1 ?& i7 D) U
  40.                 HAL_ADC_Stop(&hadc);
    ' C% h* U  c4 q+ ]
  41.         }
    ) U$ R( ~6 p& j2 i
  42. }
复制代码
# K+ u7 X8 \/ m

实验结果:


2 L( w6 k2 _" R

47.png

6 h# f7 ]' b& s4 e' C: K) b% o

1 Q" `7 {0 o1 D# u9 `
24_meitu_22.jpg
25_meitu_23.jpg
26_meitu_24.jpg
27_meitu_25.jpg
40_meitu_38.jpg
赞 收藏 1 评论0 发布时间:2020-9-28 10:09

举报

0个回答

所属标签

相似技术帖

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