OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4748|回复: 4

求助:STM32F030配置USART接收为DMA模式后,DMA没有执行搬运数据的动作

[复制链接]

1

主题

3

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2016-6-15
在线时间
2 小时
发表于 2016-6-15 17:19:15 | 显示全部楼层 |阅读模式
5金钱
本帖最后由 Jeremy_Su 于 2016-6-15 17:51 编辑

DMA配置源码如下:
#define USART_COMMUNICATE_IDX   UART2
#if USART_COMMUNICATE_IDX==UART1
    #define USART_COMMUNICATE       USART1
    #define DMA_CHANNEL_RXD     DMA1_Channel3
    #define DMA_FLAG_RXD        DMA1_FLAG_GL3
#else
    #define USART_COMMUNICATE       USART2
    #define DMA_CHANNEL_RXD     DMA1_Channel5
    #define DMA_FLAG_RXD        DMA1_FLAG_GL5
#endif

#define DMA_USART           USART_COMMUNICATE
#define DMA_USART_IDX       USART_COMMUNICATE_IDX

void LumMod_Uart_DMA_Rx_Data(void);

/* USART1的RxIRQ入口 */
void USART1_IRQHandler(void)
{
    uint8_t int_flg=0;

    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  // 空闲中断
    {
        LumMod_Uart_DMA_Rx_Data();
        USART_ClearITPendingBit(USART1, USART_IT_IDLE);
        int_flg |= 1;
    }

    if(!int_flg) {
        if ((USART1->ISR & (~0x00000008)) != RESET) {
            USART1->ICR |= 0x00000008;
        }
    }
}

/* USART2的RxIRQ入口 */
void USART2_IRQHandler(void)
{
    uint8_t int_flg=0;
    if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)  // 空闲中断
    {
        LumMod_Uart_DMA_Rx_Data();
        USART_ClearITPendingBit(USART2, USART_IT_IDLE);
        int_flg |= 1;
    }

    if(!int_flg) {
        if ((USART2->ISR & (~0x00000008)) != RESET) {
            USART2->ICR |= 0x00000008;
        }
    }
}

void LumMod_Uart_DMA_Rx_Data(void)
{
    uint16_t i;
    DMA_Cmd(DMA_CHANNEL_RXD, DISABLE);       // 关闭DMA ,防止干扰
    DMA_ClearFlag( DMA_FLAG_RXD );           // 清DMA标志位
    s_nRxdLen = LUMMOD_RX_BSIZE - DMA_GetCurrDataCounter(DMA_CHANNEL_RXD); //获得接收到的字节数
    if (FALSE==WriteBlockRoundBuf(&s_uart_round[DMA_USART_IDX], s_szBuf, s_nRxdLen)) {
        for (i=0; i<s_nRxdLen; i++){
            WriteRoundBuf(&s_uart_round[DMA_USART_IDX], s_szBuf);
        }
    }
    DMA_CHANNEL_RXD->CMAR = (uint32_t)s_szBuf;
    DMA_CHANNEL_RXD->CNDTR = LUMMOD_RX_BSIZE;    //  重新赋值计数值,必须大于等于最大可能接收到的数据帧数目
    DMA_Cmd(DMA_CHANNEL_RXD, ENABLE);  
}


void DMA_Uart_Init(void)
{
    DMA_InitTypeDef DMA_InitStructure;

    /* DMA clock enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 开启DMA1时钟

//=DMA_Configuration==============================================================================//


/*--- DMA1_Channel3 DMA (RXD) Config ---*/

    DMA_Cmd(DMA_CHANNEL_RXD, DISABLE);                           // 关DMA通道
    DMA_DeInit(DMA_CHANNEL_RXD);                                 // 恢复缺省值
    DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)(&DMA_USART->RDR);    // 设置串口接收数据寄存器
    DMA_InitStructure.DMA_MemoryBaseAddr        = (uint32_t)(&s_szBuf[0]);           // 设置接收缓冲区首地址
    DMA_InitStructure.DMA_DIR                   = DMA_DIR_PeripheralSRC;       // 设置外设为数据源,外设寄存器 -> 内存缓冲区
    DMA_InitStructure.DMA_BufferSize            = LUMMOD_RX_BSIZE;             // 需要最大可能接收到的字节数
    DMA_InitStructure.DMA_PeripheralInc         = DMA_PeripheralInc_Disable;   // 外设地址不做增加调整,调整不调整是DMA自动实现的
    DMA_InitStructure.DMA_MemoryInc             = DMA_MemoryInc_Enable;        // 内存缓冲区地址增加调整
    DMA_InitStructure.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_Byte; // 外设数据宽度8位,1个字节
    DMA_InitStructure.DMA_MemoryDataSize        = DMA_MemoryDataSize_Byte;     // 内存数据宽度8位,1个字节
    DMA_InitStructure.DMA_Mode                  = DMA_Mode_Normal;             // 单次传输模式
    DMA_InitStructure.DMA_Priority              = DMA_Priority_VeryHigh;       // 优先级设置
    DMA_InitStructure.DMA_M2M                   = DMA_M2M_Disable;             // 关闭内存到内存的DMA模式
    DMA_Init(DMA_CHANNEL_RXD, &DMA_InitStructure);              // 写入配置
    DMA_ClearFlag(DMA_FLAG_RXD);                                // 清除DMA所有标志
    DMA_Cmd(DMA_CHANNEL_RXD, ENABLE);                           // 开启接收DMA通道,等待接收数据
    USART_DMACmd(DMA_USART, USART_DMAReq_Rx, ENABLE);           // 开启串口DMA接收


}



STM32F030配置USART2 接收为DMA模式后,DMA没有执行搬运数据的动作,但是IDLE中断是正常的。
当串口改为USART1  #define USART_COMMUNICATE_IDX   UART1   DMA工作却是正常的, 我反复检查了所有相关串口DMA的配置  实在找不到配置上的差异 , 求大神解惑!!!  



最佳答案

查看完整内容[请看2#楼]

问题已解决! 虽然只有原子哥一个人帮顶,不过还是要说下问题, 原因是我代码里的UART1和UART2是枚举类型的, 原来枚举是不能参与宏表达式的,由于我之前不知道, 所以编译器一直都是编译 #if USART_COMMUNICATE_IDX==UART1分支的代码!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2016-6-15
在线时间
2 小时
 楼主| 发表于 2016-6-15 17:19:16 | 显示全部楼层

问题已解决!  虽然只有原子哥一个人帮顶,不过还是要说下问题, 原因是我代码里的UART1和UART2是枚举类型的, 原来枚举是不能参与宏表达式的,由于我之前不知道, 所以编译器一直都是编译 #if USART_COMMUNICATE_IDX==UART1分支的代码!
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2016-6-15 20:24:09 | 显示全部楼层
帮顶
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2016-6-15
在线时间
2 小时
 楼主| 发表于 2016-6-16 09:24:56 | 显示全部楼层

原子哥有没有什么建议? 交流一下...
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2016-6-18 20:45:27 | 显示全部楼层
Jeremy_Su 发表于 2016-6-16 09:24
原子哥有没有什么建议? 交流一下...

谢谢分享
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-12 12:18

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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