1 /*
2 * Copyright (c) 2006-2024, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2024-05-17 QT-one first version
9 */
10
11 #include <rtdbg.h>
12 #include "drv_adc.h"
13
14
15 #ifdef RT_USING_ADC
16 #if !defined(BSP_USING_ADC0) && !defined(BSP_USING_ADC1)
17 #error "Please define at least one BSP_USING_ADCx"
18 /* this driver can be disabled at menuconfig RT-Thread Components Device Drivers */
19 #endif
20
21 struct ht32_adc
22 {
23 struct rt_adc_device ht32_adc_device;
24 HT_ADC_TypeDef *adc_x;
25 char *name;
26 };
27
28 /* ADC Peripheral List */
29 static struct ht32_adc ht32_adc_obj[] =
30 {
31 #ifdef BSP_USING_ADC0
32 {
33 .adc_x = HT_ADC0,
34 .name = BSP_USING_ADC0_NAME,
35 },
36 #endif
37
38 #ifdef BSP_USING_ADC1
39 {
40 .adc_x = HT_ADC1,
41 .name = BSP_USING_ADC1_NAME,
42 },
43 #endif
44 };
45
ht32_adc_enabled(struct rt_adc_device * device,rt_int8_t channel,rt_bool_t enabled)46 static rt_err_t ht32_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
47 {
48 HT_ADC_TypeDef *adc_x;
49 RT_ASSERT(device != RT_NULL);
50 adc_x = (HT_ADC_TypeDef*)device->parent.user_data;
51
52 if(enabled)
53 {
54 ht32_adc_gpio_init(adc_x,channel);
55 /* Configure the CK_ADCn prescaler */
56 #ifdef BSP_USING_ADC0
57 if(HT_ADC0 == adc_x)
58 {
59 CKCU_SetADCnPrescaler(CKCU_ADCPRE_ADC0,CKCU_ADCPRE_DIV64);
60 }
61 #endif
62 #ifdef BSP_USING_ADC1
63 if(HT_ADC1 == adc_x)
64 {
65 CKCU_SetADCnPrescaler(CKCU_ADCPRE_ADC1,CKCU_ADCPRE_DIV64);
66 }
67 #endif
68 /* Configure conversion mode and sequence length (number of conversion channels) */
69 ADC_RegularGroupConfig(adc_x,ONE_SHOT_MODE,1,0);
70
71 #ifdef SOC_SERIES_HT32F5
72 /* Configuring the Sampling Time */
73 ADC_SamplingTimeConfig(adc_x,0);
74 /* Configuring Channel Priority */
75 ADC_RegularChannelConfig(adc_x,channel,0);
76 #endif
77 #ifdef SOC_SERIES_HT32F1
78 /* Configuring Channel Priority */
79 ADC_RegularChannelConfig(adc_x,channel,0,0);
80 #endif
81 /* Configuring the Trigger Source */
82 ADC_RegularTrigConfig(adc_x,ADC_TRIG_SOFTWARE);
83 /* Enable ADC */
84 ADC_Cmd(adc_x,ENABLE);
85 }
86 else
87 {
88 /* Disable ADC */
89 ADC_Cmd(adc_x,DISABLE);
90 }
91 return RT_EOK;
92 }
93
ht32_adc_convert(struct rt_adc_device * device,rt_int8_t channel,rt_uint32_t * value)94 static rt_err_t ht32_adc_convert(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
95 {
96 HT_ADC_TypeDef *adc_x;
97 rt_uint32_t timeout = 0;
98 FlagStatus adc_writ_flag = RESET;
99 RT_ASSERT(device != RT_NULL);
100 adc_x = (HT_ADC_TypeDef*)device->parent.user_data;
101
102 /* Toggle the acquisition channel */
103 #ifdef SOC_SERIES_HT32F5
104 ADC_RegularChannelConfig(adc_x,channel,0);
105 #endif
106 #ifdef SOC_SERIES_HT32F1
107 ADC_RegularChannelConfig(adc_x,channel,0,0);
108 #endif
109
110 /* enable Software triggered */
111 ADC_SoftwareStartConvCmd(adc_x,ENABLE);
112 while((!adc_writ_flag) && (timeout < 0xFFFF))
113 {
114 /* Wait for the conversion to complete */
115 adc_writ_flag = ADC_GetFlagStatus(adc_x,ADC_FLAG_SINGLE_EOC);
116 timeout++;
117 }
118 if(timeout >= 0xFFFF)
119 {
120 LOG_D("channel%d converts timeout, please confirm adc_x enabled or not", channel);
121 /* disable Software triggered */
122 ADC_SoftwareStartConvCmd(adc_x,DISABLE);
123 return -RT_ERROR;
124 }
125 /* clear ADC_FLAG_SINGLE_EOC flag */
126 ADC_ClearIntPendingBit(adc_x,ADC_FLAG_SINGLE_EOC);
127 /* get adc value */
128 *value = ADC_GetConversionData(adc_x,ADC_REGULAR_DATA0);
129 /* disable Software triggered */
130 ADC_SoftwareStartConvCmd(adc_x,DISABLE);
131 return RT_EOK;
132 }
133
ht32_adc_get_resolution(struct rt_adc_device * device)134 static rt_uint8_t ht32_adc_get_resolution(struct rt_adc_device *device)
135 {
136 return 0;
137 }
138
ht32_adc_get_vref(struct rt_adc_device * device)139 static rt_int16_t ht32_adc_get_vref(struct rt_adc_device *device)
140 {
141 return 0;
142 }
143
144 /* ADC Device Operation Function Interface */
145 static const struct rt_adc_ops ht32_adc_ops =
146 {
147 .enabled = ht32_adc_enabled,
148 .convert = ht32_adc_convert,
149 .get_resolution = ht32_adc_get_resolution,
150 .get_vref = ht32_adc_get_vref,
151 };
152
rt_hw_adc_init(void)153 static int rt_hw_adc_init(void)
154 {
155 int result = RT_EOK;
156 int i = 0;
157 for (i = 0; i < sizeof(ht32_adc_obj) / sizeof(ht32_adc_obj[0]); i++)
158 {
159 /* register ADC device */
160 if (rt_hw_adc_register(&ht32_adc_obj[i].ht32_adc_device, ht32_adc_obj[i].name, &ht32_adc_ops, ht32_adc_obj[i].adc_x) == RT_EOK)
161 {
162 LOG_D("%s register success", ht32_adc_obj[i].name);
163 }
164 else
165 {
166 LOG_E("%s register failed", ht32_adc_obj[i].name);
167 result = -RT_ERROR;
168 }
169 }
170 return result;
171 }
172 INIT_BOARD_EXPORT(rt_hw_adc_init);
173
174 #endif /* RT_USING_ADC */
175