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

【经验分享】STM32CUBEMX--ADC通过DMA方式采样,USART打印

[复制链接]
STMCU小助手 发布时间:2022-5-1 17:11
概述
7 S' W8 c- }2 S直接存储器访问(DMA)用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何CPU操作的情况下通过DMA快速传输传输。这样节省的CPU资源可供其它操作使用。/ Z7 }! Q7 j2 C; V
DMA允许在后台执行数据传输,无需Cortex-MO处理器干预。在此操作过程中,主处理器可以执行其它任务,仅当整个数据块需要处理时,才会中断主处理器。这样即使传输大量数据也不会对系统性能造成太大影响。
6 Y- `6 c# R, D9 nDMA主要用于为不同的外设模块实现集中数据缓冲存储(通常在系统SRAM中)。与分布式解决方案(其中每个外设都需要实现自己的本地数据存储)相比,DMA解决方案在硅片成本和功耗方面的成本较低。; t( _7 M% U8 o& u$ Z7 {
根据使用的产品型号的不同,有一个或两个DMA模块。8 J! Z1 g# f  {/ V' S
STM32F0XX DMA控制器总共有5个通道用于DMA1,每个通道都专门管理来自一个或多个外设的存储器访问请求。它具有一个仲裁器,用于处理不同的DMA请求的优先级。) m& z! w4 G* v2 _/ Z# J5 e# \- Q
本篇文章主要介绍如何使用STM32CubeMX实现ADC在DMA下快速采集,并且打印出去。- N' }8 R- O2 o
- M1 G- N& o1 A! Y! ]5 e5 G4 k
EQ{ERVW)DSXLA%RR%PC{8UM.png " R2 q8 S, U3 O' [

2 i8 ~3 Y  J+ I# f( f: t2 \  f硬件准备3 P. k. q6 w/ O. H
首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:
; D5 A! B  `! z$ B2 x1 \
) t* N/ I, r) F. s4 e" ]3 ` `A2E78`G2A(G4WWEN{[1R%A.png : `( J( Z" e0 R/ z# H+ d% D) g

