mcal ADC硬件触发和软件触发混用DEMO
-
1.背景
在PWM的下降沿触发ADC采集
2.需求- PWM(eTMR0_CH0)的每个周期中,上升沿触发ADC转换10次后,切换到3个软件触发的group的采集。
- MCAL: 2.2.0 , gcc
- YTM32B1ME0X
3.解决方案描述:
由于PWM模块没有提供MID值的设置API,采用手写代码设置MID值:
eTMR0->SYNC |= eTMR_SYNC_CLDOK_MASK; eTMR0->MID = eTMR0->CH[0].VAL1; eTMR0->SYNC |= eTMR_SYNC_LDOK(1);
测试波形:

示例工程:12694718-26d0-4c88-a824-16035e3174d3-Adc_HwTrig_Demo.zip -

我这里弄错了,ADC重新初始化才需要Disable,不进行重新初始化不需要Disable ADC HW触发信号输出,只需要在采样完成进入中断后按用户需求重新配置ADC就行,配置完后执行以下流程重装载回调函数和开启ADC,等待标志位base->INTE = ADC_INTE_EOSEQIE(1U); /* Enable end of sequence interrupt */ INT_SYS_InstallHandler(ADC0_IRQn, adcISR, NULL); INT_SYS_EnableIRQ(ADC0_IRQn); base->CTRL = ADC_CTRL_TSEN(1U) | /* Enable temperature sensor */ ADC_CTRL_ADEN(1U); /* Enable ADC */ base->CTRL |= ADC_CTRL_ADSTART(1U); /* Start ADC */ while(!(base->STS & ADC_STS_ADRDY_MASK)); /* Wait for ADC ready */ -
不是的,我们的单电阻电机demo就是这样操作的,ADCHW触发,step采样完成后,切换成ADCSW触发,continue采样,完成后切换回ADCHW触发,是这个意思吧,ME0是这样做的,别的芯片也一样,寄存器操作有细微区别
void HW_SetupAdcSeq1Mode(const uint8_t *channels, uint8_t channel_cnt, const isr_t adcISR) { ADC_Type *base = ADC0; /* Setup adc configuration */ base->CFG0 = ((channel_cnt - 1) & 0xFU) << ADC_CFG0_SEQLEN_SHIFT | /* Sequence length */ ADC_CFG0_DISCEN(1U) | ADC_CFG0_CONT(0U) | ADC_CFG0_TRIGMD(1U); base->CFG1 = ADC_CFG1_STCNT(32U) | ADC_CFG1_PRS(0); /* Start time count */ base->SMP = ADC_SMP_SMP(1U); /* Sample time */ /* Configure sequence 0 channels for current sensing */ ADC0->CHSEL[0] = ADC_CHSEL_CHSEL(ADC_V_PHASE_CHANNEL); ADC0->CHSEL[1] = ADC_CHSEL_CHSEL(ADC_V_PHASE_CHANNEL); base->INTE = ADC_INTE_EOSEQIE(1U); /* Enable end of sequence interrupt */ INT_SYS_InstallHandler(ADC0_IRQn, adcISR, NULL); INT_SYS_EnableIRQ(ADC0_IRQn); base->CTRL = ADC_CTRL_ADEN(1U); /* Enable ADC */ base->CTRL |= ADC_CTRL_ADSTART(1U); /* Start ADC */ while(!(base->STS & ADC_STS_ADRDY_MASK)); /* Wait for ADC ready */ } void HW_SetupAdcSeq2Mode(const uint8_t *channels, uint8_t channel_cnt, const isr_t adcISR) { ADC_Type *base = ADC0; /* Setup adc configuration */ base->CFG0 = ((channel_cnt - 1) & 0xFU) << ADC_CFG0_SEQLEN_SHIFT | /* Sequence length */ ADC_CFG0_CONT(0U) | ADC_CFG0_DISCEN(0U) | ADC_CFG0_TRIGMD(0U); base->CFG1 = ADC_CFG1_STCNT(32U) | ADC_CFG1_PRS(0); /* Start time count */ base->SMP = ADC_SMP_SMP(16U); /* Sample time */ for (int i = 0; i < channel_cnt; i++) { base->CHSEL[i] = ADC_CHSEL_CHSEL(channels[i]); /* Setup channel */ } base->INTE = ADC_INTE_EOSEQIE(1U); /* Enable end of sequence interrupt */ INT_SYS_InstallHandler(ADC0_IRQn, adcISR, NULL); INT_SYS_EnableIRQ(ADC0_IRQn); base->CTRL = ADC_CTRL_TSEN(1U) | /* Enable temperature sensor */ ADC_CTRL_ADEN(1U); /* Enable ADC */ base->CTRL |= ADC_CTRL_ADSTART(1U); /* Start ADC */ while(!(base->STS & ADC_STS_ADRDY_MASK)); /* Wait for ADC ready */ } uint8_t ADCTrgCnt = 0U; void Motor_AdcFOCISR(void) { // GPIOE->PSOR = 1 << 10; /* Clear the interrupt flag */ MC_ADC->STS = ADC_STS_EOSEQ_MASK; if(ADCTrgCnt == 0U) { CIM->SWTRIG = CIM_SWTRIG_SWT(1U) | CIM_SWTRIG_SWTCNT(0U); /* User code */ ADCTrgCnt = 1; HW_SetupAdcSeq2Mode(motorAdcFocUserSample2, 2, Motor_AdcFOCISR); } else { /* User code */ HW_SetupAdcSeq1Mode(motorAdcFocUserSample1, 2, Motor_AdcFOCISR); ADCTrgCnt = 0U; } // GPIOE->PCOR = 1 << 10; }
快速上手云途开发生态
发帖前请查看
帮助改进和优化YT CONFIG TOOL,有机会抽取YTM32B1ME0 EVB哦...