请选择 进入手机版 | 继续访问电脑版

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

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

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

STM32-ADC模数转换概述

STM32-单通道采集实例

STM32-多通道采集实例

( ?4 w1 \; l7 L

STM32-ADC模数转换概述
. j- y, Y  D* o& `% w# Z) y2 _5 j

内容概要:

ADC简介

STM32F0-ADC时钟

STM32F0-ADC转化模式

STM32F0-ADC转化时间

STM32F0-ADC模拟看门狗

( Y; D" Q- H7 P9 I' J: q) E

# F* b/ O' k1 O9 b, }# D5 o  B5 q' i

ADC简介:

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


* C* l- J) H# g4 l1 a8 }) z  K  x

ADC的性能指标:

    量程:能测量的电压范围

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

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

+ b0 a  G1 L6 ]) _- J7 B$ q

1_meitu_1.jpg

0 k6 K! M+ v7 w6 i% M# Q& m

STM32F0-ADC特性:

8 @# t! g# m: x/ q! d( N

2_meitu_2.jpg

9 @4 d/ n0 o( ~/ E! y0 c& @) x

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


: l  f" q% v+ Y, i- {

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

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

供电范围:2.4V ~ 3.6V

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

# S; E1 A* F' U2 }: k

采样时间可配置


' ~9 N' q+ e& I8 Q  l" M+ ^0 G% v

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

1 ]  v% d& V( @% ~4 ^/ c7 P6 W  g

STM32F0-ADC时钟:


2 q# _( C7 a! K# Q1 h8 K

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

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

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

3 i: ]. r$ P% ?2 U# x# \1 t


2 k/ b4 d3 e4 C* U# c/ P6 q

片上14MHZ HSI RC振荡器

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

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


( M; m6 L' \; ]" o" r1 a

# ~( E2 L2 |0 B& O" n- Z8 z

3_meitu_1.jpg

# n, \1 h! H% _1 t

STM32F0-ADC通道的选择:

4_meitu_2.jpg


9 l7 t- P3 f" z6 J% }4 n7 z' W$ R9 A; r# P6 S# t, m& Z( C

19路复用通道:

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

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

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


* E: e: E; f2 z- V, i6 w


0 `4 e/ ^: g8 _- d; G; n

STM32F0-ADC转化模式:

5_meitu_3.jpg

2 a: Z4 K0 B7 f' [% Z# H' P5 k4 j2 q
" d! U$ z' D/ f9 Y/ C1 w- a

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

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

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

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


& @% ?1 y6 e) U1 D" y5 Q7 L+ c

" v+ Q8 l. C6 i. e) C

6_meitu_4.jpg

5 ]" c# F/ U5 \* T

7_meitu_5.jpg

: N8 z% s# D- Z: i/ W1 U6 g3 K
  ~) W% X- x" P/ f

STM32F0-ADC转化时间:

可编程采样时间 (SMP):

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

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


9 ~  _/ k5 `9 P7 ^; H

转化的时间:

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

% S' z6 q, l8 C0 x3 U6 C4 ^" e

8_meitu_6.jpg

+ n! i8 h7 Y; d
( J& |) @% w4 T! y$ N( ?, C

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

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

/ D0 t; `3 I) w2 H5 L. t5 T' b9 a

9 C/ u5 ?* }4 }# w2 L7 g7 C

9_meitu_7.jpg

! ^/ P7 W3 Q0 l3 C5 ]

* O; a/ V6 [) m" R9 j

STM32F0-ADC触发方式:

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

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


& U* c2 v9 v1 x; k/ _' @

