【前言】
昨天移植好了zephyr adc 的驱动,开发板上板载了一个可调电位器,通过调节电位器可以实现adc的验证,同时ADC0的内部通道也有内部温度的读取与参考电压的获取。本篇将分享如何进行读取与展示。
【原理图】
1、开发板的使用手册有电位器的提供,如下所示:

从原理图得知他的ADC接入是PC0/ADC0/channel 10.
同时开发板的电路也使用33欧的电阻行了阻抗的匹配,也添加了电容进行滤波。
2、ADC内部通道。
在GD32F50x用户手册中有提到ADC的内部通道:

【编程设计】
1、配置adc的通道,同时配置采样时间,采样单次转换。
2、添加一个ui,用于电压的展示。
【代码设计】
1、prj.con
添加CONFIG_ADC=y 开启ADC
2、ui.c
配置一下adc的通道采样时间等
tatic int adc_setup_channels_once(void)
{
if (adc_ch_setup_done) {
return 0;
}
if (!device_is_ready(adc_dev)) {
return -1;
}
/* ch10 = PC0 电位器,低阻抗 — 默认采样时间即可。 */
struct adc_channel_cfg cfg_pot = {
.gain = ADC_GAIN_1,
.reference = ADC_REF_INTERNAL,
.acquisition_time = ADC_ACQ_TIME_DEFAULT,
.channel_id = ADC_CH_POT,
.differential = false,
};
int rc = adc_channel_setup(adc_dev, &cfg_pot);
if (rc < 0) {
return rc;
}
/* ch16 = 内置温度传感器 — 高阻抗源,必须 239.5 cycles。 */
struct adc_channel_cfg cfg_temp = {
.gain = ADC_GAIN_1,
.reference = ADC_REF_INTERNAL,
.acquisition_time = ADC_ACQ_TIME(ADC_ACQ_TIME_TICKS, 240),
.channel_id = ADC_CH_TEMP,
.differential = false,
};
rc = adc_channel_setup(adc_dev, &cfg_temp);
if (rc < 0) {
return rc;
}
/* ch17 = 内置 Vrefint — 高阻抗源,必须 239.5 cycles。 */
struct adc_channel_cfg cfg_vref = {
.gain = ADC_GAIN_1,
.reference = ADC_REF_INTERNAL,
.acquisition_time = ADC_ACQ_TIME(ADC_ACQ_TIME_TICKS, 240),
.channel_id = ADC_CH_VREFINT,
.differential = false,
};
rc = adc_channel_setup(adc_dev, &cfg_vref);
if (rc < 0) {
return rc;
}
adc_ch_setup_done = true;
return 0;
}读取三个电压值:
/* 单通道读 — Zephyr gd32 ADC driver 当前只支持单 channel per call。
* 跟 adc_read_three 拆三通道对应,3 次调用各读一个通道。
* 每次 blocked ≈ 75 µs @ 10 MHz ADC,3 次共 ≈ 225 µs,
* 在 500 ms cadence 下完全无感。 */
static int adc_read_one(int ch, uint16_t *raw)
{
int rc = adc_setup_channels_once();
if (rc < 0) {
return rc;
}
struct adc_sequence seq = {
.channels = BIT(ch),
.buffer = raw,
.buffer_size = sizeof(*raw),
.resolution = ADC_RESOLUTION,
.calibrate = false,
.oversampling = 0,
};
return adc_read(adc_dev, &seq);
}
/* 顺序读三通道:Zephyr gd32 driver 不支持多通道 sequence,
* 改成 3 次独立 adc_read()。
* 内部通道 ch16/ch17 需要 TSVEN/INREFEN (driver init 已开);
* 顺序:先 PC0,再 ch16 温度,最后 ch17 Vrefint (为避免先读 Vrefint 干扰)。 */
static int adc_read_three(uint16_t *raw_pot, uint16_t *raw_temp,
uint16_t *raw_vref)
{
int rc;
rc = adc_read_one(ADC_CH_POT, raw_pot);
if (rc < 0) {
return rc;
}
rc = adc_read_one(ADC_CH_TEMP, raw_temp);
if (rc < 0) {
return rc;
}
rc = adc_read_one(ADC_CH_VREFINT, raw_vref);
if (rc < 0) {
return rc;
}
return 0;
}【效果展示】

我要赚赏金
