Files
mr-library/bsp/wch/driver/drv_adc.c

182 lines
4.7 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)
#warning "Please enable at least one ADC driver"
#endif /* !defined(MR_USING_ADC1) && !defined(MR_USING_ADC2) */
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 */
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 */
};
static struct drv_adc_data adc_drv_data[] =
{
#ifdef MR_USING_ADC1
{ADC1, RCC_APB2Periph_ADC1},
#endif /* MR_USING_ADC1 */
#ifdef MR_USING_ADC2
{ADC2, RCC_APB2Periph_ADC2},
#endif /* MR_USING_ADC2 */
};
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_InitTypeDef ADC_InitStructure = {0};
/* Configure clock */
RCC_APB2PeriphClockCmd(adc_data->clock, state);
#ifdef MR_USING_CH32V00X
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
#else
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
#endif /* MR_USING_CH32V00X */
/* Configure ADC */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(adc_data->instance, &ADC_InitStructure);
ADC_Cmd(adc_data->instance, state);
return MR_EOK;
}
static int drv_adc_channel_configure(struct mr_adc *adc, int channel, int state)
{
struct drv_adc_channel_data *adc_channel_data = drv_adc_get_channel_data(channel);
GPIO_InitTypeDef GPIO_InitStructure = {0};
/* Check channel is valid */
if (adc_channel_data == NULL)
{
return MR_EINVAL;
}
/* Configure clock */
RCC_APB2PeriphClockCmd(adc_channel_data->gpio_clock, ENABLE);
/* Configure pin */
if (adc_channel_data->port != MR_NULL)
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = adc_channel_data->pin;
GPIO_Init(adc_channel_data->port, &GPIO_InitStructure);
}
#ifndef MR_USING_CH32V00X
/* Configure temp-sensor */
if ((adc_channel_data->channel == ADC_Channel_16) || (adc_channel_data->channel == ADC_Channel_17))
{
ADC_TempSensorVrefintCmd(ENABLE);
}
#endif /* MR_USING_CH32V00X */
return MR_EOK;
}
static uint32_t drv_adc_read(struct mr_adc *adc, int channel)
{
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);
size_t i = 0;
/* Check channel is valid */
if (adc_channel_data == NULL)
{
return 0;
}
/* Read data */
#ifdef MR_USING_CH32V00X
ADC_RegularChannelConfig(adc_data->instance, adc_channel_data->channel, 1, ADC_SampleTime_15Cycles);
#else
ADC_RegularChannelConfig(adc_data->instance, adc_channel_data->channel, 1, ADC_SampleTime_13Cycles5);
#endif /* MR_USING_CH32V00X */
ADC_SoftwareStartConvCmd(adc_data->instance, ENABLE);
while (ADC_GetFlagStatus(adc_data->instance, ADC_FLAG_EOC) == RESET)
{
i++;
if (i > UINT16_MAX)
{
return 0;
}
}
ADC_ClearFlag(adc_data->instance, ADC_FLAG_EOC);
return ADC_GetConversionValue(adc_data->instance);
}
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 */
};
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 */