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

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

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

STM32-ADC模数转换概述

STM32-单通道采集实例

STM32-多通道采集实例


5 o6 h) P7 m8 C* Q! _

STM32-ADC模数转换概述/ \& E4 Y! Q* N) W) W) M

内容概要:

ADC简介

STM32F0-ADC时钟

STM32F0-ADC转化模式

STM32F0-ADC转化时间

STM32F0-ADC模拟看门狗

/ @% j- C- ]* u


( l' G# |- O! |5 f, W! t

ADC简介:

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

3 S% V8 D' Y0 p' U0 S

ADC的性能指标:

    量程:能测量的电压范围

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

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


! y0 e4 X( @, L0 }# x' W5 S0 }5 U

1_meitu_1.jpg


/ }$ c7 I( @1 T# e* P- g6 m+ D

STM32F0-ADC特性:


; y9 M1 e' Z3 |

2_meitu_2.jpg


6 t8 n( V! w5 K4 g! }: E: P2 a9 h

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


3 D7 q+ {+ z- R% \+ ~% B- B3 H! C3 x

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

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

供电范围:2.4V ~ 3.6V

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


5 a0 `9 P( n% i1 y6 q( K, K

采样时间可配置


+ y8 Q- O# G) E! U# v2 [

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

5 j( Z9 |( {. f# U

STM32F0-ADC时钟:

+ {- [9 O$ C8 ~% r8 {/ V

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

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

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


; W( D, w$ S- Y6 e+ A- M; y, {


# M0 p' n" T9 q5 }% K6 t$ s. k" E

片上14MHZ HSI RC振荡器

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

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

7 W7 j/ A- x1 \3 ]' y: r4 e

- o( y& D5 }" I" a& R6 a

3_meitu_1.jpg

, A3 S1 a) F# L

STM32F0-ADC通道的选择:

4_meitu_2.jpg


- \6 K+ J# u# g0 M: K: h. B4 h
) V  x+ e5 |, P: K

19路复用通道:

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

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

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


/ j$ x4 i+ Z7 s! z/ E2 n


  G* i* y' W6 ~% ?( W- c6 T7 X' p

STM32F0-ADC转化模式:

5_meitu_3.jpg


0 q8 i  R. e4 S2 \& k5 Z
* ?1 l: a' s& Z& o. B

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

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

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

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

6 ^0 }. E9 y  Y! U2 r: D

3 ~. v, w& _0 y6 j) y

6_meitu_4.jpg


% L8 f, a7 w. X+ n

7_meitu_5.jpg


; H+ A1 i3 Y: Y" Z' n+ `
9 [8 i* x: w% t3 P4 u* e: p

STM32F0-ADC转化时间:

可编程采样时间 (SMP):

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

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


6 j3 K) g  I$ D2 M

转化的时间:

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

. \3 H7 g) V6 s8 ]8 B# l* }

8_meitu_6.jpg


0 O4 ^4 ?; Z; z, N% b8 C: n0 R; `% q8 {

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

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


( `" `( V6 t5 L! r/ ]

# M/ c: A" s( I! D7 N8 D" R3 U

9_meitu_7.jpg

' O$ {1 o# B) p1 V0 E) N
! w* q3 z8 B+ L5 s

STM32F0-ADC触发方式:

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

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

