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

关于HAL库的STM32F767的DMA通过IDLE中断接收数据

[复制链接]
chuangyi2000 提问时间:2018-3-8 10:36 /
本帖最后由 chuangyi2000 于 2018-3-9 08:01 编辑

问题描述;  开启了USART1的DMA接收和发送,开启了USART1的IDLE中断,IDLE中断正常,能成功接收到数据。通过仿真能看到接收缓冲区数组中的数据,但不能访问,如果不访问,再开启DMA接收能正常接收,并且在仿真状态下也能查看。只要访问一次这个数组,下一次开启DMA接收后就不能接收数据了。

原代码如下:

                if(rx_end == 1){
                        rx_end = 0;
                        
                        HAL_UART_DMAStop(&UART1_Handler);

                        LCD_ShowString(300, 400, 200, 16, 16, "success!");
                        LCD_ShowString(230, 400, 200, 16, 16, aRxBuffer);            //这条不能执行,执行就不能再接收数据  
                                                                                                                     //屏蔽掉这条在仿真状态下能观察aRxBuffer接收正常
                        
                        HAL_UART_Receive_DMA(&UART1_Handler, aRxBuffer, RXBUFFERSIZE);
                }        


配置原代码如下:

{
        __HAL_RCC_DMA2_CLK_ENABLE();                        //DMA2ʱÖÓʹÄÜ        
        __HAL_RCC_GPIOA_CLK_ENABLE();                        //ʹÄÜGPIOAʱÖÓ
        __HAL_RCC_USART1_CLK_ENABLE();                        //ʹÄÜUSART1ʱÖÓ

        GPIO_Initure.Pin=GPIO_PIN_9;                        //PA9
        GPIO_Initure.Mode=GPIO_MODE_AF_PP;                //¸´ÓÃÍÆÍìÊä³ö
        GPIO_Initure.Pull=GPIO_PULLUP;                        //ÉÏÀ­
        GPIO_Initure.Speed=GPIO_SPEED_FAST;                //¸ßËÙ
        GPIO_Initure.Alternate=GPIO_AF7_USART1;        //¸´ÓÃΪUSART1
        HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //³õʼ»¯PA9

        GPIO_Initure.Pin=GPIO_PIN_10;                        //PA10
        HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //³õʼ»¯PA10
        
        UART1_Handler.Instance=USART1;                                            //USART1
        UART1_Handler.Init.BaudRate=9600;                                    //²¨ÌØÂÊ
        UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //×Ö³¤Îª8λÊý¾Ý¸ñʽ
        UART1_Handler.Init.StopBits=UART_STOPBITS_1;            //Ò»¸öֹͣλ
        UART1_Handler.Init.Parity=UART_PARITY_NONE;                    //ÎÞÆæżУÑéλ
        UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //ÎÞÓ²¼þÁ÷¿Ø
        UART1_Handler.Init.Mode=UART_MODE_TX_RX;                    //ÊÕ·¢Ä£Ê½
        HAL_UART_Init(&UART1_Handler);                                            //HAL_UART_Init()»áʹÄÜUART1

    //Tx DMAÅäÖÃ
        UART1TxDMA_Handler.Instance = DMA2_Stream7;                           //Êý¾ÝÁ÷Ñ¡Ôñ
        UART1TxDMA_Handler.Init.Channel = DMA_CHANNEL_4;                      //ͨµÀÑ¡Ôñ
        UART1TxDMA_Handler.Init.Direction = DMA_MEMORY_TO_PERIPH;             //´æ´¢Æ÷µ½ÍâÉè
        UART1TxDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;                 //ÍâÉè·ÇÔöÁ¿Ä£Ê½
        UART1TxDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;                     //´æ´¢Æ÷ÔöÁ¿Ä£Ê½
        UART1TxDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;    //ÍâÉèÊý¾Ý³¤¶È:8λ
        UART1TxDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;       //´æ´¢Æ÷Êý¾Ý³¤¶È:8λ
        UART1TxDMA_Handler.Init.Mode = DMA_NORMAL;                            //ÍâÉèÁ÷¿Øģʽ
        UART1TxDMA_Handler.Init.Priority = DMA_PRIORITY_MEDIUM;               //ÖеÈÓÅÏȼ¶
        UART1TxDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;              
        UART1TxDMA_Handler.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;      
        UART1TxDMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE;                 //´æ´¢Æ÷Í»·¢µ¥´Î´«Êä
        UART1TxDMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;              //ÍâÉèÍ»·¢µ¥´Î´«Êä

//    HAL_DMA_DeInit(&UART1TxDMA_Handler);   
        HAL_DMA_Init(&UART1TxDMA_Handler);
        __HAL_LINKDMA(&UART1_Handler, hdmatx, UART1TxDMA_Handler);

    //Rx DMAÅäÖÃ
        UART1RxDMA_Handler.Instance = DMA2_Stream2;                           //Êý¾ÝÁ÷Ñ¡Ôñ
        UART1RxDMA_Handler.Init.Channel = DMA_CHANNEL_4;                      //ͨµÀÑ¡Ôñ
        UART1RxDMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;             //´æ´¢Æ÷µ½ÍâÉè
        UART1RxDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;                 //ÍâÉè·ÇÔöÁ¿Ä£Ê½
        UART1RxDMA_Handler.Init.MemInc = DMA_MINC_ENABLE;                     //´æ´¢Æ÷ÔöÁ¿Ä£Ê½
        UART1RxDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;    //ÍâÉèÊý¾Ý³¤¶È:8λ
        UART1RxDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;       //´æ´¢Æ÷Êý¾Ý³¤¶È:8λ
        UART1RxDMA_Handler.Init.Mode = DMA_NORMAL;                            //ÍâÉèÁ÷¿Øģʽ
        UART1RxDMA_Handler.Init.Priority = DMA_PRIORITY_MEDIUM;               //ÖеÈÓÅÏȼ¶
        UART1RxDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;              
        UART1RxDMA_Handler.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;      
        UART1RxDMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE;                 //´æ´¢Æ÷Í»·¢µ¥´Î´«Êä
        UART1RxDMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE;              //ÍâÉèÍ»·¢µ¥´Î´«Êä

        HAL_DMA_Init(&UART1RxDMA_Handler);
        __HAL_LINKDMA(&UART1_Handler, hdmarx, UART1RxDMA_Handler);

        __HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler);
        __HAL_UART_ENABLE_IT(&UART1_Handler, UART_IT_RXNE);                //¿ªÆô½ÓÊÕÖжÏ
        HAL_NVIC_EnableIRQ(USART1_IRQn);                                                        //ʹÄÜUSART1ÖжÏͨµÀ
        HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);                                        //ÇÀÕ¼ÓÅÏȼ¶3£¬×ÓÓÅÏȼ¶3

        HAL_UART_Receive_DMA(&UART1_Handler, aRxBuffer, RXBUFFERSIZE);              //开启了一次

}

