打印
[技术问答]

定时器触发ADC采样+DMA多路传输

[复制链接]
261|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ZJY1|  楼主 | 2024-6-25 17:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
使用官方库样例ADC可以得到数据但是DMA传不出数据   代码如下
dma.c
#include "dma.h"

#define ADC_UNIT                        (CM_ADC1)  //ADC1基地址(起始地址)

#define ADC_DR_START                    ((uint32_t)&ADC_UNIT->DR0)  //DMA数据源地址
#define PTTM_VAL_IDX                    (11U)  //DMA缓存区大小为11 表示11个通道,即11个模拟量

#define DMA_UNIT                        (CM_DMA1)    //DMA1基地址
#define DMA_PERIPH_CLK                  (FCG0_PERIPH_DMA1)  //DMA1使能时钟
#define DMA_CH                          (DMA_CH0)    //通道0地址
#define DMA_AOS_TRIG_SEL                (AOS_DMA1_0)   //外设电路之间的联动(AOS自动运行系统)

#define DMA_TRANS_CNT                   (0U)     //设置DMA传输次数,0表示传输无限次(传输次数要大于0)
#define DMA_BLOCK_SIZE                  (ADC_CH14 - ADC_CH0 + 1U)    //设置DMA数据块大小
#define DMA_DATA_WIDTH                  (DMA_DATAWIDTH_16BIT)    //设置数据宽度,也决定了源地址和目的地址增加或者减少多少
#define DMA_SRC_ADDR                     ADC_DR_START     //DMA数据源地址
#define DMA_DEST_ADDR                   ((uint32_t)(&m_au16AdcValue[0U]))    //DMA数据目的地址

#define DMA_TRIG_EVT                    (EVT_SRC_ADC1_EOCA)    //选择AOS触发源 ADC1序列A转换完成事件

#define DMA_INT_TYPE                    (DMA_INT_BTC_CH0)    //选择DMA中断类型为:数据块传输完成中断
#define DMA_INT_SRC                     (INT_SRC_DMA1_BTC0)    //选择DMA中断类型为:数据块传输完成
#define DMA_INT_IRQn                    (INT028_IRQn)     //DMA中断序号为028
#define DMA_INT_PRIO                    (DDL_IRQ_PRIO_00)    //DMA中断优先级为00(根据自己需要设定)
#define DMA_INT_FLAG                    (DMA_FLAG_BTC_CH0)    //DMA数据块传输完成中断标志位

/* ADC reference voltage. The voltage of pin VREFH. */
#define ADC_VREF                        (3.3F)    //ADC参考电压3.3V

/* ADC accuracy(according to the resolution of ADC). */
#define ADC_ACCURACY                    (1UL << 12U)    //设置ADC分辨率为12位,2^12次方=4096

#define ADC_CAL_VOL(adcVal)             (uint16_t)((((float32_t)(adcVal) * ADC_VREF) / ((float32_t)ADC_ACCURACY)) )    //计算ADC采样电压 ADC_CAL_VOL = adcVal*3.3/4096


static uint16_t m_au16AdcValue[DMA_BLOCK_SIZE];     //DMA接受数据缓存区定义

void DMA_init(void){   //DMA配置

        FCG_Fcg0PeriphClockCmd(DMA_PERIPH_CLK, ENABLE);    //使能DMA外围时钟
    DMA_DeInit(DMA_UNIT, DMA_CH);    //复位DMA1通道0
        //DMA基本配置
    stc_dma_init_t stcDmaInit;
    DMA_StructInit(&stcDmaInit);
    stcDmaInit.u32IntEn       = DMA_INT_DISABLE;    //开启DMA中断
    stcDmaInit.u32SrcAddr     = DMA_SRC_ADDR;    //DMA源地址
    stcDmaInit.u32DestAddr    = DMA_DEST_ADDR;    //DMA目的地址
    stcDmaInit.u32DataWidth   = DMA_DATA_WIDTH;    //DMA传输数据宽度 16位
    stcDmaInit.u32BlockSize   = DMA_BLOCK_SIZE;    //DMA数据块大小 15
    stcDmaInit.u32TransCount  = DMA_TRANS_CNT;    //DMA传输计数
    stcDmaInit.u32SrcAddrInc  = DMA_SRC_ADDR_INC;    //DMA源地址增量方式 递增
    stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_INC;    //DMA目的地址增量方式 递增
    DMA_Init(DMA_UNIT, DMA_CH, &stcDmaInit);
       
    DMA_Cmd(DMA_UNIT, ENABLE);
    DMA_ChCmd(DMA_UNIT, DMA_CH, ENABLE);
       
          //DMA重复模式配置
    stc_dma_repeat_init_t stcDmaRptInit;
        DMA_RepeatStructInit(&stcDmaRptInit);
    stcDmaRptInit.u32Mode      = DMA_RPT_BOTH;    //DMA重复模式 DMA源和目标重复启用
    stcDmaRptInit.u32SrcCount  = DMA_BLOCK_SIZE;    //DMA源重复大小=DMA数据块大小(15)
    stcDmaRptInit.u32DestCount = DMA_BLOCK_SIZE;    //DMA目的重复大小=DMA数据块大小(15)
    DMA_RepeatInit(DMA_UNIT, DMA_CH, &stcDmaRptInit);
   
        ADC_GetStatus(ADC_UNIT, ADC_FLAG_EOCA);
    /* Enable AOS clock */
    FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_AOS, ENABLE);
    /* Set DMA trigger source 设置DMA触发源*/   
    AOS_SetTriggerEventSrc(DMA_AOS_TRIG_SEL, DMA_TRIG_EVT);    //ADC转换完成->DMA传输数据
    /* DMA IRQ configuration. */    //DMA中断处理函数
    DmaIrqConfig();
       
       
}

/**
* @brief  DMA interrupt configuration.
* @param  None
* @retval None
*/
static void DmaIrqConfig(void)    //        DMA中断函数配置
{
    stc_irq_signin_config_t stcIrqSignConfig;

    stcIrqSignConfig.enIntSrc    = DMA_INT_SRC;
    stcIrqSignConfig.enIRQn      = DMA_INT_IRQn;
    stcIrqSignConfig.pfnCallback = &DMA_IrqCallback;

    (void)INTC_IrqSignIn(&stcIrqSignConfig);
    DMA_ClearTransCompleteStatus(DMA_UNIT, DMA_INT_FLAG);

    /* NVIC setting */    //中断控制设置
    NVIC_ClearPendingIRQ(DMA_INT_IRQn);
    NVIC_SetPriority(DMA_INT_IRQn, DMA_INT_PRIO);
    NVIC_EnableIRQ(DMA_INT_IRQn);
}

/**
* @brief  DMA IRQ handler.
* @param  None
* @retval None
*/
static void DMA_IrqCallback(void)    //DMA中断回调函数
{
        if(SET == DMA_GetTransCompleteStatus(DMA_UNIT, DMA_INT_FLAG)){
           DMA_Cmd(DMA_UNIT, DISABLE);
       DMA_ClearTransCompleteStatus(DMA_UNIT, DMA_INT_FLAG);
           DMA_Cmd(DMA_UNIT, ENABLE);
                }
}

使用特权

评论回复
沙发
ZJY1|  楼主 | 2024-6-25 18:02 | 只看该作者
用的是HC32F460

使用特权

评论回复
板凳
mbutterfly| | 2024-6-26 14:31 | 只看该作者
之前遇到STM的DMA初始化放到后面,就不能用。

使用特权

评论回复
地板
亚瑟| | 2024-6-28 18:30 | 只看该作者
为什么放后面就不行了啊?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

0

粉丝