2021-09-28 14:26:28 +08:00

171 lines
6.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//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));
}
}