8 y5 b, W8 E. u! e+ i" R) @选择芯片型号
( h* W  ?( H' U* Z5 j2 Z( x使用STM32CUBEMX选择芯片stm32f030r8,如下所示:
! k2 g$ F  }9 b6 _7 j
( J0 g; Z, ]- k/ f' O3 [ 7@~P`VDI2ZVN8KZP2A4JI]Y.png
  g4 p2 A9 |* ?! J9 y2 `6 w$ L' `; Z# E& m5 g, j  d
配置时钟源

! b( I6 O$ v+ e3 x# bHSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:( {1 H" c& o, s7 [2 L0 C( E5 U7 v

3 Y4 _* P# y8 S! u& _ $I~6X}E})}@@]PYOY]B1$JG.png
# h+ z* E5 x5 _# W. @2 Y
" t. @3 i; u; _* ]6 _配置时钟树

7 H2 S5 ]0 H- ySTM32F0的最高主频到48M,所以配置48即可:- B* A& p& N. ^2 Z$ x& ?7 B+ x

' v0 S$ n7 V( O8 E) Z) Y (OEN}M$Q2{KHJM[[}B]HOBX.png & v- d* ?9 s7 U

" Q2 V: w0 y7 r* b# a串口配置
( Q$ b4 H1 k7 G3 E/ G本次实验使用的串口1进行串口通信,波特率配置为115200。+ a( l" {3 A( n. o5 j& X
5 W1 ?1 j- D+ c! R5 T$ o
{OI]$~~3XNBOXF(35TG3AUB.png
6 g- h+ H! n" f4 y+ O8 P* t: g9 O6 c/ ]& J
ADC配置
, b* m* S+ W+ e* U. n6 F# ZSTM32f030中,有一个ADC(模拟/数字转换器),每个 ADC 有 12 位、 10 位、 8 位和 6 位可选,每个ADC有16个外部通道、2个内部通道和一个VBAT 通道的信号。
* l2 j3 y% `( K* J! R* H7 a本文将开ADC的IN0、IN1、IN4一共三个通道,来分别读取ADC,由于串口2和IN2,IN3复用,故不使用IN2、IN3。配置如下:
4 i8 w. ]! X; n3 p, Z
  t/ I, F% Z' k; |. P/ I# l V(J4H2S~U3IP2UIXE$NX.png 0 E, |) Z0 A. e6 U+ l: B

- b& O7 a6 l  k5 `开启DMA:/ M' _% h( a  N, z: @
- k$ y+ R4 B7 M& m# k) R2 r% \4 V. O
%FYL5Q]37{8F~7WN9MYNE4S.png 9 b* _8 C- @6 ^& [! ?2 v
) ]4 v( x  S4 o/ M
打开中断:% Q& I! o8 o: c( A) C2 d

: Y& R1 N, `6 V! N* j %V6V}0CP}R`LGX7S)LA0G`N.png 3 C; H( W) t9 G) l

9 l6 _3 q5 c8 ?' P1 }5 X9 I0 ?生成工程设置
( J% ~. e; S% e3 i' E0 ]最后设置生成独立的初始化文件:
# b  h8 l) [; t) h! ?
7 f+ i! K" i' w. [: L 1NV@N1R}%)7J(8K6D[F{$ZN.png 0 K- e; |( z3 J
" ?" J: B! m! Z, {- m3 Q5 `
生成代码. x4 M+ v0 S6 h

# N1 i# O& \$ U" O, p1 Z
$ S  L" H3 z, ^6 D! h8 |% _& v4 W( c& X% u$ `
配置keil
7 }' d& x% x- n8 N9 Z) c

! T: b/ W' D; K; G `WR%J2DLCU@7AU2I3QB{N2L.png
. c& Q+ X/ x& E0 F5 V: X/ R3 D" C
代码
; Y! b9 K* L7 a4 Q7 L在main.c中,添加头文件,若不添加会出现 identifier “FILE” is undefined报错。
5 f$ [# G, }' \6 o# ?: K* |0 j: y+ O0 `4 w
  1. /* USER CODE BEGIN Includes */! S* A2 X% }- t
  2. #include "stdio.h"  S: `, B! D0 o3 t
  3. /* USER CODE END Includes */
复制代码
% @3 V: E6 K( e& \+ Z' U2 U
函数声明和串口重定向:
! C9 @. l& g! x" ~' a. _6 ]& I- @6 l5 k4 I; |6 t
  1. /* USER CODE BEGIN PFP */$ t4 L2 E1 v+ v/ X# n
  2. #ifdef __GNUC__
    1 q3 G; Y0 G" b! w# @' H0 f# J
  3. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    2 _, J7 q4 s: Z( }1 I1 }; q
  4. #else; }$ b( V7 E2 a8 Y6 R; D! i) s
  5. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    . L* ~7 E6 V5 ^; K5 m
  6. #endif /* __GNUC__ */9 J- {7 x7 @# d6 y; m' {9 G, _
  7. /* USER CODE END PFP */
复制代码
  1. /* USER CODE BEGIN 0 */2 y0 n( H0 q* H
  2. PUTCHAR_PROTOTYPE
    + [3 ^! K; a  b! i: E' O
  3. {% n3 D! j4 X9 I9 q# H: x- q
  4.     HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);2 D4 N# a$ c, X, ^1 X4 D
  5.     return ch;% _5 j$ N9 k, }3 Z0 Y. j2 t
  6. }, `: N- {2 F/ T1 V
  7. /* USER CODE END 0 */
复制代码
3 w& w5 l, B. e0 n4 D0 j$ Z
变量定义:
4 P7 k+ m* k+ S9 B$ K0 U% L8 @% x' D6 j+ }
  1. /* USER CODE BEGIN 1 */$ `. X! Q8 ^7 R
  2.                 uint32_t ADC_1, ADC_2,ADC_3;
    2 h# J) Y/ k/ f$ {( P
  3.                 //各采样30次,故30*3为903 [2 }. ~& C( o$ O# u! ]. s4 K
  4.                 uint32_t ADC_Value[90];
    4 i8 m$ @; N/ f
  5.                 uint8_t i;
    0 ]" v9 |/ B) l' Q
  6.   /* USER CODE END 1 */
复制代码

- t) v  Q: W, k! S" E0 U; Z使用DMA传输:
, @1 O+ L5 m# r8 P6 e' L! S7 D: x' c% T- R
  1.   /* USER CODE BEGIN 2 */
    ; v3 a9 f* f6 {" r4 q
  2.         HAL_ADC_Start_DMA(&hadc,(uint32_t*)&ADC_Value,90);    //使用DMA传输
    5 J+ i9 ~" Y- f' ~# I8 o; P
  3.   /* USER CODE END 2 */
复制代码

8 {  c1 ]- x) _& U& {主循环:
! |. X$ C, @5 c+ r  o/ @- v1 P: k% p' _, Z6 S% c7 ~$ I
  1. /* USER CODE BEGIN WHILE */) a' ?: J5 ~' z! u6 s
  2.   while (1)
    7 y- [* Q/ B' h4 H
  3.   {
    9 W" z4 i! D, D7 y. d/ L
  4.                 //放个延迟,防止程序运行第一次读出数据有误
      a  U2 q3 m4 b% v& ]- G
  5.                 HAL_Delay(100);
    / s! Y  l( Z  ^( d3 s
  6.                 ADC_1=0;9 x. _0 J+ l. F, b# N' L
  7.                 ADC_2=0;& d8 k* o: Z4 }0 }( y2 [! P8 @7 J
  8.                 ADC_3=0;* C6 D- {2 [# k" v
  9.                     for(i=0,ADC_1=0,ADC_2=0;i<90;)
    2 I* e, J4 f) e% v1 N$ @
  10.                 {* ~3 L* e& y" r" W& C# D
  11.                            ADC_1+=ADC_Value[i++];   1 d. p% C( s0 ~3 ]; `0 u
  12.                     ADC_2+=ADC_Value[i++];: s9 d" v1 c. ^& @) e" W
  13.                         ADC_3+=ADC_Value[i++];
    : K' Q3 x1 [8 l* \$ ~: H& j2 a
  14.                 }
    + O* _) z* |* V* w1 P
  15.     printf("ADC数据如下\n");
    : D" ?( Y9 W: @$ n# s
  16. //除以30为求30次平均ADC值,乘以3.3为以3.3电压为基准,除以4096为ADC配置为12位
    ! j: N5 w. f; Y; O" t1 P4 B
  17. ( Q7 `/ [7 A8 {4 O
  18.                 printf("ADC_IN0=%1.4f\r\n",ADC_1/30*3.3f/4096);" J# D; V6 {; P2 x  `3 C
  19.                 printf("ADC_IN1=%1.4f\r\n",ADC_2/30*3.3f/4096);/ g2 X( B! x0 }$ y8 S& n0 z
  20.                 printf("ADC_IN2=%1.4f\r\n",ADC_3/30*3.3f/4096);( f0 c" Z4 K2 c7 z5 k, T4 g$ g
  21.     /* USER CODE END WHILE */
    3 u1 S& `, u% J: M
  22. 3 h9 m. L0 i$ w5 Y* ~4 `) G( J
  23. 4 W& g' s5 J' `+ B9 }. c& S2 k6 K
  24.     /* USER CODE BEGIN 3 */
    3 a" [, u& J8 N4 t
  25.                 HAL_Delay(900);
    7 a: Z# _6 b7 ?- z  ^* O5 S2 {
  26.   }
    + x' }/ I2 R3 u5 v; B0 L. {4 I+ q. {
  27.   /* USER CODE END 3 */
复制代码
5 @5 e% Q' I/ C6 C
演示效果
) f; r' z& m* ~设定adc1口接3.3V,adc2口接GND,adc口接1.5V,输出如下。
9 z1 ]# l) Z" v; a: X$ N( v
/ {$ Q1 X- w  L F}6~C58F%[5GI$]B70YG_G1.png
* C3 J; I6 e: ^% o" M+ ~/ s2 F5 f5 A2 G; @! ^0 _! p
, _2 d/ G3 Q' F# U$ [% Z
赞 收藏 评论0 发布时间:2022-5-1 17:11

举报

0个回答

所属标签

相似技术帖

官网相关资源

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