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

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

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

STM32-ADC模数转换概述

STM32-单通道采集实例

STM32-多通道采集实例

3 q+ M5 k. t0 f

STM32-ADC模数转换概述
( j6 B# [0 R6 v# i' s4 ]& o

内容概要:

ADC简介

STM32F0-ADC时钟

STM32F0-ADC转化模式

STM32F0-ADC转化时间

STM32F0-ADC模拟看门狗

+ a2 f2 E- [  ^! p

- w8 E: [/ g+ i3 e& y- o' p

ADC简介:

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

& c2 H: N8 E$ M' E5 \

ADC的性能指标:

    量程:能测量的电压范围

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

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

: i2 c9 n9 J# ?" U' j4 H

1_meitu_1.jpg

! [2 D  T" X9 ]9 z

STM32F0-ADC特性:


% O! l; ]8 y9 x5 A/ ]3 D  k6 Q3 b

2_meitu_2.jpg


3 O8 B% b9 z# e  l3 u$ O. t

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

: h* k; ~/ @' A7 y2 l# |0 t8 F

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

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

供电范围:2.4V ~ 3.6V

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

3 [. A% i) P$ U- D: {

采样时间可配置


' k  {/ z. j+ h! }* }

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

2 Y! c+ L( }. d, ^! M( Q

STM32F0-ADC时钟:


. ^. s- Q! }, m6 U

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

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

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

: G9 K2 }! \% f& c: y


) H+ `, }+ I; v8 b% s9 D5 |/ r3 u

片上14MHZ HSI RC振荡器

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

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

9 z; h( g3 a. {9 X* v* e


& z; |7 x% t+ |

3_meitu_1.jpg

. I) B8 O9 p$ e6 P( e* c

STM32F0-ADC通道的选择:

4_meitu_2.jpg

% d' Q. p4 z# e5 n

4 U2 L, e$ U" B4 R- g

19路复用通道:

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

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

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


, `+ }; ^+ z) O5 X4 F/ P% V. }6 H

( H2 X, Y0 s7 G. l2 N7 m5 H3 z

STM32F0-ADC转化模式:

5_meitu_3.jpg


9 s1 Q. E& q8 B+ N$ z6 l; Q/ d& I/ F

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

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

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

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

% I' ]5 J7 z* {2 s! ]8 t/ z, S3 T

! G/ r. D2 K! F# q0 j( w: ~5 D

6_meitu_4.jpg


! Z& Y! }. ?+ [  N4 H

7_meitu_5.jpg


  [6 w' |* x- [2 ?  A4 ~# e
: {( Y. g8 q& z3 k, V6 }1 v" |

STM32F0-ADC转化时间:

可编程采样时间 (SMP):

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

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

* N& E5 B% M$ ]; D: x

转化的时间:

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


. [/ c) d0 D! N: C% L: m- \) s  S

8_meitu_6.jpg

9 [# D7 x6 D) q1 c
& X) k/ [1 W/ s

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

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

/ O( i; i4 Q! r


$ g2 ?* |7 u* s, m

9_meitu_7.jpg


5 Z' m/ t3 r8 J- c. l/ ~1 u4 C9 u6 N% ^. ~5 z& S1 p

STM32F0-ADC触发方式:

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

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


. a, W. ]. F; z5 \6 c8 D3 g& E$ i


' `9 X# U6 Q" x; d: s7 e2 H

10_meitu_8.jpg

! \& y8 |9 _, b6 x: d6 }; Z
+ ^! V. S1 p# d: u# K" Q

11_meitu_9.jpg


, q& ]; K: R1 [2 M/ M+ {- M
; L+ \' `6 h8 M

STM32F0-ADC模拟看门狗:

) P4 _5 p$ ^. H% z

12_meitu_10.jpg


% N2 Z( z: d+ m" L

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

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

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

! K+ q5 J5 P' O  |

模拟看门狗的使能控制:

    AWDEN@ADC_CFGR1      

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

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


" ]/ J6 s; z! I& R& @* k9 F2 ~

3 I! E' @5 A# w" U- z: _6 @( @

STM32-单通道采集实例
2 t. a' ]" ^  T- G

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

9 Z) s; b0 B; R9 Q2 S* k2 e

- ]& Y& ?, W5 ~, g) G% H2 J1 G

