DMA + TIM触发, DAC无输出。
本帖最后由 Sam131208 于 2023-7-7 15:12 编辑如下图,传输数据到DAC,用tim2做触发,tim2比较中断24KHZ, tim2比较中断正常进入。但是DMA中断一直没有。 换了DMA软件触发就正常了。
static void start_dma(en_dma_channel_t ch, const void *src, const void *dst, uint16_t blk_size)
{
stc_dma_cfg_t DmaInitStruct;
Sysctrl_SetPeripheralGate(SysctrlPeripheralDma, TRUE); ///< 使能DMA模块的外设时钟
DDL_ZERO_STRUCT(DmaInitStruct); //结构体变量值清零
DmaInitStruct.enMode =DmaMskBlock; ///< 选择块传输
DmaInitStruct.u16BlockSize = 1; ///< 块传输个数
DmaInitStruct.u16TransferCnt = blk_size; ///< 块传输次数,一次传输数据大小为 块传输个数*BUFFER_SIZE
DmaInitStruct.enTransferWidth = DmaMsk16Bit; ///< 传输数据的宽度,此处选择字(16Bit)宽度
DmaInitStruct.enSrcAddrMode = DmaMskSrcAddrInc; ///< 源地址自增
DmaInitStruct.enDstAddrMode = DmaMskDstAddrFix; ///< 目的地址自增
DmaInitStruct.enDestAddrReloadCtl = DmaMskDstAddrReloadDisable; ///< 禁止重新加载传输目的地址
DmaInitStruct.enSrcAddrReloadCtl = DmaMskSrcAddrReloadDisable;///< 使能重新加载传输源地址
DmaInitStruct.enSrcBcTcReloadCtl = DmaMskBcTcReloadDisable; ///< 使能重新加载BC/TC值
DmaInitStruct.u32SrcAddress = (uint32_t)src; ///< 源地址
DmaInitStruct.u32DstAddress = (uint32_t)dst; ///< 目标地址:DAC_DHR12R0
DmaInitStruct.enRequestNum = DmaTIM2ATrig; ///< 设置TIM2A触发
DmaInitStruct.enTransferMode = DmaMskOneTransfer; ///< 传输一次,DMAC传输完成时清除CONFA:ENS位
DmaInitStruct.enPriority = DmaMskPriorityFix; ///< 各通道固定优先级,CH0优先级 > CH1优先级
Dma_InitChannel(ch,&DmaInitStruct); ///< 初始化dma通道0
Dma_EnableChannelIrq(ch); //传输成功完成时产生中断
EnableNvic(DMAC_IRQn,IrqLevel3,TRUE); //NVIC对应DMAC中断位使能
Dma_Enable(); ///< 使能DMA
Dma_EnableChannel(ch); ///< 使能DMA通道0
}
代码里没有设置DMA的AOS事件,要将DMA通道的触发事件设置为TMER2的事件,并打开TIMER2对应的外设中断使能。
MCU@baize 发表于 2023-6-29 18:00
代码里没有设置DMA的AOS事件,要将DMA通道的触发事件设置为TMER2的事件,并打开TIMER2对应的外设中断使能。 ...
使用的是HC32L196, 如何设置TIM2 的AOS事件?
void App_Timer2Cfg(uint16_t u16Period, uint16_t u16CHxACompare, uint16_t u16CHxBCompare)
{
uint16_t u16CntValue;
uint8_t u8ValidPeriod;
stc_bt_mode23_cfg_t stcBtBaseCfg;
stc_bt_m23_compare_cfg_t stcBtPortCmpCfg;
stc_bt_m23_adc_trig_cfg_tstcBtTrigAdc;
stc_bt_m23_dt_cfg_t stcBtDeadTimeCfg;
DDL_ZERO_STRUCT(stcBtBaseCfg);
DDL_ZERO_STRUCT(stcBtPortCmpCfg);
DDL_ZERO_STRUCT(stcBtTrigAdc);
DDL_ZERO_STRUCT(stcBtDeadTimeCfg);
Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE); //Base Timer外设时钟使能
stcBtBaseCfg.enWorkMode = BtWorkMode2; //三角波模式
stcBtBaseCfg.enCT = BtTimer; //定时器功能,计数时钟为内部PCLK
stcBtBaseCfg.enPRS = BtPCLKDiv1; //PCLK
stcBtBaseCfg.enCntDir = BtCntUp; //向上计数,在三角波模式时只读
stcBtBaseCfg.enPWMTypeSel= BtIndependentPWM; //独立输出PWM
stcBtBaseCfg.enPWM2sSel = BtSinglePointCmp; //单点比较功能
stcBtBaseCfg.bOneShot = FALSE; //循环计数
stcBtBaseCfg.bURSSel = FALSE; //上下溢更新
Bt_Mode23_Init(TIM2, &stcBtBaseCfg); //TIM0 的模式23功能初始化
Bt_M23_ARRSet(TIM2, u16Period, TRUE); //设置重载值,并使能缓存
Bt_M23_CCR_Set(TIM2, BtCCR0A, u16CHxACompare); //设置比较值A,(PWM互补模式下只需要设置比较值A)
stcBtPortCmpCfg.enCH0ACmpCtrl = BtPWMMode2; //OCREFA输出控制OCMA:PWM模式2
stcBtPortCmpCfg.enCH0APolarity= BtPortPositive; //正常输出
stcBtPortCmpCfg.bCh0ACmpBufEn = TRUE; //A通道缓存控制
stcBtPortCmpCfg.enCh0ACmpIntSel = BtCmpIntNone; //A通道比较控制:无
stcBtPortCmpCfg.enCH0BCmpCtrl = BtPWMMode2; //OCREFB输出控制OCMB:PWM模式2(PWM互补模式下也要设置,避免强制输出)
stcBtPortCmpCfg.enCH0BPolarity= BtPortPositive; //正常输出
stcBtPortCmpCfg.bCH0BCmpBufEn = TRUE; //B通道缓存控制使能
stcBtPortCmpCfg.enCH0BCmpIntSel = BtCmpIntNone; //B通道比较控制:无
Bt_M23_PortOutput_Cfg(TIM2, &stcBtPortCmpCfg); //比较输出端口配置
stcBtTrigAdc.bEnTrigADC = TRUE; //使能ADC触发全局控制
stcBtTrigAdc.bEnUevTrigADC = TRUE; //Uev更新触发ADC
Bt_M23_TrigADC_Cfg(TIM2, &stcBtTrigAdc); //触发ADC配置
u8ValidPeriod = 1; //事件更新周期设置,0表示三角波每半个周期更新一次,每+1代表延迟半个周期
Bt_M23_SetValidPeriod(TIM2,u8ValidPeriod); //间隔周期设置
stcBtDeadTimeCfg.bEnDeadTime = TRUE;
stcBtDeadTimeCfg.u8DeadTimeValue= 0xFF;
Bt_M23_DT_Cfg(TIM2, &stcBtDeadTimeCfg); //死区配置
u16CntValue = 0;
Bt_M23_Cnt16Set(TIM2, u16CntValue); //设置计数初值
Bt_ClearAllIntFlag(TIM2); //清中断标志
Bt_Mode23_EnableIrq(TIM2,BtCA0Irq); //使能TIM0 UEV更新中断
EnableNvic(TIM2_IRQn, IrqLevel0, TRUE); //TIM0中断使能
}
void Tim2_IRQHandler(void)
{
//Timer2 模式23 溢出中断
if(TRUE == Bt_GetIntFlag(TIM2, BtCA0Irq))
{
Bt_ClearIntFlag(TIM2,BtCA0Irq); //中断标志清零
}
}
添加以下代码:
stc_bt_m23_trig_dma_cfg_t stcbtdmatrigCfg;
DDL_ZERO_STRUCT(stcbtdmatrigCfg);
stcbtdmatrigCfg.bCmpATrigDMA = TRUE;
stcbtdmatrigCfg.bTITrigDMA = TRUE;
stcbtdmatrigCfg.enCmpUevTrigDMA = TRUE;
stcbtdmatrigCfg.bUevTrigDMA = TRUE;
Bt_M23_EnDMA(TIM2, &stcbtdmatrigCfg);
淘宝店铺:白泽开发板
各类国产品牌MCU评估板(小华、GD、极海,持续更新中。。。。。。)
【淘宝】https://m.tb.cn/h.5aCN4a4?tk=sF14dsQXD6p CZ0001 「小华HC32F448MCTI 核心板开发板 工程板」
点击链接直接打开 或者 淘宝搜索直接打开 MCU@Baize 发表于 2023-6-30 12:26
添加以下代码:
stc_bt_m23_trig_dma_cfg_t stcbtdmatrigCfg;
DDL_ZERO_STRUCT(stcbtdmatrigCfg);
你好,DMA可以工作了。
只是DAC似乎没有反应。以下是我的代码。
tim_trigdma_cfg(TIM2, 16000);
audio_dac_opa_enable(true);
start_dma(DmaCh0, dac_tream.mem_block, 0x4000250C, block_size); //输出DAC0 ,左对齐
static void start_dma(en_dma_channel_t ch, const void *src, const void *dst, uint16_t blk_size)
{
stc_dma_cfg_t DmaInitStruct;
Sysctrl_SetPeripheralGate(SysctrlPeripheralDma, TRUE); ///< 使能DMA模块的外设时钟
DDL_ZERO_STRUCT(DmaInitStruct); //结构体变量值清零
DmaInitStruct.enMode =DmaMskBlock; ///< 选择块传输
DmaInitStruct.u16BlockSize = 1; ///< 块传输个数
DmaInitStruct.u16TransferCnt = blk_size; ///< 块传输次数,一次传输数据大小为 块传输个数*BUFFER_SIZE
DmaInitStruct.enTransferWidth = DmaMsk16Bit; ///< 传输数据的宽度,此处选择字(16Bit)宽度
DmaInitStruct.enSrcAddrMode = DmaMskSrcAddrInc; ///< 源地址自增
DmaInitStruct.enDstAddrMode = DmaMskDstAddrFix; ///< 目的地址自增
DmaInitStruct.enDestAddrReloadCtl = DmaMskDstAddrReloadDisable; ///< 禁止重新加载传输目的地址
DmaInitStruct.enSrcAddrReloadCtl = DmaMskSrcAddrReloadDisable;///< 使能重新加载传输源地址
DmaInitStruct.enSrcBcTcReloadCtl = DmaMskBcTcReloadDisable; ///< 使能重新加载BC/TC值
DmaInitStruct.u32SrcAddress = (uint32_t)src; ///< 源地址
DmaInitStruct.u32DstAddress = (uint32_t)dst; ///< 目标地址:DAC_DHR12R0
DmaInitStruct.enRequestNum = DmaTIM2ATrig; ///< 设置TIM2A触发
DmaInitStruct.enTransferMode = DmaMskOneTransfer; ///< 传输一次,DMAC传输完成时清除CONFA:ENS位
DmaInitStruct.enPriority = DmaMskPriorityFix; ///< 各通道固定优先级,CH0优先级 > CH1优先级
Dma_InitChannel(ch,&DmaInitStruct); ///< 初始化dma通道0
Dma_EnableChannelIrq(ch); //传输成功完成时产生中断
EnableNvic(DMAC_IRQn,IrqLevel3,TRUE); //NVIC对应DMAC中断位使能
Dma_Enable(); ///< 使能DMA
Dma_EnableChannel(ch); ///< 使能DMA通道0
Dma_ClrStat(ch); ///< 清零:STAT
}
static void tim_trigdma_cfg(en_bt_unit_t TIMx, uint16_t sample_rate)
{
uint16_t period = Sysctrl_GetPClkFreq() / sample_rate;
uint8_t u8ValidPeriod;
stc_bt_mode23_cfg_t stcBtBaseCfg;
stc_bt_m23_trig_dma_cfg_tstcbtdmatrigCfg;
Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE); //Base Timer外设时钟使能
DDL_ZERO_STRUCT(stcBtBaseCfg);
stcBtBaseCfg.enWorkMode = BtWorkMode2; //三角波模式
stcBtBaseCfg.enCT = BtTimer; //定时器功能,计数时钟为内部PCLK
stcBtBaseCfg.enPRS = BtPCLKDiv1; //PCLK
stcBtBaseCfg.enCntDir = BtCntUp; //向上计数,在三角波模式时只读
stcBtBaseCfg.enPWMTypeSel= BtIndependentPWM; //独立输出PWM
stcBtBaseCfg.enPWM2sSel = BtSinglePointCmp; //单点比较功能
stcBtBaseCfg.bOneShot = FALSE; //循环计数
stcBtBaseCfg.bURSSel = FALSE; //上下溢更新
Bt_Mode23_Init(TIMx, &stcBtBaseCfg); //TIM0 的模式23功能初始化
DDL_ZERO_STRUCT(stcbtdmatrigCfg);
stcbtdmatrigCfg.bCmpATrigDMA = TRUE;
stcbtdmatrigCfg.bTITrigDMA = TRUE;
Bt_M23_EnDMA(TIMx, &stcbtdmatrigCfg);
Bt_M23_ARRSet(TIMx, period, TRUE); //设置重载值,并使能缓存
Bt_M23_CCR_Set(TIMx, BtCCR0A, period / 2); //设置比较值A,(PWM互补模式下只需要设置比较值A)
Bt_M23_SetValidPeriod(TIMx, 1); //间隔周期设置, 事件更新周期设置,0表示三角波每半个周期更新一次,每+1代表延迟半个周期
Bt_M23_Cnt16Set(TIMx, 0); //设置计数初值
}
static void audio_dac_opa_enable(bool enable)
{
if(enable){
stc_dac_cfg_tdac_initstruct;
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); // 使能GPIO模块的时钟
Sysctrl_SetPeripheralGate(SysctrlPeripheralDac, TRUE); ///< 使能DAC模块的时钟
//Sysctrl_SetPeripheralGate(SysctrlPeripheralOpa, TRUE); // 使能OPA模块的时钟
Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE); // 使能BGR模块的时钟
Gpio_SetAnalogMode(GpioPortA, GpioPin4); //PA04作为DAC的模拟输出
dac_initstruct.boff_t = DacBoffEnable;
dac_initstruct.ten_t= DacTenDisable;
dac_initstruct.sref_t = DacVoltageAvcc;
dac_initstruct.mamp_t = DacMenp4095;
dac_initstruct.tsel_t = DacSwTriger; ///< 软件触发方式
dac_initstruct.align= DacLeftAlign; ///< 左对齐
Dac_Init(&dac_initstruct);
Dac_Cmd(TRUE);
Dac_DmaCmd(TRUE); ///< DAC通道DMA使能
//Bgr_BgrEnable();
//Opa_Cmd(FALSE); // 禁止OPA(注:此时的OPA输入时通过DAC的输出提供信号)
//Opa_CmdBuf(TRUE); // 使能OPABUFEN
}else{
Bgr_BgrDisable();
Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE); // 使能BGR模块的时钟
Sysctrl_SetPeripheralGate(SysctrlPeripheralOpa, TRUE); // 使能OPA模块的时钟
}
}
有人能解决问题吗
页:
[1]