- u( r" x8 h2 r2 p


2 \3 `" |/ o8 `9 p2 o

10_meitu_8.jpg


3 b% f5 s& Z* v- o1 [( L$ O5 k' x$ `. y9 u# g( T6 o- H7 B

11_meitu_9.jpg

7 a% r* z8 }# Z* v( q" W

, K, Q( i9 i( h

STM32F0-ADC模拟看门狗:


% a* K6 F# U+ |1 q* L  U4 A0 M

12_meitu_10.jpg


6 ^& [9 G5 m* x. v2 ]

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

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

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

! U" E7 [! x. P+ k

模拟看门狗的使能控制:

    AWDEN@ADC_CFGR1      

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

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

$ C$ \$ X8 |: s$ a/ T' D' [% Q+ \


& w, |6 ^1 [" ?; Y* G

STM32-单通道采集实例7 j' @. H+ x7 K* @

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


4 l2 a5 K% ?$ L5 W( i


4 X9 j, W6 D' S" Y& @

13_meitu_11.jpg

% E2 F% X' a% Q5 D! X, f

! y( b6 X1 k# R, k

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


3 c1 @- K, s1 h  q) F3 C

过程如下:

2 f6 o/ I$ Y3 r5 m


) b2 m) A  J9 R( u# k& Y7 |! N

14_meitu_12.jpg


* \9 v8 W; e" v; v
$ U+ Y0 C- a( ~: _& {

15_meitu_13.jpg

7 n0 U# E4 ^2 ]7 ]% O$ m; Z
" l5 ~" L, h3 b/ q3 l- Z+ j

16_meitu_14.jpg

9 J( B$ ~% L: N* \: J5 F

, F  x) Z. s6 W2 `- _

17_meitu_15.jpg

) t. F5 p& n! r0 i7 q% k- U

- A$ l0 z8 r5 _7 n& B1 u6 \2 d# d

18_meitu_16.jpg


9 }( q, F* A% c) }+ C9 V8 X3 |  Q4 F' w; g/ q

19_meitu_17.jpg


2 P" Z# `) s' g8 l- ^7 A* k' [  O

20_meitu_18.jpg

: ^6 D; w( X) \8 _8 G

( t& `- B  o0 w# }0 F- f) c

21_meitu_19.jpg


: n& v7 f7 m) ?% t8 c. X4 f8 D

22_meitu_20.jpg


1 O: K+ k) k. e) {0 W7 j, z# r
' E4 y0 \1 ?7 {8 f3 p* G7 p0 A+ R, ~

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

23_meitu_21.jpg


+ N0 L: b: A) p5 H2 r$ Z# @/ S% ~) ]9 P$ P' f
HAL_ADC_Start_IT(&hadc);//启动ADC转化并使能中断

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

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

! h: K; n+ Y( j7 d4 \  b$ E2 \

  1. ; ~4 U* @: d' j4 ?0 d' h- t1 q
  2. int fputc(int ch,FILE *f){       
    * d! ^  p  y% G; R5 A) E
  3.     while((USART1->ISR&(1<<7)) == 0);        0 ?& p7 e, h" G6 W0 Y4 [+ W0 S
  4.     USART1->TDR=(uint8_t)ch;) Y' C" c- j( _- [' B' u6 L8 m1 E
  5.     return ch;
    8 v' n3 I: \( Z, {/ v
  6. }
复制代码
  1. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)4 @& x/ Y$ R. J) l- [% |
  2. {
    : h. n' Z0 z* J  b6 ?1 s6 Y* O" ]
  3.         uint32_t light_value;* P7 d- Z. y- Z' Z2 Z
  4.         light_value = HAL_ADC_GetValue(hadc);  //获取ADC中数据寄存器采集的值* w7 l2 p! ]0 T% O
  5.         printf("light_value = %d\n",light_value);
    # g4 u0 q- l2 h
  6. }
复制代码
% K; `/ K. U8 ]& G5 q* T& d' }1 X

测试结果:

9 M+ U0 @6 _" q, u9 \# r- f  E% r2 \1 H


% p9 T4 [% U3 T. m; D

28.png

5 e' Q+ d/ t  h8 o4 H
% U  v9 D: d( ^3 A9 O
STM32-多通道采集实例

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

原理图分析:

29_meitu_27.jpg


: d$ M, T' p/ a
& a5 S, V( I$ w8 l! z' i6 d

实验过程:

30_meitu_28.jpg

1 b6 \5 g7 |4 i' e  P
1 P; e. U( c. g9 b

31_meitu_29.jpg


$ H) O8 q6 U. o) t, J0 W) _9 B9 H. X3 b& x& U# t- M: Y

32_meitu_30.jpg

) _. h4 Z! Y; d: V9 f7 Q

/ C, F: q0 b& Y& N' w

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

33_meitu_31.jpg


% U# d1 K: l' \- B. U& V& F& y

打开按键中断:

34_meitu_32.jpg

; G. ]" B* w; [' ?3 S% i5 Q
& p" r- q% e) o+ a/ g$ ~; y

导出工程:

35_meitu_33.jpg

1 G8 s# g5 W2 W8 u7 K+ m
+ ^& `/ A) {" K; K. C1 ~; {: q# K

36_meitu_34.jpg


' |- ?! u' J2 q
. ?; O; B, q* F* Z9 [

追加到按键中断回调函数

37_meitu_35.jpg


  u: ?4 r  B2 @$ s

38_meitu_36.jpg

- O1 d. u+ p- `* u" f& m

! e4 B- T; C5 r4 b; H

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

* e( K3 g3 v$ |$ r- m$ C

4 s$ u1 a2 E& _. F

39_meitu_37.jpg


: k; e, C  U, Z7 ?. r7 G
  1. #include "adc.h"
    + _* l! K0 G7 u. t
  2. #include "usart.h"" u" c( m  k. L( V& ?

  3. ( u! H& ]5 o, `5 f# @- x! |
  4. int fputc(int ch,FILE *f){        & _; m# U& ^# R
  5.     while((USART1->ISR&(1<<7)) == 0);       
    & x2 t) s: N  u( E3 i
  6.     USART1->TDR=(uint8_t)ch;5 a5 e1 P: u, ]) Z# D, `7 Y& p
  7.     return ch;
      d. d4 j+ h( P! |
  8. }
    # R/ N( K8 N# Z- A( K" P

  9. ) r0 e+ |7 c+ b; v/ }. y& h: q$ V
  10. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)3 G2 }" T3 I; p# N$ I" a
  11. {
    & L% ]( {. U( G$ r  T' X4 l
  12.         uint32_t temp = 0;
    7 ^9 V9 E! C! A, a
  13.         if(GPIO_Pin == GPIO_PIN_8)& I/ {" [( W# y8 i; U
  14.         {  R  Z7 Y9 C$ Y0 g# _
  15.                 HAL_ADC_Start(&hadc);   //启动ADC
      {9 S: P# m5 b, x
  16.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束
    5 A$ u" x; z6 a& b: @) u$ w4 {6 U- C
  17.                 temp = HAL_ADC_GetValue(&hadc);
    % c& x2 @& ]4 r$ Q4 a* e$ T4 F' q
  18.                 printf("key adc value = %d\n", temp);
    : U; C; f# R1 Y, Z" |0 F8 C
  19.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束
    $ d$ s: \7 h9 c0 Y2 F. }9 `' \5 @
  20.                 temp = HAL_ADC_GetValue(&hadc);7 I4 F4 t4 e% s) u1 ?' \2 n
  21.                 printf("light adc value = %d\n", temp);' t) k1 X# \  s6 |7 C
  22.                 HAL_ADC_Stop(&hadc);  //关闭ADC
    2 s) w( Y9 a* G7 P# `& f* d
  23.         }
    ! b( `. A. T& \. T! g1 r7 E
  24. }
复制代码
; X* W/ R( ]( Y* A% u
: H4 l& Y2 ?+ ?7 n2 B% h

0 m; T. g$ A+ B$ c+ M& o3 T' v9 Z* p

测试结果:

1 ^6 _) @) B# }/ g


. w* @# b- z+ w4 ~) w

利用中断和ADC识别五向键,即五向键任一按键拨动时能通过串口打印出是那个按键
; c3 {6 W# C3 s+ `% M
+ M* d2 u' F! G. e& H

41_meitu_39.jpg


. K1 r$ F/ `  J+ ^- t7 Z6 J! H# \5 E% G. Z/ Y+ d1 i/ M$ J: F

42_meitu_40.jpg


. p/ P# s- |# J0 M- s% y4 R" @4 u" z  B/ X2 v

) f8 m( d* ]9 Z9 ^  j

43_meitu_41.jpg


9 t( {. C( D" f. _. T8 }$ M) S( K: n( e: \2 N' ^

44_meitu_1.jpg

( a- S  `' e' _% Q

- q/ s- v: |* X) p$ v3 }, N1 g

45_meitu_2.jpg

7 g. J* V( q! M. j: W- d
. t9 I$ W& l) v$ H) S  u6 @

46_meitu_3.jpg


. \9 E9 ~) J! I9 @! h" |  A$ o
  1. 7 ?4 w3 ]" R' O% D- |
  2. #include "adc.h"1 i0 {8 y' [/ }8 l
  3. #include "usart.h"1 S8 o, ?* B# o

  4. ; @4 C, Y8 Y  R+ e
  5. int fputc(int ch,FILE *f){        8 ?' s1 I# q  B6 x8 \3 @
  6.     while((USART1->ISR&(1<<7)) == 0);        ; S' U4 j2 X# ~6 `
  7.     USART1->TDR=(uint8_t)ch;
    . m2 N+ N) }& O
  8.     return ch;
    ! q0 A' c9 H) \- u& w! x
  9. }
    ; j8 ]( B- \3 S2 w; K4 I* F$ L
  10. 4 L/ u9 Z+ G4 S5 S
  11. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    - z3 ?, F2 ]) V( b  M; W5 S
  12. {, O6 h' e+ {- t. U2 z
  13.         if(GPIO_Pin == GPIO_PIN_8)
    ( }, `) y! w! k0 \8 i5 N# ~4 {! _( s
  14.         {5 h  ~0 o# Z# P2 C
  15.                 uint32_t data = 0;! z: t0 c& l; Y2 X) {
  16.                 HAL_ADC_Start(&hadc);- H- F# h1 R  K; F! ~5 V& _3 Q' {
  17.                 while(!(hadc.Instance->ISR & (1<<2)));
    ( E& i  t: S, j% F. A& ^
  18.                 data = HAL_ADC_GetValue(&hadc);! j5 h# B* ]# F, ^  s- \, {5 j
  19.                 printf("key value = %d    ", data);' J  w3 }, E$ ~; d
  20.                 if(data > 0 && data < 500)' w  R: X+ X0 |' F+ _5 Q
  21.                 {
    & O' N: ?. ~3 h. J1 R
  22.                         printf("下边的按键被按下\n");
    8 z5 R5 T6 _, @0 M3 j* L0 H2 ?) u6 w
  23.                 }
    ( z) Q- o4 y2 x0 g: F5 k+ L/ G
  24.                 else if(data < 1600)) M7 k3 q: q8 f4 g6 L+ X3 L
  25.                 {* Z5 t% p2 X4 T1 v5 j9 k
  26.                         printf("左边的按键被按下\n");1 V$ g" ~" F3 l( j6 |
  27.                 }
      r2 C. z- t/ L9 s6 y3 C1 ]. u+ Y
  28.                 else if(data < 2200). t/ Q, f& U' _/ ]1 ~
  29.                 {
    % H. ^$ f& v7 P' }
  30.                         printf("上边的按键被按下\n");
    8 Z* ]% Q2 C3 _
  31.                 }
    ' |7 s% U" |8 U8 y, L, B3 ?
  32.                 else if(data < 2700)# `- E9 J1 B& b0 l. m, D
  33.                 {% l! n5 q. a# W, f' R! \7 j5 \
  34.                         printf("中间的按键被按下\n");9 T( Z) g% H( d& u
  35.                 }& Q" ]# v, a& z9 ~
  36.                 else if(data < 3100)
    & U* d8 G, @8 d" a
  37.                 {
    9 L# R! v! b6 g4 R* ]2 x3 G5 K
  38.                         printf("右边的按键被按下\n");+ k, x4 d( }+ t
  39.                 }% |' N; `! i  B" q' J( N& j" f
  40.                 HAL_ADC_Stop(&hadc);* q) X, b2 V3 r) |% @
  41.         }& m5 I, X5 H+ t# M; G$ ~) L5 b
  42. }
复制代码
6 z5 M3 ~9 V+ I$ G# |* _1 T

实验结果:

; ?- e3 F* P+ @# K4 e# g# X

47.png


# b/ F- ^0 P' d+ w# T, J! H9 }
: O. D4 I6 t8 n8 O4 w( s0 W! j
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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版