STM32单片机ADC规则组多通道转换-DMA模式

       模数转换器(Analog To Digital Converter)简称ADC(也可以写成A/D),是指将连续变化的模拟信号转换为离散的数字信号的器件。

       直接存储器存取技术(Direct Memory Access)简称DMA。DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省CPU的资源可以做其他操作。DMA传输的本质是地址到地址的操作,可以把DMA理解为CPU的“秘书”。

       ADC的参考电压是ADC的一个重要指标。STM32芯片只有100及以上引脚的型号才具备外部参考电压引脚VREF+和VREF-;64及小于64脚的型号,参考电压引脚在芯片内部默认连接到ADC的电源引脚VDDA和VSSA。

图 1  ADC电源和基准电源电路

       由于ADC规则组多通道转换时,只能读取到最后一个通道的数据,因此ADC的多通道转换天生适合DMA模式,当每个通达转换完毕后,发送DMA请求,通过DMA直接传输到设定的内存缓存区中,从而解决了ADC多通道转换数据被覆盖的问题,同时CPU不需要频繁读取ADC的数据,大幅提高执行效率。

       通过查阅STM32F1的参考手册,我们可以知道ADC1的DMA传输通道映射到了DMA1的Channel1。ADC1可由TIM3_TRGO事件触发转换。本文通过TIM3的更新事件触发ADC规则组4路通道转换。实际项目中,我们使用这4路ADC读取四个霍尔角度传感器的输出电压进而计算机械臂的角度,采用外部触发ADC规则组转换可以避免因ADC循环转换模式造成的资源浪费。接下来上代码。

void Timer_Init(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
    TIM_TimeBaseStructure.TIM_Period=1000-1;
    TIM_TimeBaseStructure.TIM_Prescaler=72-1;
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
	
    TIM_Cmd(TIM3, ENABLE);
    TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update);//设置更新事件作为触发输出
}
void ADC_DMA_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72M/6=12M
    //init GPIO
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    //init DMA
    DMA_DeInit(DMA1_Channel1);
    DMA_InitStructure.DMA_PeripheralBaseAddr=(unsigned int)&(ADC1->DR);
    DMA_InitStructure.DMA_MemoryBaseAddr=(unsigned int)&ADCBuffer[0];
    DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize=4;
    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_M2M=DMA_M2M_Disable;
    DMA_Init(DMA1_Channel1,&DMA_InitStructure);
    DMA_Cmd(DMA1_Channel1,ENABLE);
    //init ADC1
    ADC_DeInit(ADC1);
    ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode=ENABLE;
    ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T3_TRGO;//设置外部信号TIM3_TRGO出发
    ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel=4;
    ADC_Init(ADC1,&ADC_InitStructure);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_6,1,ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_7,2,ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_8,3,ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_9,4,ADC_SampleTime_239Cycles5);
    ADC_DMACmd(ADC1,ENABLE);
    ADC_Cmd(ADC1,ENABLE);
    //calibrate ADC1
    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));
    //enable ADC1 external trigger
    ADC_ExternalTrigConvCmd(ADC1,ENABLE);
}

在main函数中调用初始化函,TIM3、ADC、DMA配置好后,TIM3将每1ms触发一次ADC规则组通道转换,转换的结果将有DMA转移至预先定义的缓冲区ADCBuffer,只要及时读取ADCBuffer中的数据便可得到各ADC通道转换的数值。如果读取数据不及时,容易出现读取数据被覆盖的现象,为此可以将ADCBuffer及DMA通道缓存(DMA_BufferSize)设置成被测数据的2倍大小,当第一次规则组4通道依次转换完毕后,DMA将数据依次传输到缓冲区的前半区,同时设置DMA传输过半标志位,此时可以读取当前4通道转换的数据。同时规则组继续转换,当第二次4个通道依次转换完毕时,转换数据被存储到缓冲区的后半区,同时设置DMA传输完成标志位,此时可以读取第二次转换的数据。

代码下载链接:STM32F1系列单片机多通道ADC-DMA模式配置方法_单片机的dma-C文档类资源-CSDN下载

  • 7
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值