. i0 P( J$ u6 U$ `

10_meitu_8.jpg


. k' O) D  Z' o7 {& S0 a0 m
1 l  J! r, |1 y' J9 c0 o

11_meitu_9.jpg


: z: t7 }7 [3 r0 V( `* }; i2 [/ e" \7 j  V& q' Y

STM32F0-ADC模拟看门狗:

: a% o3 _, ?* B( G* ^

12_meitu_10.jpg

# N% {9 i# y) O; T. S! R- u

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

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

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

4 `$ E" x0 U8 Q0 N9 z

模拟看门狗的使能控制:

    AWDEN@ADC_CFGR1      

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

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

$ l; k* V: \" c+ k: C1 R9 j7 V

) T) v7 t& [2 W# n' _

STM32-单通道采集实例9 _$ W; X9 U9 u7 [+ j, |' f7 p7 o

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


, L1 O3 Q' r, x( O4 @+ \4 J

7 ^6 u( h6 H$ q" o9 C5 ?5 j

13_meitu_11.jpg


* C5 y1 ^3 G' U  a$ W$ h4 C7 n0 {# K/ n6 r! s0 k0 L7 n

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

+ b. b' y' y. r2 h+ E' K8 v  ^" g

过程如下:

  \; s: ^3 s0 d# z4 y/ Y6 X& K  L1 _

1 I' U: N% N$ k5 s: {

14_meitu_12.jpg


' `: g4 V# U' M  b. h, P5 B8 l" V7 L  o& b3 a- h( s

15_meitu_13.jpg


  M2 d) b+ j* I* A
8 Z, G4 v2 S+ N8 |+ ~

16_meitu_14.jpg


$ N; M+ A- L0 e! U; O- E" w
$ v, A) w* ~3 Q  l! @( R$ E; g

17_meitu_15.jpg


( g( i5 T- \( N% @! |' j) {2 G5 D$ N3 q7 D2 A' f  T% q

18_meitu_16.jpg

( I! r% Q  L& |8 E* U$ I

. q! E1 e: U" {" R% {

19_meitu_17.jpg


" T: V+ M$ l, T/ i7 @0 I/ p
  f- `4 q* j! l  b% w

20_meitu_18.jpg


& p: L9 g: s: C$ w; c2 h* Z
& V4 p3 S( C$ D4 U: l8 z7 a) p

21_meitu_19.jpg

- t( t1 v8 c( G# c

22_meitu_20.jpg

" L% [/ @  H* x$ c+ I/ E: n) F- N! K+ f
2 P, {) o- ?2 x9 ^  Z

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

23_meitu_21.jpg

- Z' h" v( {. e# X
3 J0 h$ A" Z" e! D1 ^
HAL_ADC_Start_IT(&hadc);//启动ADC转化并使能中断

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

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


" m) ^/ V# i# G' X  F9 `1 T

  1. - r7 U8 f1 Q9 \
  2. int fputc(int ch,FILE *f){        / b: ?% x" p+ F" L& B
  3.     while((USART1->ISR&(1<<7)) == 0);        . z8 k6 R6 o) [' C, Q) I5 b
  4.     USART1->TDR=(uint8_t)ch;. K0 c1 }+ O% e# i
  5.     return ch;
    ; r, Z. S8 ]' G6 v* E7 h8 v' g& M; \& u
  6. }
复制代码
  1. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)3 I' x: R6 f1 O, w
  2. {
    $ F  X( l7 ^3 ]8 o  Q4 E, e2 Y9 ]+ v
  3.         uint32_t light_value;
    % u% ~& }7 M: A# ^
  4.         light_value = HAL_ADC_GetValue(hadc);  //获取ADC中数据寄存器采集的值9 q. f  O2 {" I6 [; ]+ n3 l
  5.         printf("light_value = %d\n",light_value);
    9 J4 W3 H4 V) P
  6. }
复制代码
2 b% E; W; K7 S$ @! W, I) Y3 [

测试结果:

- ?( h, c- ~  ]: h+ C$ R7 Y9 Q


/ T# d7 l& K- y5 n* b. T

28.png

+ O1 P- k4 c* r- I3 ^

7 b! g2 F9 |* F. G6 {) \1 O7 FSTM32-多通道采集实例

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

原理图分析:

29_meitu_27.jpg

5 Q4 I, V# M! e  U. c
# m' I8 N" I5 G2 n# \

实验过程:

30_meitu_28.jpg


  |  W$ D1 d2 x5 g' }3 X
$ b: E1 @" Z% G

31_meitu_29.jpg

& M9 D6 @% f8 F& i
" V+ R# j9 Q0 s" I: Q7 E5 z

32_meitu_30.jpg

! B$ Z$ i8 h+ X; n  S% Y0 X+ P8 B

& T. w: Q' c) x& p  S) x) B9 c

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

33_meitu_31.jpg


, Z' M' e+ ^+ \: m! n

打开按键中断:

34_meitu_32.jpg


4 ^! ~) h* n/ ~$ ~
- W3 e! \  x- o, P