13_meitu_11.jpg

2 Y" m4 ^2 b% u9 h

4 {6 C$ ?6 _, ^' c* E9 v/ m! s

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


  X' y9 X! |- a0 O/ H4 ~( q

过程如下:


6 ^4 \) K# C1 X  ]/ @/ j

- b. J+ B- s9 T  c) a( G' w& m

14_meitu_12.jpg

1 [3 r  i% L- B" N, }

  y; U3 z, z; o6 c& w

15_meitu_13.jpg


5 d3 m$ c6 Y- o- P: m4 k
3 G( t: F+ V6 o0 r( u- o

16_meitu_14.jpg


0 d2 Z8 L& U3 w' p0 I, q5 Z9 O5 a4 B7 ]  i" {" p1 N) _8 K

17_meitu_15.jpg


3 w: D& r3 c* \" U
( h3 h) h: h) ]; v

18_meitu_16.jpg

7 s" B- b5 W5 u7 L, W, F8 B
& q5 A, P. ]  |2 G5 u$ y# s

19_meitu_17.jpg

! e% Q1 [8 x& f

- k5 `  y2 ?& i' X: }

20_meitu_18.jpg

9 U  Y9 A( k, r* Z. }
- x( [' @) V8 Y1 }% W8 Y8 t2 K8 Y

21_meitu_19.jpg

# i9 n) Z: n' V$ P8 u: A+ ?

22_meitu_20.jpg

, i% G0 K; t. A, D

  x- N- Y# y; X- v: Q

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

23_meitu_21.jpg


9 E* J% @& M" D4 e; x' n0 n
( j% w2 X/ A) k! g3 ^4 NHAL_ADC_Start_IT(&hadc);//启动ADC转化并使能中断

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

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


& S/ n; f9 T$ C" S7 R


  1. 0 {9 {! J7 Q7 m! A% C
  2. int fputc(int ch,FILE *f){       
    ; E: v9 U3 d, y
  3.     while((USART1->ISR&(1<<7)) == 0);        ) O# ~3 u' ?7 m( F3 e
  4.     USART1->TDR=(uint8_t)ch;1 @4 j  {! `( }4 c) }
  5.     return ch;: O& B, K# c" ^' c  u! d1 L0 q/ p
  6. }
复制代码
  1. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)7 s1 i; E: w5 Z0 d" e* [
  2. {. O. V# ]3 s9 {6 y  `; A
  3.         uint32_t light_value;1 l7 I. y+ ?/ i" a  c% `- j# }
  4.         light_value = HAL_ADC_GetValue(hadc);  //获取ADC中数据寄存器采集的值
    7 P5 ~/ v$ ]2 w- B
  5.         printf("light_value = %d\n",light_value);8 @, G8 h# P$ H: _" O4 c
  6. }
复制代码

; x( s; t1 O! D: Y

测试结果:

  T8 V+ m# I' p! q+ O4 `' I8 r

. a6 k& i2 L9 w8 }! m9 X& t

28.png


# }6 q  ^2 B, x
3 G; l5 e& n! b" Z2 R+ hSTM32-多通道采集实例

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

原理图分析:

29_meitu_27.jpg

0 g) B: T: B* x4 Z9 B

' X: U# v8 e) \

实验过程:

30_meitu_28.jpg


" V9 Q  s% ~$ s, q4 l" z7 _7 \* V) ]0 _6 g

31_meitu_29.jpg


9 Q/ ^; I  I1 e. u7 d* O8 Q3 u% n& _/ ^

32_meitu_30.jpg

% I9 Q7 T3 l8 t/ N3 Z
6 _! k2 _- l+ h8 m

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

33_meitu_31.jpg

* Z7 H' e/ ~4 e% ^; o$ X

打开按键中断:

34_meitu_32.jpg


' f: {5 c+ ~& l6 e* @+ _- K# a0 \

