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

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

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

STM32-ADC模数转换概述

STM32-单通道采集实例

STM32-多通道采集实例


) x2 z1 Y1 |& g! B& G

STM32-ADC模数转换概述# s7 Y* _5 H- R; Q$ \

内容概要:

ADC简介

STM32F0-ADC时钟

STM32F0-ADC转化模式

STM32F0-ADC转化时间

STM32F0-ADC模拟看门狗


0 L5 r, P7 j, c: i! J; D8 R* l& C


# y2 I4 _! K$ H8 r4 a) n

ADC简介:

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

0 A: K1 V- l% n! ^% u) x4 ?

ADC的性能指标:

    量程:能测量的电压范围

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

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

' Q5 W! S, T, [* H

1_meitu_1.jpg

* U' k: ~8 j: J5 l2 Q8 H2 T

STM32F0-ADC特性:

+ k% [, A+ X$ [6 q

2_meitu_2.jpg


+ t' r' n3 g6 [' ^# |1 {0 r5 K

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


! X$ |# ~7 l0 O( i/ r4 z# E2 b

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

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

供电范围:2.4V ~ 3.6V

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

$ W7 c4 P; O* X. c" \

采样时间可配置

) K  T/ ~4 n" l; \

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

, X& K! u; C8 q& t( y% m

STM32F0-ADC时钟:


$ Q0 \3 S$ S1 Z8 S( l1 c

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

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

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

# U8 `9 F* n$ D' y. u: w9 Z& k" |7 X


$ O- }# u9 C, o0 l: N( r  d

片上14MHZ HSI RC振荡器

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

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

+ F' g' R) F! M5 D+ `' c


4 X5 J3 O+ h5 H( _6 h- l, _

3_meitu_1.jpg

1 q( ^% x9 b4 Q0 H# n9 z

STM32F0-ADC通道的选择:

4_meitu_2.jpg

0 i' K. D+ x& @6 w

' v4 z. I  v% F) |. U

19路复用通道:

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

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

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


1 l% I7 q$ r' f

+ ]+ Z  s) y! W( c' q8 A

STM32F0-ADC转化模式:

5_meitu_3.jpg

3 a% u/ j  ^" n" E: B% _5 W& k
& r& A- R, b/ y4 b4 p4 x0 }7 B

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

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

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

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


$ f% v/ Z3 H7 j- F) U. b, r7 W


9 w: o1 S  {* I4 s, d

6_meitu_4.jpg

9 O% s3 j; ^# V7 e6 S

7_meitu_5.jpg

" y- s7 Y9 i# _% l
6 q( `4 F3 D' }; I

STM32F0-ADC转化时间:

可编程采样时间 (SMP):

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

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


7 ~; H& O8 E% R% B/ V; l3 A( T: O* ?, a

转化的时间:

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

4 \! R8 ?: d  {7 K9 f3 w. e" k

8_meitu_6.jpg

% x( T4 r' v9 Q" c+ ~3 M: W
8 v& y# ~/ s5 \" b

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

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


( c2 x! y; }& e2 R; C, ^# Q

- ]3 Y4 s5 V9 t5 e0 O7 `& u$ G

9_meitu_7.jpg


! ~9 Z7 V; z) p, ]# G3 r! X
0 I1 ]2 G' ?* [( h2 u) \! Z

STM32F0-ADC触发方式:

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

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

6 o# V" p1 G& I2 H- e6 f

) V+ r+ [! \6 [

10_meitu_8.jpg


# ?* W# \0 @' \* D  n$ q
) c8 }% x6 F9 ?3 Y

11_meitu_9.jpg


3 q. r8 g. Z2 c! ~! k! |6 E1 e
/ ?. t1 b! f0 A( E% `/ K6 ]

STM32F0-ADC模拟看门狗:

7 Y8 ~$ {# Z) j) E' ?

12_meitu_10.jpg

  }1 j5 K4 V8 s' a! s7 W1 b

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

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

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


+ A+ h! v7 A  b. n, u! ~+ Y

模拟看门狗的使能控制:

    AWDEN@ADC_CFGR1      

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

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


- ^7 E: m# s- s& w


4 O# z" a7 b0 f2 v6 S

STM32-单通道采集实例$ {2 J  W: l3 d! y& |: _

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

9 n! a3 W1 `& g9 d2 \8 ?

- n5 I) p5 {8 X

13_meitu_11.jpg

: Z% I8 L! ]; @- |7 D- C, F

+ G% N% |" ~- ?& I# [7 ~- i

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


8 ~' p/ m! r) \

过程如下:

6 Q! g! d* J/ v) ?

4 B5 i; z+ C5 k: K0 v

14_meitu_12.jpg


% B+ {' w" o! `1 K7 z: a) e! G
, [: u+ K7 t0 X. q' b" ^+ i% I

15_meitu_13.jpg

- q' Z- d$ P7 P5 }0 s- M
, z5 R: X0 u" }1 D9 z

16_meitu_14.jpg

; }3 r' J( M+ }& P# l1 ]) B
+ n. [+ d- ~% \- d/ w4 V% A

17_meitu_15.jpg


$ c% ]" m4 {) t
& Z+ ^$ a1 o& s: N$ O

18_meitu_16.jpg


+ R' ]* f$ y* B/ i* Z5 b/ V3 p* q( Z3 h

19_meitu_17.jpg


9 _! v5 g# [- X1 H/ M. r% v* i$ ]/ I4 v4 i

20_meitu_18.jpg

. A& ~0 ~  C2 a: a7 c
( H5 X1 x7 `5 }

21_meitu_19.jpg

5 j# P* t' |/ U  n5 W

22_meitu_20.jpg


4 ~# E7 m, U+ H% z" G; p, u9 d5 I, ~4 y! i6 ^! _

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

23_meitu_21.jpg


9 L# u. S2 U: ?% S- B0 _9 F+ P: q0 ^
HAL_ADC_Start_IT(&hadc);//启动ADC转化并使能中断

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

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

' f+ S- l& s* p. X- c) F' G7 Q2 v


  1. ' n# j# S, G( Z( A0 b3 R
  2. int fputc(int ch,FILE *f){       
    - q4 e- ^+ v) N6 t9 o
  3.     while((USART1->ISR&(1<<7)) == 0);       
    5 n. a- s( X% L7 c9 u
  4.     USART1->TDR=(uint8_t)ch;
    6 d1 y( o$ T  [6 T9 |; L/ x- [. F
  5.     return ch;, ^5 P+ {- j2 Z9 n0 k  h
  6. }
复制代码
  1. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
    1 w( K  {) F  a% e
  2. {3 h6 m. Z4 j. u5 Z. T
  3.         uint32_t light_value;1 Z4 P8 W. t7 l" c3 e: [" {
  4.         light_value = HAL_ADC_GetValue(hadc);  //获取ADC中数据寄存器采集的值+ ~3 X7 e! k, Z; o6 E. ~
  5.         printf("light_value = %d\n",light_value);. B1 d0 G. \. C7 v6 m  w
  6. }
复制代码
8 A$ L# B2 m$ ]# L

测试结果:

7 y* q, a- f: g" c+ G5 X

9 B9 k" ~8 f7 k" v+ e7 v

28.png


# a' H$ T) ~2 g& u4 v
+ f4 j2 H$ {0 p: @5 gSTM32-多通道采集实例

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

原理图分析:

29_meitu_27.jpg


  P5 C1 F! b5 Q# g; A# L  ~
& h. Q" g8 }$ j4 U1 w' S

实验过程:

30_meitu_28.jpg

2 ^8 R* k) `1 A8 o  f
: a  U3 _4 U* B4 \- f8 Q

31_meitu_29.jpg

: I1 n7 p1 W4 W* M
$ p, h6 c- P3 M: u& O

32_meitu_30.jpg

, |. o7 l5 s$ n* R8 i8 ^9 [
) w9 x# ]8 E1 I. e4 Q& I

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

33_meitu_31.jpg

: Y) {' |4 G- R! _- i

打开按键中断:

34_meitu_32.jpg

8 I" U; \8 Z8 Z! f
3 i( }# L+ X7 k: B( j. U

导出工程:

35_meitu_33.jpg

" H1 H, R* B- q6 c6 |* `& Y
, q4 y1 b6 y, d' ~3 I

36_meitu_34.jpg


' Q+ ~' L% W% I+ E8 L! r
+ x( d" z5 A' k- |# ]

追加到按键中断回调函数

37_meitu_35.jpg


3 x1 M6 X' p9 J0 ~$ o1 n, _% |

38_meitu_36.jpg

$ A" k* J4 r2 [, N2 T7 w

% o0 ?! P; N4 O6 P' `& O

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

0 w! E7 `7 w4 S4 n. |. \' X) h5 X- ]" o


" [' K0 s5 l- ]% @, y% t8 c

39_meitu_37.jpg


( {+ C3 H; R9 q: u
  1. #include "adc.h"
    0 G7 L/ \4 M9 U3 {5 C/ C5 C
  2. #include "usart.h", i4 r  p4 B  l! j& N! L* A! b& \/ z+ b
  3. - O# T9 C4 R1 V* t
  4. int fputc(int ch,FILE *f){       
    7 D$ \# x2 g( x4 T
  5.     while((USART1->ISR&(1<<7)) == 0);       
    2 t- o' Y/ F; l4 y5 B
  6.     USART1->TDR=(uint8_t)ch;
      D  u' y( G' Y% M4 E$ t
  7.     return ch;
    & R- i; X2 h6 R1 q/ b3 B
  8. } 3 ]% y! J4 H: d! t+ h& j0 U" F

  9. 0 n/ \- J9 d% v6 c% i: C
  10. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)0 R7 |$ @+ _0 E  K4 M% p
  11. {; c2 i+ Z2 M+ u2 F9 C, r( ~( C
  12.         uint32_t temp = 0;
    ; u" J& @( W: i( T3 P
  13.         if(GPIO_Pin == GPIO_PIN_8)
    * Q5 B% D) q( L+ U) d- W
  14.         {
    4 Q* H% j  V6 N! O2 D/ L- P; \( F
  15.                 HAL_ADC_Start(&hadc);   //启动ADC
    . N% X, X- z$ h  s- D- ~# F
  16.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束
    % ?7 I- W/ w8 r4 r3 g
  17.                 temp = HAL_ADC_GetValue(&hadc);
    - }7 e' ]; q- s6 p/ O# J
  18.                 printf("key adc value = %d\n", temp);
    % @: F4 k9 Z" `' t* h
  19.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束- c5 ^: r6 N1 Y* I& V( `  R
  20.                 temp = HAL_ADC_GetValue(&hadc);
    $ a9 h4 r& }/ [9 D. U" ], U
  21.                 printf("light adc value = %d\n", temp);
    1 o3 v2 t1 q7 m  A$ P
  22.                 HAL_ADC_Stop(&hadc);  //关闭ADC, \; o5 R: v% b
  23.         }
    ' `8 s* T% i# h, ]% Z3 D, `6 _2 {
  24. }
复制代码

5 S" r  \! o) [" \6 H% h/ ?0 k
+ y  k( t0 p- b& o; t1 I" K) {/ v7 m$ G( h2 t  \: p% S

6 c! ~/ D) }- B+ H

测试结果:


  @" y, C! e0 H" m* l/ W


5 a- w8 Q, L3 x, ^$ b5 p4 c

利用中断和ADC识别五向键,即五向键任一按键拨动时能通过串口打印出是那个按键& l( \4 ~5 u$ ^5 D3 V
4 [1 [7 p1 G' x# N8 O8 a+ y

41_meitu_39.jpg


5 T7 l1 E8 X* _: y
: i4 L! J* h. I' P7 [

42_meitu_40.jpg

  x% v  c, {( M0 B; p

+ t7 O1 ]9 ^* a0 A  b
$ d% R  P1 G+ g" N1 }

43_meitu_41.jpg


0 Z' D  f# q* e9 o6 V& @( L. M4 A% F6 w; P! |! v6 X

44_meitu_1.jpg

; I6 |+ P/ f. X( ?4 u' A
7 _- y# I$ M7 K  C, g% `

45_meitu_2.jpg


" U8 K  w! k% {5 u# L+ [
1 j3 I" h/ C+ \% \8 J( U* i" E

46_meitu_3.jpg


6 a: r# ^! u* \$ j  F( O
  1. - r0 |/ h% l/ ]" @
  2. #include "adc.h"% O! z0 I% y+ w
  3. #include "usart.h"4 u6 F6 K, J2 j3 R% p. w( ^
  4. ; @) j0 j" m1 X3 q- w& ]% y* y
  5. int fputc(int ch,FILE *f){        7 I$ ^0 t7 I" Q  z2 |% g! Q; u1 \6 _
  6.     while((USART1->ISR&(1<<7)) == 0);        5 i- _3 m: L& \6 a' w6 a
  7.     USART1->TDR=(uint8_t)ch;
    0 W3 Q. h) z4 E" b0 n: o* q8 K) k
  8.     return ch;
      E! Z4 f' X2 }, |
  9. }# A: ^1 D' Z* F, q% [8 b

  10. " p( j0 L! p, V6 d. \2 a0 w
  11. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    / {- m8 S" F) |$ V5 o/ w/ S
  12. {3 ^( J" Y) D5 s& ?5 m
  13.         if(GPIO_Pin == GPIO_PIN_8)
    ! b$ u# {- h& u$ g! u4 g- \
  14.         {
    & G  V, W" N; {+ X# T2 R
  15.                 uint32_t data = 0;& o7 H0 i, E9 k* V/ C' v  u$ _% |
  16.                 HAL_ADC_Start(&hadc);+ K' e5 q5 L8 x5 Q% Y+ x7 g7 ?+ E1 C
  17.                 while(!(hadc.Instance->ISR & (1<<2)));
    6 ?, u' }2 a; R4 [% U0 K( n- o
  18.                 data = HAL_ADC_GetValue(&hadc);8 t7 s" Y3 u9 V  |
  19.                 printf("key value = %d    ", data);  L, \5 l9 K6 [( a& n
  20.                 if(data > 0 && data < 500)" |0 M: H) C( L$ O0 w* }4 T' L9 @& r
  21.                 {
    ! K6 @: W1 \1 \* ^5 a& _
  22.                         printf("下边的按键被按下\n");/ z9 `" ]) v; x& A- c/ x
  23.                 }
    3 i9 c7 E6 t3 z$ {$ N. i/ o2 p, `
  24.                 else if(data < 1600)
    - Y# O3 H8 x$ b% ~9 P, q
  25.                 {4 F8 O# H$ `' }) B  \+ X; Q2 R2 `
  26.                         printf("左边的按键被按下\n");2 B) B( L( X. L$ T
  27.                 }
    * d$ a; _2 Y6 q- d7 C; \. e
  28.                 else if(data < 2200)
    0 q2 Y9 r* n& n! o' V4 \+ B
  29.                 {
    , G, ]* N, F, y8 r1 y
  30.                         printf("上边的按键被按下\n");7 v; s" k7 f# }4 [
  31.                 }$ s, d. e+ ]4 p; t( M# d
  32.                 else if(data < 2700)6 |4 |2 Z" }! Y, v. k, r3 q+ o
  33.                 {, V- M" t1 T% D1 f' s
  34.                         printf("中间的按键被按下\n");+ x+ D2 s0 n2 {8 m% M
  35.                 }
    8 V, c! G0 v% F7 L2 H) x
  36.                 else if(data < 3100)
    1 J, Y/ i; m9 Z5 U' _% I2 A
  37.                 {. ]9 r3 h4 `( u
  38.                         printf("右边的按键被按下\n");/ ?- o" g# N! t
  39.                 }4 f$ `! T- o- [
  40.                 HAL_ADC_Stop(&hadc);( x) H3 a' g" i: C) y
  41.         }
    " S3 W  [+ Q; Q3 e9 ?
  42. }
复制代码
/ I( }  Y5 N2 h6 ?% Q$ |

实验结果:


$ R' H$ V) \: m. H2 n

47.png

4 Q. [$ k7 e1 P! W

: N7 w6 F! ?* T4 ?, q
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 手机版