MM32F003的ADC可以通过启用DMA功能,加快ADC数据的获取,并减轻系统开销。本例程通过开启DMA中断,直接将ADC数据搬运至指定内存空间,减少系统开销。
ADC的配置方式与例程解析【5】
相同。这里重点介绍DMA的初始化过程。
1 DMA的初始化
void DMAInit(void)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) & (ADC1->ADDATA); //DMA transfer peripheral address
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADCValue; //DMA transfer memory address
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA transfer direction from peripheral to memory
DMA_InitStructure.DMA_BufferSize = ADCSCANNUM; //DMA cache size
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //After receiving the data, the peripheral address is forbidden to move backward
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //After receiving the data, the memory address is shifted backward
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //Define the peripheral data width to 16 bits
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //Define the memory data width to 16 bits
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //Cycle conversion mode
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA priority is high
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //M2M mode is disabled
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); //DMA interrupt initialization
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
DMA的初始化主要修改DMA的数据源地址DMA_InitStructure.DMA_PeripheralBaseAddr
、DMA的数据目标地址DMA_InitStructure.DMA_MemoryBaseAddr
和DMA的数据区大小DMA_InitStructure.DMA_BufferSize
这三个参数。
2 DMA中断服务程序
void DMA1_Channel1_IRQHandler(void)
{
ADC_SoftwareStartConvCmd(ADC1, DISABLE); //Stop Conversion
DMA_ClearITPendingBit(DMA1_IT_TC1); //Clear interrupt flag
ADCflag = 1; //Erected transmission complete flag
}
DMA的数据目标地址存满后会产生中断,进入DMA中断服务程序。
3 main主程序
int main(void)
{
u16 chan, averagenumber = 0;
Uart_ConfigInit(9600);
// SystemInit();
// InitSystick();
//Initialize DMA
//
DMAInit();
ADCConfig(ADCch0); //PA0
ADCConfig(ADCch10); //PB3
ADCConfig(ADCch11); //PB4
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //Start Conversion
while(1) {
if(ADCflag == 1) {
ADCflag = 0;
for(chan = 0; chan < ADCSCANNUM; chan++) {
varADCavarage[averagenumber][chan] = ADCValue[chan];
}
//memcpy(&(varADCavarage[averagenumber][0]),ADCValue,ADCSCANNUM);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
averagenumber++;
if(averagenumber >= AVERAGELEN) {
averagenumber = 0;
ADCTrigFilterflag = 1;
}
}
if(ADCTrigFilterflag) { //Determine whether the second-order filter is over
ADCFilter();
ADCTrigFilterflag = 0; //Clear the filter end flag
Get_ADCVolatge(); //Convert the filtered value to voltage
}
}
}
每次进入DMA中断服务程序都会修改标志位,主程序会通过while()
循环去查询标志位ADCflag
,当ADCflag
为1时,即对ADC读取的数据进行累加计算平均值和ADC数值转换电压数值的操作。