找回密码
 注册
关于网站域名变更的通知
查看: 261|回复: 5
打印 上一主题 下一主题

HAL库的STM32F767的DMA通过IDLE中断接收数据但不能访问

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-12-27 10:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
问题描述;  开启了USART1的DMA接收和发送,开启了USART1的IDLE中断,IDLE中断正常,能成功接收到数据。通过仿真能看到接收缓冲区数组中的数据,但不能访问,如果不访问,再开启DMA接收能正常接收,并且在仿真状态下也能查看。只要访问一次这个数组,下一次开启DMA接收后就不能接收数据了。% x; X( w3 q  j) I
# ~; K" `3 x. g, V, _; o/ i2 S
原代码如下:9 R' o" A/ z2 M7 y
4 X5 G, g8 D  F, B& k- D0 G
                if(rx_end == 1){, E$ G9 M) N: h3 Y; y- h
                        rx_end = 0;3 c) w0 _9 t! K: s2 |
                        
/ S) ~6 D4 V6 Q9 b& k, B; J                        HAL_UART_DMAStop(&UART1_Handler);8 R$ k; W4 @, E, N2 U% c* b
: |; d2 w5 V: l  ]: B0 |; J
                        LCD_ShowString(300, 400, 200, 16, 16, "success!");" S1 `$ L$ i: k% ~% n5 j' c9 c* Q
                        LCD_ShowString(230, 400, 200, 16, 16, aRxBuffer);            //这条不能执行,执行就不能再接收数据  
* P' v6 W. f* b; H! s8 R8 B                                                                                                                     //屏蔽掉这条在仿真状态下能观察aRxBuffer接收正常' Q9 \  v" v( y* {- H
                        
