rt-thread-official/bsp/n32g452xx/Libraries/rt_drivers/drv_adc.c

213 lines
5.0 KiB
C

/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-08-20 breo.com first version
*/
#include <board.h>
#include "drv_adc.h"
#if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3)
#define DRV_DEBUG
#define LOG_TAG "drv.adc"
#include <drv_log.h>
struct n32_adc
{
struct rt_adc_device n32_adc_device;
ADC_Module *ADC_Handler;
char *name;
};
static struct n32_adc n32_adc_obj[] =
{
#ifdef BSP_USING_ADC1
ADC1_CONFIG,
#endif
#ifdef BSP_USING_ADC2
ADC2_CONFIG,
#endif
#ifdef BSP_USING_ADC3
ADC3_CONFIG,
#endif
};
static rt_uint32_t n32_adc_get_channel(rt_uint32_t channel)
{
rt_uint32_t n32_channel = 0;
switch (channel)
{
case 0:
n32_channel = ADC_CH_0;
break;
case 1:
n32_channel = ADC_CH_1;
break;
case 2:
n32_channel = ADC_CH_2;
break;
case 3:
n32_channel = ADC_CH_3;
break;
case 4:
n32_channel = ADC_CH_4;
break;
case 5:
n32_channel = ADC_CH_5;
break;
case 6:
n32_channel = ADC_CH_6;
break;
case 7:
n32_channel = ADC_CH_7;
break;
case 8:
n32_channel = ADC_CH_8;
break;
case 9:
n32_channel = ADC_CH_9;
break;
case 10:
n32_channel = ADC_CH_10;
break;
case 11:
n32_channel = ADC_CH_11;
break;
case 12:
n32_channel = ADC_CH_12;
break;
case 13:
n32_channel = ADC_CH_13;
break;
case 14:
n32_channel = ADC_CH_14;
break;
case 15:
n32_channel = ADC_CH_15;
break;
case 16:
n32_channel = ADC_CH_16;
break;
case 17:
n32_channel = ADC_CH_17;
break;
case 18:
n32_channel = ADC_CH_18;
break;
}
return n32_channel;
}
static rt_err_t n32_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
{
ADC_Module *n32_adc_handler;
ADC_InitType ADC_InitStructure;
RT_ASSERT(device != RT_NULL);
n32_adc_handler = device->parent.user_data;
n32_msp_adc_init(n32_adc_handler);
ADC_InitStruct(&ADC_InitStructure);
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = DISABLE;
ADC_InitStructure.ContinueConvEn = DISABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 1;
ADC_Init(n32_adc_handler, &ADC_InitStructure);
if (((n32_adc_handler == ADC1) || (n32_adc_handler == ADC2))
&& ((n32_adc_get_channel(channel) == ADC_CH_16)
|| (n32_adc_get_channel(channel) == ADC_CH_18)))
{
ADC_EnableTempSensorVrefint(ENABLE);
}
if (enabled)
{
/* Enable ADC1 */
ADC_Enable(n32_adc_handler, ENABLE);
/*Check ADC Ready*/
while (ADC_GetFlagStatusNew(n32_adc_handler, ADC_FLAG_RDY) == RESET);
/* Start ADCx calibration */
ADC_StartCalibration(n32_adc_handler);
/* Check the end of ADCx calibration */
while (ADC_GetCalibrationStatus(n32_adc_handler));
}
else
{
/* Enable ADCx */
ADC_Enable(n32_adc_handler, DISABLE);
}
return RT_EOK;
}
static rt_err_t n32_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
{
ADC_Module *n32_adc_handler;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(value != RT_NULL);
n32_adc_handler = device->parent.user_data;
/* ADCx regular channels configuration */
ADC_ConfigRegularChannel(n32_adc_handler, n32_adc_get_channel(channel), 1, ADC_SAMP_TIME_28CYCLES5);
/* Start ADCx Software Conversion */
ADC_EnableSoftwareStartConv(n32_adc_handler, ENABLE);
/* Wait for the ADC to convert */
while (ADC_GetFlagStatus(n32_adc_handler, ADC_FLAG_ENDC) == RESET);
ADC_ClearFlag(n32_adc_handler, ADC_FLAG_ENDC);
/* get ADC value */
*value = ADC_GetDat(n32_adc_handler);
return RT_EOK;
}
static const struct rt_adc_ops at_adc_ops =
{
.enabled = n32_adc_enabled,
.convert = n32_get_adc_value,
};
static int rt_hw_adc_init(void)
{
int result = RT_EOK;
int i = 0;
for (i = 0; i < sizeof(n32_adc_obj) / sizeof(n32_adc_obj[0]); i++)
{
/* register ADC device */
if (rt_hw_adc_register(&n32_adc_obj[i].n32_adc_device,
n32_adc_obj[i].name, &at_adc_ops,
n32_adc_obj[i].ADC_Handler) == RT_EOK)
{
LOG_D("%s register success", n32_adc_obj[i].name);
}
else
{
LOG_E("%s register failed", n32_adc_obj[i].name);
result = -RT_ERROR;
}
}
return result;
}
INIT_BOARD_EXPORT(rt_hw_adc_init);
#endif /* BSP_USING_ADC */