kyhly 发表于 2018-8-9 19:45:20

STM32F1系列实现ADC多信道采样

目前正在研究如何在STM32F107芯片上添加多个传感器,现在想采用单ADC实现多个信道数据采集,使用的HAL库,具体程序如下:
/************ADC初始化定义*****************/
#define ADCx_RCC_CLK_ENABLE()    __HAL_RCC_ADC1_CLK_ENABLE()
#define ADCx_RCC_CLK_DISABLE()   __HAL_RCC_ADC1_CLK_DISABLE()
#define DMAx_RCC_CLK_ENABLE()    __HAL_RCC_DMA1_CLK_ENABLE()

#define ADCx                     ADC1   
#define ADCx_IRQ               ADC1_2_IRQn
#define ADCx_IRQHandler          ADC1_2_IRQHandler

#define ADC_DMAx_CHANNELn      DMA1_Channel1
#define ADC_DMAx_CHANNELn_IRQn   DMA1_Channel1_IRQn
#define ADC_DMAx_CHANNELn_IRQHANDLERDMA1_Channel1_IRQHandler
/*******ADC2******/
//#define ADC2_RCC_CLK_ENABLE()    __HAL_RCC_ADC2_CLK_ENABLE()
//#define ADC2_RCC_CLK_DISABLE()   __HAL_RCC_ADC2_CLK_DISABLE()
//#define ADC_2                     ADC2   
//#define ADCx_IRQ               ADC1_2_IRQn
//#define ADCx_IRQHandler          ADC1_2_IRQHandler
/*******ADC3*****/
//#define ADCx_RCC_CLK_ENABLE()    __HAL_RCC_ADC3_CLK_ENABLE()
//#define ADCx_RCC_CLK_DISABLE()   __HAL_RCC_ADC3_CLK_DISABLE()
//#define ADCx                     ADC3   
//#define ADCx_IRQ               ADC3_IRQn
//#define ADCx_IRQHandler          ADC3_IRQHandler

//PIN¿Ú¶¨Òå
#define ADC_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()
#define ADC_GPIO                   GPIOA
#define ADC_GPIO_PIN_0             GPIO_PIN_0
#define ADC_CHANNEL                ADC_CHANNEL_0
#define ADC_GPIO_PIN_4             GPIO_PIN_4
#define ADC_CHANNEL4               ADC_CHANNEL_4   
#define ADC_GPIO_PIN_5             GPIO_PIN_5
#define ADC_CHANNEL5               ADC_CHANNEL_5
#define ADC_NUMOFCHANNEL            2

//#define ADC_GPIO_PIN               GPIO_PIN_1
//#define ADC_CHANNEL                ADC_CHANNEL_11
/****À©Õ¹±äÁ¿***************************************/
extern ADC_HandleTypeDefhadcx;

extern DMA_HandleTypeDefdma_adcx;

void MX_ADCx_Init(void);

void ADCx_Start(void);
#endifbsp_adc.c代码如下:
#include "bsp_adc.h"

ADC_HandleTypeDefhadcx;
DMA_HandleTypeDefhdma_adcx;

void MX_ADCx_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
       
//ADC初始化配置
hadcx.Instance = ADCx;//Resiger base adress
// ADC_InitTypeDef   Init
hadcx.Init.ScanConvMode = ADC_SCAN_ENABLE;//ÊÇ·ñʹÓÃɨÃèģʽ
hadcx.Init.ContinuousConvMode = ENABLE;//µ¥Ò»/Á¬Ðø×ª»»Ä£Ê½
hadcx.Init.DiscontinuousConvMode = DISABLE;//Ö»ÔÚContinuousConvMode = DISABLEÊDzÅÓÐЧ£¬·ñÔòÅׯú
hadcx.Init.ExternalTrigConv = ADC_SOFTWARE_START;// ²»ÓÃÍⲿ´¥·¢×ª»»£¬Èí¼þ¿ªÆô¼´¿É
hadcx.Init.DataAlign = ADC_DATAALIGN_RIGHT;//ת»»½á¹ûÓÒ¶ÔÆë
hadcx.Init.NbrOfConversion = ADC_NUMOFCHANNEL;//¼ä¶ÏģʽÖÐÒ»¸ö×éµÄͨµÀÊýÄ¿

       
if(HAL_ADC_Init(&hadcx) != HAL_OK)//¼ÓÔØADCÊôÐÔ
{ while(1){HAL_Delay(1000);}
}


//采样信道配置

//PIN ->A4Channel 4
sConfig.Channel = ADC_CHANNEL4;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;//²ÉÑùʱ¼ä
if(HAL_ADC_ConfigChannel(&hadcx,&sConfig) != HAL_OK){
while(1){HAL_Delay(1000);}
}

//PIN ->A5 Channel 5
sConfig.Channel = ADC_CHANNEL_5;
sConfig.Rank = 2;

if(HAL_ADC_ConfigChannel(&hadcx,&sConfig) != HAL_OK){
while(1){HAL_Delay(1000);}
}
}