导出工程:

35_meitu_33.jpg

3 @6 O4 z) _$ e  C5 Y

- j) d7 E( n4 D& b; H

36_meitu_34.jpg


, @/ g. o+ Y# ~$ T! U. ?3 V% x7 r# O" q

追加到按键中断回调函数

37_meitu_35.jpg


) k7 G0 o' P, g" V7 o

38_meitu_36.jpg


  p, s) ^. l5 U; q$ O! c& m+ c4 ^4 s# r6 t; g. j/ H4 g

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


$ |9 {+ [' O' @' u% y; ^

! ]+ D' U' q- B# c* W  u6 Q. `7 T

39_meitu_37.jpg

4 r& M. d) ^$ S/ W
  1. #include "adc.h"
    . F$ h. C% _+ O4 o3 d8 I6 q6 t
  2. #include "usart.h"' G5 U& K# J/ N$ |9 f9 T9 \

  3. % T, N* W3 A7 j. x& z" ^# y
  4. int fputc(int ch,FILE *f){       
    1 Q. q2 a+ e: s' m
  5.     while((USART1->ISR&(1<<7)) == 0);        ! `6 [- C. B, z
  6.     USART1->TDR=(uint8_t)ch;
    # h3 B( a, Y5 g& B& H+ l/ W+ b
  7.     return ch;
    9 J0 D- Y; j; r% ]
  8. } * w: \3 M: Y( n8 F

  9. 6 V8 Q( ^4 g" e7 V8 R" v; f2 s
  10. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    4 I6 l4 Z7 Y# f  p+ T  K' J8 Y+ N
  11. {3 s4 j' Y  l8 T8 Y
  12.         uint32_t temp = 0;
    ; A3 k( r# x- t/ l
  13.         if(GPIO_Pin == GPIO_PIN_8)
    8 \2 J5 ?, t' o) y6 T. O
  14.         {4 z  E4 |" o3 o' f* H/ |
  15.                 HAL_ADC_Start(&hadc);   //启动ADC- r( C- t+ a" [1 J9 K% Y3 S
  16.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束, x0 e* j3 x# B7 `" g
  17.                 temp = HAL_ADC_GetValue(&hadc);
    ! ^! q/ X- h# T3 F4 s3 w) x
  18.                 printf("key adc value = %d\n", temp);
    & I. T) _) y- U, b6 ]. g7 Z
  19.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束
    + G+ W; e0 j6 @+ Q1 d
  20.                 temp = HAL_ADC_GetValue(&hadc);
    : y0 h6 s9 u8 j; b
  21.                 printf("light adc value = %d\n", temp);
    7 k5 Q: z* p+ \, b
  22.                 HAL_ADC_Stop(&hadc);  //关闭ADC# B$ v5 N1 D' R3 |# C
  23.         }
      _: U$ Q) @$ ~& _# ]9 }5 J( e  o
  24. }
复制代码

# [% i2 \* G* }/ F! P
9 d$ z: E2 [! E+ t; @
9 O  x& u  d7 u4 \3 r
' A& u! d! H! B( ~3 H. {

测试结果:

* S7 Y" z: D, G


* S/ o* l  Z4 q3 r( P! s

利用中断和ADC识别五向键,即五向键任一按键拨动时能通过串口打印出是那个按键; M0 A* G; F3 a. ?, G4 P0 t- V* J& l

, O% E. @, S+ p' E

41_meitu_39.jpg


; B+ I, y1 t3 F1 X/ D
. t* Y6 Y/ _7 }

42_meitu_40.jpg


3 z' g* Z, k) D3 T: {: t1 @8 o
- o. _5 }2 p/ x/ J: x% k9 l- y( V: A# ^, M' M1 a; ^

43_meitu_41.jpg

8 G- X/ }- }0 R: U! k& H

/ V4 [9 ?8 S  ^- L8 z  s

44_meitu_1.jpg

( ~$ t; z0 _' t+ j( l2 _% {
! h+ T) Q8 N3 t

45_meitu_2.jpg

8 n) i& R" F6 C' R! K; G

