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

【经验分享】STM32F7实现ADC采集(软件触发+轮询)

[复制链接]
STMCU小助手 发布时间:2021-12-12 22:12
基于HAL库,实现最简单ADC采集。
& T/ W# [$ ?) Q7 M" r$ n$ _' G第一步,使用CubeMX配置时钟。1 d5 n; O* m  @
202004191224273.png
6 \! _4 j# q: ?) N
6 M$ D3 r* ^+ l% M4 M( C" z7 z3 A: u
然后是adc的配置:$ v+ x4 Q' n8 C  Y. c7 j
9 B- N5 ~- K9 L/ T2 k% l6 y
20200419125831989.png
, _2 }- G* U0 h* T

, H4 m# S( B7 M9 W将,稍微修改一下风格,并手写头文件和源文件。
( d- j+ e3 B9 k' T8 G9 i- m7 t4 v$ Y
adc.h很简单,就不说了。. k+ @+ R) `7 v/ R
2 W% {! v% B  H" L8 Q; r
  1. #ifndef __ADC_H
    7 b6 V9 O6 J* N: P1 x/ Z
  2. #define __ADC_H
    3 q/ q/ N" u$ l+ ?5 ~
  3. #include "sys.h"4 ^) m% G7 {; T( l
  4. : M. e/ }. B$ Q# Q
  5. void MY_ADC_Init(void);                                 //ADC通道初始化
    ) _# B7 L$ v* |7 f7 B5 m
  6. u16  Get_Adc(void);                         //获得某个通道值
    6 Q. I2 V8 N$ }. V1 [, z
  7. #endif
复制代码
; U% n. U- V& ?6 p
其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。3 j% B$ X4 M) i) G. ~

! b" P  k: U% a- Q: _# g
  1. #include "adc.h"
    2 v4 M* [1 E- n! ~% |
  2. #include "delay.h"8 q0 d% j2 U& o  t. V0 P# F
  3. # G6 X) }" W0 J8 r& \

  4. : ~- R4 S' y& R
  5. ADC_HandleTypeDef ADC1_Handler;                 //ADC句柄
    * A# n# L: S1 W6 H
  6. ADC_ChannelConfTypeDef ADC1_ChanConf;       //ADC通道配置句柄
    9 F* A# \" z: x8 _) P& J6 [

  7. * }( e8 A8 s4 o) S) p
  8. 3 r# _3 ~) |; c% Y
  9. //初始化ADC
    & }5 P( A% F% T( S; ]) }0 ?
  10. void MY_ADC_Init(void)
    3 U6 w! o3 R7 ^' K) |, @$ s
  11. {
    - h' K& w; H* B7 P
  12.     ADC1_Handler.Instance = ADC1;
    $ v6 l" ~2 \  J8 M1 w( k# X
  13.     ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ( x# {1 L3 L# `/ |, E
  14.     ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B;           //12位模式
    ! w- e% K  u4 N
  15.     ADC1_Handler.Init.ScanConvMode = DISABLE;                    //非扫描模式* o) `$ q: G& p8 T1 g! Y/ K
  16.     ADC1_Handler.Init.ContinuousConvMode = DISABLE;              //关闭连续转换
    2 O9 ]; r0 K- V) a( E
  17.     ADC1_Handler.Init.DiscontinuousConvMode = DISABLE;           //禁止不连续采样模式
    & ^. q. k. k: h& ?( }9 ~: W/ C
  18.     ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发7 z( h. d6 N3 y9 V
  19.     ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START;     //软件触发( S8 L- [: x% F9 f7 o+ @. g  r9 \" o
  20.     ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;           //右对齐* T& @- Q) p) l( K2 h3 Q
  21.     ADC1_Handler.Init.NbrOfConversion = 1;                       //1个转换在规则序列中 也就是只转换规则序列1
    % l2 G1 e  T7 a. ~0 C5 I
  22.     ADC1_Handler.Init.NbrOfDiscConversion = 0;                   //不连续采样通道数为0
    4 M9 |5 W8 s& y6 a
  23.     ADC1_Handler.Init.DMAContinuousRequests = DISABLE;           //关闭DMA请求5 ?& X' r5 ?* v5 v# u
  24.     ADC1_Handler.Init.EOCSelection = DISABLE;                    //关闭EOC中断3 p) A5 G1 f+ s0 _2 I* }2 M
  25.     HAL_ADC_Init(&ADC1_Handler);                                 //初始化
    2 z6 O/ R% ?1 {6 P
  26. 8 l* M" H% O( e$ o1 X) M' W
  27.     ADC1_ChanConf.Channel = ADC_CHANNEL_5;                      //通道5 PA5
    / A' O! y: U( _. J
  28.     ADC1_ChanConf.Rank = 1;                                     //1个序列
    * E/ A2 s/ i) d9 _; D- @( z0 L; _
  29.     ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES;      //采样时间
    ; X3 B) J3 s3 n, x, ^
  30.     ADC1_ChanConf.Offset = 0;9 d* K4 \% z) `. H9 c6 ]* R
  31.     HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf);       //通道配置
    ( _8 R' Q) ^/ `- J7 D* P* ]& G& B5 Y

  32. ( H* U* _/ b2 D( v- K- i
  33. }
    0 v& Y% Z* R: S/ x$ l2 Y! a5 d1 M
  34. ' a- `2 H; v  t7 n4 ?0 X+ Y  i
  35. //ADC底层驱动,引脚配置,时钟使能
    / K+ k2 g- M0 |! n) j
  36. //此函数会被HAL_ADC_Init()调用2 U/ I$ n+ B8 j1 s2 z; r7 P
  37. //hadc:ADC句柄
    * Y; u1 ^9 ?7 a: a. t1 _
  38. void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
    # N2 S. c& H, m  p( S! g
  39. {. j4 L; s6 V% {. {
  40.     GPIO_InitTypeDef GPIO_Initure;& k" u1 M6 p7 N! a( r( D
  41.     __HAL_RCC_ADC1_CLK_ENABLE();            //使能ADC1时钟. H, v9 \2 m7 i+ N" m6 Z5 X- M
  42.     __HAL_RCC_GPIOA_CLK_ENABLE();           //开启GPIOA时钟
    6 b. ^3 {/ l3 B9 N: n% H- P4 `

  43. : v% Y/ Q8 U. \2 s' g3 ]2 K& t5 c
  44.     GPIO_Initure.Pin = GPIO_PIN_5;          //PA5
    # P2 R+ y1 |7 n* _1 b7 ~: w, B7 w! @
  45.     GPIO_Initure.Mode = GPIO_MODE_ANALOG;   //模拟
    6 x+ m2 g0 a. j: F
  46.     GPIO_Initure.Pull = GPIO_NOPULL;        //不带上下拉
    5 q8 l$ o  y: r/ ~* i
  47.     HAL_GPIO_Init(GPIOA, &GPIO_Initure);
    $ ]. O9 `' {% |' y# x# j/ K1 f! K
  48. }
    0 b  Q( p* y( w& V7 Q( g
  49. - [8 U9 ]- _" i1 B( {7 F- `
  50. //获得ADC值0 T8 v# Y: R# C
  51. //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
    1 g& O  `+ K4 F. U" i, P, t$ S) V/ B; m
  52. //返回值:转换结果
    3 z1 y& A  L6 d- j* Y( T  V
  53. u16 Get_Adc()
    5 s. ^8 ^' y/ V; s0 L! X
  54. {  |+ C5 B3 v0 n+ W: K, P& o
  55.     HAL_ADC_Start(&ADC1_Handler);                               //开启ADC. J  g, X# F0 l
  56.     HAL_ADC_PollForConversion(&ADC1_Handler, 10);               //轮询转换
    2 ~) W2 O  }: y! `5 R5 W
  57.     return (u16)HAL_ADC_GetValue(&ADC1_Handler);                //返回最近一次ADC1规则组的转换结果
    : `- u* b5 c9 L/ t8 t5 L
  58. }
复制代码

" |7 A. L$ U. [2 X7 l4 V8 Rmain.c中,主函数初始化之后,直接读取adc的值,并打印。
) D. `4 i( H! }7 x
1 S* ~+ r% b3 o$ j
  1. #include "sys.h"
    & x3 |+ x4 I1 T
  2. #include "delay.h"# n9 k/ q. V) c* R+ N% _; K$ @; a
  3. #include "usart.h"
    ! K" u3 c5 E- T; j  c9 \" _
  4. #include "adc.h"
    ; g# f5 e( p3 q. n0 t

  5. $ w2 Y6 M; j. \
  6. int main(void)
    % A: f' `0 l: L9 G; ?: \
  7. {
    - h4 w: }& ]* @" P/ w# Q% e
  8.     u16 adcx;# M; S* l6 ~6 T3 K: c3 q' G
  9.     Cache_Enable();                 //打开L1-Cache
    , |9 H0 a- R& c; s' e( E8 t
  10.     HAL_Init();                     //初始化HAL库
    2 C, \: U: l; Q+ d7 ^* B/ `
  11.     Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz
    + t! G5 Y# Z. h( |1 w
  12.     delay_init(216);                //延时初始化5 l2 o& v: a  _: A9 `+ @
  13.     uart_init(115200);              //串口初始化
    . I! ~; l% ]4 E* b
  14.     MY_ADC_Init();                  //初始化ADC1通道52 V+ [4 k' p: s3 Q) e
  15.         
    $ Y0 m  e1 x" h7 e, p* m- J
  16.     while (1)3 Q. y) ?) v1 p* P
  17.     {
    : ?( Z! n' L2 V$ H
  18.         adcx = Get_Adc(); //获取通道5的转换值,20次取平均/ r! ], S8 e. E) r: u5 Y
  19.         printf("%d\r\n", adcx);8 ]$ Z$ R: A  j, Y$ {
  20.         delay_ms(250);
    / @: d3 a7 T; U. n
  21.     }+ f# K% A; Y4 X3 ?& d9 C
  22. }
复制代码

6 @; A# `, d6 b9 H0 x+ v$ n* V如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:; `" X' |( Y, `6 J7 h

+ E3 E2 y9 w* k
  1. //获得ADC值
    " K( i* Q$ O6 F5 s$ s1 u- B
  2. //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16# f$ J3 L5 u: l/ v" Q) ]
  3. //返回值:转换结果0 n9 z  G- w0 I+ a8 n1 A* a" S
  4. u16 Get_Adc(u32 ch)   ; S* L- t1 W( M. F+ K( |, g
  5. {! J+ d( K# B4 Z, E
  6.     ADC_ChannelConfTypeDef ADC1_ChanConf;
    : t& |2 e, U! J4 H6 H# G1 s

  7. , O2 T. m- n% M. s( j$ |
  8.     ADC1_ChanConf.Channel=ch;                                   //通道  r" t( a. s- F2 N: j7 v: t: q
  9.     ADC1_ChanConf.Rank=1;                                       //1个序列7 N7 T  D0 @9 m. D$ S
  10.     ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES;        //采样时间
    / m8 b% M2 v$ n' C# u2 a
  11.     ADC1_ChanConf.Offset=0;                 3 \6 d8 I, _9 A; H0 {$ a
  12.     HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf);        //通道配置
    ! r2 p9 Y- X2 G
  13.         
    ! @% Q- l+ A" ]/ u' e% P
  14.     HAL_ADC_Start(&ADC1_Handler);                               //开启ADC5 A0 W# h/ i9 g" P
  15.         8 \% c, I# C* U- s
  16.     HAL_ADC_PollForConversion(&ADC1_Handler,10);                //轮询转换+ Q' a) _# N1 w, _9 ~3 M* m( r) V
  17. * I! s5 |8 e$ ^
  18.         return (u16)HAL_ADC_GetValue(&ADC1_Handler);                    //返回最近一次ADC1规则组的转换结果
    * N5 f. T* ^; F! k
  19. }/ R; D4 V# o$ m, ^, A
复制代码

( g' d5 s1 W1 F8 X- I
# [2 Q. W/ O+ a4 K, l6 R5 M3 ~2 C" i+ ~4 P9 B* w) P+ V
赞 收藏 评论0 发布时间:2021-12-12 22:12

举报

0个回答

所属标签

相似技术帖

官网相关资源

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