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

基于STM32F7进行ADC采集解决更新问题

[复制链接]
攻城狮Melo 发布时间:2023-3-14 11:26
ADC1DMA_Handler.Init.Mode6 M: k5 c, D( b
DMA的正常模式(DMA_NORMAL):采集到DMA_BufferSize 的个数后,DMA停止。  k% q* G# x( ~; u
DMA的循环模式(DMA_CIRCULAR):采集到DMA_BufferSize 的个数后,重新回到设置的RAM的起点位置,如此循环。. J! S1 Y4 H: ~! W/ R3 [
虽然道理很好理解,但个人感觉要配合触发信号来用,通过HAL_ADC_Start_DMA软件触发需要设置起点位置和长度,否则这个参数是没有意义的。
1 }3 H+ S1 o' r& P
( q) y. F' Z& _% z. r
ADC1_Handler.Init.ScanConvMode

8 Q3 A4 }% p, x% s扫描模式(ENABLE):ADC会依次扫描设置的各个rank+ d9 U  d4 S! B1 O, }" s
非扫描模式(DISABLE):ADC只会读取rank1,即使设置的DMA_BufferSize大于2,也只会读取第一个;如果没设置rank1(此时我的设置里rank2接的3V3,rank3接的gnd),读出来的结果是516这种奇怪的东西,我也不知道是个什么鬼东西……
$ B& ?3 P, o( _  o" {2 c即使需要只读取rank1的值,把NbrOfConversion不就可以了嘛~
3 d7 o" D( W4 p所以这个参数我建议设置成ENABLE,我也不知道什么时候该用DISABLE。; c6 J6 w2 D! g9 g3 P9 {+ z

0 G: x) e7 K, g# I2 u4 X2 IADC1_Handler.Init.ContinuousConvMode. A/ J  m4 y1 i4 p0 a
开启连续转换:开启了连续转换后,adc会一直转换,直到DMA_BufferSize大小,如图是HAL_ADC_Start_DMA 64个长度的结果。
1 D; ~* t+ T. }7 _) u6 D- B) w# |$ `1 j! Y2 J
20200419192759329.png 9 G/ Q  s4 {  D) [" E* S( f
3 F. |. x) h9 |$ Y$ E! h
而不开启连续转换,长度为64的同时,DMA的传输中断都不会进。
$ `5 k9 `  p6 k; o/ W) j0 `4 |9 R* V2 {
20200419192936345.png 8 `/ X8 P; f8 A
4 }' y- h8 c' s! _9 Q, o  \# l
而将传输长度设置为3的时候,就进入了传输完成过半的中断。+ {2 \3 p8 n0 c) z& ~, E0 g
20200419194129548.png 7 q# S) I8 r6 ~' W3 C& O9 v" O0 {
2 v7 l* ~& a+ ?0 Y/ c& W
如果我们需要采集连续的N个次结果求平均值,用这个连续转换会很方便。3 B" A% H8 m( b6 r
也从侧面说明,dma的传输中断是一定要有那么长的真实采集数据来才能进的。
: e, }1 i% h) |  L" f/ m3 d# i; \
7 F% e8 z% S! U6 k
在另外一篇博文里看到了这么一个表格,希望能够辅助大家理解:3 M2 m6 a( \+ H$ i9 j- e

* l4 U7 D- M" q* V7 [- A0 U
20200421214739891.png
# E( {7 f# a1 b: b( q1 [0 d
9 D( K; k9 T: N7 N/ g
ADC1_Handler.Init.DMAContinuousRequests
4 S; J) [* b* r/ t7 [3 }当设置了定时器触发DMA之后,这个参数如果设置为DISABLE,就只会采集一轮数据,然后结束。
3 u1 p- h4 D& E4 A8 C这个数据设置成了ENABLE之后,这个参数设置为ENABLE,一轮采集完成之后,感觉就会自动调用一次HAL_ADC_Start_DMA(&ADC1_Handler, (uint32_t *)buffer, 100);,触发DMA请求,以实现不停采集。+ s+ u; K4 r+ V8 k! S# ~

) w+ y9 @4 B0 ?5 i1 i$ \6 q( x9 o但是需要注意,如果开启了连续转换,又开启了DMA连续请求,adc将一直进行采集,一刻也不停歇……
. h7 y* q, h6 H/ T
. z; z$ C/ i1 Y( ]( k3 oADC1_Handler.Init.EOCSelection& z2 x+ U- W$ h" x( l& k
偶然看到一个帖子的回复:+ A' X" S7 r$ ^2 W% s
当有CPU和其它主设备【如DMA】共同访问某可缓存的二级存储器比方SRAM1,同时该存储器又具有回写属性,此时就可能发生数据一致性问题。因为该存储器的回写属性,导致通过CPU欲写入存储器的数据只是缓冲在CACHE里,而没有及时写入存储器。如果此时DMA访问该二级存储器的话,读到的数据可能跟预期不一致。% g2 q: v9 `: ^+ T* S( J* U
为了避免数据不一致的问题,我们需要做D-CACHE维护操作。一般有如下四种方法: 1、当对一个可缓存的二级存储器做了写数据操作之后,通过软件对D-CACHE进行清除操作,即运行SCB_CleanDCache()。这样将CACHE里的缓存内容写回到二级存储器,比如把那些DIRTY8 [7 @1 `" j8 O6 O- P$ Y1 U
CACHE行的数据写进SRAM1。: I; Q% ~4 P1 A/ J4 G
2、通过MPU调整可缓存存储器的存储属性,将其CACHE使用方式改为透写模式。这样保证每次写入CACHE里的内容也同时写入二级存储器,比如写进SRAM1。+ b# Z6 b* C& v; K$ ^7 h9 @7 k8 O
3、通过MPU调整可缓存存储器的存储属性,将其共享属性改为可共享的【SHAREABLE】。此后该二级存储器将变为不可缓存。, K3 W: c/ D# ]1 U' l
4、通过配置CACR寄存器中的D-CACHE位,强制将所有写操作配置为透写属性。
+ r8 z& W/ m8 i' n' q' h2 ~: T! L# g8 t8 c. J4 |, u( u. H; _
在main函数中关闭cache,DMA采集的数据就可以更新了。0 }# R& W( l+ i. k2 k, i9 @, O

3 ]7 [/ \0 b4 u$ s3 l, l* c, g
20200419215859139.png ; y; a- y, P+ Y. ]" D

3 c! K/ R, ^6 K9 q4 J# @3 h- B附上成功时候的配置,注释掉HAL_NVIC_EnableIRQ是因为中断服务函数里的打印会导致main函数无法继续执行。8 e( }& {4 ?  ~9 N4 _  E. E
  1. #include "adc.h"1 p; A1 H5 ?- O# _3 \
  2. #include "delay.h"
    , F& w1 D  ~2 N% {' n! {9 ^8 W

  3. & G1 L( i9 h( c0 M  r( h2 S
  4. ADC_HandleTypeDef ADC1_Handler;//ADC句柄8 I- C6 L. i/ s0 }/ c' h+ u# I
  5. DMA_HandleTypeDef ADC1DMA_Handler;
    * W8 o$ c, J0 M+ J+ Z6 S: I
  6. ADC_ChannelConfTypeDef ADC1_ChanConf;
    0 I, f! F( D8 h: d9 L6 c+ d8 m
  7. - G. J" `) f6 K
  8. uint16_t buffer[128];+ v- k( j, h( w0 V9 G: i1 {

  9. ) A9 r5 {# ~7 j
  10. 7 N0 _9 O  F' c$ |7 u, ^& R
  11. //初始化ADC
    + K- f- I* a0 z5 L% o/ U7 M
  12. //ch: ADC_channels& o( \) Q# p( j  m; z1 Y. E
  13. //通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
    : R0 _2 d# d3 D
  14. void MY_ADC_Init(void)* j0 n- \* y' l/ e/ d7 ]0 `
  15. {
    % z1 e- a: r. d! ]
  16.     __HAL_RCC_DMA2_CLK_ENABLE();! Q: _$ N- z3 T% q1 z; H
  17.     HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
    % i2 t" ]9 f/ u; f
  18.     //HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);2 N) h# W3 h/ a

  19. 7 W( a$ W* J* U5 }8 G. W
  20.     ADC1DMA_Handler.Instance = DMA2_Stream0;
    1 l$ e9 f5 }& l; N* \
  21.     ADC1DMA_Handler.Init.Channel = DMA_CHANNEL_0;: x0 ^* l2 ?  u3 d% ]
  22.     ADC1DMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;* \; P. [& C% v' h9 u0 p* H
  23.     ADC1DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;               //外设非增量模式3 W8 [' j+ o# J( G0 q5 a0 G$ S% o
  24.     ADC1DMA_Handler.Init.MemInc = DMA_MINC_ENABLE;                   //存储器增量模式
      g, T/ K% b2 w
  25.     ADC1DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  //外设数据长度:16位; f/ g+ f7 c. p  l; v6 Q& G
  26.     ADC1DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     //存储器数据长度:16位/ h4 Q! |) K' ^& I
  27.     ADC1DMA_Handler.Init.Mode = DMA_CIRCULAR;                          //传输一次就结束
    1 X- Z4 V4 A! z9 l0 P& z8 c
  28.     ADC1DMA_Handler.Init.Priority = DMA_PRIORITY_LOW;             //中等优先级7 ]7 O2 x' M' R0 Z2 }: @" r" b
  29.     ADC1DMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;            /* 禁止FIFO*// C6 U$ K* s6 B

  30. ! i7 u8 X( d( }
  31.     HAL_DMA_Init(&ADC1DMA_Handler);/ k% g: _. Y6 v+ Q5 p+ d& i6 }
  32. 0 a( N+ @9 w; u* Q
  33.     __HAL_LINKDMA(&ADC1_Handler, DMA_Handle, ADC1DMA_Handler);                //将DMA与ADC联系起来
    " w. _5 ^& `; n" U8 }( K2 o2 d( `8 ~

  34. 6 F( p! m5 Z% I- f0 }3 N+ `; h4 k
  35. , B1 h. c0 y" |; ?. J- L
  36.     ADC1_Handler.Instance = ADC1;
    2 I6 x# l3 _8 R$ x0 ?. U+ m9 `
  37.     ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
    - O: {. w3 P7 U+ x/ b- l
  38.     ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B;           //12位模式
    1 C; t# n( t+ h5 h0 N
  39.     ADC1_Handler.Init.ScanConvMode = ENABLE;                    //非扫描模式
    * k/ t6 D' q. a# l  o8 J
  40.     ADC1_Handler.Init.ContinuousConvMode = ENABLE;              //关闭连续转换
    6 I4 j2 X# p$ N$ t
  41.     ADC1_Handler.Init.DiscontinuousConvMode = DISABLE;           //禁止不连续采样模式
    - \5 }/ X- R2 J# w" S& C
  42.     ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发
    ( U0 J9 _5 k' B6 Y8 Z5 W
  43.     ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START;     //软件触发
    9 i) [3 H* y8 q/ v  h# O
  44.     ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;           //右对齐
    8 j1 ]- t1 e& `5 S
  45.     ADC1_Handler.Init.NbrOfConversion = 2;                       //1个转换在规则序列中 也就是只转换规则序列1
    + f& @7 ]/ f1 }  w6 q
  46.     ADC1_Handler.Init.DMAContinuousRequests = ENABLE;           //关闭DMA请求5 t( C; L& N9 m) Q2 d# A
  47.     ADC1_Handler.Init.EOCSelection = ADC_EOC_SINGLE_CONV;        
    $ {% O" H9 d" I+ W+ p0 N. L
  48.     HAL_ADC_Init(&ADC1_Handler);  e% n9 K+ Z  o

  49. / x& M7 @5 F  j  X& k
  50.     ADC1_ChanConf.Channel = ADC_CHANNEL_5;                                 //通道
    3 i- A. f6 f/ e) A
  51.     ADC1_ChanConf.Rank = 1;                                     //序列1
    - U% v0 D- h* |$ K
  52.     ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES;      //采样时间& B+ N8 U! g: [. q( j4 `) V
  53.     ADC1_ChanConf.Offset = 0;
    ) @! R% O: l% j2 A5 ~0 x
  54.     HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf);       //通道配置
    1 w6 P0 O7 C2 C$ F, ?

  55. 0 q/ m! H3 |' J! l# l! z- ]  H
  56.     ADC1_ChanConf.Channel = ADC_CHANNEL_6;                                 //通道
    $ ^" S! V3 A0 `
  57.     ADC1_ChanConf.Rank = 2;                                     //序列28 N7 n* N, W/ p4 Q8 l
  58.     ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES;      //采样时间8 H. `- f. |4 X
  59.     ADC1_ChanConf.Offset = 0;% X3 {0 d' v: z- L; c4 v
  60.     HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf);       //通道配置
    5 Q8 h/ p. F) |# r4 ~) v4 \& r
  61. 6 U% o1 d; q+ O5 h5 M
  62.                 HAL_ADC_Start_DMA(&ADC1_Handler, (uint32_t *)buffer, 100);2 u7 Y. g* s8 h6 Y6 M
  63. }
    - Z" u( y, A0 e2 F8 |

  64. 9 _5 L. h! \$ e" P
  65. //ADC底层驱动,引脚配置,时钟使能) [2 x% [- k5 q& k: P
  66. //此函数会被HAL_ADC_Init()调用
    # \6 Y7 _+ M& ?& e. \" a4 l2 B
  67. //hadc:ADC句柄$ F+ n$ l6 ~# g" {- c# R
  68. void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)4 k& `; z* z/ s; r
  69. {% y/ i/ M! F3 q
  70.     GPIO_InitTypeDef GPIO_Initure;# [" [# m8 e) h. g* g
  71.     __HAL_RCC_ADC1_CLK_ENABLE();            //使能ADC1时钟( n& y) e% S9 b0 W8 N, J" V
  72.     __HAL_RCC_GPIOA_CLK_ENABLE();           //开启GPIOA时钟7 ~, y/ C8 U% L  ]0 |' D6 i

  73. / q; X, g# C$ L, b( X! F
  74.     GPIO_Initure.Pin = GPIO_PIN_5|GPIO_PIN_6;          //PA5# Y1 s7 j( o7 {6 r/ t0 O
  75.     GPIO_Initure.Mode = GPIO_MODE_ANALOG;   //模拟9 M1 t0 d  S) K! B" q
  76.     GPIO_Initure.Pull = GPIO_NOPULL;        //不带上下拉3 ]* Y, z- q/ e, ]* B3 Y4 ?
  77.     HAL_GPIO_Init(GPIOA, &GPIO_Initure);. Z# z- U; q' g# B+ q  R+ _/ b7 _% j
  78. }- A. w' v' N! k5 O
  79. $ |. M9 L1 C' u
  80. void DMA2_Stream0_IRQHandler(void)1 K/ u  Z# K6 T8 Y7 C
  81. {
    4 t$ B; D5 M0 H- T: y
  82.     HAL_DMA_IRQHandler(&ADC1DMA_Handler);
    / W. q5 R+ f* q$ z' I, [8 @+ z
  83. }! l1 E9 @- Y. B+ p

  84. " ^  M9 R9 ?. E9 b5 y* A5 G' T9 Z
  85. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
    2 e' b  T0 |/ u- z  Z
  86. {
    7 @: ~# H' ?, ?4 c- X1 x; m
  87.         printf("DMA transfer complete\r\n");
    6 L7 w0 z" F7 |
  88. }0 V+ W, K  f) K+ B
  89. void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
    : n! C8 N( K# k: a( c0 q! C
  90. {
      y$ \0 t! ~1 a# D$ c, s% v
  91.         printf("DMA Half transfer complete\r\n");
    0 q4 s0 K; y* _( x3 F
  92. }
    8 B" M# c! d' X5 p: p( p, L/ D: g
  93. ' q8 \# t+ y  e2 O: o
  94. void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
    2 N$ r9 ^# X4 G. I5 I$ o
  95. {
    + o, {" K8 g# \- t) G* d  P
  96.         printf("DMA transfer error\r\n");
    1 m4 j& S, \# K1 S- v
  97. }; {- Z; G+ Z9 W
复制代码
  1. #include "sys.h"  d* @/ ]# }1 T: k
  2. #include "delay.h"9 _, c9 q( z4 r4 V$ g2 M
  3. #include "usart.h"
    : w( Y. S8 T6 Z' G" z
  4. ' `6 w' `$ _, a( `  {5 Q8 }7 N3 {6 O
  5. #include "adc.h"
      Q0 _! D% R4 J' ?6 O

  6. 9 Q: l* V/ @& _5 B& p7 C& H
  7. extern uint16_t buffer[128];. Q* }. v$ i! _# H$ r* S, o" t
  8. - Y0 L5 v: ~3 H8 b5 }) a/ a$ j
  9. void show()
    ! W8 l7 Q1 {+ x/ M: c
  10. {# z+ f; {: P) A" c1 ^$ a, a4 a
  11.     int i;4 j: l2 H7 g" r# h5 ^3 |5 q0 c) b5 Z
  12.     printf("\r\ndata:");
    . y- ]+ j. T3 f
  13.     for (i = 0; i < 128; i++)% @# C4 c% n4 r  Z' ~3 C
  14.     {6 q' ^) C8 ?% {+ l. Y2 }1 R
  15.         if (i % 16 == 0) printf("\r\n");- G$ S. Y  {. v" w7 @, v1 j
  16.         printf("%6d", buffer[i]);& t- i1 `0 K3 L2 t5 W
  17.                         buffer[i]=0;
    # L8 L" B4 Y  \( q1 A0 O2 W
  18. ; w2 C" r' ^$ b& C
  19.     }
    ; q3 z8 [$ }2 h% }1 i
  20.     printf("\r\n");
    1 r- X; c& f. b( O
  21. }( a" y/ t) m' Q
  22. 7 r! {# b; W: Y( D( K) B+ b

  23. . s( `) ^' f3 {3 W
  24. int main(void)( k/ e( Y" T  `  H4 I4 C  T2 \8 Z$ i
  25. {; v+ p  e* k! j0 l* O* z1 I% q
  26.     //Cache_Enable();                 //打开L1-Cache6 _' A4 n1 ]% p$ N, |/ x' [- m6 d
  27.     HAL_Init();                     //初始化HAL库
    2 m. v# [* C+ O6 r; X
  28.     Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz" l% G) R5 s7 A0 w$ r  {! I: }
  29.     delay_init(216);                //延时初始化( G+ _9 N* }- ^; \% z9 q- `
  30.     uart_init(115200);              //串口初始化5 a' C9 D/ Y; j- M0 ~7 t
  31. 5 I' @; K; X# w& B+ C% I
  32.     printf("start\r\n");: X0 L' e) j) o
  33.     MY_ADC_Init();                  //初始化ADC1通道55 I: v8 p  t+ P
  34.     2 D, I/ E7 R$ L2 s! i% P2 k) Y
  35.     while (1)
    " P! R/ j1 |, b& p8 p& U
  36.     {  }; W4 @# Q$ G) Y' I! ]; m
  37.         show();) i' W* Z7 }+ d9 P& U
  38.         delay_ms(1000);
    ( {% L) d1 p! ]; i1 S! N8 s
  39.     }" O) P0 ?9 S& k: ~# g- k
  40. }
复制代码

  l1 |6 F6 W. c. `, Y9 [————————————————& m5 l; R! u/ b1 z7 I' _' `0 p' g
版权声明:小盼你最萌哒
7 b& l7 U$ J+ ?. }如有侵权请联系删除
8 j0 q7 G: c  e0 N5 Q5 [
; H' S/ a  Y  {7 h7 d; f
收藏 评论0 发布时间:2023-3-14 11:26

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版