From 2fd672a09895d2796c897099d1a018f9a2e4c3a3 Mon Sep 17 00:00:00 2001 From: "lxbpxylps@126.com" Date: Tue, 28 Sep 2021 14:26:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=20ADC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- System/adc/adc.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++ System/adc/adc.h | 10 +++ 2 files changed, 180 insertions(+) create mode 100644 System/adc/adc.c create mode 100644 System/adc/adc.h diff --git a/System/adc/adc.c b/System/adc/adc.c new file mode 100644 index 0000000..c5d8adb --- /dev/null +++ b/System/adc/adc.c @@ -0,0 +1,170 @@ +//ADC 库 + +#include "sys.h" +#include "tim.h" + +#include "adc.h" + +//32 字节对齐 +ALIGN_32BYTES(uint16_t __attribute__((section(".RAM_D3"))) ADCxValues[2]); + +/** + * @brief ADC 初始化函数 + */ +void ADC_Init(void) +{ + ADC_HandleTypeDef AdcHandle = {0}; + DMA_HandleTypeDef DMA_Handle = {0}; + ADC_ChannelConfTypeDef sConfig = {0}; + GPIO_InitTypeDef GPIO_InitStruct; + + //配置时钟 + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC; + PeriphClkInitStruct.PLL2.PLL2M = 25; + PeriphClkInitStruct.PLL2.PLL2N = 504; + PeriphClkInitStruct.PLL2.PLL2P = 7; + PeriphClkInitStruct.PLL2.PLL2Q = 7; + PeriphClkInitStruct.PLL2.PLL2R = 7; + PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_0; + PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE; + PeriphClkInitStruct.PLL2.PLL2FRACN = 0; + PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(__FILE__, __LINE__); + } + + //GPIO + __HAL_RCC_GPIOC_CLK_ENABLE(); + + GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + //DMA + __HAL_RCC_DMA1_CLK_ENABLE(); + DMA_Handle.Instance = DMA1_Stream1; //使用的DMA1 Stream1 + DMA_Handle.Init.Request = DMA_REQUEST_ADC3; //请求类型采用 DMA_REQUEST_ADC3 + DMA_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY; //传输方向是从存储器到外设 + DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE; //外设地址自增禁止 + DMA_Handle.Init.MemInc = DMA_MINC_ENABLE; //存储器地址自增使能 + DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //外设数据传输位宽选择半字,即 16bit + DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //存储器数据传输位宽选择半字,即 16bit + DMA_Handle.Init.Mode = DMA_CIRCULAR; //循环模式 + DMA_Handle.Init.Priority = DMA_PRIORITY_LOW; //优先级低 + DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; //禁止 FIFO + DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE; + DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE; + + if (HAL_DMA_Init(&DMA_Handle) != HAL_OK) + { + Error_Handler(__FILE__, __LINE__); + } + + //关联 ADC 句柄和 DMA 句柄 + __HAL_LINKDMA(&AdcHandle, DMA_Handle, DMA_Handle); + + //配置 ADC + __HAL_RCC_ADC3_CLK_ENABLE(); + AdcHandle.Instance = ADC3; + AdcHandle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV8; //采用PLL异步时钟,8分频,即 72MHz / 8 = 36MHz + AdcHandle.Init.Resolution = ADC_RESOLUTION_16B; //16 位分辨率 + AdcHandle.Init.ScanConvMode = ADC_SCAN_ENABLE; //开启扫描 + AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; //EOC 转换结束标志 + AdcHandle.Init.LowPowerAutoWait = DISABLE; //禁止低功耗自动延迟特性 + AdcHandle.Init.ContinuousConvMode = ENABLE; //启用自动转换 + AdcHandle.Init.NbrOfConversion = 2; //使用了 2 个转换通道 + AdcHandle.Init.DiscontinuousConvMode = DISABLE; //禁止不连续模式 + AdcHandle.Init.NbrOfDiscConversion = 1; //禁止不连续模式后,此参数忽略,此位是用来配置不连续子组中通道数 + AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START; //采用软件触发 + AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; //采用软件触发的话,此位忽略 + AdcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; //DMA 循环模式接收 ADC 转换的数据 + AdcHandle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; //ADC 转换溢出的话,覆盖 ADC 的数据寄存器 + AdcHandle.Init.OversamplingMode = DISABLE; //禁止过采样 + + //初始化 ADC + if (HAL_ADC_Init(&AdcHandle) != HAL_OK) + { + Error_Handler(__FILE__, __LINE__); + } + + //校准 ADC,采用偏移校准 + if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK) + { + Error_Handler(__FILE__, __LINE__); + } + + //序列 1,采样 PC0 引脚 + sConfig.Channel = ADC_CHANNEL_10; + sConfig.Rank = ADC_REGULAR_RANK_1; + sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5; //采样周期 + sConfig.SingleDiff = ADC_SINGLE_ENDED; //单端输入 + sConfig.OffsetNumber = ADC_OFFSET_NONE; //无偏移 + sConfig.Offset = 0; + sConfig.OffsetRightShift = DISABLE; //禁止右移 + sConfig.OffsetSignedSaturation = DISABLE; //禁止有符号饱和 + + if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK) + { + Error_Handler(__FILE__, __LINE__); + } + + //序列 2,采样 PC1 引脚 + sConfig.Channel = ADC_CHANNEL_11; + sConfig.Rank = ADC_REGULAR_RANK_2; + sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5; + sConfig.SingleDiff = ADC_SINGLE_ENDED; + sConfig.OffsetNumber = ADC_OFFSET_NONE; + sConfig.Offset = 0; + sConfig.OffsetRightShift = DISABLE; + sConfig.OffsetSignedSaturation = DISABLE; + + if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK) + { + Error_Handler(__FILE__, __LINE__); + } + + //启动 ADC 的 DMA 方式传输 + if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)ADCxValues, 2) != HAL_OK) + { + Error_Handler(__FILE__, __LINE__); + } + + //设置定时器 + TIM_Set(TIM3, 1000, 0, 0); +} + +/** + * @brief 获取 PC0 电压 + * @retval 电压,单位 V + */ +float ADC_Get_PC0(void) +{ + return ADCxValues[0] * 3.3 / 65536; +} + +/** + * @brief 获取 PC1 电压 + * @retval 电压,单位 V + */ +float ADC_Get_PC1(void) +{ + return ADCxValues[1] * 3.3 / 65536; +} + +/** + * @brief TIM3 中断处理 + */ +void TIM3_IRQHandler(void) +{ + if ((TIM3->SR & TIM_FLAG_UPDATE) != RESET) + { + //清除更新标志 + TIM3->SR = ~TIM_FLAG_UPDATE; + + SCB_InvalidateDCache_by_Addr((uint32_t *)ADCxValues, sizeof(uint32_t)); + } +} diff --git a/System/adc/adc.h b/System/adc/adc.h new file mode 100644 index 0000000..2d9cc61 --- /dev/null +++ b/System/adc/adc.h @@ -0,0 +1,10 @@ +//ADC 库 + +#ifndef __ADC_H +#define __ADC_H + +void ADC_Init(void); +float ADC_Get_PC0(void); +float ADC_Get_PC1(void); + +#endif