libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
esp_adc.hpp
1#pragma once
2
3#include <atomic>
4#include <cstdint>
5
6#include "adc.hpp"
7#include "esp_adc/adc_continuous.h"
8#include "hal/adc_types.h"
9
10#if (SOC_ADC_DIGI_RESULT_BYTES == 2)
11#define XR_ADC_DMA_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1
12#define XR_ADC_DMA_GET_CHANNEL(p_data) ((p_data)->type1.channel)
13#define XR_ADC_DMA_GET_DATA(p_data) ((p_data)->type1.data)
14#else
15#define XR_ADC_DMA_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
16#define XR_ADC_DMA_GET_CHANNEL(p_data) ((p_data)->type2.channel)
17#define XR_ADC_DMA_GET_DATA(p_data) ((p_data)->type2.data)
18#endif
19
20namespace LibXR
21{
22
34{
35 public:
40 class Channel : public ADC
41 {
42 public:
47 Channel() : parent_(nullptr), idx_(0), channel_num_(0) {}
48
57 Channel(ESP32ADC *parent, uint8_t idx, uint8_t channel_num)
58 : parent_(parent), idx_(idx), channel_num_(channel_num)
59 {
60 }
61
68 float Read() override { return parent_ ? parent_->ReadChannel(idx_) : 0.f; }
69
76 uint8_t ChannelNumber() const { return channel_num_; }
77
78 private:
80 uint8_t idx_;
81 uint8_t channel_num_;
82 };
83
99 adc_unit_t unit, const adc_channel_t *channels, uint8_t num_channels,
100 uint32_t freq = SOC_ADC_SAMPLE_FREQ_THRES_LOW,
101 adc_atten_t attenuation = ADC_ATTEN_DB_12,
102 adc_bitwidth_t bitwidth = static_cast<adc_bitwidth_t>(SOC_ADC_DIGI_MAX_BITWIDTH),
103 float reference_voltage = 3.3f, size_t dma_buf_size = 256)
104 : m_unit_(unit),
105 m_num_channels_(num_channels),
106 m_attenuation_(attenuation),
107 m_bitwidth_(bitwidth),
108 m_reference_voltage_(reference_voltage),
109 m_max_raw_((1 << bitwidth) - 1)
110 {
111 m_patterns_ = new adc_digi_pattern_config_t[m_num_channels_];
114 m_sum_buf_ = new int[m_num_channels_];
115 m_cnt_buf_ = new int[m_num_channels_];
116
117 for (uint8_t i = 0; i < m_num_channels_; ++i)
118 {
119 m_patterns_[i].atten = static_cast<uint8_t>(m_attenuation_);
120 m_patterns_[i].channel = channels[i];
121 m_patterns_[i].unit = static_cast<uint8_t>(m_unit_);
122 m_patterns_[i].bit_width = static_cast<uint8_t>(m_bitwidth_);
123 m_channels_[i] = Channel(this, i, channels[i]);
124 m_latest_values_[i] = 0.f;
125 }
126
127 adc_continuous_handle_cfg_t adc_config = {
128 .max_store_buf_size = dma_buf_size,
129 .conv_frame_size = dma_buf_size / 2,
130 };
131 ESP_ERROR_CHECK(adc_continuous_new_handle(&adc_config, &m_handle_));
132
133 adc_continuous_config_t dig_cfg = {};
134 dig_cfg.sample_freq_hz = freq;
135 if (m_unit_ == ADC_UNIT_1)
136 {
137 dig_cfg.conv_mode = ADC_CONV_SINGLE_UNIT_1;
138 }
139 else
140 {
141 dig_cfg.conv_mode = ADC_CONV_SINGLE_UNIT_2;
142 }
143 dig_cfg.format = XR_ADC_DMA_OUTPUT_TYPE;
144 dig_cfg.adc_pattern = m_patterns_;
145 dig_cfg.pattern_num = m_num_channels_;
146 ESP_ERROR_CHECK(adc_continuous_config(m_handle_, &dig_cfg));
147
148 adc_continuous_evt_cbs_t cbs = {
149 .on_conv_done = &ESP32ADC::OnConvDone,
150 };
151 ESP_ERROR_CHECK(adc_continuous_register_event_callbacks(m_handle_, &cbs, this));
152 ESP_ERROR_CHECK(adc_continuous_start(m_handle_));
153 }
154
160 {
161 if (m_handle_)
162 {
163 adc_continuous_stop(m_handle_);
164 adc_continuous_deinit(m_handle_);
165 }
166 delete[] m_patterns_;
167 delete[] m_channels_;
168 delete[] m_latest_values_;
169 delete[] m_sum_buf_;
170 delete[] m_cnt_buf_;
171 }
172
179 Channel &GetChannel(uint8_t idx) { return m_channels_[idx]; }
180
187 float ReadChannel(uint8_t idx) { return m_latest_values_[idx]; }
188
189 private:
194 static bool IRAM_ATTR OnConvDone(adc_continuous_handle_t handle,
195 const adc_continuous_evt_data_t *edata,
196 void *user_data)
197 {
198 auto *self = reinterpret_cast<ESP32ADC *>(user_data);
199 self->HandleSamples(edata->conv_frame_buffer, edata->size);
200 return false;
201 }
202
210 void HandleSamples(const void *buf, size_t size_bytes)
211 {
212 for (uint8_t idx = 0; idx < m_num_channels_; ++idx)
213 {
214 m_sum_buf_[idx] = 0;
215 m_cnt_buf_[idx] = 0;
216 }
217
218 size_t n = size_bytes / sizeof(adc_digi_output_data_t);
219 const adc_digi_output_data_t *samples =
220 static_cast<const adc_digi_output_data_t *>(buf);
221
222 for (size_t i = 0; i < n; ++i)
223 {
224 uint8_t ch = XR_ADC_DMA_GET_CHANNEL(&samples[i]);
225 for (uint8_t idx = 0; idx < m_num_channels_; ++idx)
226 {
227 if (ch == m_channels_[idx].ChannelNumber())
228 {
229 int raw = XR_ADC_DMA_GET_DATA(&samples[i]);
230 m_sum_buf_[idx] += raw;
231 m_cnt_buf_[idx] += 1;
232 break;
233 }
234 }
235 }
236
237 for (uint8_t idx = 0; idx < m_num_channels_; ++idx)
238 {
239 if (m_cnt_buf_[idx] > 0)
240 {
241 float avg = Normalize(static_cast<float>(m_sum_buf_[idx]) / m_cnt_buf_[idx]);
242 m_latest_values_[idx] = avg;
243 }
244 }
245 }
246
254 float Normalize(float raw) const
255 {
256 return (raw / static_cast<float>(m_max_raw_)) * m_reference_voltage_;
257 }
258
259 adc_digi_pattern_config_t *m_patterns_;
264
265 adc_unit_t m_unit_;
267 adc_atten_t m_attenuation_;
268 adc_bitwidth_t m_bitwidth_;
270 uint16_t m_max_raw_;
271 adc_continuous_handle_t m_handle_ = nullptr;
272};
273
274} // namespace LibXR
模拟数字转换器(ADC)基类
Definition adc.hpp:18
ADC通道对象,提供通道级数据访问和抽象接口。
Definition esp_adc.hpp:41
uint8_t channel_num_
物理通道号 / Physical ADC channel number
Definition esp_adc.hpp:81
uint8_t ChannelNumber() const
获取物理ADC通道号 Get the physical ADC channel number.
Definition esp_adc.hpp:76
Channel(ESP32ADC *parent, uint8_t idx, uint8_t channel_num)
构造指定父ADC和通道编号的通道对象 Construct with given parent ADC and channel numbers.
Definition esp_adc.hpp:57
float Read() override
读取当前通道归一化电压值(单位:V) Read normalized voltage (unit: V) for this channel.
Definition esp_adc.hpp:68
uint8_t idx_
逻辑通道号 / Logical index
Definition esp_adc.hpp:80
Channel()
默认构造函数 Default constructor.
Definition esp_adc.hpp:47
ESP32ADC * parent_
父ADC对象 / Parent ADC pointer
Definition esp_adc.hpp:79
ESP32 ADC多通道驱动
Definition esp_adc.hpp:34
int * m_cnt_buf_
计数缓冲 / Count buffer
Definition esp_adc.hpp:263
float m_reference_voltage_
参考电压 / Reference voltage
Definition esp_adc.hpp:269
float ReadChannel(uint8_t idx)
读取指定通道最新均值(已归一化为电压) Read latest averaged and normalized value (in volts) for the given channel.
Definition esp_adc.hpp:187
Channel & GetChannel(uint8_t idx)
获取通道对象的引用 Get a reference to channel object by index.
Definition esp_adc.hpp:179
float Normalize(float raw) const
原始ADC值归一化到电压 Normalize raw ADC value to voltage.
Definition esp_adc.hpp:254
adc_continuous_handle_t m_handle_
ESP-IDF采集句柄 / ADC handle.
Definition esp_adc.hpp:271
float * m_latest_values_
最新均值(每通道)/ Latest average value (per channel)
Definition esp_adc.hpp:261
ESP32ADC(adc_unit_t unit, const adc_channel_t *channels, uint8_t num_channels, uint32_t freq=SOC_ADC_SAMPLE_FREQ_THRES_LOW, adc_atten_t attenuation=ADC_ATTEN_DB_12, adc_bitwidth_t bitwidth=static_cast< adc_bitwidth_t >(SOC_ADC_DIGI_MAX_BITWIDTH), float reference_voltage=3.3f, size_t dma_buf_size=256)
构造函数:初始化ADC与DMA、参数配置 Constructor: Initialize ADC, DMA, and config parameters.
Definition esp_adc.hpp:98
void HandleSamples(const void *buf, size_t size_bytes)
采样缓冲区数据解析与均值计算 Parse DMA buffer and calculate channel averages.
Definition esp_adc.hpp:210
Channel * m_channels_
通道对象数组 / Channel objects array
Definition esp_adc.hpp:260
adc_unit_t m_unit_
ADC单元 / ADC unit.
Definition esp_adc.hpp:265
uint8_t m_num_channels_
通道数 / Number of channels
Definition esp_adc.hpp:266
int * m_sum_buf_
求和缓冲 / Accumulation buffer
Definition esp_adc.hpp:262
static bool IRAM_ATTR OnConvDone(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data)
DMA采集完成中断回调。内部调用。 DMA conversion done callback. Called internally by ESP-IDF.
Definition esp_adc.hpp:194
uint16_t m_max_raw_
最大原始采样值 / Max raw value
Definition esp_adc.hpp:270
adc_digi_pattern_config_t * m_patterns_
ADC采样模式数组 / Pattern config array.
Definition esp_adc.hpp:259
~ESP32ADC()
析构函数,释放所有资源 Destructor. Free all resources and stop ADC.
Definition esp_adc.hpp:159
adc_bitwidth_t m_bitwidth_
位宽 / Bit width
Definition esp_adc.hpp:268
adc_atten_t m_attenuation_
衰减档位 / Attenuation
Definition esp_adc.hpp:267
LibXR 命名空间
Definition ch32_gpio.hpp:9