Wiki
Clone wikiMilandr / ADC DMA
По переполнению таймера создается запрос в ДМА который устанавливает бит ADC1_CFG_REG_GO в регистре ADC1_CFG, который стартует преобразование АЦП. После выполнения преобразования создается запрос на передачу результата преобразования из регистра ADC1_RESULT в массив ADCConvertedValue. По выполнении ADC_BUFFER/2 передач DMA вызывает прерывание в котором по очереди в зависимости от текущей рабочей конфигурации (Primary / Alternative) счетчик передач в DMA переинициализируется и заново устанавливается режим DMA DMA_Mode_PingPong.
#!c #define ADC_BUFFER 32 uint16_t ADCConvertedValue[ADC_BUFFER]; uint32_t ADC_Go = ADC1_CFG_REG_GO | 0x0C002201; /* DMA Configuration */ /* Reset all settings */ DMA_DeInit(); /* DMA ADC1 */ DMA_StructInit(&DMA_InitStr); /* Set Primary Control Data */ DMA_PriCtrlStr.DMA_SourceBaseAddr = (uint32_t)(&(MDR_ADC->ADC1_RESULT)); DMA_PriCtrlStr.DMA_DestBaseAddr = (uint32_t)&ADCConvertedValue[0]; DMA_PriCtrlStr.DMA_SourceIncSize = DMA_SourceIncNo; DMA_PriCtrlStr.DMA_DestIncSize = DMA_DestIncHalfword; DMA_PriCtrlStr.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_PriCtrlStr.DMA_Mode = DMA_Mode_PingPong; DMA_PriCtrlStr.DMA_CycleSize = ADC_BUFFER/2; DMA_PriCtrlStr.DMA_NumContinuous = DMA_Transfers_1; DMA_PriCtrlStr.DMA_SourceProtCtrl = DMA_SourcePrivileged; DMA_PriCtrlStr.DMA_DestProtCtrl = DMA_DestPrivileged; /* Set Alternate Control Data */ DMA_AltCtrlStr.DMA_SourceBaseAddr = (uint32_t)(&(MDR_ADC->ADC1_RESULT)); DMA_AltCtrlStr.DMA_DestBaseAddr = (uint32_t)&ADCConvertedValue[ADC_BUFFER/2]; DMA_AltCtrlStr.DMA_SourceIncSize = DMA_SourceIncNo; DMA_AltCtrlStr.DMA_DestIncSize = DMA_DestIncHalfword; DMA_AltCtrlStr.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_AltCtrlStr.DMA_Mode = DMA_Mode_PingPong; DMA_AltCtrlStr.DMA_CycleSize = ADC_BUFFER/2; DMA_AltCtrlStr.DMA_NumContinuous = DMA_Transfers_1; DMA_AltCtrlStr.DMA_SourceProtCtrl = DMA_SourcePrivileged; DMA_AltCtrlStr.DMA_DestProtCtrl = DMA_DestPrivileged; /* Set Channel Structure */ DMA_InitStr.DMA_PriCtrlData = &DMA_PriCtrlStr; DMA_InitStr.DMA_AltCtrlData = &DMA_AltCtrlStr; DMA_InitStr.DMA_Priority = DMA_Priority_Default; DMA_InitStr.DMA_UseBurst = DMA_BurstClear; DMA_InitStr.DMA_SelectDataStructure = DMA_CTRL_DATA_PRIMARY; /* Init DMA channel ADC1 */ DMA_Init(DMA_Channel_ADC1, &DMA_InitStr); /* Enable dma_req or dma_sreq to generate DMA request */ MDR_DMA->CHNL_REQ_MASK_CLR = (1<<DMA_Channel_ADC1); MDR_DMA->CHNL_USEBURST_CLR = (1<<DMA_Channel_ADC1); /* Enable DMA channel ADC1 */ DMA_Cmd(DMA_Channel_ADC1, ENABLE); /* DMA Timer1 */ /* Set Primary Control Data */ DMA_PriCtrlStr.DMA_SourceBaseAddr = (uint32_t)(&ADC_Go); DMA_PriCtrlStr.DMA_DestBaseAddr = (uint32_t)(&(MDR_ADC->ADC1_CFG)); DMA_PriCtrlStr.DMA_SourceIncSize = DMA_SourceIncNo; DMA_PriCtrlStr.DMA_DestIncSize = DMA_DestIncNo; DMA_PriCtrlStr.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; DMA_PriCtrlStr.DMA_Mode = DMA_Mode_PingPong; DMA_PriCtrlStr.DMA_CycleSize = ADC_BUFFER/2; DMA_PriCtrlStr.DMA_NumContinuous = DMA_Transfers_1; DMA_PriCtrlStr.DMA_SourceProtCtrl = DMA_SourcePrivileged; DMA_PriCtrlStr.DMA_DestProtCtrl = DMA_DestPrivileged; /* Set Alternate Control Data */ DMA_AltCtrlStr.DMA_SourceBaseAddr = (uint32_t)(&ADC_Go); DMA_AltCtrlStr.DMA_DestBaseAddr = (uint32_t)(&(MDR_ADC->ADC1_CFG)); DMA_AltCtrlStr.DMA_SourceIncSize = DMA_SourceIncNo; DMA_AltCtrlStr.DMA_DestIncSize = DMA_DestIncNo; DMA_AltCtrlStr.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; DMA_AltCtrlStr.DMA_Mode = DMA_Mode_PingPong; DMA_AltCtrlStr.DMA_CycleSize = ADC_BUFFER/2; DMA_AltCtrlStr.DMA_NumContinuous = DMA_Transfers_1; DMA_AltCtrlStr.DMA_SourceProtCtrl = DMA_SourcePrivileged; DMA_AltCtrlStr.DMA_DestProtCtrl = DMA_DestPrivileged; /* Set Channel Structure */ DMA_InitStr.DMA_PriCtrlData = &DMA_PriCtrlStr; DMA_InitStr.DMA_AltCtrlData = &DMA_AltCtrlStr; DMA_InitStr.DMA_Priority = DMA_Priority_Default; DMA_InitStr.DMA_UseBurst = DMA_BurstClear; DMA_InitStr.DMA_SelectDataStructure = DMA_CTRL_DATA_PRIMARY; /* Init DMA channel Timer1 */ DMA_Init(DMA_Channel_TIM1, &DMA_InitStr); /* Enable dma_req or dma_sreq to generate DMA request */ MDR_DMA->CHNL_REQ_MASK_CLR = (1<<DMA_Channel_TIM1); MDR_DMA->CHNL_USEBURST_CLR = (1<<DMA_Channel_TIM1); /* Enable DMA channel Timer1 */ DMA_Cmd(DMA_Channel_TIM1, ENABLE); /* Enable DMA IRQ */ NVIC_EnableIRQ(DMA_IRQn);
#!c void Initialize_Timers (void) { TIMER_CntInitTypeDef TIMER_CntInitStructure; /* TIMER1 Configuration ------------------------------------------------- */ RST_CLK_PCLKcmd(RST_CLK_PCLK_TIMER1, ENABLE); TIMER_DeInit(MDR_TIMER1); // Deinitializes the TIMERx peripheral registers to their default reset values. TIMER_CntStructInit(&TIMER_CntInitStructure); // Fills each TIMER_CntInitStruct member with its default value. TIMER_CntInitStructure.TIMER_Prescaler = 0; TIMER_CntInitStructure.TIMER_Period = 148; // 56Mhz/12.5kbps/2 halfwave/3 chan/5 samples = 149,333 TIMER_CntInit(MDR_TIMER1, &TIMER_CntInitStructure); // Initializes the TIMERx Counter peripheral according to the specified parameters in the TIMER_CntInitStruct. TIMER_BRGInit(MDR_TIMER1,TIMER_HCLKdiv1); /* Enable TIMER1 clock */ TIMER_Cmd(MDR_TIMER1, ENABLE); // Enables or disables the specified TIMER peripheral. TIMER_DMACmd(MDR_TIMER1, TIMER_STATUS_CNT_ARR, ENABLE); }
#!c void Initialize_ADC (void) { /* ADC Configuration */ RST_CLK_PCLKcmd(RST_CLK_PCLK_ADC,ENABLE); /* Reset all ADC settings */ ADC_DeInit(); ADC_StructInit(&sADC); sADC.ADC_SynchronousMode = ADC_SyncMode_Independent; sADC.ADC_StartDelay = 0; sADC.ADC_IntVRefConversion = ADC_VREF_CONVERSION_Disable; sADC.ADC_IntVRefTrimming = 1; ADC_Init (&sADC); /* ADC1 Configuration */ ADCx_StructInit (&sADCx); sADCx.ADC_ClockSource = ADC_CLOCK_SOURCE_CPU; sADCx.ADC_SamplingMode = ADC_SAMPLING_MODE_SINGLE_CONV; sADCx.ADC_ChannelSwitching = ADC_CH_SWITCHING_Enable; sADCx.ADC_Channels = ADC_CH_ADC0_MSK | ADC_CH_ADC1_MSK | ADC_CH_ADC2_MSK; sADCx.ADC_LevelControl = ADC_LEVEL_CONTROL_Disable; sADCx.ADC_LowLevel = 0; sADCx.ADC_HighLevel = 0; sADCx.ADC_VRefSource = ADC_VREF_SOURCE_INTERNAL; sADCx.ADC_IntVRefSource = ADC_INT_VREF_SOURCE_INEXACT; sADCx.ADC_Prescaler = ADC_CLK_div_4; sADCx.ADC_DelayGo = 6; ADC1_Init (&sADCx); /* Enable ADC1 EOCIF and AWOIFEN interupts */ ADC1_ITConfig((ADCx_IT_END_OF_CONVERSION | ADCx_IT_OUT_OF_RANGE), DISABLE); /* ADC1 enable */ ADC1_Cmd (ENABLE); }
#!c void DMA_IRQHandler(void) { if((MDR_DMA->CHNL_PRI_ALT_SET & (1<<DMA_Channel_ADC1)) == (0<<DMA_Channel_ADC1)) { DMA_ControlTable[DMA_Channel_ADC1+32].DMA_Control |= ((ADC_BUFFER/2 - 1) << 4) | DMA_Mode_PingPong; DMA_ControlTable[DMA_Channel_TIM1+32].DMA_Control |= ((ADC_BUFFER/2 - 1) << 4) | DMA_Mode_PingPong; PORT_WriteBit(MDR_PORTA, PORT_Pin_0, Bit_SET); } else if((MDR_DMA->CHNL_PRI_ALT_SET & (1<<DMA_Channel_ADC1)) == (1<<DMA_Channel_ADC1)) { DMA_ControlTable[DMA_Channel_ADC1].DMA_Control |= ((ADC_BUFFER/2 - 1) << 4) | DMA_Mode_PingPong; DMA_ControlTable[DMA_Channel_TIM1].DMA_Control |= ((ADC_BUFFER/2 - 1) << 4) | DMA_Mode_PingPong; Ready = 1; PORT_WriteBit(MDR_PORTA, PORT_Pin_0, Bit_RESET); } }
Updated