* o( I1 j0 P2 @; j% G

46_meitu_3.jpg

' y/ |4 Q; }3 q7 V
  1. 2 Q- _% L+ m4 V) K+ U
  2. #include "adc.h"
    6 L2 O9 O& [+ g2 D# s
  3. #include "usart.h"
    3 V: f: d3 e8 U- o7 j: W; E
  4. ! i* k  ^9 p) n. z0 m
  5. int fputc(int ch,FILE *f){        1 J8 x8 Y& `$ N1 \
  6.     while((USART1->ISR&(1<<7)) == 0);        ( H4 l/ B+ @: ^) B
  7.     USART1->TDR=(uint8_t)ch;$ d7 ]2 n) y' P  }: `* T- z4 X
  8.     return ch;; W) ~3 A& ]* u+ Y4 f% L
  9. }$ c- j9 _2 d5 L# i1 i% O; w4 t0 V

  10. 3 _. K4 r. p, Y
  11. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)% j: \/ u4 i9 T4 U* D: X5 c% q
  12. {
    / i: v8 Z) _: L/ o" j
  13.         if(GPIO_Pin == GPIO_PIN_8)# K3 e! b8 l% P5 m
  14.         {  a; t' a3 J; D9 L/ e! p+ [* a2 ]
  15.                 uint32_t data = 0;
    0 @) w7 r8 e5 t$ I7 p' I$ S
  16.                 HAL_ADC_Start(&hadc);
      e" @$ M7 B1 i
  17.                 while(!(hadc.Instance->ISR & (1<<2)));
    + L& q7 P" M& {1 {' z8 a& T, R& J9 c2 H
  18.                 data = HAL_ADC_GetValue(&hadc);
    1 S5 X: @2 _. r
  19.                 printf("key value = %d    ", data);
    0 I' ~) p3 C$ {9 f, ?
  20.                 if(data > 0 && data < 500)  q( W8 T& C, i9 a# B
  21.                 {+ B7 ?0 w- ]& Z0 y# }! Z
  22.                         printf("下边的按键被按下\n");1 T7 w+ b% _# I2 o. g' f
  23.                 }
    & {/ R1 A7 I. _4 s. b2 O6 }
  24.                 else if(data < 1600)# ?' @4 p( {3 t/ d! x* K
  25.                 {6 Q# K( d, r( G
  26.                         printf("左边的按键被按下\n");
    ; X3 N4 Y3 `) ]# @7 h9 c, a
  27.                 }
    1 e) N- j$ J) i# _* }
  28.                 else if(data < 2200)% {# g" T) p: t6 p4 W3 |  A% @1 j; ?
  29.                 {! {8 r" d, N7 N. i
  30.                         printf("上边的按键被按下\n");
    * f6 e$ h8 i% Z/ K4 v6 L% s
  31.                 }5 x$ r- W6 t% o4 c3 B# V
  32.                 else if(data < 2700)
      s7 t5 X' ]/ L% E4 e
  33.                 {4 @0 o. _9 ?0 ?7 u5 v: f
  34.                         printf("中间的按键被按下\n");
    9 }; d8 N3 _" m/ n$ k( U* L
  35.                 }1 [$ j( G2 z+ C: {0 H) g9 `
  36.                 else if(data < 3100)
    - Y- \$ ^! C. `( M( B; |7 q0 B
  37.                 {
    % D1 P# h' `. |  |% n" P# \
  38.                         printf("右边的按键被按下\n");$ R. n- G3 z7 B) Y7 S  F  [: |& |
  39.                 }- @3 h( n, A2 T/ C7 Z
  40.                 HAL_ADC_Stop(&hadc);3 D; h( ^! E# @7 \3 H2 O1 l
  41.         }5 U$ x& P4 ~  ~5 z
  42. }
复制代码
: b# S) Q% Q6 S! y' O0 [" Y

实验结果:

% f6 I0 n3 r; _; A3 G9 G) I

47.png

7 l8 G1 R7 \( F' G- C3 i$ Y

& o$ Q% o0 j# P+ ^' a  I
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 手机版