接收中断函数

void USART1_IRQHandler(void)                        
{
unsigned short y;
        
        if((__HAL_UART_GET_FLAG(&UART1_Handler, UART_IT_RXNE) != RESET))
        {
                y = 400;
                LCD_ShowString(30, y, 200, 16, 16, "UART_IT_RXNE");
                LCD_ShowNum(180, y, RX_ADDR, 3, 16);
               
                rx_end = 1;
               
                if(RX_ADDR < 900){
                        RX_ADDR++;
                }
                else{
                        RX_ADDR = 0;
                }
        }

        HAL_UART_IRQHandler(&UART1_Handler);        
}



收藏 评论9 发布时间:2018-3-8 10:36

举报

9个回答
jjbboox 回答时间:2018-3-8 11:19:08
本帖最后由 jjbboox 于 2018-3-8 11:23 编辑

你没有把DMA关闭。先把DMA关闭以后才可以访问DMA内存区域。另外一般读取串口数据都应该是在主循环里面,判断读取标志为1,不要在中断函数中处理读取到的内容。

__HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler);

y= UART1_Handler.Instance->SR;
y= UART1_Handler.Instance->DR;


HAL_UART_DMAStop(&
UART1_Handler);






评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

chuangyi2000 回答时间:2018-3-8 11:54:14
jjbboox 发表于 2018-3-8 11:19
你没有把DMA关闭。先把DMA关闭以后才可以访问DMA内存区域。另外一般读取串口数据都应该是在主循环里面,判 ...

你好, 谢谢回复。

我的访问是在主程序中, IDLE中断函数中  rx_end = 1;  主函数中判断  rx_end==1 后
关闭DMA   HAL_UART_DMAStop(&UART1_Handler);
访问数据    LCD_ShowString(230, 400, 200, 16, 16, aRxBuffer);
重启DMA    HAL_UART_Receive_DMA(&UART1_Handler, aRxBuffer, RXBUFFERSIZE);


                        y = UART1_Handler.Instance->ISR;
                        y = UART1_Handler.Instance->RDR;
                        HAL_UART_DMAStop(&UART1_Handler);
关闭DMA前加上那两条后  现象还是一样的   不能访问接收缓冲数组。
chuangyi2000 回答时间:2018-3-8 12:00:56
总是只能显示第一次的数据,访问后重启DMA,后面的数据就收不到了,仿真状态也是看不到缓冲数组中的数据
Dandjinh 回答时间:2018-3-8 14:35:41
本帖最后由 Dandjinh 于 2018-3-8 14:42 编辑

有可能是Cache的问题

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

chuangyi2000 回答时间:2018-3-8 17:19:37
Dandjinh 发表于 2018-3-8 14:35
有可能是Cache的问题

谢谢,非常像,因为当我不能查看到接收缓冲数据的时候,DMA接收数据的数量能够正确更新。
chuangyi2000 回答时间:2018-3-9 07:54:46
Dandjinh 发表于 2018-3-8 14:35
有可能是Cache的问题

jjbboox 回答时间:2018-3-9 08:46:01
chuangyi2000 发表于 2018-3-8 11:54
你好, 谢谢回复。

我的访问是在主程序中, IDLE中断函数中  rx_end = 1;  主函数中判断  rx_end==1 后 ...

你可以参考下面这个链接
我就是照着这个方法做的,效果很好。
http://blog.csdn.net/youmeichifan/article/details/51750435
chuangyi2000 回答时间:2018-3-12 08:08:07
jjbboox 发表于 2018-3-9 08:46
你可以参考下面这个链接
我就是照着这个方法做的,效果很好。
http://blog.csdn.net/youmeichifan/articl ...

谢谢回复。
我程序功能基本实现了,实际上是访问数据访问的Cache,DMA更新的是缓冲区,导致存储器内容不一致,读出数据给人感觉就是没收到数据一样。
埃斯提爱慕 回答时间:2018-3-15 16:22:39
提示: 作者被禁止或删除 内容自动屏蔽
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版