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

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

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

STM32-ADC模数转换概述

STM32-单通道采集实例

STM32-多通道采集实例

2 _$ n6 q- j% i6 X# u; J4 t" s! i

STM32-ADC模数转换概述
  M: v- S" w' ~* n. Z1 y

内容概要:

ADC简介

STM32F0-ADC时钟

STM32F0-ADC转化模式

STM32F0-ADC转化时间

STM32F0-ADC模拟看门狗

+ w" y% ^" r6 z8 v' L, P- x3 ?5 H! l

. g  W8 d' N7 `! R' ^$ Q

ADC简介:

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

8 Q& T; F2 t8 T: `$ s( h

ADC的性能指标:

    量程:能测量的电压范围

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

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

- N+ Q( }5 D6 h+ a+ `

1_meitu_1.jpg


9 o7 |. S5 [: G! k3 }

STM32F0-ADC特性:

9 ?( n5 N, V' D1 _+ M2 R) H

2_meitu_2.jpg


: r" o! W0 i. g  a

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

3 v8 q7 A: x. {' h4 Y4 F9 j$ V

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

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

供电范围:2.4V ~ 3.6V

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

! T# R- h1 X& F) h

采样时间可配置

' X6 e# J* @3 j. ^9 G

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


2 _6 g) M* t, y2 X/ s

STM32F0-ADC时钟:

% ~1 K8 Z) E% C5 a! M

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

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

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

; l3 u5 D# m% k. S3 w" k


; b" R4 ~. U) m  v" s& L

片上14MHZ HSI RC振荡器

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

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

/ w! H) O, Y3 g; p


7 S) m, l# y5 {# ^! x. t6 A

3_meitu_1.jpg

2 O2 a$ |7 K& ]% Z

STM32F0-ADC通道的选择:

4_meitu_2.jpg


# n5 o7 T( {% X  z3 S0 \& Q, Z) Y2 P5 j6 |

19路复用通道:

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

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

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


3 K/ f0 K$ a  x$ e$ I/ ?1 ~" R


