195 lines
5.4 KiB
C
195 lines
5.4 KiB
C
/*
|
|
* @copyright (c) 2023-2024, MR Development Team
|
|
*
|
|
* @license SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* @date 2023-11-11 MacRsh First version
|
|
*/
|
|
|
|
#include "drv_adc.h"
|
|
|
|
#ifdef MR_USING_ADC
|
|
|
|
#if !defined(MR_USING_ADC1) && !defined(MR_USING_ADC2) && !defined(MR_USING_ADC3)
|
|
#warning "Please enable at least one ADC driver"
|
|
#endif /* !defined(MR_USING_ADC1) && !defined(MR_USING_ADC2) && !defined(MR_USING_ADC3) */
|
|
|
|
enum drv_adc_index
|
|
{
|
|
#ifdef MR_USING_ADC1
|
|
DRV_INDEX_ADC1,
|
|
#endif /* MR_USING_ADC1 */
|
|
#ifdef MR_USING_ADC2
|
|
DRV_INDEX_ADC2,
|
|
#endif /* MR_USING_ADC2 */
|
|
#ifdef MR_USING_ADC3
|
|
DRV_INDEX_ADC3,
|
|
#endif /* MR_USING_ADC3 */
|
|
DRV_INDEX_ADC_MAX
|
|
};
|
|
|
|
static const char *adc_path[] =
|
|
{
|
|
#ifdef MR_USING_ADC1
|
|
"adc1",
|
|
#endif /* MR_USING_ADC1 */
|
|
#ifdef MR_USING_ADC2
|
|
"adc2",
|
|
#endif /* MR_USING_ADC2 */
|
|
#ifdef MR_USING_ADC3
|
|
"adc3",
|
|
#endif /* MR_USING_ADC3 */
|
|
};
|
|
|
|
static struct drv_adc_data adc_drv_data[] =
|
|
{
|
|
#ifdef MR_USING_ADC1
|
|
{{0}, ADC1},
|
|
#endif /* MR_USING_ADC1 */
|
|
#ifdef MR_USING_ADC2
|
|
{{0}, ADC2},
|
|
#endif /* MR_USING_ADC2 */
|
|
#ifdef MR_USING_ADC3
|
|
{{0}, ADC3},
|
|
#endif /* MR_USING_ADC3 */
|
|
};
|
|
|
|
static struct drv_adc_channel_data adc_channel_drv_data[] = DRV_ADC_CHANNEL_CONFIG;
|
|
|
|
static struct mr_adc adc_dev[MR_ARRAY_NUM(adc_drv_data)];
|
|
|
|
static struct drv_adc_channel_data *drv_adc_get_channel_data(int channel)
|
|
{
|
|
if (channel >= MR_ARRAY_NUM(adc_channel_drv_data))
|
|
{
|
|
return NULL;
|
|
}
|
|
return &adc_channel_drv_data[channel];
|
|
}
|
|
|
|
static int drv_adc_configure(struct mr_adc *adc, int state)
|
|
{
|
|
struct drv_adc_data *adc_data = (struct drv_adc_data *)adc->dev.drv->data;
|
|
adc_data->handle.Instance = adc_data->instance;
|
|
|
|
if (state == ENABLE)
|
|
{
|
|
/* Configure ADC */
|
|
#if defined(ADC_RESOLUTION_12B)
|
|
adc_data->handle.Init.Resolution = ADC_RESOLUTION_12B;
|
|
#elif defined(ADC_RESOLUTION_10B)
|
|
adc_data->handle.Init.Resolution = ADC_RESOLUTION_10B;
|
|
#elif defined(ADC_RESOLUTION_8B)
|
|
adc_data->handle.Init.Resolution = ADC_RESOLUTION_8B;
|
|
#endif /* defined(ADC_RESOLUTION_12B) */
|
|
adc_data->handle.Init.ScanConvMode = DISABLE;
|
|
adc_data->handle.Init.ContinuousConvMode = DISABLE;
|
|
adc_data->handle.Init.DiscontinuousConvMode = DISABLE;
|
|
adc_data->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
|
|
adc_data->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
|
|
adc_data->handle.Init.NbrOfConversion = 1;
|
|
#if defined(ADC_EOC_SINGLE_CONV)
|
|
adc_data->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
|
|
#endif /* defined(ADC_EOC_SINGLE_CONV) */
|
|
HAL_ADC_Init(&adc_data->handle);
|
|
} else
|
|
{
|
|
/* Configure ADC */
|
|
HAL_ADC_DeInit(&adc_data->handle);
|
|
}
|
|
return MR_EOK;
|
|
}
|
|
|
|
static int drv_adc_channel_configure(struct mr_adc *adc, int channel, int state)
|
|
{
|
|
return MR_EOK;
|
|
}
|
|
|
|
static int drv_adc_read(struct mr_adc *adc, int channel, uint32_t *data)
|
|
{
|
|
struct drv_adc_data *adc_data = (struct drv_adc_data *)adc->dev.drv->data;
|
|
struct drv_adc_channel_data *adc_channel_data = drv_adc_get_channel_data(channel);
|
|
ADC_ChannelConfTypeDef sConfig = {0};
|
|
|
|
#ifdef MR_USING_ADC_CHANNEL_CHECK
|
|
/* Check channel is valid */
|
|
if (adc_channel_data == NULL)
|
|
{
|
|
return MR_EINVAL;
|
|
}
|
|
#endif /* MR_USING_ADC_CHANNEL_CHECK */
|
|
|
|
/* Read data */
|
|
sConfig.Channel = adc_channel_data->channel;
|
|
sConfig.Rank = 1;
|
|
#if defined(ADC_SAMPLETIME_55CYCLES_5)
|
|
sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
|
|
#elif defined(ADC_SAMPLETIME_56CYCLES)
|
|
sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
|
|
#elif defined(ADC_SAMPLETIME_71CYCLES_5)
|
|
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
|
|
#elif defined(ADC_SAMPLETIME_84CYCLES)
|
|
sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES;
|
|
#elif defined(ADC_SAMPLETIME_112CYCLES)
|
|
sConfig.SamplingTime = ADC_SAMPLETIME_112CYCLES;
|
|
#elif defined(ADC_SAMPLETIME_144CYCLES)
|
|
sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES;
|
|
#elif defined(ADC_SAMPLETIME_239CYCLES_5)
|
|
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
|
|
#elif defined(ADC_SAMPLETIME_247CYCLES_5)
|
|
sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
|
|
#elif defined(ADC_SAMPLETIME_480CYCLES)
|
|
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
|
|
#endif /* defined(ADC_SAMPLETIME_55CYCLES_5) */
|
|
HAL_ADC_ConfigChannel(&adc_data->handle, &sConfig);
|
|
HAL_ADC_Start(&adc_data->handle);
|
|
if (HAL_ADC_PollForConversion(&adc_data->handle, UINT16_MAX) == HAL_OK)
|
|
{
|
|
*data = HAL_ADC_GetValue(&adc_data->handle);
|
|
HAL_ADC_Stop(&adc_data->handle);
|
|
return MR_EOK;
|
|
}
|
|
HAL_ADC_Stop(&adc_data->handle);
|
|
return MR_ETIMEOUT;
|
|
}
|
|
|
|
static struct mr_adc_ops adc_drv_ops =
|
|
{
|
|
drv_adc_configure,
|
|
drv_adc_channel_configure,
|
|
drv_adc_read
|
|
};
|
|
|
|
static struct mr_drv adc_drv[] =
|
|
{
|
|
#ifdef MR_USING_ADC1
|
|
{
|
|
&adc_drv_ops,
|
|
&adc_drv_data[DRV_INDEX_ADC1],
|
|
},
|
|
#endif /* MR_USING_ADC1 */
|
|
#ifdef MR_USING_ADC2
|
|
{
|
|
&adc_drv_ops,
|
|
&adc_drv_data[DRV_INDEX_ADC2],
|
|
},
|
|
#endif /* MR_USING_ADC2 */
|
|
#ifdef MR_USING_ADC3
|
|
{
|
|
&adc_drv_ops,
|
|
&adc_drv_data[DRV_INDEX_ADC3],
|
|
},
|
|
#endif /* MR_USING_ADC3 */
|
|
};
|
|
|
|
static void drv_adc_init(void)
|
|
{
|
|
for (size_t i = 0; i < MR_ARRAY_NUM(adc_dev); i++)
|
|
{
|
|
mr_adc_register(&adc_dev[i], adc_path[i], &adc_drv[i]);
|
|
}
|
|
}
|
|
MR_INIT_DRV_EXPORT(drv_adc_init);
|
|
|
|
#endif /* MR_USING_ADC */
|