案例 stm32单片机,adc的双通道+dma 内部温度
可以这样理解
先配置adc :有几个通道就配置几个通道.
然后配置dma,dma是针对adc的,而不是针对通道的.
一开始我以为一个adc通道对应一个dma通道.(这里是错的,其实是我想复杂了)
一个adc,对应一个dma.
adc可以开多个通道.比如采集电池的电量是一个通道,采集单片机温度是另一个通道.
adc1的所有通道对应着dma的某一个通道.
然后开启后dma,就会依次把各通道的数据存入数组:
数组元素1: 通道1的数据
数组元素2: 通道2的数据
数组元素3: 通道3的数据
数组元素4: 通道4的数据
数组元素5: 通道5的数据
然后又会从头存,一直循环下去....
这样可以设置成 多维数组
比如 100行 5列的数组
然后dma传输长度设置成500;
这样每个通道的数据,就自动存入 a[100][5] 的数组中,且每一列代表一个通道,可以除以100进行平均
下面给出一个程序:
adc1开启有两个通道,
一个通道用于采集电量.
另一个通道用于采集单片机内部温度.
首先,配置采集电量引脚的:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //使用PC0做模拟输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC,&GPIO_InitStructure);
然后配置adc,adc中使用了两个通道,一个是采集电量,一个是采集内部温度:
static void ADC_Configuration(void) { ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* ADC Common Init **********************************************************/ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; //独立工作模式 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure); /* ADC3 Init ****************************************************************/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = ENABLE; //扫描模式 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续转换 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //由软件触发转换 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; //外部触发源 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据右对其 ADC_InitStructure.ADC_NbrOfConversion = 2; //转换序列长度 因为有两个通道,这里是2 ADC_Init(ADC1, &ADC_InitStructure); ADC_TempSensorVrefintCmd(ENABLE); //使能内部温度传感器
//采集电压的通道 ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_480Cycles); //内部温度的通道 ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 2, ADC_SampleTime_480Cycles); /* Enable DMA request after last transfer (Single-ADC mode) */ ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); /* Enable ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); ADC_SoftwareStartConv(ADC1); }
之后为adc的两个通道,配置一个dma.
ADCConvertedValue这个变量是一个二维数组,代表了两个通道,dma会把数据存入到这里.
/* Enable DMA2 and GPIO clocks ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); /* DMA2 Stream0 channel2 configuration **************************************/ DMA_DeInit(DMA2_Stream4); DMA_InitStructure.DMA_Channel = DMA_Channel_0; //DMA通道 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS; //外设基地址 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue; //数据存储区 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //转换方向为外设到存储区 DMA_InitStructure.DMA_BufferSize = 200; //转换队列长度 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设基地址固定不变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //数据存储区地址不变 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据宽度为半字 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //存储到内存的数据宽度为半字 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High; //优先级为高 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream4, &DMA_InitStructure); DMA_Cmd(DMA2_Stream4, ENABLE);