在做控制无人机(也包括小车)的时候需要用到2.4G无线通信将遥感和按键的值传输过去,需要用到ADC。如果用中断来做的话需要频繁进入中断,按键多的话占用的资源就很多,摇杆加上按键一共有14个了,再加上需要读取电池的电量啊等等需要用到蛮多的数模转换。所以直接搞个DMA来查询ADC岂不美哉?废话不都说,直接贴代码
首先时钟初始化
/* ADCCLK = PCLK2/4 */
RCC_ADCCLKConfig(RCC_APB2CLK_Div16);
RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_ADC1, ENABLE);
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPERIPH_DMA1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPERIPH_DMA2, ENABLE);
然后配置GPIO口
GPIO_InitType GPIO_InitStructure;
//ADC1_IN0 VBAT PA0
//ADC1_IN1 S2 PA1
//ADC1_IN2 S2 PA2
//ADC1_IN3 S3 PA3
//ADC1_IN4 S3 PA4
//ADC1_IN10 S4 S5 PC0
//ADC1_IN11 S6 S7 PC1
//ADC1_IN12 S8 S9 PC2
//ADC1_IN13 S10 S11 PC3
GPIO_InitStructure.GPIO_Pins = GPIO_Pins_0 | GPIO_Pins_1 | GPIO_Pins_2 | GPIO_Pins_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_ANALOG;
GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pins = GPIO_Pins_0 | GPIO_Pins_1 | GPIO_Pins_2 |GPIO_Pins_3 |GPIO_Pins_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_ANALOG;
GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//charge PB4 stanby PB5
GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_2MHz;
GPIO_InitStructure.GPIO_Pins = GPIO_Pins_4 | GPIO_Pins_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
最后配置好DMA和ADC
ADC_InitType ADC_InitStructure;
DMA_InitType DMA_InitStructure;
/* DMA1 Channel1 Configuration ----------------------------------------------*/
DMA_Reset(DMA1_Channel1);
DMA_DefaultInitParaConfig(&DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->RDOR;
// DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1->RDOR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)adc_raw_buffer;
DMA_InitStructure.DMA_Direction = DMA_DIR_PERIPHERALSRC;
DMA_InitStructure.DMA_BufferSize = DMA1_CH1_ADC1_BUFFER_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
DMA_InitStructure.DMA_PeripheralDataWidth = DMA_PERIPHERALDATAWIDTH_HALFWORD;
DMA_InitStructure.DMA_MemoryDataWidth = DMA_MEMORYDATAWIDTH_HALFWORD;
DMA_InitStructure.DMA_Mode = DMA_MODE_CIRCULAR;
DMA_InitStructure.DMA_Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA1 channel1 */
DMA_ChannelEnable(DMA1_Channel1, ENABLE);
/* ADC1 Configuration ------------------------------------------------------*/
ADC_StructInit(&ADC_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanMode = ENABLE;
ADC_InitStructure.ADC_ContinuousMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrig = ADC_ExternalTrig_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NumOfChannel = adc_count;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_ExternalTrigConvCtrl(ADC1, ENABLE);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239_5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239_5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239_5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_239_5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_239_5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 6, ADC_SampleTime_239_5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 7, ADC_SampleTime_239_5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 8, ADC_SampleTime_239_5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 9, ADC_SampleTime_239_5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint, 10, ADC_SampleTime_239_5);
/*Enable internal temp vref convert channel*/
ADC_TempSensorVrefintCtrl(ENABLE);
/* Enable ADC1 DMA */
ADC_DMACtrl(ADC1, ENABLE);
/* Enable JEOC interrupt */
// ADC_INTConfig(ADC1, ADC_INT_EC, ENABLE);
DMA_INTConfig(DMA1_Channel1, DMA_INT_TC, ENABLE);
/* Enable ADC1 */
ADC_Ctrl(ADC1, ENABLE);
/* Enable ADC1 reset calibration register */
ADC_RstCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
// while (ADC_GetResetCalibrationStatus(ADC1))
;
// /* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
// while (ADC_GetCalibrationStatus(ADC1))
;
/* Test on channel1 transfer complete flag */
// while (!DMA_GetFlagStatus(DMA1_FLAG_TC1));
// /* Clear channel1 transfer complete flag */
// DMA_ClearFlag(DMA1_FLAG_TC1);
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCtrl(ADC1, ENABLE);
然后直接去adc_raw_buffer里面读取需要的值就可以了。