/ X( t  ]7 H  D& j* Y$ W9 B; |) v                        HAL_UART_Receive_DMA(&UART1_Handler, aRxBuffer, RXBUFFERSIZE);
* @5 ]0 W5 ]! a# ^4 {                }        
) c7 @- H1 X* q6 ~% N. ~
7 X  E$ ^9 u/ }- ?1 T1 F$ Q7 J! [: X; s2 {% `1 s$ N
配置原代码如下:2 D3 b- _) P) n  E, Y

8 X2 R0 o: i- a{) m# X% P" r- x& X" Z% _, g/ N
        __HAL_RCC_DMA2_CLK_ENABLE();                        //DMA2ê±Öóê1Äü        
' l; C' Q7 ~& Z8 c6 V$ E  H; U        __HAL_RCC_GPIOA_CLK_ENABLE();                        //ê1ÄüGPIOAê±Öó
8 t6 |; S% R- b" S" u        __HAL_RCC_USART1_CLK_ENABLE();                        //ê1ÄüUSART1ê±Öó
) K8 ?" P- z6 m, f% t
& c; ?, t. ^7 h6 [. k( O" w7 @1 A$ }        GPIO_Initure.Pin=GPIO_PIN_9;                        //PA9; b: I: Z9 U, B4 Q4 q( W) D/ [! z; L6 B
        GPIO_Initure.Mode=GPIO_MODE_AF_PP;                //¸′óÃíÆíìêä3ö1 k% J& h, S# E, t
        GPIO_Initure.Pull=GPIO_PULLUP;                        //éÏà-
* C7 M7 Y! h9 {$ d" p, _/ z        GPIO_Initure.Speed=GPIO_SPEED_FAST;                //¸ßËù0 Y' }9 D- C" s9 D$ j# _
        GPIO_Initure.Alternate=GPIO_AF7_USART1;        //¸′óÃÎaUSART1
$ w+ \$ M0 C7 x% p/ ]$ u5 Z        HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //3õê¼»ˉPA9  ?8 h: y% n  X$ f: k4 K' h

- s# x5 u& a3 F& l        GPIO_Initure.Pin=GPIO_PIN_10;                        //PA10
) u. D3 \( g8 X/ p: t        HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //3õê¼»ˉPA10
  C4 y  P- `8 x0 n* o; d0 w* H! A        : ?6 w  B: _" y/ l
        UART1_Handler.Instance=USART1;                                            //USART15 `% P2 ]; w& b  E7 O0 W. r/ }
        UART1_Handler.Init.BaudRate=9600;                                    //2¨ìØÂê
; T3 k+ u" p7 {        UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //×Ö3¤Îa8λêy¾Y¸ñê½
1 |( p. e* s0 L$ M! U( K! q8 g3 A        UART1_Handler.Init.StopBits=UART_STOPBITS_1;            //ò»¸öí£Ö1λ3 y' i$ T7 t5 W7 o7 o7 w
        UART1_Handler.Init.Parity=UART_PARITY_NONE;                    //ÎTÆæÅ¼D£Ñéλ8 U2 L5 A% L# S  I; E
        UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //ÎTó2¼tá÷¿Ø
  i3 p! K8 `+ n* [  H* r# P        UART1_Handler.Init.Mode=UART_MODE_TX_RX;                    //êÕ·¢Ä£ê½
3 H8 u( n" t0 S8 Z        HAL_UART_Init(&UART1_Handler);                                            //HAL_UART_Init()»áê1ÄüUART1
' M' T/ {3 K$ [: }
' `5 y$ X9 O: N9 N    //Tx DMAÅäÖÃ
! |/ J3 ~) a% r9 ]; j- L2 h        UART1TxDMA_Handler.Instance = DMA2_Stream7;                           //êy¾Yá÷Ñ¡Ôñ
* g  x0 c% t+ [" J        UART1TxDMA_Handler.Init.Channel = DMA_CHANNEL_4;                      //í¨μàÑ¡Ôñ0 q6 m) Z% w7 m) U+ g% b
        UART1TxDMA_Handler.Init.Direction = DMA_MEMORY_TO_PERIPH;             //′æ′¢Æ÷μ½íaéè
4 V0 f5 H8 X: E; O2 j1 V3 p3 [        UART1TxDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;                 //íaéè·ÇÔöá¿Ä£ê½
9 n! a6 @; _  z& h# ^1 V        UART1TxDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;                     //′æ′¢Æ÷Ôöá¿Ä£ê½
& z. u" l5 o' O. }        UART1TxDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;    //íaéèêy¾Y3¤¶è:8λ
: J. O" g) x: W        UART1TxDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;       //′æ′¢Æ÷êy¾Y3¤¶è:8λ
4 V8 q7 Q: E# {        UART1TxDMA_Handler.Init.Mode = DMA_NORMAL;                            //íaéèá÷¿ØÄ£ê½
, g2 t& |+ Y% ~: }( A/ ~        UART1TxDMA_Handler.Init.Priority = DMA_PRIORITY_MEDIUM;               //ÖDμèóÅÏè¼¶
. a+ x; V2 P5 n* J        UART1TxDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;              
& K7 R" q# s, q0 l, C& Y. a        UART1TxDMA_Handler.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;      1 v2 l% ~7 r6 W) [$ ~- ]  L5 I
        UART1TxDMA_Handler.Init.Memburst = DMA_MBURST_SINGLE;                 //′æ′¢Æ÷í»·¢μ¥′Î′«êä
% S; R( n. c3 K' u        UART1TxDMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;              //íaéèí»·¢μ¥′Î′«êä$ b3 f- J. m& y( A- w2 z' A  D/ c& V* r

  W5 r$ D3 W, M4 h- o0 i//    HAL_DMA_DeInit(&UART1TxDMA_Handler);   
9 G5 z- G6 s& z# k" a8 t# o" s. x        HAL_DMA_Init(&UART1TxDMA_Handler);/ s& J" I/ h9 S1 ]
        __HAL_LINKDMA(&UART1_Handler, hdmatx, UART1TxDMA_Handler);
* s0 J( X' V# C1 R$ \4 V, R# a1 R0 r" A( a: E
    //Rx DMAÅäÖÃ# M, {  y, k! @3 G* _
        UART1RxDMA_Handler.Instance = DMA2_Stream2;                           //êy¾Yá÷Ñ¡Ôñ- E2 D, A  i! \
        UART1RxDMA_Handler.Init.Channel = DMA_CHANNEL_4;                      //í¨μàÑ¡Ôñ% j  [$ _2 b% ^2 }# x
        UART1RxDMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;             //′æ′¢Æ÷μ½íaéè, [% R8 V, f! R9 p( \
        UART1RxDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;                 //íaéè·ÇÔöá¿Ä£ê½2 \5 Q: {/ `2 N; `0 z; |1 A
        UART1RxDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;                     //′æ′¢Æ÷Ôöá¿Ä£ê½0 W2 g- O  O! m- |& K+ x4 r8 W
        UART1RxDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;    //íaéèêy¾Y3¤¶è:8λ- B8 r' n/ V$ h& B
        UART1RxDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;       //′æ′¢Æ÷êy¾Y3¤¶è:8λ) ~4 ~/ ^0 U& i4 d' k
        UART1RxDMA_Handler.Init.Mode = DMA_NORMAL;                            //íaéèá÷¿ØÄ£ê½0 G' W! K" }1 A/ E. a. F2 k! a" m
        UART1RxDMA_Handler.Init.Priority = DMA_PRIORITY_MEDIUM;               //ÖDμèóÅÏè¼¶
6 P) T  c2 f0 ]$ F$ K( W& n1 h9 \        UART1RxDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;              
' ]: D0 d% q# F1 R: O7 Z5 H        UART1RxDMA_Handler.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;      
# ^6 u4 c3 W4 ?+ F5 R% U/ A& M        UART1RxDMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE;                 //′æ′¢Æ÷í»·¢μ¥′Î′«êä
+ p# T; U  }# }& ~        UART1RxDMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;              //íaéèí»·¢μ¥′Î′«êä
  P! p9 j9 E3 |* F8 e, m1 `* l3 Z4 ~# S6 c, L1 e% w1 q2 g* Z) l  x4 M
        HAL_DMA_Init(&UART1RxDMA_Handler);
7 N; _1 {$ D3 s3 O# A# _        __HAL_LINKDMA(&UART1_Handler, hdmarx, UART1RxDMA_Handler);9 b! j2 t+ x! @+ u) D5 B

, O! u0 O/ R  V$ v+ A        __HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler);, d2 p* M0 Z8 q8 r- D
        __HAL_UART_ENABLE_IT(&UART1_Handler, UART_IT_RXNE);                //¿aÆô½óêÕÖD¶Ï
/ D9 O, r% q1 p7 j5 H: i# j: D3 Y$ y        HAL_NVIC_EnableIRQ(USART1_IRQn);                                                        //ê1ÄüUSART1ÖD¶Ïí¨μà
% z: J- k, S$ H' P7 [+ u7 N$ L        HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);                                        //ÇàÕ¼óÅÏè¼¶3£¬×óóÅÏè¼¶3' }$ B# I( }! I0 w- w- N3 m

$ r: U7 S6 Y5 a8 l/ K        HAL_UART_Receive_DMA(&UART1_Handler, aRxBuffer, RXBUFFERSIZE);              //开启了一次
  U# `9 e% C/ z+ G3 }0 O. V5 g3 D+ K& I/ T7 R
}
  |$ ^! w# e, T% a7 u" J- j8 h3 h( F. O
接收中断函数
7 K+ B5 M, B- I1 K- G, W, N3 ^# o& {
void USART1_IRQHandler(void)                        5 g9 x* p2 j' E! s7 Y
{
4 m3 Q3 K) B. S$ `# ]- Kunsigned short y;
- h) D  Y! V9 x) @" x        6 D: @  T( X0 n6 c# e8 v
        if((__HAL_UART_GET_FLAG(&UART1_Handler, UART_IT_RXNE) != RESET))/ m' l. ~& W- r% F
        {
% ]4 l+ m4 A: `+ X: @( L3 c                y = 400;
8 h- H& d- Y$ s0 w: R                LCD_ShowString(30, y, 200, 16, 16, "UART_IT_RXNE");
, \9 d9 S, X8 u) Y# ^; v                LCD_ShowNum(180, y, RX_ADDR, 3, 16);5 C  |  U1 F7 V4 i8 n
               " F! s. f% _  M  v0 n
                rx_end = 1;7 E: T# m" W" d0 A+ J" a
               % k6 X% c4 x% C6 ?) H: p
                if(RX_ADDR < 900){
8 k4 v( x/ }) l# n( ]' q                        RX_ADDR++;' h. t4 J: ?# j% c$ t' A
                }. {5 Y" i4 H2 d. K& H! D
                else{% R7 }4 a! t( A4 I9 l# W) D" q3 S
                        RX_ADDR = 0;; O* S" R' f$ ~1 {! _0 r
                }
! @2 h* e, ]6 U1 J* i" x        }
! J# \7 g9 \' N( k, o1 ]" a; {* C4 c2 v: c2 j6 z
        HAL_UART_IRQHandler(&UART1_Handler);        
6 w8 x# A- e6 }' o7 M$ v}
. q7 R, ?! |- k( `8 H

该用户从未签到

2#
发表于 2021-12-27 11:07 | 只看该作者
你没有把DMA关闭。先把DMA关闭以后才可以访问DMA内存区域。另外一般读取串口数据都应该是在主循环里面,判断读取标志为1,不要在中断函数中处理读取到的内容。7 r( n# I! V0 j
6 X$ K! ?! w# _7 Y# d& R
__HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler);
  Q- ^; w2 b) y* J$ [
# `$ z3 I  G0 O) W5 ~y= UART1_Handler.Instance->SR;
! E; @; r  x2 ]) Y5 q: Fy= UART1_Handler.Instance->DR;
* Z! u$ w2 C" @. C6 G* }0 \. Z7 ~( a) K4 o3 l
HAL_UART_DMAStop(&UART1_Handler);