5 F0 `& E8 O, P" x

STM32F0-ADC转化模式:

5_meitu_3.jpg


, D, A4 @- j3 v: [, |# [! _& C: B. {- @6 o+ z3 R+ j: W* V! W- F' {, N

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

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

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

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

9 Z; C0 c' v. }/ F

0 Z/ Y+ z0 J- A; k9 F

6_meitu_4.jpg

& a' a3 j2 f; Q$ Y, x# F# K

7_meitu_5.jpg


) G0 A( g  L" V$ V- G
  M9 e1 c, J% x, g/ X

STM32F0-ADC转化时间:

可编程采样时间 (SMP):

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

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

. W1 q; w  O& ~- e4 {% }4 ]

转化的时间:

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

2 C3 W* p, ?# F- _' k; ?4 m  X% x

8_meitu_6.jpg


" r0 B0 `" g. M8 f( j
9 L3 l) g. _& f  E, {; Q

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

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

7 o5 B, M- t3 e% {6 L  @

4 E5 e; l2 U% e' \8 v0 t8 ]

9_meitu_7.jpg

: w4 ^6 w# I7 {: }: Y
. A: [7 L. I2 |6 I2 k

STM32F0-ADC触发方式:

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

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

/ t3 d+ M, b1 Y8 U4 v, J, w3 O, V3 r

" ~1 w& L& O* ]" H

10_meitu_8.jpg

9 u4 e2 h- C, `, J7 m. x  Z

5 C3 @: K& ^/ B7 {1 d, ]" o# ]

11_meitu_9.jpg

) H& V( {& J, l1 `- o
  p. h& Q, ~5 ~; k+ f

STM32F0-ADC模拟看门狗:


% E7 p  V( C0 M7 H" H$ h$ ]

12_meitu_10.jpg

3 ]  Q7 [( k' ~' }. _

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

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

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

9 L6 @0 p9 d$ s' J' c& Y# F

模拟看门狗的使能控制:

    AWDEN@ADC_CFGR1      

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

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


: I; D9 E! @6 I


  A( k1 B! t' x2 O# x+ m

STM32-单通道采集实例2 Z! E) h6 q4 {- W5 l0 a3 d

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


4 e, D: D" h) u. ?, i


0 [7 E3 p8 I/ \! w

13_meitu_11.jpg


; g' a- s  y% J% b4 A+ b( e# b2 J5 m: `

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


1 X8 O: j% k, A+ C" U: W

过程如下:

8 F" l8 B' G: k; ~$ l: |! _  m


3 z! O5 b2 q# G3 }7 W' C5 U

14_meitu_12.jpg

3 t! u% j# l" o9 F, ~7 b: [) [

7 m4 j, [! E$ G2 d, ]9 }

15_meitu_13.jpg


3 S& {6 Q. Z' |+ G" U+ O4 z8 W0 \# ?' |  [

16_meitu_14.jpg


3 X( C/ j/ c0 u0 a  k( K/ r) W2 P& O% ?; i* {% o9 O+ s

17_meitu_15.jpg


% s6 A3 @8 X% S7 ~5 H" B2 O7 i( `7 }- ^8 w- D) L

18_meitu_16.jpg


4 }/ |5 Z1 j0 ]8 N8 k6 b5 _/ c( C! B/ I; e+ \* B

19_meitu_17.jpg


$ W* A  _5 o2 ?8 E- l$ k6 t
+ N- w% c7 {0 O, r" B6 b0 G

20_meitu_18.jpg

( e; i- V8 }' L! b/ m

7 B) G3 x# F8 I+ [7 L

21_meitu_19.jpg


. |: i% s& F( ^

22_meitu_20.jpg


; E+ j2 p! ~# P5 j) ?. X' I9 @8 E0 w" D: g& F* x; a# N9 g

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

23_meitu_21.jpg

9 ]$ n8 O) |) L, ]1 I" l9 Z  A) J0 y
$ Y2 r- F0 J, R
HAL_ADC_Start_IT(&hadc);//启动ADC转化并使能中断

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

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

6 ^5 h( `, a) U; ]4 _


  1. + g, ?# F/ L8 _
  2. int fputc(int ch,FILE *f){       
    : a& o( V" z. H4 @6 v# d3 p" b
  3.     while((USART1->ISR&(1<<7)) == 0);       
    3 T4 I/ M* C! ~4 }
  4.     USART1->TDR=(uint8_t)ch;
    6 T+ u6 {0 p- H) Y
  5.     return ch;
    ; P& t% {( K2 g( X
  6. }
复制代码
  1. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
    : H* Z0 x7 Q* p/ ]2 h: \
  2. {" L8 {' R0 E- c2 O5 h
  3.         uint32_t light_value;3 j9 J9 m0 m7 c6 q* a: ]. ]- B* h
  4.         light_value = HAL_ADC_GetValue(hadc);  //获取ADC中数据寄存器采集的值
    $ m: M! X0 r5 j  U
  5.         printf("light_value = %d\n",light_value);; ~7 y+ E" |& G
  6. }
复制代码

& x. \2 g% J- _8 l! F% |; ~0 x

测试结果:


$ r- |# E! x  D6 ~


: N% Q" U, O: N

28.png


# [% T! l7 q+ X7 Q: c
6 b8 l1 }3 A2 [3 [STM32-多通道采集实例

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

原理图分析:

29_meitu_27.jpg

2 {: ^7 q; M' W
9 Z8 R) u1 T3 Q9 g

实验过程:

30_meitu_28.jpg


5 Q3 s: t' h  P- j: E9 e8 ]9 {# Q+ F, l+ \

31_meitu_29.jpg

" \) y! ~" X7 D7 \$ T* t# F9 I0 t
# R+ B0 D: ^$ B8 ?6 O' S

32_meitu_30.jpg


) L" {9 n& k& w: z. \! C8 }
+ Z8 Y+ F/ P0 d8 F

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

33_meitu_31.jpg

. s0 J) {; x; ^* g7 n. d; N' V

打开按键中断:

34_meitu_32.jpg

# n8 J8 z! v3 b( }; D% s' R$ @. ?
# w5 z( r6 K; b" H0 X- ~1 @7 E, P, a

导出工程:

35_meitu_33.jpg

: t# `. t# h* @% e2 u  H# M! S

( F; e4 Y/ U9 z7 ?

36_meitu_34.jpg

! h0 u( f- K; p1 F

7 ~6 L/ W3 E3 M8 Q6 _2 |4 ^" m

追加到按键中断回调函数

37_meitu_35.jpg


' S7 J" Z; L! e8 j, V

38_meitu_36.jpg

3 B8 ]+ Y' N; o$ h" l. Y
- Q" M" `; t* T+ E, k

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

* F' m. v* Q4 D$ w( D


/ t; W& M6 \: O, z

39_meitu_37.jpg

/ u* b% s0 o' S7 M' E
  1. #include "adc.h"
    0 a1 J2 E) n  }' v4 g9 H
  2. #include "usart.h"
    1 m! K2 {+ G, }

  3. . ]( J: U% B0 z3 _/ S
  4. int fputc(int ch,FILE *f){       
    ( _& k- d. f2 J# |
  5.     while((USART1->ISR&(1<<7)) == 0);        0 F) N0 j5 h+ N' l" x
  6.     USART1->TDR=(uint8_t)ch;' c8 c  Z3 ^, E) a
  7.     return ch;
    ; y$ C: q0 N$ }/ g4 }
  8. }
    5 n5 Z$ Q1 ?/ R$ Y4 k1 b
  9.   W7 B& s9 [' K
  10. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    ' T4 s! }2 a7 m5 E& \
  11. {8 h  D2 e5 ^# H$ F
  12.         uint32_t temp = 0;
    $ n2 c3 Q3 e9 N" J' ~  s
  13.         if(GPIO_Pin == GPIO_PIN_8)7 W* i1 Z* q5 d" H- _. Y
  14.         {
    % [; `2 E( e( V% ^* y
  15.                 HAL_ADC_Start(&hadc);   //启动ADC5 G. i# B5 \' u1 t, n5 Q; \
  16.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束
    ! w% v. X# Q8 I4 Z/ O7 G
  17.                 temp = HAL_ADC_GetValue(&hadc);
    ) j5 k4 J, s6 l& q
  18.                 printf("key adc value = %d\n", temp);
    2 K' [+ c" J+ G$ u, l, b
  19.                 while(!(hadc.Instance->ISR & (1<<2)));//如果ADC的状态寄存器中的EOC置位,则表示当前通道转化结束
    3 Y. i: I; }+ N& ~- y, F
  20.                 temp = HAL_ADC_GetValue(&hadc);
    # @: \/ c+ y* u$ m8 l
  21.                 printf("light adc value = %d\n", temp);) o- j- V: ?: L9 o7 ~
  22.                 HAL_ADC_Stop(&hadc);  //关闭ADC- }3 C- s6 o( y) U
  23.         }
    1 r. c) m' f. |4 C/ _6 M# ]
  24. }
复制代码

0 e; W3 A% @! m9 i2 m# t/ }5 ~% W6 f5 E; A8 a2 s8 m
8 S' z; Q9 |6 T$ `0 n
+ X8 p% {0 A. I

测试结果:


' D6 o9 w( U( j( B. S. N

& h. J9 F2 |: k; U

利用中断和ADC识别五向键,即五向键任一按键拨动时能通过串口打印出是那个按键& d9 |5 f- }) ^' a) i" h
( R3 Y1 C# C9 D" l+ q) \

41_meitu_39.jpg

* K9 D: _" E2 l: R5 g

, g/ q4 T. Q9 n

42_meitu_40.jpg


" l1 p5 ]9 s/ i" e
; D0 M9 U9 ]1 }  g# b
8 `, N% K8 ?" Y1 U. ]7 m

43_meitu_41.jpg


; l4 D, y0 h  x1 G& v3 ]* q' `) B% W

