Files
mr-library/bsp/wch/driver/drv_adc.c
2023-05-22 22:29:55 +08:00

126 lines
3.0 KiB
C

/*
* Copyright (c) 2023, mr-library Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-05-22 MacRsh first version
*/
#include "drv_adc.h"
#undef LOG_TAG
#define LOG_TAG "drv_adc"
#if (MR_CONF_ADC == MR_CONF_ENABLE)
static struct ch32_adc ch32_adc[] =
{
#ifdef BSP_ADC_1
{"adc1",
{ADC1,
RCC_APB2Periph_ADC1}},
#endif
#ifdef BSP_ADC_2
{"adc2",
{ADC2,
RCC_APB2Periph_ADC2}},
#endif
};
static struct mr_adc hw_adc[mr_array_get_length(ch32_adc)];
mr_err_t ch32_adc_configure(mr_adc_t adc, mr_state_t state)
{
struct ch32_adc *hw = (struct ch32_adc *)adc->device.data;
ADC_InitTypeDef ADC_InitStructure = {0};
RCC_APB2PeriphClockCmd(hw->hw_adc.adc_periph_clock, (FunctionalState)state);
RCC_ADCCLKConfig(RCC_PCLK2_Div2);
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(hw->hw_adc.Instance, &ADC_InitStructure);
ADC_Cmd(hw->hw_adc.Instance, (FunctionalState)state);
return MR_ERR_OK;
}
mr_err_t ch32_adc_channel_configure(mr_adc_t adc, mr_uint16_t channel, mr_state_t state)
{
struct ch32_adc *hw = (struct ch32_adc *)adc->device.data;
GPIO_InitTypeDef GPIO_InitStructure = {0};
GPIO_TypeDef *GPIOx = {0};
if (channel <= 7)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIOx = GPIOA;
} else if (channel <= 10)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIOx = GPIOB;
} else
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIOx = GPIOC;
}
if (state == MR_ENABLE)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
else
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = (1 << channel);
GPIO_Init(GPIOx, &GPIO_InitStructure);
MR_LOG_D(LOG_TAG,
"Config %s %d %d\r\n",
hw->name,
channel,
state);
return MR_ERR_OK;
}
mr_uint32_t ch32_adc_read(mr_adc_t adc, mr_uint16_t channel)
{
struct ch32_adc *hw = (struct ch32_adc *)adc->device.data;
mr_uint32_t data = 0;
ADC_RegularChannelConfig(hw->hw_adc.Instance, channel, 1, ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(hw->hw_adc.Instance, ENABLE);
while (! ADC_GetFlagStatus(hw->hw_adc.Instance, ADC_FLAG_EOC));
data = ADC_GetConversionValue(hw->hw_adc.Instance);
ADC_ClearFlag(hw->hw_adc.Instance, ADC_FLAG_EOC);
return data;
}
mr_err_t mr_hw_adc_init(void)
{
mr_err_t ret = MR_ERR_OK;
mr_size_t count = mr_array_get_length(hw_adc);
static struct mr_adc_ops ops =
{
ch32_adc_configure,
ch32_adc_channel_configure,
ch32_adc_read,
};
while (count --)
{
ret = mr_hw_adc_add(&hw_adc[count], ch32_adc[count].name, &ops, &ch32_adc[count]);
MR_ASSERT(ret == MR_ERR_OK);
}
return MR_ERR_OK;
}
INIT_BOARD_EXPORT(mr_hw_adc_init);
#endif