void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct;
       
if(hadc->Instance==ADCx)
{
    /*时钟使能*/
    ADCx_RCC_CLK_ENABLE();
   
    /* ADC引脚始终初始化*/
    ADC_GPIO_CLK_ENABLE();
   
    /* AD转换引脚配置 */
   
                GPIO_InitStruct.Pin = ADC_GPIO_PIN_4|ADC_GPIO_PIN_5;
                GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
                GPIO_InitStruct.Pull = GPIO_NOPULL;
                HAL_GPIO_Init(ADC_GPIO,&GPIO_InitStruct);
               
//                GPIO_InitStruct.Pin = ADC_GPIO_PIN_5;
//    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
//                GPIO_InitStruct.Pull = GPIO_NOPULL;
//    HAL_GPIO_Init(ADC_GPIO, &GPIO_InitStruct);
               
                /* DMA初始化 */
    hdma_adcx.Instance = ADC_DMAx_CHANNELn;
    hdma_adcx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adcx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adcx.Init.MemInc = DMA_MINC_ENABLE;
                //ÈôÏëÒªDMA»ñÈ¡µÄ½öΪADC1 µÄÖµ
    hdma_adcx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;       
    hdma_adcx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adcx.Init.Mode = DMA_CIRCULAR;
    hdma_adcx.Init.Priority = DMA_PRIORITY_MEDIUM;

    HAL_DMA_Init(&hdma_adcx);
   
                /* 连接DMA */
    __HAL_LINKDMA(hadc,DMA_Handle,hdma_adcx);
   
                /*ÍâÉèÖжÏÓÅÏȼ¶ÅäÖúÍʹÄÜÖÐ¶Ï */
   //HAL_NVIC_SetPriority(ADCx_IRQ, 1, 0);
   // HAL_NVIC_EnableIRQ(ADCx_IRQ);
       
       //HAL_NVIC_SetPriority(ADC_DMAx_CHANNELn_IRQn, 5, 0);
   //HAL_NVIC_EnableIRQ(ADC_DMAx_CHANNELn_IRQn);
               
//                /*ÉèÖÃADCУ׼*/
//                HAL_ADCEx_Calibration_Start(&hadcx);
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance==ADCx||hadc->Instance == ADC2)
{
    /* 禁用ADC外设时钟 */
    ADCx_RCC_CLK_DISABLE();

    /* ADC转换引脚反初始化 */
    HAL_GPIO_DeInit(ADC_GPIO, ADC_GPIO_PIN_5|ADC_GPIO_PIN_4);
   
    /* ½ ½ûÓÃÍâÉèÖÐ¶Ï */
    HAL_NVIC_DisableIRQ(ADCx_IRQ);
                HAL_DMA_DeInit(hadc->DMA_Handle);

}
} mian函数代码如下:
int main(void)
{
/* STM32F103xB HAL library initialization:
       - Configure the Flash prefetch
       - Systick timer is configured by default as source of time base, but user
         can eventually implement his proper time base source (a general purpose
         timer for example or other time source), keeping in mind that Time base
         duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
         handled in milliseconds basis.
       - Set NVIC Group Priority to 4
       - Low Level Initialization
   */
HAL_Init();

/* Configure the system clock to 64 MHz */
SystemClock_Config();

/* Configure LED2 */
//BSP_LED_Init(LED2);

bsp_led_init();
__HAL_RCC_GPIOA_CLK_ENABLE();
   __HAL_RCC_DMA1_CLK_ENABLE();
       HAL_NVIC_SetPriority(ADC_DMAx_CHANNELn_IRQn, 5, 0);
   HAL_NVIC_EnableIRQ(ADC_DMAx_CHANNELn_IRQn);
       
       MX_ADCx_Init(); //开启ADC
printf("ADC - DMA ¶àÐŵÀÊý¾Ý²É¼¯\n");
if( HAL_ADC_Start_DMA(&hadcx,uhADCxConvertedValue,ADC_NUMOFCHANNEL) != HAL_OK){
    printf("ADC_Start_DMA() Error!\n");
}

while(1){
       //HAL_Delay(1000);
       printf("Channel 1: %d\nChannel 2:%d\n",uhADCxConvertedValue,uhADCxConvertedValue);
}但是现在无法获取数据,获得的数据均为0,不知道如何解决。

feixiang20 发表于 2018-8-9 23:20:41

先检查下硬件连接

电子星辰 发表于 2018-8-10 09:48:57

1、HAL_ADC_Start_DMA之前好像没有加校验,HAL_ADCEx_Calibration_Start(&hadc1);
2、配置是用的半字传输,uhADCxConvertedValue这个变量不知道你是定义的什么类型;最好定义16位int,然后用的时候强制转换;
3、ADC_Start_DMA()这个函数是做什么的?不知道你用uhADCxConvertedValue的时候有没有取低12位有效数据?
页: [1]
查看完整版本: STM32F1系列实现ADC多信道采样