|
: h! A- v; y) n3 _* e* g 问题描述:7 [4 H. d. U: g9 @, o/ y' x 利用CubeMX初始化ADC和DMA,发现DMA设置CCR寄存器不能设置成功,导致DMA不能按照预定工作模式工作,后经调试发现,Cube生成的初始化代码先进行ADC设置代码中也对DMA一部分寄存器进行了设置,但这部分设置由于DMA未启动,导致设置不成功。具体描述如下: % j& m: l9 c- K7 ^ # T; z( L9 a% s( o 软件版本:CubeMXV5.4.0* f8 H/ c6 U3 r+ D" Z" v+ q ADC设置:6 E' N0 a/ Z1 }- e. ~
! f! E1 m/ B5 I* }. m& | ; E3 ]* r: _& n! B. m, ^ 7 S1 t4 n% c6 | DMA设置:7 O/ {7 M6 w* M& N1 W: P
, b/ W3 t7 o/ A8 x4 b) G4 G 生产初始化代码为:% Z8 x$ t# Q6 F) S! B5 } /* Initialize all configured peripherals */ ( r$ j3 n7 r- j" K( R MX_GPIO_Init(); 7 [3 A& Q7 w/ q MX_ADC1_Init(); , y' H. U# T3 s- I* } MX_DAC1_Init(); MX_RTC_Init(); 4 O8 S8 \" G; _) w& ^% ]) a MX_TIM6_Init(); MX_DMA_Init(); - u. {1 E, l8 O* j L0 z3 }MX_ADC1_Init->HAL_ADC_Init->HAL_ADC_MspInit: voidHAL_ADC_MspInit(ADC_HandleTypeDef* hadc): /* ADC1 DMA Init */ /* ADC1 Init */ hdma_adc1.Instance = DMA1_Channel1; 6 f) A- A0 Z7 r5 Y, S# N% j# g) f, C hdma_adc1.Init.Request = DMA_REQUEST_0; ' _. D z: o0 G" k P hdma_adc1.Init.Direction =DMA_PERIPH_TO_MEMORY; hdma_adc1.Init.PeriphInc =DMA_PINC_DISABLE; * W- Q3 k- r) ^) s! ?- {1 _0 K hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; / ]* A% |; l4 z: n hdma_adc1.Init.PeriphDataAlignment =DMA_PDATAALIGN_HALFWORD; 1 t& P& k" \ Q( u; B2 ` hdma_adc1.Init.MemDataAlignment =DMA_MDATAALIGN_HALFWORD; ! z0 z, O' J1 p6 x7 x8 i" L- c$ r hdma_adc1.Init.Mode = DMA_CIRCULAR; hdma_adc1.Init.Priority =DMA_PRIORITY_HIGH; & M2 h7 }6 R+ I if (HAL_DMA_Init(&hdma_adc1)!= HAL_OK) { / {9 {- a) T0 i1 \; E Error_Handler(); } __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1); ( m% n h; A9 P8 V /* ADC1 interrupt Init */ # @- |; h& h7 T1 _ HAL_NVIC_SetPriority(ADC1_IRQn, 5, 0); & h9 _2 ?/ \4 T3 \4 }; C HAL_NVIC_EnableIRQ(ADC1_IRQn); , x' w! Q5 U6 @5 t* R: L8 ? /* USER CODE BEGIN ADC1_MspInit 1 */ HAL_DMA_Init: HAL_StatusTypeDefHAL_DMA_Init(DMA_HandleTypeDef *hdma) " c1 x) @' T0 x- `& d{ 2 }* \( v, z3 R7 i uint32_t tmp; ' `) U! J% \9 V9 B /* Check the DMA handle allocation */ 2 V% `1 G2 y$ |) u7 f7 { if(hdma == NULL) * a+ T- `% [) \5 R" a/ s { return HAL_ERROR; ( F0 C! D" Q- g } /* Check the parameters */ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); assert_param(IS_DMA_DIRECTION(hdma->Init.Direction)); 2 I/ \3 N# h4 Q2 ? assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc)); 1 Q! g4 d9 v$ V! ~0 s assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc)); 8 z. d3 U8 Y% p) L assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment)); % i7 x8 R# d$ h assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment)); , ?7 n: K" }# ?. `, P2 Q assert_param(IS_DMA_MODE(hdma->Init.Mode)); [9 ]: i( }2 i/ P6 p assert_param(IS_DMA_PRIORITY(hdma->Init.Priority)); assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request)); /* Compute the channel index */ if ((uint32_t)(hdma->Instance) <(uint32_t)(DMA2_Channel1)) { /* DMA1 */ " J: W: T3 ^9 I( t hdma->ChannelIndex =(((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) /((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U; & Z- p( g# C @7 z: S# }0 ] hdma->DmaBaseAddress = DMA1; } else b3 q: a, D% |7 N3 I { 9 s6 A. H) y( e; K /* DMA2 */ hdma->ChannelIndex =(((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) /((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U; % l0 A' K4 ~/ N$ Q% r. } hdma->DmaBaseAddress = DMA2; # }9 j* Z2 D2 | q1 c6 D8 i5 C: g2 | } /* Change DMA peripheral state */ 0 O. X) i2 u2 E+ n: o0 v$ [ hdma->State = HAL_DMA_STATE_BUSY; /* Get the CR register value */ / Z k6 p) @3 ^! k% X tmp = hdma->Instance->CCR; / H2 w% _) u+ U4 r9 W8 P7 \ /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC,DIR and MEM2MEM bits */ O+ Z+ S2 n( O6 e: o tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | 4 p6 v2 O( r% r2 G6 ~ DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | $ x3 J% y: p# L" }0 a7 d; m" z DMA_CCR_DIR | DMA_CCR_MEM2MEM)); /* Prepare the DMA Channel configuration */ ( F5 W9 I/ ^. }. M! R tmp |= hdma->Init.Direction | hdma->Init.PeriphInc | hdma->Init.MemInc | . w3 E8 }& N4 e$ [7 F hdma->Init.PeriphDataAlignment |hdma->Init.MemDataAlignment | hdma->Init.Mode | hdma->Init.Priority; /* Write to DMA Channel CR register */ - e5 F9 v8 I! s0 ?1 S( ]3 i hdma->Instance->CCR = tmp; $ f) Q/ _: I; g d上述初始化代码为CubeMX根据配置生产,代码本身没有问题。在此时设置DMA时,需要设置CCR寄存器,但此时DMA的使能并没有打开,因此设置不成功。
如果调整一开始的初始化顺序,先进行DMA初始化,调整代码如下: /* Initialize allconfigured peripherals */ " v0 R9 y! _" Y7 N M$ x( L# D MX_GPIO_Init(); MX_DMA_Init(); 2 F- j- f7 T" D, T. |1 J; g( | MX_ADC1_Init(); MX_DAC1_Init(); 3 W0 ?% n3 D. [: v3 l# ^+ U MX_RTC_Init(); MX_TIM6_Init();
此时DMA1EN为1,CCR1寄存器也设置成功。 $ e j6 H2 @9 B! p4 y 以前也是这么用的,也没这个问题,等到更新了CubeMX版本后,就出现了这个问题。总感觉CubeMX更新太快,而且每次更新变化太大,刚刚适应的一更新又变了,而且更新完了还有问题。虽然更新是好事情,但不能没测试好就更新吧,这么多人把代码用在产品中,出一点问题就增加多少人的工作量和隐患呢?希望以后更新能慎重。 / `1 `- p# D( @% N6 O, C* J, j |
微信公众号
手机版
改为如下,才能正常工作:, k, J) c% b4 k+ u1 r6 R
看了以前版本生成的代码,DMA初始化在前面,就没有问题,不知道为什么后来的版本调整为后面了。