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

STM32L412KB DMA1与DMA2数据冲突?

[复制链接]
不想上学的举高手 提问时间:2022-4-14 20:28 / 未解决

DMA1用于进行ADC数据的搬移,ADC配置为规则同步模式,同步采集两个通道,由TIM3触发,采样速度50k,16倍过采样,4bit右移,DMA1数据传输长度为200,开通半传输以及传输完成标志,半传输标志时开启LPUART的数据RX,使用DMA2进行数据传输,但是数据在传输时会存在串口数据不正确的情况

即便是降低采样的速度,输出数据依旧出现乱码的情况,两个DMA的总线之间应该是没有交集的,降速后也应该不会存在总线仲裁的问题,有没有大神知道原因

// DMA1配置
void DMA1_TRANS_INIT(void)
{
    //通道1外设数据地址(adc双路转换结果)
    LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_1, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA_MULTI));
    //通道1内存数据地址
    LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&ADC_DUAL);
    //通道1数据传输长度
    LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, ADC_DUAL_LENGTH/2);
    //关闭半传输,打开传输完成中断,打开传输错误中断
    LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_1);
    LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
    LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_1);
    //通道1使能
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);


}

//DMA2
void DMA2_TRANS_INIT(void)
{
    //设置外设地址
    LL_DMA_SetPeriphAddress(DMA2,LL_DMA_CHANNEL_6,LL_LPUART_DMA_GetRegAddr(LPUART1,LL_LPUART_DMA_REG_DATA_TRANSMIT));

    //关闭半传输,打开传输完成中断,关闭传输错误中断
    LL_DMA_DisableIT_HT(DMA2, LL_DMA_CHANNEL_6);
    LL_DMA_EnableIT_TC(DMA2, LL_DMA_CHANNEL_6);
    LL_DMA_DisableIT_TE(DMA2, LL_DMA_CHANNEL_6);

    //通道6使能
    LL_DMA_EnableChannel(DMA2, LL_DMA_CHANNEL_6);
    //使能发送DMA传输请求
    LL_LPUART_EnableDMAReq_TX(LPUART1);

}

void LPUSART_DMA_SEND(uint32_t data,uint32_t len)
{
    //等待上次传输完成
    while(LL_LPUART_IsActiveFlag_TC(LPUART1) == RESET);

    if(LL_LPUART_IsActiveFlag_TXE(LPUART1)!=RESET){
        // 重新设置传输地址需要先关闭对应DMA通道
        LL_DMA_DisableChannel(DMA2,LL_DMA_CHANNEL_6);
        LL_DMA_SetMemoryAddress(DMA2,LL_DMA_CHANNEL_6,data);
        //设置传输长度
        LL_DMA_SetDataLength(DMA2,LL_DMA_CHANNEL_6,len);

        LL_DMA_EnableChannel(DMA2,LL_DMA_CHANNEL_6);

    }
}
#define ADC_DUAL_LENGTH 200
__align(8) uint16_t ADC_DUAL[ADC_DUAL_LENGTH];
void main()
{
    while(1){
        if(dma_tc_status == 1) {
            dma_tc_status = 0;

            LPUSART_DMA_SEND((uint32_t )&ADC_DUAL[ADC_DUAL_LENGTH/2],ADC_DUAL_LENGTH);
        }

        if(dma_ht_status == 1) {
            dma_ht_status = 0;
            //debug("\r");
            while(LL_LPUART_IsActiveFlag_TC(LPUART1) == RESET);
            LL_LPUART_TransmitData8(LPUART1, 13);

            LPUSART_DMA_SEND((uint32_t )&ADC_DUAL[0],ADC_DUAL_LENGTH);
        }
    }

}
//中断配置
void DMA1_Channel1_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
    if(LL_DMA_IsActiveFlag_TC1(DMA1) == 1)
    {
        LL_DMA_ClearFlag_TC1(DMA1);
        dma_tc_status = 1;
        receive_number++;
    }
    if(LL_DMA_IsActiveFlag_HT1(DMA1) == 1)
    {
        LL_DMA_ClearFlag_HT1(DMA1);
        dma_ht_status = 1;
    }


    if(LL_DMA_IsActiveFlag_TE1(DMA1) == 1)
    {
        LL_DMA_ClearFlag_TE1(DMA1);
        dma_te_status = 1;
    }
  /* USER CODE END DMA1_Channel1_IRQn 0 */

  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */

  /* USER CODE END DMA1_Channel1_IRQn 1 */
}

/**
  * @brief This function handles DMA2 channel6 global interrupt.
  */
void DMA2_Channel6_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Channel6_IRQn 0 */
    if(LL_DMA_IsActiveFlag_TC6(DMA2)!=RESET)
    {
        LL_DMA_ClearFlag_TC6(DMA2);
    }

  /* USER CODE END DMA2_Channel6_IRQn 0 */

  /* USER CODE BEGIN DMA2_Channel6_IRQn 1 */

  /* USER CODE END DMA2_Channel6_IRQn 1 */
}

收藏 评论4 发布时间:2022-4-14 20:28

举报

4个回答
butterflyspring 回答时间:2022-4-15 10:00:58

串口的传输速率与ADC的采样速率(50K)比是相当慢,所以建议将采样速率降至100HZ一下试试。 或者改为手动触发使能DMA(DMA配置为NORMAL模式)。

xmshao 回答时间:2022-4-15 10:53:43
从你描述来看,没法确定是DMA1、DMA2发生冲突了。你干脆基于DMA2对LPUART的传输进行测试,等这边OK了,然后再将ADC的数据传输关联起来。你目前LPUART的时钟是什么,支持的波特率可以到多少,结合手册看下。另外,你开启了DMA传输中断,记得中断服务程序里将相应中断标志及时清零。
这个事情很尴尬 回答时间:2022-4-15 11:18:05

我推荐,您加一个DMA通道做内存TO内存,估计您这个问题就解决了

奇迹 回答时间:2022-4-15 18:07:02
应该不是冲突的问题
建议两部分功能分开调,正常之后在合并到一起。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版