STM32学习笔记【26.ADC三个小实验】
文章目录前言实验1ADC单通道采集实验1.实验目的2. 硬件清单3. 项目框图4. 构思环节5.出现的问题6. 代码展示7.实验结果实验2ADC单通道采集实验DMA读取1.实验目的2. 硬件清单3. 项目框图4. 构思环节5.出现的问题6. 代码展示7.实验结果实验3ADC多通道采集实验DMA读取1.实验目的2. 硬件清单3. 项目框图4. 构思环节5.出现的问题6. 代码展示7.实验结果总结前言本文主要做三个ADC通道采集实验分别为ADC单通道采集、ADC单通道采集DMA读取、ADC多通道采集DMA读取使用光敏电阻传感器最终实验数据采集。实验1ADC单通道采集实验1.实验目的使用ADC1采集通道1的电压值通道1连接光敏电阻传感器2. 硬件清单上官二号光敏电阻传感器ST-LinkUSB转TTL光敏电阻传感器接线VCC:3.3VGND:GNDAO:PA13. 项目框图4. 构思环节void adc_init(void){// 使用ADC1// 右对齐// 不扫描// 连续转换模式DISABLE// 转换个数1只用了一个通道// 间断模式DISABLE// 间断模式个数0// 外部触发ADC_SOFTWARE_STARTHAL_ADC_Init();// ADC校准HAL_ADCEx_Calibration_Start()}// Msp初始化NVIC、CLOCK、GPIOvoid HAL_ADC_MspInit(){// 判断是否为ADC// 打开时钟// 打开GPIO时钟// 配置GPIO//Pin1// 模式模拟量输入HAL_GPIO_Init();// 配置时钟// 配置各个参数外设时钟选择和ADC预分频器选择6分频HAL_RCCEx_PeriphCLKConfig();}// 通道配置void adc_channel_config(句柄通道位置rank采样时间stime){// 配置通道// 配置序列// 配置采样时间HAL_ADC_ConfigChannel();}// 获取值uint32_t adc_get_result(uint32_t ch){adc_channel_config();// 开启ADCHAL_ADC_Start();// 等待转换完成HAL_ADC_PollForConversion();// 获取值return HAL_ADC_GetValue();}5.出现的问题ADC初始化配置要注意voidadc_init(void){adc_handle.InstanceADC1;adc_handle.Init.DataAlignADC_DATAALIGN_RIGHT;// 采用右对齐adc_handle.Init.ScanConvModeADC_SCAN_DISABLE;// 扫描方式不扫描adc_handle.Init.ContinuousConvModeDISABLE;// 连续转换模式adc_handle.Init.NbrOfConversion1;// 转换个数1只用了一个通道// 间断模式adc_handle.Init.DiscontinuousConvModeDISABLE;// 不连续转换模式adc_handle.Init.NbrOfDiscConversion0;// 外部触发adc_handle.Init.ExternalTrigConvADC_SOFTWARE_START;HAL_ADC_Init(adc_handle);// ADC校准HAL_ADCEx_Calibration_Start(adc_handle);}6. 代码展示adc.c#includeadc.hADC_HandleTypeDef adc_handle{0};GPIO_InitTypeDef gpio_handle{0};RCC_PeriphCLKInitTypeDef periphlk_handle{0};voidadc_init(void){adc_handle.InstanceADC1;adc_handle.Init.DataAlignADC_DATAALIGN_RIGHT;adc_handle.Init.ScanConvModeADC_SCAN_DISABLE;// 扫描adc_handle.Init.ContinuousConvModeDISABLE;// 连续模式adc_handle.Init.NbrOfConversion1;// 转换个数1// 间断模式adc_handle.Init.DiscontinuousConvModeDISABLE;// 不连续转换模式adc_handle.Init.NbrOfDiscConversion0;// 外部触发adc_handle.Init.ExternalTrigConvADC_SOFTWARE_START;HAL_ADC_Init(adc_handle);// ADC校准HAL_ADCEx_Calibration_Start(adc_handle);}// Msp初始化voidHAL_ADC_MspInit(ADC_HandleTypeDef*hadc){if(hadc-InstanceADC1){// 打开时钟__HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();// 配置GPIOgpio_handle.PinGPIO_PIN_1;gpio_handle.ModeGPIO_MODE_ANALOG;gpio_handle.PullGPIO_NOPULL;HAL_GPIO_Init(GPIOA,gpio_handle);// 配置时钟periphlk_handle.PeriphClockSelectionRCC_PERIPHCLK_ADC;periphlk_handle.AdcClockSelectionRCC_ADCPCLK2_DIV6;HAL_RCCEx_PeriphCLKConfig(periphlk_handle);}}// 通道配置voidadc_channel_config(ADC_HandleTypeDef*hadc,uint32_tch,uint32_trank,uint32_tstime){ADC_ChannelConfTypeDef adc_ch_config{0};adc_ch_config.Channelch;adc_ch_config.Rankrank;adc_ch_config.SamplingTimestime;HAL_ADC_ConfigChannel(hadc,adc_ch_config);}// 获取值uint32_tadc_get_result(uint32_tch){// 通道配置adc_channel_config(adc_handle,ch,ADC_REGULAR_RANK_1,ADC_SAMPLETIME_239CYCLES_5);// 开启ADCHAL_ADC_Start(adc_handle);// 等待转换完成HAL_ADC_PollForConversion(adc_handle,10);// 获取值ADC1转换的结果放在DR寄存器的低16位// 这里强转为uint16_t就可以直接获取。// DR寄存器的高16位存放的是ADC2的转换结果return(uint16_t)HAL_ADC_GetValue(adc_handle);}adc.h#ifndef__ADC_H__#define__ADC_H__#includesys.hvoidadc_init(void);uint32_tadc_get_result(uint32_tch);#endifmain.c#includesys.h#includedelay.h#includeled.h#includeuart1.h#includeadc.hintmain(void){HAL_Init();/* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);/* 设置时钟, 72Mhz */led_init();uart1_init(115200);adc_init();printf(hello world! \r\n);while(1){printf(adc recv: %d\r\n,(uint16_t)adc_get_result(ADC_CHANNEL_1));delay_ms(1000);}}7.实验结果光照越亮电阻越小对应电压也越小// 换算成电压形式printf(adc recv: %f\r\n,(float)adc_get_result(ADC_CHANNEL_1)/4096*3.3);实验2ADC单通道采集实验DMA读取1.实验目的使用ADC1采集通道1的电压值DMA读取通道1连接光敏电阻传感器。2. 硬件清单上官二号光敏电阻传感器ST-LinkUSB转TTL3. 项目框图4. 构思环节adc初始化函数//用到DMA,所以是连续转换adc_handle.Init.ContinuousConvMode ENSABLE;dma初始化函数复制之前做过的dma初始化函数并做修改查看参考手册ADC1是通道1修改对齐方式修改成HALFWORD,因为ADC的DR寄存器是16位搬运方式是循环搬运句柄是adc成员变量为DMA_Handle5.出现的问题采集的数据不随光敏电阻传感器变化原因未打开连续转换模式adc_handle.Init.ContinuousConvModeENABLE;// 连续转换模式6. 代码展示adc.c#includeadc.hADC_HandleTypeDef adc_handle{0};DMA_HandleTypeDef dma_handle{0};GPIO_InitTypeDef gpio_handle{0};RCC_PeriphCLKInitTypeDef periphlk_handle{0};voidadc_config(void){adc_handle.InstanceADC1;adc_handle.Init.DataAlignADC_DATAALIGN_RIGHT;// 采用右对齐adc_handle.Init.ScanConvModeADC_SCAN_DISABLE;// 扫描方式不扫描adc_handle.Init.ContinuousConvModeENABLE;// 连续转换模式adc_handle.Init.NbrOfConversion1;// 转换个数1只用了一个通道// 间断模式adc_handle.Init.DiscontinuousConvModeDISABLE;// 不连续转换模式adc_handle.Init.NbrOfDiscConversion0;// 外部触发adc_handle.Init.ExternalTrigConvADC_SOFTWARE_START;HAL_ADC_Init(adc_handle);// ADC校准HAL_ADCEx_Calibration_Start(adc_handle);}voiddma_config(void){__HAL_RCC_DMA1_CLK_ENABLE();dma_handle.InstanceDMA1_Channel1;// 数据搬运方式dma_handle.Init.DirectionDMA_MEMORY_TO_MEMORY;// 内存相关配置dma_handle.Init.MemDataAlignmentDMA_MDATAALIGN_HALFWORD;dma_handle.Init.MemIncDMA_MINC_ENABLE;// 外设相关配置dma_handle.Init.PeriphDataAlignmentDMA_PDATAALIGN_HALFWORD;dma_handle.Init.PeriphIncDMA_PINC_ENABLE;dma_handle.Init.PriorityDMA_PRIORITY_MEDIUM;dma_handle.Init.ModeDMA_CIRCULAR;HAL_DMA_Init(dma_handle);__HAL_LINKDMA(adc_handle,DMA_Handle,dma_handle);}// Msp初始化voidHAL_ADC_MspInit(ADC_HandleTypeDef*hadc){if(hadc-InstanceADC1){// 打开时钟__HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();// 配置GPIOgpio_handle.PinGPIO_PIN_1;gpio_handle.ModeGPIO_MODE_ANALOG;gpio_handle.PullGPIO_NOPULL;HAL_GPIO_Init(GPIOA,gpio_handle);// 配置时钟periphlk_handle.PeriphClockSelectionRCC_PERIPHCLK_ADC;periphlk_handle.AdcClockSelectionRCC_ADCPCLK2_DIV6;HAL_RCCEx_PeriphCLKConfig(periphlk_handle);}}// 通道配置voidadc_channel_config(ADC_HandleTypeDef*hadc,uint32_tch,uint32_trank,uint32_tstime){ADC_ChannelConfTypeDef adc_ch_config{0};adc_ch_config.Channelch;adc_ch_config.Rankrank;adc_ch_config.SamplingTimestime;HAL_ADC_ConfigChannel(hadc,adc_ch_config);}voidadc_dma_init(uint32_t*mar){adc_config();adc_channel_config(adc_handle,ADC_CHANNEL_1,ADC_REGULAR_RANK_1,ADC_SAMPLETIME_239CYCLES_5);dma_config();HAL_ADC_Start_DMA(adc_handle,mar,1);}adc.h#ifndef__ADC_H__#define__ADC_H__#includesys.hvoidadc_dma_init(uint32_t*mar);#endifmain.c#includesys.h#includedelay.h#includeled.h#includeuart1.h#includeadc.huint16_tadc_result0;intmain(void){HAL_Init();/* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);/* 设置时钟, 72Mhz */led_init();uart1_init(115200);adc_dma_init((uint32_t*)adc_result);printf(hello world! \r\n);while(1){printf(adc recv: %f\r\n,(float)adc_result/4096*3.3);delay_ms(1000);}}7.实验结果实验3ADC多通道采集实验DMA读取1.实验目的使用ADC1采集通道0~3的电压值DMA读取通道1连接光敏电阻传感器。2. 硬件清单上官二号光敏电阻传感器ST-LinkUSB转TTL3. 项目框图与实验2一样4. 构思环节修改扫描模式ENABLE如果不扫描永远只测一个通道设置4通道adc_handle.Init.NbrOfConversion 4; // 转换个数4用了4个通道HAL_ADC_Start_DMA(adc_handle, mar, 4);adc_channel_config();4个通道都要写上GPIO口的引脚有4个GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3main.c修改5.出现的问题问题只采集到第一个通道的电压解决adc_handle.Init.NbrOfConversion 4; // 转换个数4用了4个通道// 外设配置dma_handle.Init.PeriphInc DMA_PINC_DISABLE;6. 代码展示多通道在实验2基础上修改adc.cadc_config修改voidadc_config(void){adc_handle.Init.ScanConvModeADC_SCAN_ENABLE;// 扫描方式扫描adc_handle.Init.ContinuousConvModeENABLE;// 连续转换模式adc_handle.Init.NbrOfConversion4;// 转换个数4用了4个通道}dma_config修改voiddma_config(void){// 数据搬运方式dma_handle.Init.DirectionDMA_PERIPH_TO_MEMORY;// 内存相关配置dma_handle.Init.MemDataAlignmentDMA_MDATAALIGN_HALFWORD;dma_handle.Init.MemIncDMA_MINC_ENABLE;// 外设相关配置dma_handle.Init.PeriphDataAlignmentDMA_PDATAALIGN_HALFWORD;dma_handle.Init.PeriphIncDMA_PINC_DISABLE;dma_handle.Init.PriorityDMA_PRIORITY_MEDIUM;dma_handle.Init.ModeDMA_CIRCULAR;HAL_DMA_Init(dma_handle);__HAL_LINKDMA(adc_handle,DMA_Handle,dma_handle);}HAL_ADC_MspInit修改处voidHAL_ADC_MspInit(ADC_HandleTypeDef*hadc){if(hadc-InstanceADC1){// 配置GPIOgpio_handle.PinGPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;gpio_handle.ModeGPIO_MODE_ANALOG;}}adc_dma_init修改处voidadc_dma_init(uint32_t*mar){adc_config();adc_channel_config(adc_handle,ADC_CHANNEL_0,ADC_REGULAR_RANK_1,ADC_SAMPLETIME_239CYCLES_5);adc_channel_config(adc_handle,ADC_CHANNEL_1,ADC_REGULAR_RANK_2,ADC_SAMPLETIME_239CYCLES_5);adc_channel_config(adc_handle,ADC_CHANNEL_2,ADC_REGULAR_RANK_3,ADC_SAMPLETIME_239CYCLES_5);adc_channel_config(adc_handle,ADC_CHANNEL_3,ADC_REGULAR_RANK_4,ADC_SAMPLETIME_239CYCLES_5);dma_config();HAL_ADC_Start_DMA(adc_handle,mar,4);}main.c#includesys.h#includedelay.h#includeled.h#includeuart1.h#includeadc.huint16_tadc_result[4]{0};intmain(void){HAL_Init();/* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);/* 设置时钟, 72Mhz */led_init();uart1_init(115200);adc_dma_init((uint32_t*)adc_result);printf(hello world! \r\n);while(1){printf(通道0电压: %f\r\n,(float)adc_result[0]/4096*3.3);printf(通道1电压: %f\r\n,(float)adc_result[1]/4096*3.3);printf(通道2电压: %f\r\n,(float)adc_result[2]/4096*3.3);printf(通道3电压: %f\r\n\r\n,(float)adc_result[3]/4096*3.3);delay_ms(1000);}}7.实验结果通道2AO口接到PA2手靠近D2红灯慢慢变暗电压越大。通道3AO口接到PA3手靠近D4蓝灯慢慢变暗电压越大。总结三个ADC采集实验了解到如何用ADC采集数据且用DMA读取数据实现单通道或多通道采集ADC进行数据转换最终接收数据。