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

【经验分享】STM32 ADC程序示例

[复制链接]
STMCU小助手 发布时间:2022-6-15 17:00
01. ADC简介
2 B' ]6 B' _; o% l  J6 X! ?STM32F4xx 系列一般都有 3 个 ADC,这些 ADC 可以独立使用,也可以使用双重/三重模式(提高采样率)。STM32F4 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 19 个通道,可测量 16 个外部源、2 个内部源和 Vbat 通道的信号。这些通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。
3 j2 K. p" W( `& L- B/ H5 X' [" c0 k8 ]/ `% V
STM32F407ZGT6 包含有 3 个 ADC。STM32F4 的 ADC 最大的转换速率为 2.4Mhz,也就是转换时间为 0.41us(在 ADCCLK=36M,采样周期为 3 个 ADC 时钟下得到),不要让 ADC 的时钟超过 36M,否则将导致结果准确度下降。# r' D: ^/ S1 H- s0 z

0 Z; E* h/ ]% ^$ eSTM32F4 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。" Q, y0 X3 ^7 {8 J4 }

) u' Y4 l+ e+ c# a5 |02. 硬件资源
) Z/ o# T$ W) }7 o7 ?! I/ \用到的硬件资源有:
9 g( r3 i8 k3 S: h; Y1) 指示灯 DS0
. B' {- M; h. A# M" ~4 G2) TFTLCD 模块+ U3 V5 d- t( M/ W, S3 y
3) ADC, y0 m4 j- w: I  s
4) 杜邦线1 i* u! g* B) W" G  p

! ?8 }1 g' c# \1 O03. 编程思路# M( i+ I/ w/ N" }1 [$ {6 t- S
①开启PA口时钟和ADC1时钟,设置PA1为模拟输入。* P" {4 Q6 r* {( z* {/ v3 O
: ]4 b4 l! Z, U! i
RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
9 A' X( i1 S, s, Y
+ J$ o5 R; h+ M. ^RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);' ~& [/ z* z$ n

9 Q: R. ~7 L& i& Y3 I( d$ j; n' gGPIO_Init();: ~" x2 q5 C4 S9 ~  B
8 C; R1 x4 @6 b" l: ^0 V- I/ N
② 复位ADC1,同时设置ADC1分频因子。6 a. l  p! R' C

4 K, C: r  N. z  N8 aADC_DeInit(ADC1);
/ l0 {& N1 w. i
* J; W# U7 N6 N9 P③ 初始化ADC_CCR寄存器。
+ Y/ `9 n; I( _! c* Z+ U  ^; p. M  s" `  R7 T! z
ADC_CommonInit();/ ^+ c0 K" U$ S+ P
! M- p- M4 ]- d$ A  L8 _% M. e
④初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。/ Z% B2 K* @: B  R

  j% @6 y! O/ `; J5 [( @) p& Xvoid ADC_Init(ADC_TypeDefADCx,ADC_InitTypeDef* ADC_InitStruct);*
& h. b, m1 D7 ?# \/ B8 \. |: ]. L8 L4 P5 M" V9 U$ {7 V- a
⑤ 使能ADC。
6 c2 ^' O5 \* e/ `; Q6 s$ Y# Z0 Z- m6 j( N. F
​ ADC_Cmd(ADC1, ENABLE);7 ~7 h3 R6 E$ ^

  R% e9 ~  E. p+ Z. [  Q⑥配置规则通道参数:
0 ]9 K4 ?& j1 L( L: [6 J& z* A) D, B( v
ADC_RegularChannelConfig();
' l; W) j: C0 t$ F5 R. l' f  s/ J7 `3 q8 u
⑦开启软件转换:ADC_SoftwareStartConvCmd(ADC1);7 g% V# l" [2 H' V2 ]# h7 W
/ P: s2 o# Z* k2 r) V, m
⑧ 等待转换完成,读取ADC值。; c- |0 I( m, {( t  \* }. h

  f% E4 U+ {5 R; ?' q! VADC_GetConversionValue(ADC1);; I* v& ]; z4 H
# J" V6 y' R: x; p* @! k- q
04. 程序示例
4 l; H9 Z' R( I: G5 r  dadc.h
/ ]; f) q3 {4 @; x( d/ p/ M
2 ?6 ?+ z5 K: o
  1. #ifndef __ADC_H__& g, H' w# y, F9 L6 |" |
  2. #define __ADC_H__
    0 X- O1 r* z) d
  3. 1 K! ^  e: L& k1 N
  4. #include "sys.h"
    9 j" l( n7 B! V6 Z# H

  5. 7 t' i+ d% \+ x7 L0 J
  6. //ADC通道初始化3 G" `  j* i3 N# e) X! J( P
  7. void ADC1_Init(void);
    + J& a' l) j; {" W" \+ V% l

  8. % R5 a# k' y0 z7 M1 Z+ P. l1 b7 Y
  9. //获取某个通道的值
    9 b8 Q! `# Q  _! l, _8 \
  10. u16 Get_Adc(u8 ch);5 x/ ]: o( h. ~! U3 p
  11. 2 r- d5 `' s" C9 Y
  12. //获取某个通道给定次数采样平均值! N6 G! E- P. W
  13. u16 Get_Adc_Average(u8 ch, u8 times);
    5 Q& [$ o& I! I0 e" N  J4 R* t* a

  14. ) Q! L! r2 P6 F- i
  15. #endif/*__ADC_H__*/
复制代码

; d) i4 Q2 e- B& a8 Zadc.c& O# G5 W+ m5 D
  1. - x: Y+ d/ ~9 N9 X( g# H; A
  2. #include "adc.h"
    * x& t4 p8 S- x
  3. #include "delay.h"6 X9 q% g. @5 j0 [

  4. ) |4 L( l5 w2 ~1 z, b4 o
  5. - i! j; ^; j2 ]7 f' J) L
  6. //ADC通道初始化+ \9 ^, c9 k! g! Z% X
  7. void ADC1_Init(void)
    $ y4 t% m  w- r
  8. {
    : u# d* T" S+ X( h& W
  9.         GPIO_InitTypeDef gpio_InitTypeDef;) e& N2 I# \, h
  10.         7 Q' n% x, r& x: N) `' h
  11.         ADC_InitTypeDef ADC_InitStruct;& }- s- j5 y9 o' @
  12.         
    6 d% |2 p- E1 d, }" y
  13.         ADC_CommonInitTypeDef ADC_CommonInitStruct;7 u/ }, s; o0 j! A% n- F: A
  14.         ! `# O- W4 t% E" |4 v0 _
  15.         //开启ADC1时钟
    0 l9 Z3 X+ k3 K: S
  16.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    ! D" }, w8 u% t/ ]+ ^9 M: Z
  17.         
    6 Z, Y7 ]+ x4 S  N
  18.         //开启GPIO时钟 PA52 m9 J' W1 K  D: o% [- d& G  U
  19.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
      P! y) [) [& S7 W3 v8 r
  20.         
    2 w! Z% B* W9 O3 H2 S3 W
  21.         
    & a  k# }3 ~+ M2 N1 P% I
  22.         //GPIO初始化 初始化为模拟功能
    & H# ^: Q$ q, |
  23.         gpio_InitTypeDef.GPIO_Pin = GPIO_Pin_5;2 S3 y0 S: k7 ^* L8 V5 o
  24.         gpio_InitTypeDef.GPIO_Mode = GPIO_Mode_AN;/ Q$ m4 `: h0 g/ J
  25.         gpio_InitTypeDef.GPIO_PuPd = GPIO_PuPd_NOPULL;3 S: {, M& W" d0 c
  26.         GPIO_Init(GPIOA, &gpio_InitTypeDef);' S' ~+ g2 `) v% A0 W0 w
  27.         # \3 L, [* h8 |  ^0 U
  28.         RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);          //ADC1复位4 ?" u- I2 d% g
  29.         RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);        //复位结束        1 Z9 |7 o& _! p; O
  30.         9 h# }8 C' a4 `6 ]  ]: |# L
  31.         
    7 c, i; }! Y; s0 d' g0 s! k5 h
  32.         //初始化ADC_CCR寄存器
    " v0 w7 G  r1 M$ c; L
  33.         ADC_CommonInitStruct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;0 Z# E: n2 k0 P2 q, g
  34.         ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent;, ?. x, @* [% t$ R* t3 g
  35.         ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div4;
    3 s  p; S. r. R3 a8 b  C5 a
  36.         ADC_CommonInitStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    5 l! h, w: o: B! A$ o
  37.         ADC_CommonInit(&ADC_CommonInitStruct);
    . d" r  c5 z. C9 U
  38.         + E- y) y0 v  T. N/ z4 s6 o
  39.         //初始化ADC1
    6 U8 R( u/ [$ E8 l. z0 r% |0 Q+ u+ w
  40.         ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
    $ y- I8 ^0 o' a; E3 r$ x3 `
  41.         ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
    6 Q3 b& U6 V$ J6 ]* R. s% p! F1 B
  42.         ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    * [! J0 {1 E5 p' |; b1 T
  43.         ADC_InitStruct.ADC_NbrOfConversion = 1;
    9 I) _1 p7 G8 o5 R; T
  44.         ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
    ! ^, i# b+ f' o8 J; h1 r
  45.         ADC_InitStruct.ADC_ScanConvMode = DISABLE;% I* j6 H  T  u! ^9 p- Y' r5 m% U! K
  46.         ADC_Init(ADC1, &ADC_InitStruct);
    # S9 l4 [! n0 h. X$ Y4 p
  47.         7 F; v* U3 y  ^& o  w7 r  C  s6 r
  48.         //使能ADC( E9 w$ T2 d5 V6 M2 V0 N
  49.         ADC_Cmd(ADC1, ENABLE);
    $ D7 A0 T0 ^0 F2 G5 f! t6 L( @
  50.         2 O/ N: ]# f& Q$ j. [2 D1 o
  51. }& O, z/ Z. n  r  x% p

  52. . E( R* |! C/ S' Q1 t0 i+ \* E
  53. //获取某个通道的值
    / `6 z  I; Q8 s3 M  p0 i8 J
  54. u16 Get_Adc(u8 ch)+ O$ I# s. v% h6 W9 v7 d
  55. {( r5 C* ?  [2 d% F! M! m
  56. 8 s% |# J6 V' b$ f9 b# Y+ X
  57.         //设置ADC规则组通道 一个序列 采样时间$ e; r7 L! v4 y8 ~5 w# i7 l5 q
  58.         ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_480Cycles);  H% }' z( Y9 x& }, k& N% P
  59.         
    / S. {2 v( j2 e# W- v* T
  60.         //开启软件转换
    % n4 V& g2 O) I; D) y  Q3 j
  61.         ADC_SoftwareStartConv(ADC1);
    7 s' [8 }) o) k6 c
  62.         
      E" E7 i! K/ b* u) L; v! l. I
  63.         //等待转换结束
    - g- H7 t" f% E7 Z
  64.         while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)
    ) ?5 K; t, V+ R& @6 v+ f- E4 k- [
  65.                 ;
    6 f0 k6 M$ J7 F6 A8 M' X
  66. % m. \1 y: r; l4 v- |+ \
  67.         //读取ADC的值7 o' g2 x: {  P- }1 f! A1 X+ P
  68.         return  ADC_GetConversionValue(ADC1);( P/ a, n7 |- w
  69. }
    ! Q4 D- C# |4 s) X/ Z

  70. # o. z* D* ?2 S5 }2 E2 }9 C3 Y
  71. //获取某个通道给定次数采样平均值
    ' d# J1 c7 Y% S6 C
  72. u16 Get_Adc_Average(u8 ch, u8 times)
    - i. X- J) u: f! }+ ~3 p9 _
  73. {
    ' n: G' m# }/ ^6 h
  74.         u32 tmp_val = 0;
    2 j& X' r3 c4 f/ `  W$ e1 C
  75.         , z1 K& F7 I9 z% M5 c6 t- j
  76.         u8 i = 0;
    * D# v6 Y0 ~: j) X6 H% k, w
  77.         
    - q' l0 @. |9 ~' c
  78.         for (i = 0; i < times; i++)
    ) I( t1 K3 s  y( p; o( `) x
  79.         {
    7 u1 m! V  z; @+ K% _( s5 x) E' X; X; Z
  80.                 tmp_val += Get_Adc(ch);
    $ _  }  s; F+ j) }; v
  81.                 delay_ms(5);8 e7 Y4 H4 X) c' U9 R+ @/ ?- n
  82.         }
    ; t( U5 a1 i3 x7 m4 Z# p+ B3 Y
  83. ) P$ l( J! A0 _; I2 p# R
  84.         return tmp_val / times;; g& f1 A9 E* D, p9 T
  85. }
复制代码
8 v) y7 \7 l  }" Y
main.c' x. U( m3 Z) E1 T, a( f" V
/ R" g5 l& ~8 Q' r% M
  1. #include "sys.h"6 q$ F( b; m( I# K
  2. #include "delay.h"
    ! b* _& r! K/ I& J
  3. #include "usart.h"6 P) \& _  c8 F# _2 o% D' J
  4. #include "led.h"4 f: w5 y2 P- @& U( ~; P) {
  5. #include "beep.h"
    : R2 Y+ v# l: r, [2 s- T* n
  6. #include "key.h"/ C% p) W( x# J1 L
  7. #include "usmart.h"4 U- A1 K) R9 C/ @* z3 o* U/ D9 [
  8. #include "lcd.h"
    , ]% ?2 o/ W. f
  9. #include "rtc.h"% }9 D& K  D0 [7 s* ~
  10. #include "rng.h", ^' K( d4 o) i, Z4 e
  11. #include "key.h"9 Z4 L! r6 m8 p- D9 a, }
  12. #include "wkup.h"
    - i; L) i3 V8 p  w7 H/ x# B; Q
  13. #include "adc.h"
    ! f6 P7 j9 o( }# ^- O% s+ W+ _# _

  14. 9 t) f- X7 ]; z
  15. int main(void)
    + H6 [6 G- _% z# E2 F* ^
  16. {
    ) x" b8 h  {7 Y2 p& r
  17.         u16 value = 0;
    ' D. e* E% c: _0 J
  18.         ! {# c# I$ n1 i/ I1 p1 D! U
  19.         float temp = 0;
    ) L2 o" L& Q) l9 g5 D2 }7 U
  20. 6 Y( I7 ]- n$ W" J" j
  21.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组25 I) p9 ~2 w& [9 |% N: ^, K
  22.         * |7 Y# w! H( u) Y; B+ a# V) p
  23.         delay_init(168);
    : P" J/ m9 b- |' R- {
  24.         ) c/ q+ f0 H: x
  25.         uart_init(115200);
    - H% t1 b. _# {; |
  26.         - W+ c5 b# A; l2 }( y4 {6 _- O" V
  27.         usmart_dev.init(84);2 r1 F* r- q4 ]% w9 G6 H
  28. " ^( U" N4 V) c
  29.         # j/ u: x  ^8 H3 E! G
  30.         LED_Init();, K3 t! o$ |# B: d% o% k* S$ E
  31.         7 k# w/ d( d: w0 t
  32.         
    8 b. O/ Y- ~' h) U; j$ H
  33.         LCD_Init();: V7 e( e/ G* J% e+ Q& C  E
  34. 9 M, b" h" [) L6 `7 n, E
  35.         ADC1_Init();& X' r  k' g, K) R
  36.         
    # s3 X+ Q! r. y1 ?0 ~! C) @1 P
  37.                 9 N# @$ x0 H9 D9 r
  38.         POINT_COLOR = RED;( g) N& l# O' Z# H) T
  39.         4 ]* C3 A: {0 i; G! |& q0 R
  40.         LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");        
    0 O. O( Z0 E2 }3 Y' A3 p/ K
  41.         LCD_ShowString(30,70,200,16,16,"ADC TEST");        ( |6 Z+ x; E5 e" E/ I& D0 t
  42.         LCD_ShowString(30,90,200,16,16,"ATOM@tom");
    " }1 T. d3 J; `2 ^+ `' u
  43.         LCD_ShowString(30,110,200,16,16,"2020/09/10");         " I+ a! \$ q/ f2 x# f! K5 L) K3 ]
  44.         ; M" ?" N# t  d: j7 z# _& e
  45.         //设置字体为蓝色6 u4 x4 d, B+ S1 u/ E. @$ U( w; I
  46.         POINT_COLOR = BLUE;
    + |& y* Y5 Q$ h; l/ z
  47.         LCD_ShowString(30,130,200,16,16,"ADC1_CH5_VAL:");         
    ! o+ J. f; \; C/ U
  48.         LCD_ShowString(30,150,200,16,16,"ADC1_CH5_VOL:0.000V");         / |6 Y2 C! z4 p& N1 h# ^
  49.                
    4 W+ i. g2 t& f6 W: B1 }7 b
  50.         while(1)4 ?' L" f. R9 B3 h* x9 S
  51.         {* ]5 ^9 U+ j1 c
  52.                 value = Get_Adc_Average(ADC_Channel_5, 20);
    9 _' f) }8 z; l7 `" k) }! d  l
  53.                
    1 r/ {' J1 G0 @$ c& n; ]4 t; _
  54.                 //显示采样之后的原始值0 I3 S3 G0 b0 v# i' r
  55.                 LCD_ShowxNum(134, 130, value, 4, 16, 0);- p$ N+ K8 g4 g; l$ k1 [) e
  56.                
    " e! @) j: i/ L5 x6 K( H- x- E8 a
  57.                 temp = (float)value * (3.3 / 4096);
    + h" I: N% e9 B- @) S! \% r1 W$ ~
  58.                 value = temp;
    ) Z2 `# l; p4 B
  59.                 LCD_ShowxNum(134, 150, value, 1, 16, 0);
    # E" Q* }( n! f( W
  60.                 5 M- }$ X' ^7 n% n
  61.                 //小数部分
    3 a( g3 C( M" l: }. s% }2 [$ F
  62.                 temp = temp - value;+ }- D4 A) L5 i! `( r8 p3 Z
  63.                 temp *= 1000;. Y/ j  z" ^0 |( r+ K1 y8 V# J8 _
  64.                 LCD_ShowxNum(150, 150, temp, 3, 16, 0x80);                9 y6 V+ l5 }+ X
  65.                
    . @) K- z; ?8 M2 l0 n
  66.                 LED1 = !LED1;
    7 e) Z+ r( J( D: q$ v
  67.                 : y; C6 p' V# ~1 q) \, o
  68.                 delay_ms(250);9 k# U/ C7 Y; G3 J* O9 r
  69.         }
    " J# H; U( {$ ~3 }
  70. }% u* ]3 l+ C# x! T  L( ~
复制代码
, u5 k1 s1 _6 h5 K
2 u$ O: _4 a! a' h
: y* ?' r  T! ?, G& D; C
) D1 I3 r8 f- Z6 t/ I
赞 收藏 评论0 发布时间:2022-6-15 17:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版