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

经验分享】STM32开发,野火ADC—独立模式-单通道-DMA例程BUG

[复制链接]
STMCU小助手 发布时间:2022-5-5 16:38
1 概述5 u3 s; o4 A. @# F0 K
实验的代码已经上传,无需积分。
: O3 T$ P3 v, n/ m0 ^8 V
' D7 v! {, V; ^& x1.1 资源概述
$ \# B# M: i7 s9 y开发板:正点原子STM32F103 Nano开发板
3 e: `) l2 F, t, ~+ PCUBEMX版本:1.3.07 P4 T: ~" \4 i" [
MDK版本:5.27: t+ G* y5 a2 w* I* E# t2 k0 q9 _% e
主控芯片型号:STM32F103RBT6
# `# z" c' n8 C7 X7 b. w! M6 G3 u3 h  l/ L9 r) Y4 Z, d
1OW)R5@@XAVNC_NZT627XPB.png
! O8 a+ q1 A6 I4 E. L6 ~* ^& }- S6 M. Y: k& D( a! j
1.2 实现功能9 v; \" K: U& |, X% _' g
1,移植野火ADC使用DMA传输例程,实现读取B01的电压,并通过串口打印出来。野火的程序使用的RCT6芯片,引脚与RBT6相同,改动比较简单。
6 {  R; C, b  K& _
+ S$ V8 r0 S+ k2 程序实现
4 n: o! Z! H2 s2.1主程序
$ i3 n% C2 Z% j. G1 \' l

  1. 5 o& P) ^- t5 {0 {. o6 w2 S
  2. /* Includes ------------------------------------------------------------------*/
    ' O" ^$ j2 O- q- d: b4 H! h& t
  3. #include "main.h"
    7 W; Y* E- _& {* A: C
  4. #include "stm32f1xx.h") m- k# K9 `) d. u7 |! Z
  5. #include "./usart/bsp_debug_usart.h"
    9 b* l2 N9 @3 @8 P
  6. #include "./led/bsp_led.h"5 s5 c! L$ K- J' H8 v' N  ^# M: d( r
  7. #include <stdio.h>3 K: W5 T  B% N+ S3 T
  8. #include "./adc/bsp_adc.h"
    # j7 F6 e) v- \- U7 K: Z2 `0 A/ ?* G

  9. 3 ?! k8 i% W: e3 m
  10. // ADC1转换的电压值通过MDA方式传到SRAM# ]! e0 E( Q  ]: D( s* W
  11. extern __IO uint32_t ADC_ConvertedValue;
    . w, @' X0 l! n
  12. " X) w( [  X$ m+ j, b0 n
  13. // 局部变量,用于保存转换计算后的电压值         
    " B8 w+ t  m. x: G9 q* E
  14. float ADC_Vol; " X; o' l" ^& }2 r+ t. c
  15. ; `5 ?: Q/ `6 a9 J
  16. static void Delay(__IO uint32_t nCount)         //简单的延时函数
    4 v3 Z/ ~8 I: T% z) }
  17. {
    ' o  {- g8 d4 s) N/ j
  18.         for(; nCount != 0; nCount--);0 F; h+ Q2 o- o( B" a- N) s  U' S
  19. }% ^& C* g0 D8 z
  20. /**
    # A8 A" `/ N2 O, r; d. C7 Q
  21.   * @brief  主函数& R: K$ y; t& x! ^0 P* l
  22.   * @param  无
    ) o# {: @, Q  w7 m8 w" @% s
  23.   * @retval 无( r) z1 r- F' M4 p0 D. b% o
  24.   */
    * l; e/ m& }+ N3 ]  P8 O. c6 |
  25. int main(void)( }& z8 r: w  o
  26. {   ! p1 k9 b- O8 K  m' Z  S
  27.     /* 配置系统时钟为72 MHz */
    # }1 }  D- {9 _" k4 t3 W0 E
  28.     SystemClock_Config();6 J0 w8 i3 _- I/ _
  29. ( H. B5 H3 G5 N! g% F1 m7 }, h( i
  30.     /* 初始化USART1 配置模式为 115200 8-N-1 */
    . j/ E& M7 X# I1 k0 {, B
  31.     DEBUG_USART_Config();
    - N1 Q7 w6 [: C. T; g/ W
  32. % M; N# Y% z9 Q: x7 ?$ g
  33.     Rheostat_Init();6 m, o8 p) E% u
  34.     while (1)
    ' X( c3 [  b/ _9 _" t
  35.     {
    % c7 E+ O1 K3 T: z
  36.         ADC_Vol =(float) ADC_ConvertedValue/4096*(float)3.3; // 读取转换的AD值
    % ^/ V/ V" c  v! o9 O+ a
  37.         printf("\r\n The current AD value = 0x%04X \r\n", ADC_ConvertedValue); & Y' K: \9 ~) y" L: S
  38.         printf("\r\n The current AD value = %f V \r\n",ADC_Vol);     6 @& u/ h, f* P# ]# o3 G& r( w
  39.         Delay(0x8fffff);  
    - |+ h' `5 I" ~! L4 ~: I- T$ r
  40.     }   1 @5 G1 ^6 V6 u
  41. }
    # [5 x8 D8 U& ?4 A
  42. * S+ P# q4 g; C* a  y
  43. /**
    + J, B- \" W4 e* `- e- a" _4 ^& o1 y
  44.   * @brief  System Clock Configuration: x7 ~: `9 J! e* ]) z
  45.   *         The system Clock is configured as follow : ! A1 u: {6 r- G# k: h
  46.   *            System Clock source            = PLL (HSE)
    # G/ E$ b7 A1 H
  47.   *            SYSCLK(Hz)                     = 720000003 O. J: E; t2 g6 K+ F6 K
  48.   *            HCLK(Hz)                       = 72000000! P' Y+ g. n- o# q, r. R. y
  49.   *            AHB Prescaler                  = 1
    & e" H2 t; r; Z- ?7 @* H" E* T- B
  50.   *            APB1 Prescaler                 = 2$ L* \# ?2 u7 j" K! W+ f' m
  51.   *            APB2 Prescaler                 = 17 x. O# ?' ?+ f& N
  52.   *            HSE Frequency(Hz)              = 8000000, X+ T3 z3 i- K% E5 v$ \1 Q) ?% {
  53.   *            HSE PREDIV1                    = 1
    ! m. _+ \8 q/ ?" ~" G
  54.   *            PLLMUL                         = 9
    ( {# s- u6 \, E8 ^6 }( L% z
  55.   *            Flash Latency(WS)              = 2/ `9 _4 u4 C. i2 H- r' g4 w! m
  56.   * @param  None
    2 S9 Q* _/ v8 ]2 o; q
  57.   * @retval None: w; g+ W1 Z; s, t8 p
  58.   */
    & I9 [& B) H: h5 o9 ]2 g+ f
  59. void SystemClock_Config(void)/ Y4 ?- R# B8 g$ l1 ^7 ?# W) F
  60. {
    1 N8 b+ f, e8 ^6 @3 L
  61.   RCC_ClkInitTypeDef clkinitstruct = {0};3 W1 w1 [; z/ J2 I
  62.   RCC_OscInitTypeDef oscinitstruct = {0};( \3 T4 T) L0 N& C# n4 [
  63. 6 x# s5 d. B  q- o$ F) t
  64.   /* Enable HSE Oscillator and activate PLL with HSE as source */
    * m! \7 i8 @% }
  65.   oscinitstruct.OscillatorType  = RCC_OSCILLATORTYPE_HSE;
    3 K, B6 \8 g; u4 S) a
  66.   oscinitstruct.HSEState        = RCC_HSE_ON;
    3 z/ W  d% Y3 z  c/ G( d0 B, A1 W4 x
  67.   oscinitstruct.HSEPredivValue  = RCC_HSE_PREDIV_DIV1;) |9 V# ^, X+ Z! Z4 y, P6 D4 _; q
  68.   oscinitstruct.PLL.PLLState    = RCC_PLL_ON;
    " X* _# N" S" h2 j3 P
  69.   oscinitstruct.PLL.PLLSource   = RCC_PLLSOURCE_HSE;7 b- Q( D5 [: g: ]4 d: q5 p2 U
  70.   oscinitstruct.PLL.PLLMUL      = RCC_PLL_MUL9;
    / f- g+ i2 P9 I5 A- F! ?
  71.   if (HAL_RCC_OscConfig(&oscinitstruct)!= HAL_OK)
    ; h# m' V+ y% W
  72.   {6 z: D; S1 o( d& \# R: j( W/ t
  73.     /* Initialization Error */5 _  ]! e0 L1 f
  74.     while(1);
    2 S2 v) g& B* ^0 t# r1 }0 w) T$ u
  75.   }
    0 O3 f4 a# i8 w

  76. 5 e: B; f) p1 Y: k
  77.   /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
    ( j; w6 b5 }' t( a1 G' Y
  78.      clocks dividers */
    # S0 A$ `% c/ I- U) k2 C
  79.   clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);2 y5 \8 s1 c$ P6 G
  80.   clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;6 {% S' @' S# O& @0 t2 B
  81.   clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    5 ?' H. H( z" @* A6 s  T5 Z& d+ n9 T
  82.   clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1;
    4 U7 T6 _5 D- i6 i, X. P
  83.   clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2;  
    8 O: d* X. m) E1 ~
  84.   if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2)!= HAL_OK): q. K) T/ `) V
  85.   {
    4 ~) X1 J" y, U2 Z' e9 \' d: m
  86.     /* Initialization Error */
    2 V; c$ O8 E/ I5 m
  87.     while(1);
    8 C2 O8 m2 Y6 y
  88.   }
    , B' W! F/ {5 B' T" \: s
  89. }
复制代码
9 e) T7 l5 A6 V$ Z
2.2 ADC程序" ~; D2 A0 O  x6 B; m3 A
  1. #include "./adc/bsp_adc.h"7 f9 K+ z# b- ~- T, N
  2. * z' V+ i  }2 ]$ l
  3. __IO uint32_t ADC_ConvertedValue;
    ) A/ h2 L2 d! y- G: U3 t5 d
  4. DMA_HandleTypeDef hdma_adcx;0 w& S0 V$ T7 B! W  c+ k  n
  5. ADC_HandleTypeDef ADC_Handle;+ x6 d% L* _) W- @& d
  6. ADC_ChannelConfTypeDef ADC_Config;
    & l: X- b) P0 K) \! T0 Z0 o

  7. : @6 G: K: q( d) x6 N7 c* b# o
  8. static void Rheostat_ADC_GPIO_Config(void)
    ' @4 m* E5 m4 h3 W
  9. {
      w) I  s& |" u4 d, c
  10.   GPIO_InitTypeDef GPIO_InitStructure;1 v8 c. Q4 ]6 ^6 ]0 \: |) S
  11. - t: Q5 G# ~* Y4 d$ {: F5 S; j
  12.   RHEOSTAT_ADC_CLK_ENABLE();
    / |% U- q# ]0 Q2 b0 a
  13.   // 使能 GPIO 时钟
    8 ~' [- `+ I1 g- D2 v% M
  14.   RHEOSTAT_ADC_GPIO_CLK_ENABLE();
    4 {0 ~, v; o$ l% p4 |; N& \4 i

  15. ' S1 C5 j& P+ k; ~7 a* `4 |+ ^1 Z
  16.   // 配置 IO. Z( d& L# O$ H
  17.   GPIO_InitStructure.Pin = RHEOSTAT_ADC_GPIO_PIN;" i& M3 _2 T  w
  18.   GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;            
    - l; A8 J9 g  b& m
  19. //  GPIO_InitStructure.Pull = GPIO_NOPULL ; //不上拉不下拉
    $ j* u) h! Z  }! d, T# e. E1 M) H
  20.   HAL_GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure);               
    ) y' T: M; [, I' {; r4 @. T, t
  21. }
    $ K4 {' k  K7 a+ P/ e/ O$ i; U/ [& t

  22. ( r) H. {1 V5 V3 s4 w2 q" P
  23. static void Rheostat_ADC_Mode_Config(void)
    ( d% l/ s& h0 Q' b
  24. {
    , [" r4 X- m: ]( i% q0 b% T
  25.     // ------------------DMA Init 结构体参数 初始化--------------------------
    3 v8 B3 H  N5 I6 e3 ]
  26.     // 开启DMA时钟- V4 U/ s+ d% P
  27.     RHEOSTAT_ADC_DMA_CLK_ENABLE();. D2 ^7 R" O1 M$ W! c
  28.     // 数据传输通道
    , z3 {. A/ t1 H- p
  29.      hdma_adcx.Instance = RHEOSTAT_ADC_DMA_STREAM;! W' E; G5 s: ]
  30. : |) d; q, E3 b1 p! D* f) S
  31.      hdma_adcx.Init.Direction=DMA_PERIPH_TO_MEMORY;;            //存储器到外设: }2 B4 L( I7 }, Z/ T
  32.      hdma_adcx.Init.PeriphInc=DMA_PINC_DISABLE;                 //外设非增量模式6 P  d; B# h6 }( D2 M! N4 H
  33.      hdma_adcx.Init.MemInc=DMA_MINC_DISABLE;                     //存储器增量模式
    $ a5 j  Q2 c7 H! m% P
  34.      hdma_adcx.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;//外设数据长度:16位/ m& A4 ]9 R9 E; H6 S
  35.      hdma_adcx.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;   //存储器数据长度:16位,错误已经修改
    $ i: K% Y! c7 a. P$ ^7 D# f! L# j9 f
  36.      hdma_adcx.Init.Mode= DMA_CIRCULAR;                         //外设普通模式1 s+ @/ c' W) v/ n
  37.      hdma_adcx.Init.Priority=DMA_PRIORITY_MEDIUM;               //中等优先级
      O& e% o3 c  N2 w
  38. # M4 Z0 p' d1 i8 H0 [
  39.     //初始化DMA流,流相当于一个大的管道,管道里面有很多通道
    - R6 v' t# ?! W6 ~
  40.     HAL_DMA_Init(&hdma_adcx); ) d: f6 m% R' f# t+ ~/ a

  41. 1 }4 B' Q. _: }4 h3 T9 G5 n
  42.     __HAL_LINKDMA( &ADC_Handle,DMA_Handle,hdma_adcx);
    + P, F3 _! E0 t
  43. * p( L- M+ |. l8 L0 E5 L
  44.    //---------------------------------------------------------------------------8 I0 G) {" N1 s) f
  45.     RCC_PeriphCLKInitTypeDef ADC_CLKInit;
    5 d' h- i4 h1 y. P( }
  46.     // 开启ADC时钟
    , ^: C1 Y/ N) R8 `
  47.     ADC_CLKInit.PeriphClockSelection=RCC_PERIPHCLK_ADC;                        //ADC外设时钟
    " y+ U: D2 R% m; Y& r5 S0 W% ?
  48.     ADC_CLKInit.AdcClockSelection=RCC_ADCPCLK2_DIV8;                          //分频因子6时钟为72M/8=9MHz; y% D& e' j7 e# m# j
  49.     HAL_RCCEx_PeriphCLKConfig(&ADC_CLKInit);                                              //设置ADC时钟
    , a' x( I9 q' a, _; E
  50. ' p1 e$ C- P: N! g+ b( H
  51.     ADC_Handle.Instance=RHEOSTAT_ADC;
    " K# t: Y. h3 I
  52.     ADC_Handle.Init.DataAlign=ADC_DATAALIGN_RIGHT;             //右对齐
    3 c9 g# X5 `: R% I; ]
  53.     ADC_Handle.Init.ScanConvMode=DISABLE;                      //非扫描模式0 U8 a, q: q, G
  54.     ADC_Handle.Init.ContinuousConvMode=ENABLE;                 //连续转换. v0 f% t2 h) ?& [% \! ]
  55.     ADC_Handle.Init.NbrOfConversion=1;                         //1个转换在规则序列中 也就是只转换规则序列1 7 b, W0 X$ |) d
  56.     ADC_Handle.Init.DiscontinuousConvMode=DISABLE;             //禁止不连续采样模式
    4 L: w( x* j- h) u/ \- E) Q( ~
  57.     ADC_Handle.Init.NbrOfDiscConversion=0;                     //不连续采样通道数为0
    9 b$ W8 W1 u( P6 a
  58.     ADC_Handle.Init.ExternalTrigConv=ADC_SOFTWARE_START;       //软件触发
    : ~: f) u* p6 t
  59.     HAL_ADC_Init(&ADC_Handle);                                 //初始化
    ) K: W) g" K+ [; f, Z
  60. 9 G* U4 q0 l% v  x8 I% B
  61. //---------------------------------------------------------------------------) T# I8 P3 R5 N# ?& d# E3 v
  62.     ADC_Config.Channel      = RHEOSTAT_ADC_CHANNEL;+ H! @. m( t. T* H  p
  63.     ADC_Config.Rank         = 1;6 ^. l- a) _. m/ e  h! H
  64.     // 采样时间间隔          U% H# C: i+ K0 U7 q$ Y; n( `
  65.     ADC_Config.SamplingTime = ADC_SAMPLETIME_55CYCLES_5 ;
    9 `/ o" {9 X1 Y2 Q5 |) p
  66.     // 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期
    ; S" R- S9 _, @8 ~& w7 g
  67.     HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_Config);
    ) {+ Z3 E* J9 u( O9 _

  68. ; B+ ?* b3 p$ u- Z2 N
  69.     HAL_ADC_Start_DMA(&ADC_Handle, (uint32_t*)&ADC_ConvertedValue, 1);
    ! Z. ?8 U% Z8 r, Z7 y
  70. }* G2 t2 F6 h3 c0 c3 k8 P
  71. void Rheostat_Init(void)1 A7 Y% q; B6 o) V( e7 }1 A: w
  72. {
    , ~/ z% o+ n) g2 ~* u. z: I6 p
  73.         Rheostat_ADC_GPIO_Config();
    0 @2 [- s3 E$ L: D% ^
  74.         Rheostat_ADC_Mode_Config();, l, d, t! d2 |! g# V8 s( U! M
  75. }1 Z: o8 ?4 g3 x+ B; O" G
复制代码

* U$ z1 k3 v: C2.3 ADC头文件
$ g- B6 V8 V, `0 L  L调整端口定义与正点Nano保持一致,这里需要注意的是,GBIOB1对应的是ADC_IN9, 对应的DMA1_Channel1(通道1,而不是11)。1 ^3 E& F9 O/ p. W+ K4 p  f+ {
9 `% r4 B& y+ B" k; C
  1. #ifndef __BSP_ADC_H
    & B$ W; P! z/ U9 l) b) f
  2. #define        __BSP_ADC_H
    ) g! f* [, i" L- P# e
  3. ; i* S6 l5 D- _: m  B1 _* m' |1 x& H
  4. #include "stm32f1xx.h"
      w9 n8 N, R; W6 Z8 ^
  5. ' J. x( a: g8 K2 U
  6. // ADC GPIO 宏定义& Q  A& B6 X$ D, r( g: \- |
  7. #define RHEOSTAT_ADC_GPIO_PORT              GPIOB
    . u6 g  O3 l6 J( K, F& J
  8. #define RHEOSTAT_ADC_GPIO_PIN               GPIO_PIN_1
    8 l9 l5 F' _+ {) V) O0 G
  9. #define RHEOSTAT_ADC_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOB_CLK_ENABLE()
    ! o  ?6 }- M5 F0 e# J+ q  u
  10. " P" }3 W" Z1 p& E
  11. // ADC 序号宏定义
    4 T2 M. Y9 _7 \! K( z" b
  12. #define RHEOSTAT_ADC                        ADC1" N. d5 R8 Q/ _- Z  a# O# q
  13. #define RHEOSTAT_ADC_CLK_ENABLE()           __HAL_RCC_ADC1_CLK_ENABLE(); , R) c  S+ @: J3 ~. f/ o4 [/ H
  14. #define RHEOSTAT_ADC_CHANNEL                ADC_CHANNEL_9) y; H6 z1 R! T) i

  15. % ?. Q9 Y. n5 l' r7 A( u
  16. // ADC DMA 通道宏定义,这里我们使用DMA传输
    $ M7 ~: |2 ?& e/ G
  17. #define RHEOSTAT_ADC_DMA_CLK_ENABLE()       __HAL_RCC_DMA1_CLK_ENABLE();8 x7 P0 H0 @% i3 |0 ~* [
  18. #define RHEOSTAT_ADC_DMA_STREAM             DMA1_Channel1% B9 y/ t- D) ~$ S/ c: E9 p0 t

  19. : T2 h% S, g) [- Y/ q
  20. void Rheostat_Init(void);# c9 i: Q, |( Q+ z; d& K! }: L1 \2 q4 D

  21. ! @: V: Z7 \2 ~0 q; Q
  22. #endif /* __BSP_ADC_H */
    # @, b4 Y2 b! @5 W; ^$ z. z/ I% Y
复制代码

: ]6 N! k' G1 V6 H( p  V) \0 M4 @& Q3 程序调试+ B  a" |# t/ H; j+ k- w# Z2 {" W. b) s
在程序调试过程中,串口打印一直无法输出正确的值,都是小于1的小数,而且调节滑动电阻时,数值会发生变化。由于是移植的例程,一直怀疑是我自己改程序导致的,但是经过换成别的开发板,而且ADC端口不改的情况下,还是不好用。如果开始了漫长的查找过程。路程如下:
9 e. i- ?9 b7 D/ o1.使用CUBEMX生成一个ADC DMA传输的程序,正常运行没有错误;+ t" ^* D# }1 J
2.将生成的程序,ADC以及DMA相关部分去掉,加入野火例程中的ADC相关文件;
5 y- M5 ~+ r4 V- J/ f( w9 j3.将CUBEMX生成的ADC相关文件加到野火程序中,运行正常没有错误。
6 d5 M9 |1 q! {4.运行调试发现不好用,只显示小数;
: @+ F4 D0 j( M! i4 D0 o5.将原CUBEMX生成的函数,一块一块加到野火程序中去,替代旧的函数。最后发现在配置半字时出现问题。! ?% C: `3 P$ D  D
例程中错误的配置
- H% c7 `1 l/ P5 M1 _
  1. hdma_adcx.Init.MemDataAlignment=DMA_PDATAALIGN_HALFWORD;   //存储器数据长度:16位
复制代码
9 M& J, w+ _- g& j- Q
而正确的配置为(P改为M)
* h. L) e- |% C" s$ P3 V  H4 u- F% Q5 n6 `
  1. hdma_adcx.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;   //存储器数据长度:16位
复制代码

* i1 P3 X9 n7 J# H5 r- ^修改后程序调试OK,下面为更改后和更改前的结果,在错误的程序中,第三位的B丢失了。正确的位B37,错误的为37。
; T; M$ f( A8 D6 ^- |9 h4 ?6 y( x2 S6 H3 C# x) P8 p1 Q* u
I%)L04ETGX8I~%HCCXF87)R.png
* G' U+ i3 Y! O  B" J4 y6 c6 i1 f: ~  Q$ d* b5 K9 b
4 查找原因
4 n$ A' h8 U  r7 N0 _查看官方手册继续查找原因,将程序里边的定义一层层翻出来,结果如下。0 v  C* f1 Y1 o& ?
3 \0 d* L' \3 p1 P
错误赋值函数
: w2 ]+ W* V/ S, i9 Y! I0 c! V- ?; Y" b
  1. hdma_adcx.Init.MemDataAlignment=DMA_PDATAALIGN_HALFWORD;   //存储器数据长度:16位" Z4 p) b2 a' w2 {
  2. ( z  H) t* E* Z- u
  3. #define DMA_PDATAALIGN_HALFWORD      ((uint32_t)DMA_CCR_PSIZE_0)  /*!< Peripheral data alignment: HalfWord */$ r' q, Z5 E1 z

  4. 1 y  W, @+ H* P
  5. #define DMA_CCR_PSIZE_0              (0x1U << DMA_CCR_PSIZE_Pos)        /*!< 0x00000100 */
    8 |' [% C- Z) C, v8 J" r) \$ S
  6. 4 s! \3 ]3 X0 X6 m
  7. #define DMA_CCR_PSIZE_Pos            (8U)      2 y6 x$ h# E! ?" Z
  8. 2 l% Z, V/ ^, M: Y3 ?, \3 h& V+ o: _
  9. STM32F1中文参考手册V10里边关于DMA配置寄存器的说明
    5 Q4 q5 B# h! w! J0 A7 R
  10. 位9:8
    # Q7 s3 l. X! I9 }
  11. PSIZE[1:0]:外设数据宽度 (Peripheral size) 这些位由软件设置和清除
    / t0 a# L% ^" D) c6 u
  12. 00:8位
    ; L- m+ E4 V- j, v
  13. 01:16位
    8 r8 d0 |2 q* s0 f% F! T
  14. 10:32位 8 O0 ^, ^" t+ q7 H" y6 O
  15. 11:保留
    / D: i( A4 t* f: F( c
  16. 这是错误的设置,导致外设的数据宽度设置了两次,而存储器保持默认00,即为8位,而ADC为12位右对齐,最高4位丢失。 / }5 `( N+ R6 P; p7 I
复制代码
" D7 s$ P6 m, Y3 r5 C
正确赋值的函数
! ^) L1 S( [$ p8 z

8 d1 F+ X: f; x/ {6 A
  1. hdma_adcx.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;   //存储器数据长度:16位
      b9 j! v$ C6 x

  2. + D, F& l) f0 O# v8 M/ G) T$ e
  3. #define DMA_MDATAALIGN_HALFWORD      ((uint32_t)DMA_CCR_MSIZE_0)  /*!< Memory data alignment: HalfWord */5 @2 m& k9 S+ W

  4. 8 h( h5 k3 [0 B) x
  5. #define DMA_CCR_MSIZE_0              (0x1U << DMA_CCR_MSIZE_Pos)        /*!< 0x00000400 */
    5 s+ Q4 V5 F+ @/ O4 K

  6. & s9 ^* n$ {/ V' |" K  v7 W
  7. #define DMA_CCR_MSIZE_Pos            (10U)   + s* c: a3 k9 m7 l" g7 p( a, Y0 n* O

  8. : c" z4 @& P+ d) T- o# b1 ^: U
  9. STM32F1中文参考手册V10里边关于DMA配置寄存器的说明
    8 I; e  C( ~# I5 Z7 t& t2 P% k5 [: Z
  10. 位11:10 0 S# D$ G$ Q' X* f
  11. MSIZE[1:0]:存储器数据宽度 (Peripheral size) 这些位由软件设置和清除
    : L( J: E( [5 R
  12. 00:8位 7 ^6 }# N/ X: I. t
  13. 01:16位 ; ]9 q8 H" h4 p% ]  U. n' X
  14. 10:32位
    ; D9 _" K/ m( X$ u3 @* Q+ E/ A
  15. 11:保留+ L9 p% E" `' a8 c/ ~) y7 g6 M; j9 s
  16. 这是正确的设置,存储器设置位01,即为16位,最高4位不会丢失6 Z0 |. }# l- m' C0 ]0 T
复制代码
9 I8 u& B9 p# d* @
原因分析和实际情况一致。
& M- r5 |5 ?0 `  X1 d查看野火给的资料,发现里边的这个地方是错的,和程序保持了一致。这个程序应该是被误写(使用自动补全),然后编译后实际验证没有认真检查导致。
( J4 s! F* K9 a$ L4 ?5 |6 e+ E, l/ O

8 K4 C+ U4 n" }9 h$ F( z2 ^7 {3 g1 x' @* l; ?( y& P7 y. D- F9 T
收藏 评论0 发布时间:2022-5-5 16:38

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版