导出工程:

35_meitu_33.jpg


3 U& z4 k1 C) |9 w3 B  N1 ^5 D  ^0 Z- G
; Z1 n4 n  k* @$ r

36_meitu_34.jpg


( m* `& R) A2 I: i; E3 ~. Q4 L4 ^6 j9 I

追加到按键中断回调函数

37_meitu_35.jpg


0 |- D2 [3 Q# s4 |1 S  t

38_meitu_36.jpg

$ D' L: ]5 p" L! r' e
2 k, }) \" u  ?, V( L

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

4 R( w! n8 l* R6 o


1 Z7 V) z; y* K) T; c! U) R0 F9 Q" a) K

39_meitu_37.jpg

6 c" @# h* B7 M7 y/ g
  1. #include "adc.h"
    $ _1 W# M# h9 |" L
  2. #include "usart.h"2 P+ e) m# Y8 O& n$ v  w$ h. y

  3. + U% R* H9 l" w% }! t
  4. int fputc(int ch,FILE *f){       
    " J8 e4 _% ~0 y: R; _7 K
  5.     while((USART1->ISR&(1<<7)) == 0);        7 L$ a: D0 P  d0 a
  6.     USART1->TDR=(uint8_t)ch;
    $ g0 @0 e" q! m  P2 y4 t
  7.     return ch;3 d; ^/ F! i& U; B
  8. }
    ' o# i8 f8 D& y$ u/ S/ x( ]
  9. $ n* P- @" B" B, a
  10. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    5 P: f1 Y8 o% [; s( h
  11. {
    + Y, _" Y4 c, F! O
  12.         uint32_t temp = 0;
    5 [9 H; M( x9 H' U% `& w7 ^
  13.         if(GPIO_Pin == GPIO_PIN_8)
    - N" {3 w* @* u+ j+ D$ W) V
  14.         {7 t. u$ \- Z; `2 k
  15.                 HAL_ADC_Start(&hadc);   //启动ADC4 j+ o( R" n! J
  16.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束( f4 w5 P8 o' M0 m& c
  17.                 temp = HAL_ADC_GetValue(&hadc);7 E, L7 D5 Q. c, @( x
  18.                 printf("key adc value = %d\n", temp);
    3 j9 I, b5 q/ Y6 o+ h8 f
  19.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束
    1 X  U, V' U( ?8 X
  20.                 temp = HAL_ADC_GetValue(&hadc);
    4 s1 p& N2 D9 v$ \9 E$ X! h1 K1 y
  21.                 printf("light adc value = %d\n", temp);) u4 @1 ?$ K$ b5 ?
  22.                 HAL_ADC_Stop(&hadc);  //关闭ADC
      q+ @& s9 `! V: K
  23.         }
    3 C; t  g5 k0 o7 z3 d
  24. }
复制代码
0 z; r7 h# |# c* @4 T

0 ~2 K1 j8 ^6 W8 O" b" [
2 T8 I) x6 R4 V1 {6 `/ s, R6 [% Q# q8 s5 a) g1 |+ `

测试结果:


3 y9 e3 Z3 k3 _. Y% |: B

8 O5 g: j; D& y

利用中断和ADC识别五向键,即五向键任一按键拨动时能通过串口打印出是那个按键* x6 ]3 ]& r  d  T# v! u
9 d! c, l0 n# I/ J9 G

41_meitu_39.jpg


) |- j' _! k$ U. w
  Q! N+ W9 K5 l; E6 f, I3 ?$ {

42_meitu_40.jpg

" x5 D/ M4 p+ l! q; _- V6 O

& ~. s9 ?. H4 ?" U- T8 ^
; h5 }8 Y' u1 ~* A! E0 q2 h6 i# \

43_meitu_41.jpg


9 c3 s  n/ n# [3 F* w1 g1 B& V' B1 _1 p9 v

44_meitu_1.jpg


6 y6 X2 _$ w# l1 |  K% A; h
# s  G9 N6 s/ T9 Y: C) y& |+ ]

