libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
LibXR::STM32ADC Class Reference

STM32 ADC 驱动实现 / STM32 ADC driver implementation. More...

#include <stm32_adc.hpp>

Classes

class  Channel
 ADC 通道对象 / ADC channel object. More...
 

Public Member Functions

 STM32ADC (ADC_HandleTypeDef *hadc, RawData dma_buff, std::initializer_list< uint32_t > channels, float vref)
 构造 ADC 驱动对象 / Construct ADC driver object
 
 ~STM32ADC ()
 析构函数 / Destructor
 
Channel & GetChannel (uint8_t index)
 获取 ADC 通道对象 / Get ADC channel object
 
float ReadChannel (uint8_t channel)
 读取指定通道电压 / Read channel voltage
 

Detailed Description

STM32 ADC 驱动实现 / STM32 ADC driver implementation.

Definition at line 24 of file stm32_adc.hpp.

Constructor & Destructor Documentation

◆ STM32ADC()

STM32ADC::STM32ADC ( ADC_HandleTypeDef * hadc,
RawData dma_buff,
std::initializer_list< uint32_t > channels,
float vref )

构造 ADC 驱动对象 / Construct ADC driver object

Parameters
hadcHAL ADC 句柄 / HAL ADC handle
dma_buffDMA 缓冲区 / DMA buffer
channelsADC 通道列表 / ADC channel list
vref参考电压 / Reference voltage
Note
H5 DMA 采样使用半字传输和循环链表,缓冲区、句柄及原链表在对象生命周期内有效。 H5 DMA sampling uses halfword transfers and a circular list; buffers, handles and the original list remain valid for the object's lifetime.

Definition at line 48 of file stm32_adc.cpp.