44_meitu_1.jpg

6 z- }+ `( y4 }+ q
( z7 ~9 {$ G8 d3 F4 N6 T' }

45_meitu_2.jpg


% h  S/ _# r5 Z5 u3 }9 U7 h" ?, q% _

46_meitu_3.jpg

8 e; ~1 o+ r/ {7 m

  1. ) E+ H- F$ I9 I4 n1 u0 m3 l
  2. #include "adc.h"* b* a5 H5 K' g
  3. #include "usart.h"5 w! ?! k7 }* o% v7 n" h
  4. ' _, k' m+ W7 h
  5. int fputc(int ch,FILE *f){       
    % y5 f; a( q* c3 M1 F/ J1 W' i
  6.     while((USART1->ISR&(1<<7)) == 0);        $ n4 h; S7 A& O6 Z
  7.     USART1->TDR=(uint8_t)ch;* d* k, P1 L: |- B
  8.     return ch;
    ; Y* O6 \9 q+ f! J5 ]9 i
  9. }9 x! D9 v4 X' Z+ b
  10. , i8 j8 v+ u9 ]: d' w
  11. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)+ q: r4 [0 I6 y& Q. M! x* W3 D6 O
  12. {
    / O- |: g4 B& L- r* t* _5 a
  13.         if(GPIO_Pin == GPIO_PIN_8)
    $ N% P4 a; d  f5 ~% o$ _3 P
  14.         {
    # K. p, o4 M. T! O
  15.                 uint32_t data = 0;
    4 k- m5 ?- _  x. f7 G/ f: P9 P3 {
  16.                 HAL_ADC_Start(&hadc);
    3 y/ }( e8 d8 R& {
  17.                 while(!(hadc.Instance->ISR & (1<<2)));' d3 M; q# t6 i( X0 e
  18.                 data = HAL_ADC_GetValue(&hadc);
    " m5 w. s# \7 N9 h; o( Z6 t  L* Y; z9 @
  19.                 printf("key value = %d    ", data);- j& W9 G$ W; U; x% r
  20.                 if(data > 0 && data < 500)) T& G$ I  C0 q, Z3 @
  21.                 {2 }8 t: s5 i% I. T; p4 ^
  22.                         printf("下边的按键被按下\n");* ~5 o1 i1 r: _" M& U, e
  23.                 }
    5 N5 V0 l1 T) A
  24.                 else if(data < 1600); l: Z% [0 v5 V! C' d3 x0 R! `' I) h
  25.                 {
    ) B8 r5 t" w" r0 ]; }9 q
  26.                         printf("左边的按键被按下\n");, o' x6 u& N4 q7 j
  27.                 }
    . {& z5 M# w7 G3 w% Q( `; s
  28.                 else if(data < 2200)
    ! ?# ~6 ~5 |$ y  l- w% O* v
  29.                 {" h: {% v) Y6 q7 p! f
  30.                         printf("上边的按键被按下\n");+ a. x$ v% W' H( I/ J+ V
  31.                 }* z8 t/ |+ i  y: L/ H
  32.                 else if(data < 2700)
    9 U8 A" q  S5 x9 h
  33.                 {3 j( W1 D# m6 W: n0 z6 ^/ ^5 E
  34.                         printf("中间的按键被按下\n");! I+ z1 @7 W( W' k/ k  L2 c
  35.                 }
    . H& }% Y& w% e- s/ {: A0 k
  36.                 else if(data < 3100)
    $ ~0 w5 g& h1 H8 j1 w; v6 k$ h
  37.                 {3 Z& V8 ^; x* ^( }" M0 ^
  38.                         printf("右边的按键被按下\n");
    5 v2 p  B2 p3 h* E, |3 ?$ P) i
  39.                 }  v. s& G5 Q, f) V; O- x9 }0 I
  40.                 HAL_ADC_Stop(&hadc);) W! O3 K- v8 ]- K1 J+ j# C4 Y9 q( Q
  41.         }
    % `7 y2 u+ R; g0 ?- b. p
  42. }
复制代码

( \, ^9 ^  z- |$ K$ k

实验结果:


: H. @- I2 e+ F+ l2 @( u3 K+ a

47.png

* i' I. L" Z8 Z: A' |  h
+ U5 Z& g) X$ p) X+ d2 Z
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 手机版