45_meitu_2.jpg


1 ]: j3 A' |! M
% m# |# L; j3 D4 E/ H

46_meitu_3.jpg


; M' ~! U+ Z# q+ q3 R4 w7 g8 {  b
  1. + l9 j: Y) A0 W4 J! E3 f  n
  2. #include "adc.h"; M0 m5 w% c1 Q# }( L& }
  3. #include "usart.h"
    ' S8 a. P8 y% D

  4. . p: w$ P1 C4 A! m3 b# V
  5. int fputc(int ch,FILE *f){        ( F/ {# f5 @: m7 J6 t
  6.     while((USART1->ISR&(1<<7)) == 0);       
    0 T3 v2 C. F7 r" ]
  7.     USART1->TDR=(uint8_t)ch;8 y; b6 Q( \1 s9 r- F
  8.     return ch;/ T" d/ [$ E# i: i7 I
  9. }
    3 b7 Q- c1 Y$ z$ k" y7 @$ ^
  10. 1 S6 a# S+ i* O9 j) p- f8 j4 @
  11. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)# A/ `4 r% S+ g3 K$ B; H: o
  12. {, p9 G# z. ^  g3 [
  13.         if(GPIO_Pin == GPIO_PIN_8)/ U2 m5 v& N- O+ d* i, I# m
  14.         {
    . j$ N' ~4 `% q8 {% R
  15.                 uint32_t data = 0;. l$ K7 }/ i8 E
  16.                 HAL_ADC_Start(&hadc);. F6 G0 `2 B2 n- z2 ^& F; }- f9 e
  17.                 while(!(hadc.Instance->ISR & (1<<2)));/ ?7 z/ l' ]- e
  18.                 data = HAL_ADC_GetValue(&hadc);
    % s4 i" `7 N9 [( H, G6 E% Q+ q
  19.                 printf("key value = %d    ", data);5 {; h' d) w; i  U1 G
  20.                 if(data > 0 && data < 500)
    - ]  H* l( h. a; x0 S
  21.                 {
    8 [  z9 O  M  u( `( ?/ G
  22.                         printf("下边的按键被按下\n");1 ?' w$ l/ n' p$ F, o! Q* u4 t
  23.                 }
    8 B0 t7 d2 C2 P! m) E
  24.                 else if(data < 1600): ?0 @1 v: m, I7 ~2 M3 F' J# r
  25.                 {7 s$ q3 k2 ^- n/ T$ b0 _, ?0 t0 b5 e9 ~
  26.                         printf("左边的按键被按下\n");
    / [  q2 {7 q1 }
  27.                 }! j+ {+ b9 T/ w6 K# o
  28.                 else if(data < 2200)
    ! p( W* o. }8 W" ~! a" ]" M8 H
  29.                 {0 Z, F& [: c* s- _: w! j# u0 x2 ]
  30.                         printf("上边的按键被按下\n");
    . T6 V) |) J+ \: ]6 u  w  [; u
  31.                 }  A; b( {0 m/ N
  32.                 else if(data < 2700)1 _$ g6 h% |9 S0 T
  33.                 {3 ~1 ~, d1 I/ w8 {+ u
  34.                         printf("中间的按键被按下\n");- X0 N$ ~. n( N" F( Q
  35.                 }2 D8 g2 r; y, k# K1 X3 e- N+ Q6 F1 d
  36.                 else if(data < 3100)/ j/ R) I4 W$ L" t
  37.                 {2 D% Q- C& y: E& s3 C& y
  38.                         printf("右边的按键被按下\n");
    + \! C+ s. l, o2 w% T
  39.                 }
    4 I' z, Y+ J9 J: j
  40.                 HAL_ADC_Stop(&hadc);9 d2 b3 g8 W( H, c# v
  41.         }
    ( ~+ @9 Q1 [( ~7 L4 _5 U
  42. }
复制代码
' v' e6 ]3 _5 L$ H0 K/ E

实验结果:

& K/ o. W2 S* G0 P/ f9 T! _& r* ]

47.png

4 _9 ~  ]! Q! T: q2 {

; J& l  ^4 v  L& M6 k
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管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版