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

182 lines
4.7 KiB
C
Raw Normal View History

2023-11-12 00:33:40 +08:00
/*
2024-01-02 00:02:48 +08:00
* @copyright (c) 2023-2024, MR Development Team
2023-11-12 00:33:40 +08:00
*
* @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
2023-11-12 00:33:40 +08:00
{
#ifdef MR_USING_ADC1
DRV_INDEX_ADC1,
#endif /* MR_USING_ADC1 */
#ifdef MR_USING_ADC2
DRV_INDEX_ADC2,
#endif /* MR_USING_ADC2 */
2024-01-13 03:12:09 +08:00
DRV_INDEX_ADC_MAX
2023-11-12 00:33:40 +08:00
};
static const char *adc_path[] =
2023-11-12 00:33:40 +08:00
{
#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 */
};
2023-12-11 18:02:38 +08:00
static struct drv_adc_channel_data adc_channel_drv_data[] = DRV_ADC_CHANNEL_CONFIG;
2023-11-12 00:33:40 +08:00
2023-12-31 16:32:35 +08:00
static struct mr_adc adc_dev[MR_ARRAY_NUM(adc_drv_data)];
2023-11-12 00:33:40 +08:00
static struct drv_adc_channel_data *drv_adc_get_channel_data(int channel)
{
2023-12-31 16:32:35 +08:00
if (channel >= MR_ARRAY_NUM(adc_channel_drv_data))
2023-11-12 00:33:40 +08:00
{
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);
2023-12-11 18:02:38 +08:00
#ifdef MR_USING_CH32V00X
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
#else
2023-11-12 00:33:40 +08:00
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
2023-12-11 18:02:38 +08:00
#endif /* MR_USING_CH32V00X */
2023-11-12 00:33:40 +08:00
/* 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);
2023-11-12 00:33:40 +08:00
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);
}
2023-12-11 18:02:38 +08:00
#ifndef MR_USING_CH32V00X
2023-11-12 00:33:40 +08:00
/* Configure temp-sensor */
if ((adc_channel_data->channel == ADC_Channel_16) || (adc_channel_data->channel == ADC_Channel_17))
{
ADC_TempSensorVrefintCmd(ENABLE);
2023-11-12 00:33:40 +08:00
}
2023-12-11 18:02:38 +08:00
#endif /* MR_USING_CH32V00X */
2023-11-12 00:33:40 +08:00
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);
2024-01-13 03:12:09 +08:00
size_t i = 0;
2023-11-12 00:33:40 +08:00
/* Check channel is valid */
if (adc_channel_data == NULL)
{
2023-12-09 00:18:16 +08:00
return 0;
2023-11-12 00:33:40 +08:00
}
/* Read data */
2023-12-11 18:02:38 +08:00
#ifdef MR_USING_CH32V00X
2024-01-13 03:12:09 +08:00
ADC_RegularChannelConfig(adc_data->instance, adc_channel_data->channel, 1, ADC_SampleTime_15Cycles);
2023-12-11 18:02:38 +08:00
#else
2024-01-13 03:12:09 +08:00
ADC_RegularChannelConfig(adc_data->instance, adc_channel_data->channel, 1, ADC_SampleTime_13Cycles5);
2023-12-11 18:02:38 +08:00
#endif /* MR_USING_CH32V00X */
2023-11-12 00:33:40 +08:00
ADC_SoftwareStartConvCmd(adc_data->instance, ENABLE);
while (ADC_GetFlagStatus(adc_data->instance, ADC_FLAG_EOC) == RESET)
{
i++;
2024-01-13 03:12:09 +08:00
if (i > UINT16_MAX)
2023-11-12 00:33:40 +08:00
{
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
};
2023-11-30 22:13:07 +08:00
static struct mr_drv adc_drv[] =
2023-11-12 00:33:40 +08:00
{
#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)
2023-11-12 00:33:40 +08:00
{
2024-01-13 03:12:09 +08:00
for (size_t i = 0; i < MR_ARRAY_NUM(adc_dev); i++)
2023-11-12 00:33:40 +08:00
{
mr_adc_register(&adc_dev[i], adc_path[i], &adc_drv[i]);
2023-11-12 00:33:40 +08:00
}
}
2023-12-31 16:32:35 +08:00
MR_INIT_DRV_EXPORT(drv_adc_init);
2023-11-12 00:33:40 +08:00
#endif /* MR_USING_ADC */