50 : hadc_(hadc),
51 NUM_CHANNELS(channels.size()),
52 filter_size_(CalculateFilterSize(dma_buff, channels.size())),
53 use_dma_(hadc_->DMA_Handle != nullptr),
54 dma_buffer_(dma_buff),
55 resolution_(GetADCResolution<ADC_HandleTypeDef>{}.Get(hadc)),
56 channels_(new Channel*[NUM_CHANNELS]),
57 vref_(vref)
58{
59 auto it = channels.begin();
60 for (uint8_t i = 0; i < NUM_CHANNELS; ++i)
61 {
62 channels_[i] = new Channel(this, i, *it++);
63 }
64
65#if defined(ADC_CALIB_OFFSET_AND_LINEARITY) && defined(ADC_SINGLE_ENDED)
66 HAL_ADCEx_Calibration_Start(hadc, ADC_CALIB_OFFSET_AND_LINEARITY, ADC_SINGLE_ENDED);
67#elif defined(ADC_CALIB_OFFSET_LINEARITY) && defined(ADC_SINGLE_ENDED)
68 HAL_ADCEx_Calibration_Start(hadc, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED);
69#elif defined(ADC_CALIB_OFFSET) && defined(ADC_SINGLE_ENDED)
70 HAL_ADCEx_Calibration_Start(hadc, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
71#elif defined(ADC_SINGLE_ENDED)
72 HAL_ADCEx_Calibration_Start(hadc, ADC_SINGLE_ENDED);
73#else
74 HAL_ADCEx_Calibration_Start(hadc);
75#endif
76
77 if (use_dma_)
78 {
79 /* DMA must be in circular mode */
80 AssertContinuousConvModeEnabled<H>(hadc_);
81 AssertDMAContReqEnabled<H>(hadc_);
82#if !defined(LIBXR_STM32_ADC_GPDMA)
83 AssertDMACircular<H>(hadc_);
84#endif
85 AssertNbrOfConvEq<H>(hadc_, NUM_CHANNELS);
86#if defined(LIBXR_STM32_ADC_GPDMA)
87 [[maybe_unused]] const auto adc_dma_result =
88 gpdma_adapter_.Start(hadc_, reinterpret_cast<uint32_t*>(dma_buffer_.addr_),
89 NUM_CHANNELS * filter_size_, dma_buffer_.size_);
90 REQUIRE(adc_dma_result == HAL_OK);
91#else
92 HAL_ADC_Start_DMA(hadc_, reinterpret_cast<uint32_t*>(dma_buffer_.addr_),
93 NUM_CHANNELS * filter_size_);
94#endif
95 }
96 else
97 {
98 AssertNbrOfConvEq<H>(hadc_, 1);
99 AssertContinuousConvModeDisabled<H>(hadc_);
100 HAL_ADC_Start(hadc_);
101 }
102}
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address

◆ ~STM32ADC()

STM32ADC::~STM32ADC ( )

析构函数 / Destructor

Definition at line 104 of file stm32_adc.cpp.

105{
106#if defined(LIBXR_STM32_ADC_GPDMA)
107 if (use_dma_)
108 {
109 [[maybe_unused]] const auto adc_dma_result = gpdma_adapter_.Stop(hadc_);
110 REQUIRE(adc_dma_result == HAL_OK);
111 }
112 else
113 {
114 HAL_ADC_Stop(hadc_);
115 }
116#else
117 use_dma_ ? HAL_ADC_Stop_DMA(hadc_) : HAL_ADC_Stop(hadc_);
118#endif
119 for (uint8_t i = 0; i < NUM_CHANNELS; ++i)
120 {
121 delete channels_[i];
122 }
123 delete[] channels_;
124}

Member Function Documentation

◆ GetChannel()

STM32ADC::Channel & STM32ADC::GetChannel ( uint8_t index)

获取 ADC 通道对象 / Get ADC channel object

Parameters
index通道索引 / Channel index
Returns
Channel& 通道对象引用 / Channel object reference

Definition at line 126 of file stm32_adc.cpp.

126{ return *channels_[index]; }

◆ ReadChannel()

float STM32ADC::ReadChannel ( uint8_t channel)

读取指定通道电压 / Read channel voltage

Parameters
channel通道号 / Channel number
Returns
float 电压值 / Voltage value

Definition at line 128 of file stm32_adc.cpp.

129{
130 ASSERT(channel < NUM_CHANNELS);
131
132 uint16_t* buffer = reinterpret_cast<uint16_t*>(dma_buffer_.addr_);
133 if (use_dma_)
134 {
135 STM32_InvalidateDCacheByAddr(buffer, filter_size_ * NUM_CHANNELS * 2);
136 uint32_t sum = 0;
137 for (uint8_t i = 0; i < filter_size_; ++i)
138 {
139 sum += buffer[channel + i * NUM_CHANNELS];
140 }
141 return ConvertToVoltage(static_cast<float>(sum) / static_cast<float>(filter_size_));
142 }
143
144 ADC_ChannelConfTypeDef config = {};
145 uint32_t time = 0;
146 UNUSED(time);
147#if defined(ADC_SAMPLETIME_16CYCLES)
148 time = ADC_SAMPLETIME_16CYCLES;
149#elif defined(ADC_SAMPLETIME_16CYCLES_5)
150 time = ADC_SAMPLETIME_16CYCLES_5;
151#elif defined(ADC_SAMPLETIME_17CYCLES)
152 time = ADC_SAMPLETIME_17CYCLES;
153#elif defined(ADC_SAMPLETIME_17CYCLES_5)
154 time = ADC_SAMPLETIME_17CYCLES_5;
155#elif defined(ADC_SAMPLETIME_18CYCLES)
156 time = ADC_SAMPLETIME_18CYCLES;
157#elif defined(ADC_SAMPLETIME_18CYCLES_5)
158 time = ADC_SAMPLETIME_18CYCLES_5;
159#elif defined(ADC_SAMPLETIME_19CYCLES)
160 time = ADC_SAMPLETIME_19CYCLES;
161#elif defined(ADC_SAMPLETIME_19CYCLES_5)
162 time = ADC_SAMPLETIME_19CYCLES_5;
163#elif defined(ADC_SAMPLETIME_20CYCLES)
164 time = ADC_SAMPLETIME_20CYCLES;
165#elif defined(ADC_SAMPLETIME_20CYCLES_5)
166 time = ADC_SAMPLETIME_20CYCLES_5;
167#elif defined(ADC_SAMPLETIME_21CYCLES)
168 time = ADC_SAMPLETIME_21CYCLES;
169#elif defined(ADC_SAMPLETIME_21CYCLES_5)
170 time = ADC_SAMPLETIME_21CYCLES_5;
171#elif defined(ADC_SAMPLETIME_22CYCLES)
172 time = ADC_SAMPLETIME_22CYCLES;
173#elif defined(ADC_SAMPLETIME_22CYCLES_5)
174 time = ADC_SAMPLETIME_22CYCLES_5;
175#elif defined(ADC_SAMPLETIME_23CYCLES)
176 time = ADC_SAMPLETIME_23CYCLES;
177#elif defined(ADC_SAMPLETIME_23CYCLES_5)
178 time = ADC_SAMPLETIME_23CYCLES_5;
179#elif defined(ADC_SAMPLETIME_24CYCLES)
180 time = ADC_SAMPLETIME_24CYCLES;
181#elif defined(ADC_SAMPLETIME_24CYCLES_5)
182 time = ADC_SAMPLETIME_24CYCLES_5;
183#elif defined(ADC_SAMPLETIME_25CYCLES)
184 time = ADC_SAMPLETIME_25CYCLES;
185#elif defined(ADC_SAMPLETIME_25CYCLES_5)
186 time = ADC_SAMPLETIME_25CYCLES_5;
187#elif defined(ADC_SAMPLETIME_26CYCLES)
188 time = ADC_SAMPLETIME_26CYCLES;
189#elif defined(ADC_SAMPLETIME_26CYCLES_5)
190 time = ADC_SAMPLETIME_26CYCLES_5;
191#elif defined(ADC_SAMPLETIME_27CYCLES)
192 time = ADC_SAMPLETIME_27CYCLES;
193#elif defined(ADC_SAMPLETIME_27CYCLES_5)
194 time = ADC_SAMPLETIME_27CYCLES_5;
195#elif defined(ADC_SAMPLETIME_28CYCLES)
196 time = ADC_SAMPLETIME_28CYCLES;
197#elif defined(ADC_SAMPLETIME_28CYCLES_5)
198 time = ADC_SAMPLETIME_28CYCLES_5;
199#elif defined(ADC_SAMPLETIME_29CYCLES)
200 time = ADC_SAMPLETIME_29CYCLES;
201#elif defined(ADC_SAMPLETIME_29CYCLES_5)
202 time = ADC_SAMPLETIME_29CYCLES_5;
203#elif defined(ADC_SAMPLETIME_30CYCLES)
204 time = ADC_SAMPLETIME_30CYCLES;
205#elif defined(ADC_SAMPLETIME_30CYCLES_5)
206 time = ADC_SAMPLETIME_30CYCLES_5;
207#elif defined(ADC_SAMPLETIME_31CYCLES)
208 time = ADC_SAMPLETIME_31CYCLES;
209#elif defined(ADC_SAMPLETIME_31CYCLES_5)
210 time = ADC_SAMPLETIME_31CYCLES_5;
211#elif defined(ADC_SAMPLETIME_32CYCLES)
212 time = ADC_SAMPLETIME_32CYCLES;
213#elif defined(ADC_SAMPLETIME_32CYCLES_5)
214 time = ADC_SAMPLETIME_32CYCLES_5;
215#error "Unsupported sample time"
216#endif
217
218 config.Channel = channels_[channel]->ch_;
219#if defined(ADC_REGULAR_RANK_1)
220 config.Rank = ADC_REGULAR_RANK_1;
221#else
222 config.Rank = 1;
223#endif
224#if defined(ADC_SINGLE_ENDED) && !defined(STM32L0)
225 config.SingleDiff = ADC_SINGLE_ENDED;
226#endif
227#if defined(ADC_OFFSET_NONE)
228 config.OffsetNumber = ADC_OFFSET_NONE;
229 config.Offset = 0;
230#endif
231#if !defined(STM32L0)
232 config.SamplingTime = time;
233#endif
234
235 uint32_t expected = 0U;
236
237 // Multiple threads are working on the same adc peripheral
238 // Please use dma mode
239 const bool locked = locked_.compare_exchange_strong(
240 expected, 0xF0F0F0F0U, std::memory_order_acquire, std::memory_order_relaxed);
241 REQUIRE(locked);
242
243 HAL_ADC_ConfigChannel(hadc_, &config);
244
245 uint32_t sum = 0;
246 for (uint8_t i = 0; i < filter_size_; ++i)
247 {
248 HAL_ADC_Start(hadc_);
249 HAL_ADC_PollForConversion(hadc_, 20);
250 buffer[channel + i * NUM_CHANNELS] = HAL_ADC_GetValue(hadc_);
251 sum += buffer[channel + i * NUM_CHANNELS];
252 }
253
254 locked_.store(0, std::memory_order_release);
255
256 return ConvertToVoltage(static_cast<float>(sum) / static_cast<float>(filter_size_));
257}
void STM32_InvalidateDCacheByAddr(const void *addr, size_t size)
失效指定内存范围覆盖的 D-Cache cache line Invalidates D-Cache lines covering the specified memory range

The documentation for this class was generated from the following files: