#include "stm32f1xx_hal.h"
#include "adc.h"
ADC_HandleTypeDef adc1_handle; //包含ADC所有属性(ADC句柄)
ADC_TypeDef adc1_Type; //包含ADC控制寄存器
DMA_Channel_TypeDef dma1_channel; //包含DMA控制寄存器
DMA_HandleTypeDef dma1_handle; //包含DMA的所有属性(DMA句柄)
uint8_t adc_dma_sta; //DMA是否搬运完成的状态位
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc);
/**
* @brief 初始化ADC
* @param 无
* @retval 无
*/
void adc_init(uint32_t mar)
{
ADC_ChannelConfTypeDef adc_ch_config;
adc_dma_init(); //初始化DMA(DMA初始化+DMA-ADC句柄连接)
HAL_ADC_MspInit(&adc1_handle);
//ADC工作参数 配置
adc1_handle.Instance = ADC1; //实例(寄存器基地址)
adc1_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐
adc1_handle.Init.ScanConvMode = ADC_SCAN_ENABLE; //扫描模式(多通道)
adc1_handle.Init.ContinuousConvMode = ENABLE ; //连续模式(另一种是单次模式)
adc1_handle.Init.NbrOfConversion = 4; //转换通道数目
adc1_handle.Init.DiscontinuousConvMode = DISABLE; //禁用间断模式
adc1_handle.Init.NbrOfDiscConversion = 0; //间断模式通道转换次数
adc1_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发
HAL_ADC_Init(&adc1_handle); //默认初始化函数,初始化adc
HAL_ADCEx_Calibration_Start(&adc1_handle); //数据校准
//ADC相关通道的相关参数(多通道有几个通道就要配置几个)
adc_ch_config.Channel = ADC_CHANNEL_0; //通道选择0
adc_ch_config.Rank = ADC_REGULAR_RANK_1; //通道排名序列1
adc_ch_config.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; //采样时间
HAL_ADC_ConfigChannel(&adc1_handle,&adc_ch_config); //配置 ADC 通道的相关参数
adc_ch_config.Channel = ADC_CHANNEL_1; //通道选择1
adc_ch_config.Rank = ADC_REGULAR_RANK_2; //通道排名序列2
HAL_ADC_ConfigChannel(&adc1_handle,&adc_ch_config); //配置 ADC 通道的相关参数
adc_ch_config.Channel = ADC_CHANNEL_2; //通道选择2
adc_ch_config.Rank = ADC_REGULAR_RANK_3; //通道排名序列3
HAL_ADC_ConfigChannel(&adc1_handle,&adc_ch_config); //配置 ADC 通道的相关参数
adc_ch_config.Channel = ADC_CHANNEL_3; //通道选择3
adc_ch_config.Rank = ADC_REGULAR_RANK_4; //通道排名序列4
HAL_ADC_ConfigChannel(&adc1_handle,&adc_ch_config); //配置 ADC 通道的相关参数
//DMA中断
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,3,3); //设置DMA中断优先级
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); //使能DMA中断
//DMA开启
HAL_DMA_Start_IT(&dma1_handle,(uint32_t)&ADC1->DR,mar,0); //DMA的搬运目的地址确定
HAL_ADC_Start_DMA(&adc1_handle,&mar,0); //触发ADC转换,使用DMA传输数据
}
/**
* @brief 初始化DMA
* @param 无
* @retval 无
*/
void adc_dma_init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE(); //开启DMA1的时钟
dma1_handle.Instance = DMA1_Channel1; //使用的DMA通道1
dma1_handle.Init.Direction = DMA_PERIPH_TO_MEMORY; //外存到内设
dma1_handle.Init.PeriphInc = DMA_PINC_DISABLE; //外设地址寄存器不递增--固定
dma1_handle.Init.MemInc = DMA_MINC_ENABLE; //内存地址寄存器自动递增,不递增的话若有新数据来就会直接在这个基础上直接覆盖
dma1_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //外设数据宽度--半字
dma1_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //内存数据宽度--半字
dma1_handle.Init.Mode = DMA_NORMAL ; //正常模式(循环模式仅当“内存到内存”的情况下才使用)
dma1_handle.Init.Priority = DMA_PRIORITY_MEDIUM; //优先级--中等
HAL_DMA_Init(&dma1_handle);
__HAL_LINKDMA(&adc1_handle,DMA_Handle,dma1_handle); //ADC-DMA关联函数(三个参数分别为:adc句柄,adc结构体内dma名称,dma句柄)
}
/**
* @brief 初始化ADC外设的硬件资源
* @param ADC_HandleTypeDef* hadc(ADC句柄)
* @retval 无
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
//GPI0配置
GPIO_InitTypeDef gpio_init_struct; //GPIO句柄
__HAL_RCC_GPIOC_CLK_ENABLE(); //IO口PC时钟使能
gpio_init_struct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3; //多通道的时候都需要初始化
gpio_init_struct.Mode = GPIO_MODE_ANALOG; //模拟功能
HAL_GPIO_Init(GPIOC, &gpio_init_struct); //GPIO配置完成,调用默认初始化函数
//ADC配置--时钟
RCC_PeriphCLKInitTypeDef adc_clk_init = {0}; //结构体用于配置 STM32 微控制器的外设时钟
adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC; //时钟源为ADC
adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6; //ADC的分频系数
HAL_RCCEx_PeriphCLKConfig(&adc_clk_init); //时钟分频函数(根据传入的参数配置各种外设的时钟)
}
}
/**
* @brief 获取ADC转换后的结果
* @param 无
* @retval 无
*/
uint32_t adc_get_result(void)
{
HAL_ADC_Start(&adc1_handle); //ADC转化开始
HAL_ADC_PollForConversion(&adc1_handle,10); //10ms //等待读取结束,此时的ADC1数据寄存器中就有值了
return (uint16_t)HAL_ADC_GetValue(&adc1_handle); //读取数据寄存器中的值
}
/**
* @brief 使能一次ADC-DMA传输函数
* @param uint16_t cndtr
* @retval 无
*/
void adc_dma_enable(uint16_t cndtr)
{
ADC1->CR2 &= ~(1<<0); //停止ADC的工作(寄存器操作)
DMA1_Channel1->CCR &= ~(1<<0); //停止DMA的工作(寄存器操作)
while(DMA1_Channel1->CCR & (1<<0)); //寄存器位是否为0,通道是否关闭
DMA1_Channel1->CNDTR = cndtr; //DMA通道1传输数量寄存器
DMA1_Channel1->CCR |= (1<<0); //开启DMA
ADC1->CR2 |= (1<<0); //开启ADC
ADC1->CR2 |= 1<<22; //开启转化规则通道
/****第2种方法,直接用宏定义函数
__HAL_ADC_DISABLE(&adc1_handle); //宏停止ADC
__HAL_DMA_DISABLE(&dma1_handle); //宏停止DMA
while(__HAL_DMA_GET_FLAG(&dma1_handle,__HAL_DMA_GET_TC_FLAG_INDEX(&dma1_handle)));
DMA1_Channel1->CNDTR = cndtr; //DMA通道1传输数量寄存器
__HAL_DMA_ENABLE(&dma1_handle);
__HAL_ADC_ENABLE(&adc1_handle);
HAL_ADC_Start(&adc1_handle);
****/
}