mirror of
https://github.com/WeActStudio/ArduinoCore-AT32F4.git
synced 2026-05-21 01:12:00 +00:00
256 lines
7.0 KiB
C
256 lines
7.0 KiB
C
/*
|
||
* MIT License
|
||
* Copyright (c) 2017 - 2022 _VIFEXTech
|
||
*
|
||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
* of this software and associated documentation files (the "Software"), to deal
|
||
* in the Software without restriction, including without limitation the rights
|
||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
* copies of the Software, and to permit persons to whom the Software is
|
||
* furnished to do so, subject to the following conditions:
|
||
*
|
||
* The above copyright notice and this permission notice shall be included in all
|
||
* copies or substantial portions of the Software.
|
||
*
|
||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
* SOFTWARE.
|
||
*/
|
||
#include "adc.h"
|
||
#include <stdbool.h>
|
||
|
||
#define ADC_DMA_REGMAX 18
|
||
|
||
#define IS_ADC_CHANNEL(channel) (channel <= ADC_CHANNEL_17)
|
||
|
||
/*引脚注册个数*/
|
||
static uint8_t ADC_DMA_RegCnt = 0;
|
||
|
||
/*ADC通道注册列表*/
|
||
static uint8_t ADC_DMA_RegChannelList[ADC_DMA_REGMAX] = {0};
|
||
|
||
/*ADC DMA缓存数组*/
|
||
static uint16_t ADC_DMA_ConvertedValue[ADC_DMA_REGMAX] = {0};
|
||
|
||
/**
|
||
* @brief 搜索注册列表,找出ADC通道对应的索引号
|
||
* @param ADC_Channel:ADC通道号
|
||
* @retval ADC通道注册列表对应索引号,-1:未找到对应通道号
|
||
*/
|
||
static int16_t ADC_DMA_SearchChannel(uint16_t ADC_Channel)
|
||
{
|
||
uint8_t index;
|
||
|
||
for(index = 0; index < ADC_DMA_RegCnt; index++)
|
||
{
|
||
if(ADC_Channel == ADC_DMA_RegChannelList[index])
|
||
{
|
||
return index;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* @brief ADC 配置
|
||
* @param ADCx: ADC地址
|
||
* @retval 无
|
||
*/
|
||
void ADCx_Init(adc_type* ADCx)
|
||
{
|
||
adc_base_config_type adc_base_struct;
|
||
|
||
if(ADCx == ADC1)
|
||
{
|
||
crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
|
||
}
|
||
else if(ADCx == ADC2)
|
||
{
|
||
crm_periph_clock_enable(CRM_ADC2_PERIPH_CLOCK, TRUE);
|
||
}
|
||
#ifdef ADC3
|
||
else if(ADCx == ADC3)
|
||
{
|
||
crm_periph_clock_enable(CRM_ADC3_PERIPH_CLOCK, TRUE);
|
||
}
|
||
#endif
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
crm_adc_clock_div_set(CRM_ADC_DIV_8);
|
||
adc_combine_mode_select(ADC_INDEPENDENT_MODE);
|
||
adc_base_default_para_init(&adc_base_struct);
|
||
adc_base_struct.sequence_mode = FALSE;
|
||
adc_base_struct.repeat_mode = FALSE;
|
||
adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
|
||
adc_base_struct.ordinary_channel_length = 1;
|
||
adc_base_config(ADCx, &adc_base_struct);
|
||
if (ADCx != ADC3)
|
||
adc_ordinary_conversion_trigger_set(ADCx, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
|
||
else
|
||
adc_ordinary_conversion_trigger_set(ADCx, ADC3_ORDINARY_TRIG_SOFTWARE, TRUE);
|
||
|
||
adc_enable(ADCx, TRUE);
|
||
adc_calibration_init(ADCx);
|
||
while(adc_calibration_init_status_get(ADCx));
|
||
adc_calibration_start(ADCx);
|
||
while(adc_calibration_status_get(ADCx));
|
||
}
|
||
|
||
/**
|
||
* @brief 获取 ADC 值
|
||
* @param ADCx: ADC地址
|
||
* @param ADC_Channel: ADC通道
|
||
* @retval 无
|
||
*/
|
||
uint16_t ADCx_GetValue(adc_type* ADCx, uint16_t ADC_Channel)
|
||
{
|
||
adc_ordinary_channel_set(ADCx, (adc_channel_select_type)ADC_Channel, 1, ADC_SAMPLETIME_41_5);
|
||
|
||
adc_ordinary_software_trigger_enable(ADCx, TRUE);
|
||
while(!adc_flag_get(ADCx, ADC_CCE_FLAG));
|
||
|
||
return adc_ordinary_conversion_data_get(ADCx);
|
||
}
|
||
|
||
/**
|
||
* @brief 注册需要DMA搬运的ADC通道
|
||
* @param ADC_Channel:ADC通道号
|
||
* @retval 见ADC_DMA_Res_Type
|
||
*/
|
||
ADC_DMA_Res_Type ADC_DMA_Register(uint8_t ADC_Channel)
|
||
{
|
||
/*初始化ADC通道列表*/
|
||
static bool isInit = false;
|
||
if(!isInit)
|
||
{
|
||
uint8_t i;
|
||
for(i = 0; i < ADC_DMA_REGMAX; i++)
|
||
{
|
||
ADC_DMA_RegChannelList[i] = 0xFF;
|
||
}
|
||
isInit = true;
|
||
}
|
||
|
||
/*是否是合法ADC通道*/
|
||
if(!IS_ADC_CHANNEL(ADC_Channel))
|
||
return ADC_DMA_RES_NOT_ADC_CHANNEL;
|
||
|
||
/*是否已在引脚列表重复注册*/
|
||
if(ADC_DMA_SearchChannel(ADC_Channel) != -1)
|
||
return ADC_DMA_RES_DUPLICATE_REGISTRATION;
|
||
|
||
/*是否超出最大注册个数*/
|
||
if(ADC_DMA_RegCnt >= ADC_DMA_REGMAX)
|
||
return ADC_DMA_RES_MAX_NUM_OF_REGISTRATIONS_EXCEEDED;
|
||
|
||
/*写入注册列表*/
|
||
ADC_DMA_RegChannelList[ADC_DMA_RegCnt] = ADC_Channel;
|
||
|
||
/*注册个数+1*/
|
||
ADC_DMA_RegCnt++;
|
||
|
||
return ADC_DMA_RES_OK;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取已注册的ADC DMA通道数量
|
||
* @param 无
|
||
* @retval ADC DMA通道数量
|
||
*/
|
||
uint8_t ADC_DMA_GetRegisterCount(void)
|
||
{
|
||
return ADC_DMA_RegCnt;
|
||
}
|
||
|
||
/**
|
||
* @brief ADC DMA 配置
|
||
* @param 无
|
||
* @retval 无
|
||
*/
|
||
void ADC_DMA_Init(void)
|
||
{
|
||
dma_init_type dma_init_structure;
|
||
adc_base_config_type adc_base_struct;
|
||
uint8_t index;
|
||
|
||
crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
|
||
crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
|
||
|
||
dma_reset(DMA1_CHANNEL1);
|
||
|
||
dma_default_para_init(&dma_init_structure);
|
||
dma_init_structure.buffer_size = ADC_DMA_RegCnt;
|
||
dma_init_structure.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
|
||
dma_init_structure.memory_base_addr = (uint32_t)ADC_DMA_ConvertedValue;
|
||
dma_init_structure.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
|
||
dma_init_structure.memory_inc_enable = TRUE;
|
||
dma_init_structure.peripheral_base_addr = (uint32_t) (&(ADC1->odt));
|
||
dma_init_structure.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
|
||
dma_init_structure.peripheral_inc_enable = FALSE;
|
||
dma_init_structure.priority = DMA_PRIORITY_HIGH;
|
||
dma_init_structure.loop_mode_enable = TRUE;
|
||
|
||
dma_init(DMA1_CHANNEL1, &dma_init_structure);
|
||
|
||
|
||
adc_combine_mode_select(ADC_INDEPENDENT_MODE);
|
||
adc_base_default_para_init(&adc_base_struct);
|
||
adc_base_struct.sequence_mode = FALSE;
|
||
adc_base_struct.repeat_mode = FALSE;
|
||
adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
|
||
adc_base_struct.ordinary_channel_length = 1;
|
||
adc_base_config(ADC1, &adc_base_struct);
|
||
adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
|
||
|
||
crm_adc_clock_div_set(CRM_ADC_DIV_8);
|
||
|
||
for(index = 0; index < ADC_DMA_RegCnt; index++)
|
||
{
|
||
adc_ordinary_channel_set(
|
||
ADC1,
|
||
ADC_DMA_RegChannelList[index],
|
||
index + 1,
|
||
ADC_SAMPLETIME_41_5
|
||
);
|
||
|
||
if(ADC_DMA_RegChannelList[index] == ADC_CHANNEL_16)
|
||
{
|
||
adc_tempersensor_vintrv_enable(true);
|
||
}
|
||
}
|
||
|
||
adc_dma_mode_enable(ADC1, TRUE);
|
||
|
||
adc_enable(ADC1, TRUE);
|
||
|
||
adc_calibration_init(ADC1);
|
||
while(adc_calibration_init_status_get(ADC1));
|
||
adc_calibration_start(ADC1);
|
||
while(adc_calibration_status_get(ADC1));
|
||
}
|
||
|
||
/**
|
||
* @brief 获取DMA搬运的ADC值
|
||
* @param ADC_Channel:ADC通道号
|
||
* @retval ADC值
|
||
*/
|
||
uint16_t ADC_DMA_GetValue(uint8_t ADC_Channel)
|
||
{
|
||
int16_t index;
|
||
|
||
if(!IS_ADC_CHANNEL(ADC_Channel))
|
||
return 0;
|
||
|
||
index = ADC_DMA_SearchChannel(ADC_Channel);
|
||
if(index == -1)
|
||
return 0;
|
||
|
||
return ADC_DMA_ConvertedValue[index];
|
||
}
|