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

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

[复制链接]
STMCU小助手 发布时间:2022-3-28 11:02
01. ADC简介7 s) m$ K+ {, S; g( x/ A6 ^
STM32F4xx 系列一般都有 3 个 ADC,这些 ADC 可以独立使用,也可以使用双重/三重模式(提高采样率)。STM32F4 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 19 个通道,可测量 16 个外部源、2 个内部源和 Vbat 通道的信号。这些通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。
" M$ n2 T: D* M$ Q0 ?2 a; `1 I6 H4 j, X
STM32F407ZGT6 包含有 3 个 ADC。STM32F4 的 ADC 最大的转换速率为 2.4Mhz,也就是转换时间为 0.41us(在 ADCCLK=36M,采样周期为 3 个 ADC 时钟下得到),不要让 ADC 的时钟超过 36M,否则将导致结果准确度下降。/ Q% H( |! X+ I" h! u3 s
1 ^4 F6 J' @$ `) f2 e
STM32F4 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。
0 J: G; z+ M" _9 p9 @1 f
0 s6 A- u" x. U  B% ~5 N2 F02. 硬件资源
. m- Y- |" ]+ g/ {用到的硬件资源有:9 O4 d) S/ L2 y  E8 ^
1) 指示灯 DS0' u6 K# ?6 i; E0 O- O( Z
2) TFTLCD 模块3 T0 U: c! u" U+ }) n1 `% s% ~1 [
3) ADC, l% Q6 g: ]* |$ g' A% I3 L4 c
4) 杜邦线. R; z4 r; O/ u$ ?1 Q# M
: [  ?% f( d; o! p0 D8 R
03. 编程思路
0 i: V4 A# W: U( I. o& X①开启PA口时钟和ADC1时钟,设置PA1为模拟输入。% k; e4 k4 q4 b7 h& H

- s/ l, [5 I  O  ~$ I; L. V- `# gRCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);" M8 m9 S. a$ G; H
$ x! H1 P' K- F) S9 g
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
- h" E0 n0 N4 J
6 U. |, P" F: w7 zGPIO_Init();
3 K  k% @. {  l, J2 l: i+ B* A& f% R' d$ I, T6 h4 A1 Z! S
② 复位ADC1,同时设置ADC1分频因子。
7 R; [9 m/ e" R7 P
! X; N' Y7 g0 M7 ^! W3 ^7 xADC_DeInit(ADC1);
9 h9 ?6 U1 G( G* p
) t$ S; W$ L/ }9 u$ g2 I③ 初始化ADC_CCR寄存器。
7 D- Q% q) a; y. M  G) V* f5 P
ADC_CommonInit();
0 {/ r% C. V/ K. o2 f
1 y2 H% Y; z3 m+ D" f+ C④初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。
* P. {, m2 n9 n/ ^! }( Z0 V  T" ^8 l' ?4 s* @- [+ x& j
void ADC_Init(ADC_TypeDefADCx,ADC_InitTypeDef* ADC_InitStruct);*
* N9 v$ S' U# Y' ~! ]* O7 r
* f3 f' s3 u1 {- e' p0 X⑤ 使能ADC。' h1 N, l% f; b: T; h

1 U! G* Y, H' K) _4 [% o​ ADC_Cmd(ADC1, ENABLE);% ?9 D% S9 H0 C& q" t/ V- L6 O  G, j
% F8 }" E7 ]# o, g
⑥配置规则通道参数:# B: _" v9 c% \% S8 D4 t
& U; J; O/ _( {" @
ADC_RegularChannelConfig();6 f- W) v+ @! m# u, H% s

7 ?( d# `6 G( Y⑦开启软件转换:ADC_SoftwareStartConvCmd(ADC1);
0 P# s! F8 J/ A' O9 w# @6 ~, Y' z- O: r6 T" j. d$ D
⑧ 等待转换完成,读取ADC值。- v& H% R1 p! @9 z
" f- G6 C! c6 m4 ]* m9 K! ^9 k6 ?
ADC_GetConversionValue(ADC1);8 X& T+ n- C0 D8 w! N" K. ]* Z9 a
* Z7 f' Y5 U5 l- e7 \8 j
04. 程序示例
1 K+ I  X; W  ]% t9 @) jadc.h
6 P5 E' |$ V& T, i
& y2 z# D2 z+ }$ ~$ q4 h
  1. #ifndef __ADC_H__* J8 |; [- K) a# l+ l) t
  2. #define __ADC_H__# V4 ^" m/ Y- c/ D

  3. # k; U+ J# G1 |" h, i' `  B
  4. #include "sys.h"  P5 m, ]6 ^) c; |$ k- V1 ~* \- n
  5. " j! c, r2 T9 P1 @
  6. //ADC通道初始化
    ' _6 i+ u* E  ?5 T8 ~
  7. void ADC1_Init(void);; C9 @* @7 q) N
  8. : l; S- F7 t' e7 K. B* P, s. E
  9. //获取某个通道的值( S# G- F& \3 W" ?
  10. u16 Get_Adc(u8 ch);4 T3 O4 [) d( O" r8 E2 L
  11. 4 x0 p- r/ w' x- C7 z1 K4 }0 p$ U
  12. //获取某个通道给定次数采样平均值
    0 l8 |& ~" o# f6 [1 [; M
  13. u16 Get_Adc_Average(u8 ch, u8 times);* {7 C! J+ e% N# N4 N

  14. 5 o. r+ s( f1 N- F
  15. #endif/*__ADC_H__*// C% }) t7 T3 q* N4 K: a! f, m

  16. 5 \/ |7 {2 w3 t# b* I7 O8 X2 J1 d
复制代码
3 Y! U& h- E( u1 M8 `1 q
adc.c! H2 Z' f; L7 w+ c8 D, u5 \  v2 e

6 }. {9 m2 U; ?. }/ \3 i$ t

  1. 7 w' x0 U# X% H( f, U7 v
  2. #include "adc.h"5 H7 `' @1 X5 m; I1 }6 W8 p
  3. #include "delay.h"
    : m8 w8 t8 W# D
  4. ( F5 E9 c/ N2 t. M1 c
  5. ! G4 P! {, o6 d0 \' @  s& o9 p
  6. //ADC通道初始化) J) o' w& e0 u0 ^  K
  7. void ADC1_Init(void)( g2 y, C6 D; S4 w, i
  8. {+ J" U9 V' m# i* e/ X: m, y" \3 D
  9.         GPIO_InitTypeDef gpio_InitTypeDef;; t5 V/ W/ I4 G
  10.           E% G& B* V% I+ l# ]% w
  11.         ADC_InitTypeDef ADC_InitStruct;
    # \& Q6 b$ Y! n/ I4 X
  12.         4 }% ~' x9 x% ]' F% ]5 h
  13.         ADC_CommonInitTypeDef ADC_CommonInitStruct;
    , y8 V  \' m4 s, X2 r2 {5 v
  14.         
    8 N, u: ?! f2 h7 D3 p& G
  15.         //开启ADC1时钟
    4 n. t5 a% R0 a2 R8 y0 m
  16.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    : ]/ T& E; v9 p; T
  17.         
    & ^0 A9 I' Z% O7 w
  18.         //开启GPIO时钟 PA5
    2 s7 O. ]+ w+ r
  19.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); . ?/ ?# p9 G3 j% m$ }: p
  20.         
    * A/ Y  F' b+ n. y. r4 D: J# _
  21.         
    , C1 Q' M$ ]5 H
  22.         //GPIO初始化 初始化为模拟功能- t6 a  a# a" Z2 o, S
  23.         gpio_InitTypeDef.GPIO_Pin = GPIO_Pin_5;
    3 q3 L7 n5 V; A' w  W. U! ~
  24.         gpio_InitTypeDef.GPIO_Mode = GPIO_Mode_AN;) w; c- w( w2 @" G8 S
  25.         gpio_InitTypeDef.GPIO_PuPd = GPIO_PuPd_NOPULL;) z& h+ t6 t, Z
  26.         GPIO_Init(GPIOA, &gpio_InitTypeDef);
    , e! E& B+ k1 E) A% ?" Y
  27.         
    . \8 V; j2 T" h5 p+ t, l) ]
  28.         RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);          //ADC1复位
    1 L0 [/ G2 ]  q
  29.         RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);        //复位结束        
    & G1 P$ c: i' _- _
  30.         * e5 I- _! m9 a& F& b- `1 c
  31.         & `7 W; W% k6 s* V3 H
  32.         //初始化ADC_CCR寄存器. M* F% g; z4 k: o- W/ O
  33.         ADC_CommonInitStruct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;) {; Y7 O; l6 q& P% i( E! ?4 P: `
  34.         ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent;
    3 u* p8 o- _2 y% u2 r
  35.         ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div4;
    3 d( J- K1 B  k1 e; y6 h2 n! A. a: F
  36.         ADC_CommonInitStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    * V2 `3 H: x$ O+ w7 W) h! Q
  37.         ADC_CommonInit(&ADC_CommonInitStruct);) K# O  J: i$ t" B* Y$ Y& W  x
  38.         ; I! t( l3 Q0 v9 f% A3 m
  39.         //初始化ADC1
    2 |# \7 i- I  v
  40.         ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;' k" ?. Z( D+ z5 e2 E# S2 d2 l
  41.         ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
    5 G0 Z& v. W9 `3 R
  42.         ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    3 e, P8 |3 }/ D: d2 p
  43.         ADC_InitStruct.ADC_NbrOfConversion = 1;
    7 @& ?& [- R) c4 J7 N
  44.         ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;4 s4 W9 l3 G: ^; Q2 s& V% S6 R
  45.         ADC_InitStruct.ADC_ScanConvMode = DISABLE;
    2 ~3 T% U$ {- @. N
  46.         ADC_Init(ADC1, &ADC_InitStruct);
    % E5 V/ O* b" Q- p2 q7 T) S) R
  47.         % j, A+ E1 v( Z) d3 @
  48.         //使能ADC! p" @( P" L/ K  @
  49.         ADC_Cmd(ADC1, ENABLE);% o8 Y- V. Y% |1 p
  50.         7 y2 v( M- p% @8 J# G0 g$ z
  51. }( @: h# V1 m: }2 J5 Q

  52. + x8 g7 l" Q8 [# p6 k) R; e( U
  53. //获取某个通道的值# c8 O7 J" C' `8 P
  54. u16 Get_Adc(u8 ch)- p2 C: l; L& f: a" \. C
  55. {; {, W7 X' S& D1 t, D
  56. 0 z1 l8 P0 k, @( R* g
  57.         //设置ADC规则组通道 一个序列 采样时间
    ( k* \' ?3 Q! u
  58.         ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_480Cycles);( H* z( ?, ?1 w7 I( W( {/ a' V8 u
  59.         
    $ _) S7 E  W, A2 p4 u
  60.         //开启软件转换
    7 I& S1 J$ X( K$ n% B) q9 n5 U
  61.         ADC_SoftwareStartConv(ADC1);* J( K8 K( Y. ?$ d, G
  62.         + O; p+ T4 u8 y4 t
  63.         //等待转换结束
    & Z. {& [) H% y
  64.         while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)
    ( ]# B$ G" Y/ ~, s# B& f1 C
  65.                 ;3 h( [# s* u& W" M4 A9 U" v
  66. : h, ]& N' }% t; Y7 \. _# H
  67.         //读取ADC的值
    ) R0 R6 C0 C9 c# B7 I0 a% Q* O
  68.         return  ADC_GetConversionValue(ADC1);6 {) l6 R% q( X
  69. }
    ! O1 }* @, K$ o
  70. / {/ L* b% i3 K" P
  71. //获取某个通道给定次数采样平均值
    4 ]$ |% E( i+ b5 J, j% P- h2 s2 [) U  J
  72. u16 Get_Adc_Average(u8 ch, u8 times)
    5 i: Y* @& B* P) t7 X3 |
  73. {
    ( P! H1 x5 h9 n) c0 W, U) t
  74.         u32 tmp_val = 0;' y7 N- U+ l# X' M9 `# q! h
  75.         
    ) m1 q" \2 k; d
  76.         u8 i = 0;
    1 Y6 [% r0 H$ p( U
  77.         
    * t% O1 A5 _  {& |
  78.         for (i = 0; i < times; i++)1 Q, k0 e% M2 f& D0 X( O0 ]
  79.         {3 b- `* u5 B8 P! A
  80.                 tmp_val += Get_Adc(ch);
    " Z! S3 A  J3 }0 U  M  p. R
  81.                 delay_ms(5);9 a1 q* e' c$ Y: E4 r; \
  82.         }+ x- M, T4 a7 W* J8 F: d
  83. 5 C% @, |( _/ W& \3 y
  84.         return tmp_val / times;
    + k. |# ~/ e& u
  85. }
复制代码
: q. ~( t% Y/ W
main.c7 K2 L7 d& t8 t) J

5 |/ K! d" y8 O+ i. [4 w
  1. #include "sys.h"
      m" U& l5 b- L
  2. #include "delay.h"0 Q8 z9 q0 m$ H% w# g" Y( p  r
  3. #include "usart.h"
    / T5 h& L8 y  \
  4. #include "led.h"# x" R- H6 y" M1 E; f# ?6 u# A$ `
  5. #include "beep.h"
    ' [: _3 _, b: X+ C; u& S/ N
  6. #include "key.h") i# t- g5 E  z
  7. #include "usmart.h"" r( i  O9 k+ ]
  8. #include "lcd.h"
    " E' _( H! V8 `  m' j, O6 D+ k* g/ W
  9. #include "rtc.h"
    8 ~$ w; s+ L& U
  10. #include "rng.h"
    9 x% j  K7 b+ m0 I) N
  11. #include "key.h"3 A7 q( J3 h1 `3 V& h8 [, Z
  12. #include "wkup.h"
    / q* B5 b4 K$ |2 `9 k& C
  13. #include "adc.h"6 W# W0 }; k- \" u# O5 `- O+ h

  14. 3 T, ~/ f* u/ G+ G+ |! g( f
  15. int main(void), B; g- f7 w) r% @% M2 u) G
  16. { $ K, `: x) o: r+ m
  17.         u16 value = 0;: b! F: I. D) ^/ N5 }  u
  18.         * i+ W. p; ^6 ^- H: U2 s  X" x
  19.         float temp = 0;5 B- Y* M  W1 I' F# ^; O9 S

  20. 2 [, r: c. ^" p( u
  21.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    + p$ p9 a( G4 X/ J- h7 O
  22.           N6 z4 V& I9 f. }, M1 E% c
  23.         delay_init(168);7 w# T0 G' G* b5 d; i9 I3 u; Y
  24.         
    + i  L( u5 g0 J% ?/ M8 F
  25.         uart_init(115200);! s0 ~# ]5 {2 z) l7 q# t
  26.         
    2 H0 C4 n7 F& q/ b4 H. V
  27.         usmart_dev.init(84);% s3 E; I* R1 z  w* G, \

  28. 4 f$ ?" b7 g2 F$ l7 k: e
  29.         0 I4 c5 M/ v) W* Q
  30.         LED_Init();
    : T0 e1 S* v% m5 O
  31.         " @& ^( @& z, h  y, t
  32.         : B1 G4 h# H8 x+ A& I
  33.         LCD_Init();) L* k2 ^1 U0 g
  34. $ }0 a+ W- w" F% a
  35.         ADC1_Init();! e% e3 L( p& k2 x" U- i' J: n
  36.         
    # U: t" V! V, W- Q; A! k' {
  37.                
    8 O6 M2 P8 m" [2 r! j' k) z
  38.         POINT_COLOR = RED;/ n$ ^( t1 N* D
  39.         
    " D. P" }/ L3 a2 \
  40.         LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");        
    2 B3 E1 T3 n7 H6 }
  41.         LCD_ShowString(30,70,200,16,16,"ADC TEST");        6 s  ^% [" F$ Q3 g
  42.         LCD_ShowString(30,90,200,16,16,"ATOM@tom");4 R# C2 `& x5 f6 N. S; |
  43.         LCD_ShowString(30,110,200,16,16,"2020/09/10");         8 V+ M& d4 B+ g. z' ^
  44.         
    , c+ d- n/ E# y' V& t% W3 M
  45.         //设置字体为蓝色* E! @0 b6 x- N7 D# C6 _
  46.         POINT_COLOR = BLUE;
    . ~% H4 H* `$ B# f5 `- N
  47.         LCD_ShowString(30,130,200,16,16,"ADC1_CH5_VAL:");         ' A0 V! w3 `. \8 g
  48.         LCD_ShowString(30,150,200,16,16,"ADC1_CH5_VOL:0.000V");         / l3 n+ B" b( \3 X8 z' Q
  49.                 9 p' T3 |3 g8 p2 M1 X
  50.         while(1)
    7 e4 m: t5 s. A2 u: W1 X
  51.         {
    . u! v0 F) j4 {
  52.                 value = Get_Adc_Average(ADC_Channel_5, 20);+ r# N; W# S& t! h8 m
  53.                 9 d9 X% f, Z" k0 D( ]+ @7 z
  54.                 //显示采样之后的原始值
    1 Z: V6 w; s$ \7 q. Q
  55.                 LCD_ShowxNum(134, 130, value, 4, 16, 0);
    # [; O  W+ s( L+ q  s$ `0 M8 c
  56.                
    * {: s9 X+ q( z& a
  57.                 temp = (float)value * (3.3 / 4096);
    6 U3 W9 `$ [3 |# d
  58.                 value = temp;
    8 M+ [5 ]4 ^( v
  59.                 LCD_ShowxNum(134, 150, value, 1, 16, 0);
    4 F9 s7 k+ T& z: h$ s$ n# }/ d
  60.                 7 S( w0 l3 S: A
  61.                 //小数部分: B$ D! _" O  d1 B: z$ R  P( }  U
  62.                 temp = temp - value;% r/ F; u4 N9 o4 J- `1 \
  63.                 temp *= 1000;' `1 b. p8 v( `( C! _  M
  64.                 LCD_ShowxNum(150, 150, temp, 3, 16, 0x80);                8 e! o. p$ y# R( T8 Z6 J
  65.                
    " I; [3 n" H7 j$ a4 W1 W* z
  66.                 LED1 = !LED1;" ^/ A/ S2 ^$ X; [1 P* d
  67.                   \" U, t' I# V* ~
  68.                 delay_ms(250);
    4 g; b0 l: U& d1 q
  69.         }) q" e7 k& |$ q$ ]
  70. }
    2 L. v7 _, x2 N- l4 l
复制代码

7 B" M2 Z" }( D8 B0 N) V+ s- J% m0 E4 y+ g; x/ C$ X

2 ^4 z/ }; P: R( g4 o& h/ \. m6 @$ i2 G7 k
赞 收藏 评论0 发布时间:2022-3-28 11:02

举报

0个回答

所属标签

相似技术帖

官网相关资源

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