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

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

[复制链接]
STMCU小助手 发布时间:2021-12-12 22:12
基于HAL库,实现最简单ADC采集。
" C5 R+ c( f# n第一步,使用CubeMX配置时钟。, i! m: D) e* B5 ?0 `
202004191224273.png

* N$ J+ t" u# d2 ?; u( `' A: K2 ~3 }" H
然后是adc的配置:
# b5 P/ n" L. i# \
# S3 y! t) o9 G7 t  w
20200419125831989.png

* @: o6 o& }! p- J( j* {* ^. {6 p( @2 c# M
将,稍微修改一下风格,并手写头文件和源文件。! J3 X4 Y1 c" q% J: U1 Y

7 ~2 r+ \6 |8 A% Padc.h很简单,就不说了。
. e, A* }; }* S3 }8 r' U! j  [. ~9 P' T) h" n3 K/ U$ @
  1. #ifndef __ADC_H
    6 O- I+ f# X/ [- c
  2. #define __ADC_H
    * J% v7 p6 A5 d  x" _/ x
  3. #include "sys.h"4 g: a6 ~7 l) p7 v/ N9 O$ y
  4. . r/ u  u! P- d8 h8 \& {8 A
  5. void MY_ADC_Init(void);                                 //ADC通道初始化; |9 _* Q  P9 `  O) _1 d
  6. u16  Get_Adc(void);                         //获得某个通道值
    $ R6 p* `. K$ q1 ?
  7. #endif
复制代码

( I( q( W) Q+ f- e/ d# M其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。
# l3 @! f4 L7 ~. b- ?  Z$ z' k6 X3 B& ^1 }
  1. #include "adc.h"
    9 ^' |* ^% E% x' j! k
  2. #include "delay.h"
    $ ^3 `2 h+ C; d3 S  K' ~
  3. 0 k) }/ `$ v( J! M" f! Y# j

  4.   T. t/ N! K4 e
  5. ADC_HandleTypeDef ADC1_Handler;                 //ADC句柄
    + O- P/ C7 {8 \" q0 h/ g
  6. ADC_ChannelConfTypeDef ADC1_ChanConf;       //ADC通道配置句柄3 f/ s# k' u& f2 ^1 D

  7. . {( l" n% @9 R

  8. 0 x% t1 D2 I* u) M- J, X
  9. //初始化ADC
    + a9 [) _( j+ q) t, b8 @
  10. void MY_ADC_Init(void)! O2 ]# S# G9 X3 K" x1 {8 V2 _
  11. {% A: j$ o% t; F! b. a0 m4 Y
  12.     ADC1_Handler.Instance = ADC1;, A* M- _  X( [+ }# {
  13.     ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
    9 m3 D( l9 s3 W+ @6 s
  14.     ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B;           //12位模式0 H9 r) p2 u9 m+ K/ }8 ]1 L2 m
  15.     ADC1_Handler.Init.ScanConvMode = DISABLE;                    //非扫描模式4 M  K' D1 p  i$ G+ @' V
  16.     ADC1_Handler.Init.ContinuousConvMode = DISABLE;              //关闭连续转换
    / N. {, }+ F6 x! D7 U
  17.     ADC1_Handler.Init.DiscontinuousConvMode = DISABLE;           //禁止不连续采样模式# f! @8 t8 {9 b2 [9 D
  18.     ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发
    ( t. p5 @( [  A1 U2 w
  19.     ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START;     //软件触发% F: q( |. F- \
  20.     ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;           //右对齐
    - u0 ]3 ^- I4 }
  21.     ADC1_Handler.Init.NbrOfConversion = 1;                       //1个转换在规则序列中 也就是只转换规则序列1* z6 ]6 P& s2 L
  22.     ADC1_Handler.Init.NbrOfDiscConversion = 0;                   //不连续采样通道数为0
    $ ?, T, \5 O' w( c# P! q2 j
  23.     ADC1_Handler.Init.DMAContinuousRequests = DISABLE;           //关闭DMA请求
    * X- Q( S7 y# N& j
  24.     ADC1_Handler.Init.EOCSelection = DISABLE;                    //关闭EOC中断
    , w/ C7 c) U$ M. f  Y) I! B1 Q
  25.     HAL_ADC_Init(&ADC1_Handler);                                 //初始化* M# M+ m" w0 }
  26. % {! o$ a1 Y. O7 k+ |; |. T/ D
  27.     ADC1_ChanConf.Channel = ADC_CHANNEL_5;                      //通道5 PA5! m8 t8 n( U3 G9 z; y  N
  28.     ADC1_ChanConf.Rank = 1;                                     //1个序列6 I; }, U- Z; B9 R  Q
  29.     ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES;      //采样时间+ k1 {) q, @8 O* Z/ B$ V( v; u
  30.     ADC1_ChanConf.Offset = 0;
    ) ^, ?( e2 ~8 S  D2 P( T& X1 I$ s
  31.     HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf);       //通道配置
    1 Z$ b1 [: L/ n. M9 X- B
  32. 1 w9 D# }4 B9 k  i4 L; ^
  33. }
    8 q. j1 z/ `  Y7 w  E
  34. 2 t" G& z* F: @( C: X, r% @0 y
  35. //ADC底层驱动,引脚配置,时钟使能
    ! F0 w5 ~* m3 U  ]& x7 L; v! ?
  36. //此函数会被HAL_ADC_Init()调用
    # v4 _  I5 I, o: y' Q& f, w* G
  37. //hadc:ADC句柄
    - S4 `' r9 y0 h, w9 U3 O9 N
  38. void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)$ o5 H) B9 \4 A+ v& z# ^& o
  39. {
    . w" ]0 R( h# _: H
  40.     GPIO_InitTypeDef GPIO_Initure;9 S+ a2 R; [# T) F5 P3 V
  41.     __HAL_RCC_ADC1_CLK_ENABLE();            //使能ADC1时钟8 @+ l* z5 S: R8 s" q' G) M
  42.     __HAL_RCC_GPIOA_CLK_ENABLE();           //开启GPIOA时钟
    - |3 X5 m. ~. u; Q9 I: K4 I
  43. ! d! Z- H5 a) j
  44.     GPIO_Initure.Pin = GPIO_PIN_5;          //PA5
    0 `/ H1 U5 w8 Y3 O
  45.     GPIO_Initure.Mode = GPIO_MODE_ANALOG;   //模拟
    ! I4 W7 M8 `1 g% T' S
  46.     GPIO_Initure.Pull = GPIO_NOPULL;        //不带上下拉4 [  N5 {- Z; j) Z- I9 [- B+ \% J
  47.     HAL_GPIO_Init(GPIOA, &GPIO_Initure);
    ; G$ O% N4 `( q/ s) ?/ {1 C! C+ t
  48. }
    9 L" x, U: p$ g3 h7 L

  49. * Z! [' g  A5 B0 ]+ z, Q
  50. //获得ADC值
    0 F0 i5 D' m! g( O0 }* p% Q3 K
  51. //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16$ s- I2 ]2 G" O6 t/ I
  52. //返回值:转换结果
    % w% d( }0 X- f3 e
  53. u16 Get_Adc()3 M2 P4 C& V; L
  54. {7 T- n9 X$ C* [$ Y0 [# `' g) [# j( [. ?
  55.     HAL_ADC_Start(&ADC1_Handler);                               //开启ADC
    ; t5 a; `8 b, E. B, T4 l
  56.     HAL_ADC_PollForConversion(&ADC1_Handler, 10);               //轮询转换
    # ^4 c7 q& W0 M) i0 o2 o: _
  57.     return (u16)HAL_ADC_GetValue(&ADC1_Handler);                //返回最近一次ADC1规则组的转换结果
    ' j1 l% t, T; b1 T" D7 O, j. Z8 m
  58. }
复制代码
+ U4 \; i+ w+ F7 ]" n1 v% a0 D
main.c中,主函数初始化之后,直接读取adc的值,并打印。
7 f  D9 \0 K5 Y( R3 L5 h$ h% J+ g" K
  1. #include "sys.h"7 I% \7 c* @  Y2 ^  f3 C- s
  2. #include "delay.h"
    % e+ l9 Z2 j& v/ i1 Z) m- s
  3. #include "usart.h"
    ; K5 J2 S% [% m; n) k
  4. #include "adc.h"
      k' i$ Z* |3 i& R; i( u

  5. 1 Q4 z/ e8 W! p0 i8 H! z, {
  6. int main(void)
    % m; q1 l9 p& s
  7. {8 x- Y9 d/ F: z/ E2 u8 b* \
  8.     u16 adcx;* G5 ^- j3 w, c9 H5 Q  ^
  9.     Cache_Enable();                 //打开L1-Cache# g9 _* u, ~7 j: H1 d( _; V7 P3 s# A
  10.     HAL_Init();                     //初始化HAL库
    ; S6 n/ n& X+ U) w5 u
  11.     Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz! t  u+ P. {" O
  12.     delay_init(216);                //延时初始化
    / Y! O8 c7 e" C4 B% }" G+ }
  13.     uart_init(115200);              //串口初始化
    ' a/ J$ I3 S- l: c! o1 A, W7 E8 g4 r
  14.     MY_ADC_Init();                  //初始化ADC1通道5* h5 W: X" x  Y% L# m
  15.         
    : l+ w, r2 F: n  B2 A6 a" E) q/ p! }
  16.     while (1)4 Z; w7 e3 r! l. I6 D* j; y
  17.     {7 L) f: F$ t1 u* d) a4 d
  18.         adcx = Get_Adc(); //获取通道5的转换值,20次取平均$ L3 E; z+ j2 E3 n
  19.         printf("%d\r\n", adcx);
    ' ^) W& R7 x$ b* e) {& l
  20.         delay_ms(250);
    $ M: v; Y4 w- K( _
  21.     }
    # T. e. z+ N7 h0 D
  22. }
复制代码
. c# u) g+ g8 n& n! B
如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:
' K& F1 B) K6 }2 Y6 ~, a
( J5 ^) F3 R: G+ |6 h
  1. //获得ADC值; ~0 S) Y) ?/ q) v2 L* U  ?
  2. //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
    ) `8 I! ]7 n, q/ ~5 L+ g& h% b
  3. //返回值:转换结果
    7 L7 n2 e( I# P- g7 m# Q# x+ z
  4. u16 Get_Adc(u32 ch)   
    4 T  G" N( f) _5 ^; M7 a* W4 T4 G
  5. {
    $ J/ B2 e! t2 Z. G
  6.     ADC_ChannelConfTypeDef ADC1_ChanConf;8 }. u, G/ n* _, E1 j, V

  7. # n2 O5 L) }; R4 ~9 u" H+ o
  8.     ADC1_ChanConf.Channel=ch;                                   //通道
    ' w: D& F' S; \4 v0 ?/ L& r" Y
  9.     ADC1_ChanConf.Rank=1;                                       //1个序列
    9 p. k+ w) j0 L6 @( r; J( i4 M
  10.     ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES;        //采样时间) h* O* o- r; L# J3 B6 [
  11.     ADC1_ChanConf.Offset=0;                 ' c4 L+ N; N2 `7 b8 M
  12.     HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf);        //通道配置3 _9 O, Z; j/ O/ v2 h
  13.         4 E* l7 u1 _' {
  14.     HAL_ADC_Start(&ADC1_Handler);                               //开启ADC6 @0 }5 E4 n6 f4 F
  15.         
    7 E- K! k) h4 {# Y0 V
  16.     HAL_ADC_PollForConversion(&ADC1_Handler,10);                //轮询转换" f2 k4 p/ `0 U, @1 o2 |# ~

  17. 8 e& i7 `# H; G4 Z/ V- y$ s% ^: c
  18.         return (u16)HAL_ADC_GetValue(&ADC1_Handler);                    //返回最近一次ADC1规则组的转换结果
      z' S+ p8 M& M: V- P$ j% D7 w
  19. }
    8 G5 w8 `1 z; X% `4 a
复制代码

, e6 W# I6 [0 v0 \' U; b4 U6 u
; |* A2 J8 W9 D
! m3 i& X  L4 q% |0 S" I* _
赞 收藏 评论0 发布时间:2021-12-12 22:12

举报

0个回答

所属标签

相似技术帖

官网相关资源

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