该用户从未签到

3#
发表于 2021-12-27 11:07 | 只看该作者
有可能是Cache的问题

该用户从未签到

4#
发表于 2021-12-27 11:08 | 只看该作者
实际上是访问数据访问的Cache,DMA更新的是缓冲区,导致存储器内容不一致,读出数据给人感觉就是没收到数据一样

该用户从未签到

5#
发表于 2021-12-27 11:08 | 只看该作者
/* USART6 串口空闲中断函数 */* p% @/ j6 S$ e3 p# [
void HeaterComm_Callback(void)  n9 T$ n- |( |* i$ V, B+ [
{
0 H8 D5 m0 Y) r" K& e  uint32_t TmpFlag = 0;
" f: E0 ?6 t7 q  uint32_t TmpLength;7 o. U; }. a% F* B" Q6 {4 S; c
  . m; ]/ M! Y5 G' {3 ~# Q
  TmpFlag = __HAL_UART_GET_FLAG(&huart6, UART_FLAG_IDLE);      ' i  _1 N/ e; _( m! j0 Z! `
  if((TmpFlag != RESET))
2 {3 D, f2 i; z& k: E6 ?  {
: s# v1 r6 d; j8 k" s" T' K    __HAL_UART_CLEAR_IDLEFLAG(&huart6);  
2 ?  V6 u- |, j2 K. y0 W0 o; [$ ~    //HAL_UART_AbortReceive_IT(&huart6);                             
8 v( H6 k3 a+ f- m  `+ M/ N    HAL_UART_DMAStop(&huart6);      
4 C3 N' U( p# E. p( H" f" L    TmpLength = __HAL_DMA_GET_COUNTER((DMA_HandleTypeDef *)&hdma_usart6_rx);         
2 v9 u5 _6 ?7 L9 r/ \( P    //TmpLength = hdma_usart6_rx.Instance->NDTR;' h/ x& x  Z* k. N, h% j8 k: a
    HeaterComm.DataLength = 32 - TmpLength;$ G# d4 o7 R! n* p' |1 r, z) q
    osSignalSet (HeaterComm_TaskHandle, 1);                     //HeaterComm.ReceiveFlag = 1;
9 y* D4 |% Q% |* d7 f  }
0 ~( h) A! \/ Q}

该用户从未签到

6#
发表于 2021-12-27 11:09 | 只看该作者
DMA接收数据的数量能够正确更新吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-10-12 13:03 , Processed in 0.156250 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表