想ADC每1ms扫描采集10通道,每10ms处理一次数据,用DMA搬运数据,TC只能设置成0,即一次扫描采集完成,源地址重新装载。产生一次DMA中断。TC不能设置成9,即每10次扫描转换产生一次DMA中断。现在程序里是设置TC为0,目的地址不重新装载,记录到10次中断后,重新加载一次目的地址。这样设置中断比较频繁。
DMA控制器只能在TC减到0以后才能完成一次源地址,目的地址,BC,TC重新装载?
#define ADC_BC 10
#define ADC_TC 10
uint32_t ADC_Result_Array[ADC_BC*10] = {0};
uint16_t ADC_array_write_index = 0;
uint32_t u32AdcRestult_VSEN;
uint32_t u32AdcRestult_I1;
uint32_t u32AdcRestult_I2;
extern QXSemaphore sema_adc;
uint16_t current_prev_1, current_prev_2;
uint16_t current_flag_1, current_flag_2;
void App_DmaCfg(void);
void App_Timer0Cfg(uint16_t u16Period);
void Adc_IRQHandler(void)
{
if(TRUE == Adc_GetIrqStatus(AdcMskIrqSqr))
{
Adc_ClrIrqStatus(AdcMskIrqSqr);
// u16AdcRestult_VSEN = Adc_GetSqrResult(AdcSQRCH0MUX);
// u16AdcRestult_I1 = Adc_GetSqrResult(AdcSQRCH1MUX);;
// u16AdcRestult_I1_buf[0] = Adc_GetSqrResult(AdcSQRCH1MUX);
// u16AdcRestult_I1_buf[1] = Adc_GetSqrResult(AdcSQRCH2MUX);
// u16AdcRestult_I1_buf[2] = Adc_GetSqrResult(AdcSQRCH3MUX);
// u16AdcRestult_I1_buf[3] = Adc_GetSqrResult(AdcSQRCH4MUX);
// u16AdcRestult_I2 = Adc_GetSqrResult(AdcSQRCH5MUX);
// u16AdcRestult_I2_buf[0] = Adc_GetSqrResult(AdcSQRCH5MUX);
// u16AdcRestult_I2_buf[1] = Adc_GetSqrResult(AdcSQRCH6MUX);
// u16AdcRestult_I2_buf[2] = Adc_GetSqrResult(AdcSQRCH7MUX);
// u16AdcRestult_I2_buf[3] = Adc_GetSqrResult(AdcSQRCH8MUX);
// (void)QXSemaphore_signal(&sema_adc);
}
}
void Dmac_IRQHandler(void)
{
if(DmaTransferComplete == Dma_GetStat(DmaCh0))
{
//等待传输完成
//(void)QXSemaphore_signal(&sema_adc);
Dma_ClrStat(DmaCh0);
if(ADC_array_write_index < 9){
//M0P_DMAC->DSTADR0 = (uint32_t)&ADC_Result_Array[ADC_array_write_index*10];
ADC_array_write_index++;
}else{
ADC_array_write_index = 0;
M0P_DMAC->DSTADR0 = (uint32_t)&ADC_Result_Array[ADC_array_write_index];
IO_SET(LED_1, 1);
(void)QXSemaphore_signal(&sema_adc);
}
}
if(DmaTransferComplete == Dma_GetStat(DmaCh1))
{
//等待传输完成
//IO_SET(LED_1, 1);
//(void)QXSemaphore_signal(&sema_adc);
Dma_ClrStat(DmaCh1);
//IO_SET(LED_1, 0);
}
if((DmaAccSCRErr == Dma_GetStat(DmaCh0)) || (DmaAccDestErr == Dma_GetStat(DmaCh0)))
{
Dma_ClrStat(DmaCh0);
}
}
void Tim0_IRQHandler(void)
{
//Timer0 模式0 溢出中断
if(TRUE == Bt_GetIntFlag(TIM0, BtUevIrq))
{
Bt_ClearIntFlag(TIM0,BtUevIrq); //中断标志清零
//IO_SET(LED_1, 1);
}
}
void App_Timer0Cfg(uint16_t u16Period)
{
uint16_t u16ArrValue;
uint16_t u16CntValue;
stc_bt_mode0_cfg_t stcBtBaseCfg;
stc_bt_m23_adc_trig_cfg_t stcBtTrigAdc;
DDL_ZERO_STRUCT(stcBtBaseCfg);
DDL_ZERO_STRUCT(stcBtTrigAdc);
Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE); //Base Timer外设时钟使能
stcBtBaseCfg.enWorkMode = BtWorkMode0; //定时器模式
stcBtBaseCfg.enCT = BtTimer; //定时器功能,计数时钟为内部PCLK
stcBtBaseCfg.enPRS = BtPCLKDiv8; //PCLK/256
stcBtBaseCfg.enCntMode = Bt16bitArrMode; //自动重载16位计数器/定时器
stcBtBaseCfg.bEnTog = FALSE;
stcBtBaseCfg.bEnGate = FALSE;
stcBtBaseCfg.enGateP = BtGatePositive;
Bt_Mode0_Init(TIM0, &stcBtBaseCfg); //TIM0 的模式0功能初始化
u16ArrValue = 0x10000 - u16Period;
Bt_M0_ARRSet(TIM0, u16ArrValue); //设置重载值(ARR = 0x10000 - 周期)
u16CntValue = 0x10000 - u16Period;
Bt_M0_Cnt16Set(TIM0, u16CntValue); //设置计数初值
stcBtTrigAdc.bEnTrigADC = TRUE; //使能ADC触发全局控制
stcBtTrigAdc.bEnUevTrigADC = TRUE; //Uev更新触发ADC
Bt_M23_TrigADC_Cfg(TIM0, &stcBtTrigAdc); //触发ADC配置
Bt_ClearIntFlag(TIM0,BtUevIrq); //清中断标志
//Bt_Mode0_EnableIrq(TIM0); //使能TIM0中断(模式0时只有一个中断)
//EnableNvic(TIM0_IRQn, IrqLevel3, TRUE); //TIM0中断使能
}
void aio_init(void)
{
stc_adc_cfg_t stcAdcCfg;
stc_adc_sqr_cfg_t stcAdcSqrCfg;
DDL_ZERO_STRUCT(stcAdcCfg);
DDL_ZERO_STRUCT(stcAdcSqrCfg);
Gpio_SetAnalogMode(GpioPortB, GpioPin0);
Gpio_SetAnalogMode(GpioPortB, GpioPin1);
Gpio_SetAnalogMode(GpioPortB, GpioPin11);
if (Ok != Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE))
{
Q_onAssert("adc_err", 999);
}
Bgr_BgrEnable(); ///< 开启BGR
//ADC配置
stcAdcCfg.enAdcMode = AdcScanMode; ///<采样模式-扫描
stcAdcCfg.enAdcClkDiv = AdcMskClkDiv8; ///<采样分频-8
stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle12Clk; ///<采样周期数-8
stcAdcCfg.enAdcRefVolSel = AdcMskRefVolSelInBgr2p5; ///<参考电压选择-2.5V
stcAdcCfg.enAdcOpBuf = AdcMskBufDisable; ///<OP BUF配置-
stcAdcCfg.enInRef = AdcMskInRefEnable; ///<内部参考电压使能-关
stcAdcCfg.enAdcAlign = AdcAlignRight; ///<转换结果对齐方式-右
Adc_Init(&stcAdcCfg);
stcAdcSqrCfg.bSqrDmaTrig = TRUE;
stcAdcSqrCfg.enResultAcc = AdcResultAccDisable;
stcAdcSqrCfg.u8SqrCnt = 10;
Adc_SqrModeCfg(&stcAdcSqrCfg);
Adc_CfgSqrChannel(AdcSQRCH0MUX, AdcExInputCH8);
Adc_CfgSqrChannel(AdcSQRCH9MUX, AdcExInputCH8);
Adc_CfgSqrChannel(AdcSQRCH1MUX, AdcExInputCH9);
Adc_CfgSqrChannel(AdcSQRCH2MUX, AdcExInputCH9);
Adc_CfgSqrChannel(AdcSQRCH3MUX, AdcExInputCH9);
Adc_CfgSqrChannel(AdcSQRCH4MUX, AdcExInputCH9);
Adc_CfgSqrChannel(AdcSQRCH5MUX, AdcExInputCH18);
Adc_CfgSqrChannel(AdcSQRCH6MUX, AdcExInputCH18);
Adc_CfgSqrChannel(AdcSQRCH7MUX, AdcExInputCH18);
Adc_CfgSqrChannel(AdcSQRCH8MUX, AdcExInputCH18);
Adc_ClrIrqStatus(AdcMskIrqSqr);
Adc_SqrExtTrigCfg(AdcMskTrigTimer0, TRUE); //Timer0触发扫描转换
App_DmaCfg();
//Adc_EnableIrq();
//EnableNvic(ADC_IRQn, IrqLevel3, TRUE);
delay10us(5);
App_Timer0Cfg(3000);
}
void App_DmaCfg(void)
{
stc_dma_cfg_t stcDmaCfg;
DDL_ZERO_STRUCT(stcDmaCfg); //结构体变量 初始值清零
// 使能 DMA时钟
Sysctrl_SetPeripheralGate(SysctrlPeripheralDma,TRUE);
stcDmaCfg.enMode = DmaMskBlock; //选择块传输
stcDmaCfg.u16BlockSize = 10; //块传输个数
stcDmaCfg.u16TransferCnt = 1; //Block模式,一次传输数据大小为 10,传输1次
stcDmaCfg.enTransferWidth = DmaMsk32Bit; //传输数据的宽度,此处选择字(32Bit)宽度
stcDmaCfg.enSrcAddrMode = DmaMskSrcAddrInc; //源地址自增
stcDmaCfg.enDstAddrMode = DmaMskDstAddrInc; //目的地址自增
stcDmaCfg.enDestAddrReloadCtl = DmaMskDstAddrReloadDisable; //不重新加载传输目的地址
stcDmaCfg.enSrcAddrReloadCtl = DmaMskSrcAddrReloadEnable; //使能重新加载传输源地址
stcDmaCfg.enSrcBcTcReloadCtl = DmaMskBcTcReloadEnable; //使能重新加载BC/TC值
stcDmaCfg.u32SrcAddress = (uint32_t)&(M0P_ADC->SQRRESULT0);//指定传输源地址
stcDmaCfg.u32DstAddress = (uint32_t)&ADC_Result_Array[0]; //指定传输目的地址
stcDmaCfg.enTransferMode = DmaMskContinuousTransfer; //DMAC 在传输完成时不清除 CONFA:ENS 位。这个功能允许连续传输而不需要 CPU 干预。
stcDmaCfg.enRequestNum = DmaADCSQRTrig; //设置为ADC SQR触发
Dma_InitChannel(DmaCh0,&stcDmaCfg); //初始化DMA通道0
// stcDmaCfg.enMode = DmaMskBlock; //选择块传输
// stcDmaCfg.u16BlockSize = ADC_BC; //块传输个数
// stcDmaCfg.u16TransferCnt = ADC_TC; //Block模式,一次传输数据大小为 3,传输三次
// stcDmaCfg.enTransferWidth = DmaMsk32Bit; //传输数据的宽度,此处选择字(32Bit)宽度
// stcDmaCfg.enSrcAddrMode = DmaMskSrcAddrInc; //源地址自增
// stcDmaCfg.enDstAddrMode = DmaMskDstAddrInc; //目的地址自增
// stcDmaCfg.enDestAddrReloadCtl = DmaMskDstAddrReloadEnable; //使能重新加载传输目的地址
// stcDmaCfg.enSrcAddrReloadCtl = DmaMskSrcAddrReloadEnable; //使能重新加载传输源地址
// stcDmaCfg.enSrcBcTcReloadCtl = DmaMskBcTcReloadEnable; //使能重新加载BC/TC值
// stcDmaCfg.u32SrcAddress = (uint32_t)&ADC_Result_Array[0];//指定传输源地址
// stcDmaCfg.u32DstAddress = (uint32_t)&ADC_Result_buf_Array[0]; //指定传输目的地址
// stcDmaCfg.enTransferMode = DmaMskContinuousTransfer; //DMAC 在传输完成时不清除 CONFA:ENS 位。这个功能允许连续传输而不需要 CPU 干预。
// stcDmaCfg.enRequestNum = DmaADCSQRTrig; //设置为ADC SQR触发
// Dma_InitChannel(DmaCh1,&stcDmaCfg);
//使能DMA,使能DMA0
Dma_Enable();
Dma_EnableChannel(DmaCh0);
Dma_EnableChannelIrq(DmaCh0);
Dma_EnableChannelErrIrq(DmaCh0);
//Dma_EnableChannel(DmaCh1);
//Dma_EnableChannelIrq(DmaCh1);
EnableNvic(DMAC_IRQn, IrqLevel2, TRUE);
}
|