libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
LibXR::CH32PWM Class Reference
Inheritance diagram for LibXR::CH32PWM:
[legend]
Collaboration diagram for LibXR::CH32PWM:
[legend]

Public Member Functions

 CH32PWM (TIM_TypeDef *tim, uint16_t channel, bool active_high, GPIO_TypeDef *gpio, uint16_t pin, uint32_t pin_remap=0, bool complementary=false)
 
ErrorCode SetDutyCycle (float value) override
 Sets the duty cycle of the PWM signal. 设置 PWM 信号的占空比。
 
ErrorCode SetConfig (Configuration config) override
 Configures the PWM settings. 配置 PWM 参数。
 
ErrorCode Enable () override
 Enables the PWM output. 启用 PWM 输出。
 
ErrorCode Disable () override
 Disables the PWM output. 禁用 PWM 输出。
 
- Public Member Functions inherited from LibXR::PWM

Private Member Functions

void ApplyCompare (uint32_t pulse)
 
void OcInitForChannel (uint32_t pulse)
 
void EnableChannel (bool en)
 
void EnableChannelN (bool en)
 
void ConfigureGPIO ()
 

Static Private Member Functions

static bool IsAdvancedTimer (TIM_TypeDef *t)
 
static bool OnAPB2 (TIM_TypeDef *t)
 
static uint32_t GetTimerClockHz (TIM_TypeDef *t)
 
static uint32_t ReadARR32 (TIM_TypeDef *t)
 
static void EnableGPIOClock (GPIO_TypeDef *gpio)
 
static void EnableTIMClock (TIM_TypeDef *tim)
 

Private Attributes

TIM_TypeDef * tim_
 
uint16_t channel_
 
bool active_high_
 
bool complementary_
 
GPIO_TypeDef * gpio_
 
uint16_t pin_
 
uint32_t pin_remap_
 

Detailed Description

Definition at line 9 of file ch32_pwm.hpp.

Constructor & Destructor Documentation

◆ CH32PWM()

LibXR::CH32PWM::CH32PWM ( TIM_TypeDef * tim,
uint16_t channel,
bool active_high,
GPIO_TypeDef * gpio,
uint16_t pin,
uint32_t pin_remap = 0,
bool complementary = false )

Definition at line 6 of file ch32_pwm.cpp.

8 : tim_(tim),
9 channel_(channel),
10 active_high_(active_high),
11 complementary_(complementary),
12 gpio_(gpio),
13 pin_(pin),
14 pin_remap_(pin_remap)
15{
16}

Member Function Documentation

◆ ApplyCompare()

void LibXR::CH32PWM::ApplyCompare ( uint32_t pulse)
private

Definition at line 261 of file ch32_pwm.cpp.

262{
263 const uint16_t ccr = static_cast<uint16_t>(std::min<uint32_t>(pulse, 0xFFFFu));
264 switch (channel_)
265 {
266 case TIM_Channel_1:
267 TIM_SetCompare1(tim_, ccr);
268 break;
269 case TIM_Channel_2:
270 TIM_SetCompare2(tim_, ccr);
271 break;
272 case TIM_Channel_3:
273 TIM_SetCompare3(tim_, ccr);
274 break;
275 case TIM_Channel_4:
276 TIM_SetCompare4(tim_, ccr);
277 break;
278 default:
279 break;
280 }
281}

◆ ConfigureGPIO()

void LibXR::CH32PWM::ConfigureGPIO ( )
private

Definition at line 135 of file ch32_pwm.cpp.

136{
137 // AFIO 时钟(用于重映射)
138 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
139
140 // 需要重映射则打开
141 if (pin_remap_ != 0u)
142 {
143 GPIO_PinRemapConfig(pin_remap_, ENABLE);
144 }
145
146 // 端口时钟 + 复用推挽输出
147 EnableGPIOClock(gpio_);
148 GPIO_InitTypeDef io{};
149 io.GPIO_Pin = pin_;
150 io.GPIO_Speed = GPIO_Speed_50MHz;
151 io.GPIO_Mode = GPIO_Mode_AF_PP;
152 GPIO_Init(gpio_, &io);
153}

◆ Disable()

ErrorCode LibXR::CH32PWM::Disable ( )
overridevirtual

Disables the PWM output. 禁用 PWM 输出。

Returns
ErrorCode indicating success or failure. 返回操作结果的错误码。

Implements LibXR::PWM.

Definition at line 246 of file ch32_pwm.cpp.

247{
248 if (!tim_) return ErrorCode::ARG_ERR;
249
250 if (complementary_ && IsAdvancedTimer(tim_))
251 {
252 EnableChannelN(false);
253 }
254 EnableChannel(false);
255
256 return ErrorCode::OK;
257}

◆ Enable()

ErrorCode LibXR::CH32PWM::Enable ( )
overridevirtual

Enables the PWM output. 启用 PWM 输出。

Returns
ErrorCode indicating success or failure. 返回操作结果的错误码。

Implements LibXR::PWM.

Definition at line 228 of file ch32_pwm.cpp.

229{
230 if (!tim_) return ErrorCode::ARG_ERR;
231
232 // 先开通道,后启计数器,避免毛刺
233 EnableChannel(true);
234 if (complementary_ && IsAdvancedTimer(tim_))
235 {
236 EnableChannelN(true);
237 }
238 if (IsAdvancedTimer(tim_))
239 {
240 TIM_CtrlPWMOutputs(tim_, ENABLE);
241 }
242 TIM_Cmd(tim_, ENABLE);
243 return ErrorCode::OK;
244}

◆ EnableChannel()

void LibXR::CH32PWM::EnableChannel ( bool en)
private

Definition at line 322 of file ch32_pwm.cpp.

323{
324#if defined(TIM_CCx_Enable)
325 switch (channel_)
326 {
327 case TIM_Channel_1:
328 TIM_CCxCmd(tim_, TIM_Channel_1, en ? TIM_CCx_Enable : TIM_CCx_Disable);
329 break;
330 case TIM_Channel_2:
331 TIM_CCxCmd(tim_, TIM_Channel_2, en ? TIM_CCx_Enable : TIM_CCx_Disable);
332 break;
333 case TIM_Channel_3:
334 TIM_CCxCmd(tim_, TIM_Channel_3, en ? TIM_CCx_Enable : TIM_CCx_Disable);
335 break;
336 case TIM_Channel_4:
337 TIM_CCxCmd(tim_, TIM_Channel_4, en ? TIM_CCx_Enable : TIM_CCx_Disable);
338 break;
339 default:
340 break;
341 }
342#else
343 (void)en;
344#endif
345}

◆ EnableChannelN()

void LibXR::CH32PWM::EnableChannelN ( bool en)
private

Definition at line 347 of file ch32_pwm.cpp.

348{
349 if (!IsAdvancedTimer(tim_)) return;
350 switch (channel_)
351 {
352 case TIM_Channel_1:
353 TIM_CCxNCmd(tim_, TIM_Channel_1, en ? TIM_CCxN_Enable : TIM_CCxN_Disable);
354 break;
355 case TIM_Channel_2:
356 TIM_CCxNCmd(tim_, TIM_Channel_2, en ? TIM_CCxN_Enable : TIM_CCxN_Disable);
357 break;
358 case TIM_Channel_3:
359 TIM_CCxNCmd(tim_, TIM_Channel_3, en ? TIM_CCxN_Enable : TIM_CCxN_Disable);
360 break;
361 default:
362 break; // CH4 无 N
363 }
364}

◆ EnableGPIOClock()

void LibXR::CH32PWM::EnableGPIOClock ( GPIO_TypeDef * gpio)
staticprivate

Definition at line 66 of file ch32_pwm.cpp.

67{
68 if (gpio == GPIOA)
69 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
70 else if (gpio == GPIOB)
71 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
72 else if (gpio == GPIOC)
73 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
74 else if (gpio == GPIOD)
75 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
76#if defined(GPIOE)
77 else if (gpio == GPIOE)
78 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
79#endif
80}

◆ EnableTIMClock()

void LibXR::CH32PWM::EnableTIMClock ( TIM_TypeDef * tim)
staticprivate

Definition at line 82 of file ch32_pwm.cpp.

83{
84 if (tim == TIM1) RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
85#if defined(TIM8) && defined(RCC_APB2Periph_TIM8)
86 else if (tim == TIM8)
87 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
88#endif
89#if defined(TIM9) && defined(RCC_APB2Periph_TIM9)
90 else if (tim == TIM9)
91 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);
92#endif
93#if defined(TIM10) && defined(RCC_APB2Periph_TIM10)
94 else if (tim == TIM10)
95 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, ENABLE);
96#endif
97#if defined(TIM2) && defined(RCC_APB1Periph_TIM2)
98 else if (tim == TIM2)
99 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
100#endif
101#if defined(TIM3) && defined(RCC_APB1Periph_TIM3)
102 else if (tim == TIM3)
103 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
104#endif
105#if defined(TIM4) && defined(RCC_APB1Periph_TIM4)
106 else if (tim == TIM4)
107 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
108#endif
109#if defined(TIM5) && defined(RCC_APB1Periph_TIM5)
110 else if (tim == TIM5)
111 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
112#endif
113#if defined(TIM6) && defined(RCC_APB1Periph_TIM6)
114 else if (tim == TIM6)
115 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
116#endif
117#if defined(TIM7) && defined(RCC_APB1Periph_TIM7)
118 else if (tim == TIM7)
119 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
120#endif
121#if defined(TIM12) && defined(RCC_APB1Periph_TIM12)
122 else if (tim == TIM12)
123 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12, ENABLE);
124#endif
125#if defined(TIM13) && defined(RCC_APB1Periph_TIM13)
126 else if (tim == TIM13)
127 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, ENABLE);
128#endif
129#if defined(TIM14) && defined(RCC_APB1Periph_TIM14)
130 else if (tim == TIM14)
131 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
132#endif
133}

◆ GetTimerClockHz()

uint32_t LibXR::CH32PWM::GetTimerClockHz ( TIM_TypeDef * t)
staticprivate

Definition at line 48 of file ch32_pwm.cpp.

49{
50 RCC_ClocksTypeDef c{};
51 RCC_GetClocksFreq(&c);
52
53 const bool on_apb2 = OnAPB2(t);
54 const uint32_t pclk = on_apb2 ? c.PCLK2_Frequency : c.PCLK1_Frequency;
55 const uint32_t hclk = c.HCLK_Frequency;
56
57 if (pclk == 0u || hclk == 0u) return 0u;
58
59 // APB 预分频 = HCLK / PCLK。=1 表示不分频;>1 表示分频,此时 TIMxCLK = 2 * PCLKx。
60 const uint32_t apb_div = hclk / pclk; // 1/2/4/8/16(取整足够)
61 const uint32_t timclk = (apb_div > 1u) ? (pclk * 2u) : pclk;
62
63 return timclk;
64}

◆ IsAdvancedTimer()

bool LibXR::CH32PWM::IsAdvancedTimer ( TIM_TypeDef * t)
staticprivate

Definition at line 33 of file ch32_pwm.cpp.

34{
35 return (t == TIM1)
36#if defined(TIM8)
37 || (t == TIM8)
38#endif
39#if defined(TIM9)
40 || (t == TIM9)
41#endif
42#if defined(TIM10)
43 || (t == TIM10)
44#endif
45 ;
46}

◆ OcInitForChannel()

void LibXR::CH32PWM::OcInitForChannel ( uint32_t pulse)
private

Definition at line 283 of file ch32_pwm.cpp.

284{
285 TIM_OCInitTypeDef oc{};
286 oc.TIM_OCMode = TIM_OCMode_PWM1;
287 oc.TIM_OutputState = TIM_OutputState_Enable;
288 oc.TIM_Pulse = static_cast<uint16_t>(pulse);
289 oc.TIM_OCPolarity = active_high_ ? TIM_OCPolarity_High : TIM_OCPolarity_Low;
290
291#if defined(TIM_OCNPolarity_High)
292 if (complementary_ && IsAdvancedTimer(tim_))
293 {
294 oc.TIM_OutputNState = TIM_OutputNState_Enable;
295 oc.TIM_OCNPolarity = active_high_ ? TIM_OCNPolarity_High : TIM_OCNPolarity_Low;
296 }
297#endif
298
299 switch (channel_)
300 {
301 case TIM_Channel_1:
302 TIM_OC1Init(tim_, &oc);
303 TIM_OC1PreloadConfig(tim_, TIM_OCPreload_Enable);
304 break;
305 case TIM_Channel_2:
306 TIM_OC2Init(tim_, &oc);
307 TIM_OC2PreloadConfig(tim_, TIM_OCPreload_Enable);
308 break;
309 case TIM_Channel_3:
310 TIM_OC3Init(tim_, &oc);
311 TIM_OC3PreloadConfig(tim_, TIM_OCPreload_Enable);
312 break;
313 case TIM_Channel_4:
314 TIM_OC4Init(tim_, &oc);
315 TIM_OC4PreloadConfig(tim_, TIM_OCPreload_Enable);
316 break;
317 default:
318 break;
319 }
320}

◆ OnAPB2()

bool LibXR::CH32PWM::OnAPB2 ( TIM_TypeDef * t)
staticprivate

Definition at line 18 of file ch32_pwm.cpp.

19{
20 return (t == TIM1)
21#if defined(TIM8)
22 || (t == TIM8)
23#endif
24#if defined(TIM9)
25 || (t == TIM9)
26#endif
27#if defined(TIM10)
28 || (t == TIM10)
29#endif
30 ;
31}

◆ ReadARR32()

static uint32_t LibXR::CH32PWM::ReadARR32 ( TIM_TypeDef * t)
inlinestaticprivate

Definition at line 34 of file ch32_pwm.hpp.

34{ return t->ATRLR; }

◆ SetConfig()

ErrorCode LibXR::CH32PWM::SetConfig ( Configuration config)
overridevirtual

Configures the PWM settings. 配置 PWM 参数。

Parameters
configThe configuration structure containing PWM settings. 配置结构体,包含 PWM 设置。
Returns
ErrorCode indicating success or failure. 返回操作结果的错误码。

Implements LibXR::PWM.

Definition at line 171 of file ch32_pwm.cpp.

172{
173 if (!tim_) return ErrorCode::ARG_ERR;
174 if (cfg.frequency == 0u) return ErrorCode::ARG_ERR;
175
176 // 先完成引脚与(可选)重映射
177 ConfigureGPIO();
178
179 // 确保定时器时钟已开
180 EnableTIMClock(tim_);
181
182 const uint32_t timclk = GetTimerClockHz(tim_);
183 if (timclk == 0u) return ErrorCode::INIT_ERR;
184
185 // 寻找 PSC/ARR(16 位),偏向更小的 PSC 以提升占空比分辨率
186 bool found = false;
187 uint32_t best_psc = 1, best_arr = 0;
188
189 for (uint32_t psc = 1; psc <= 0xFFFFu; ++psc)
190 {
191 const uint32_t arr = timclk / (psc * cfg.frequency);
192 if (arr == 0u) break;
193 if (arr <= 0x10000u)
194 {
195 best_psc = psc;
196 best_arr = arr; // 写寄存器时用 (arr-1)
197 found = true;
198 break;
199 }
200 }
201 if (!found || best_arr == 0u) return ErrorCode::INIT_ERR;
202
203 TIM_TimeBaseInitTypeDef tb{};
204 tb.TIM_Prescaler = static_cast<uint16_t>(best_psc - 1u);
205 tb.TIM_CounterMode = TIM_CounterMode_Up;
206 tb.TIM_Period = static_cast<uint16_t>(best_arr - 1u);
207 tb.TIM_ClockDivision = TIM_CKD_DIV1;
208 tb.TIM_RepetitionCounter = 0;
209 TIM_TimeBaseInit(tim_, &tb);
210
211 // 开启 ARR 预装载
212 TIM_ARRPreloadConfig(tim_, ENABLE);
213
214 // 配置通道为 PWM1,高电平有效;初始脉宽 0
215 OcInitForChannel(0);
216
217 // 通过 UG 把预装载推入影子寄存器
218 TIM_GenerateEvent(tim_, TIM_EventSource_Update);
219
220 // 高级定时器需开启主输出(MOE)
221 if (IsAdvancedTimer(tim_))
222 {
223 TIM_CtrlPWMOutputs(tim_, ENABLE);
224 }
225 return ErrorCode::OK;
226}

◆ SetDutyCycle()

ErrorCode LibXR::CH32PWM::SetDutyCycle ( float value)
overridevirtual

Sets the duty cycle of the PWM signal. 设置 PWM 信号的占空比。

Parameters
valueThe duty cycle as a floating-point value (0.0 to 1.0). 占空比,浮点值(0.0 到 1.0)。
Returns
ErrorCode indicating success or failure. 返回操作结果的错误码。

Implements LibXR::PWM.

Definition at line 157 of file ch32_pwm.cpp.

158{
159 if (!tim_) return ErrorCode::ARG_ERR;
160
161 if (value < 0.0f) value = 0.0f;
162 if (value > 1.0f) value = 1.0f;
163
164 const uint32_t arr = ReadARR32(tim_);
165 const uint32_t pulse = static_cast<uint32_t>((arr + 1u) * value + 0.5f);
166
167 ApplyCompare(pulse);
168 return ErrorCode::OK;
169}

Field Documentation

◆ active_high_

bool LibXR::CH32PWM::active_high_
private

Definition at line 23 of file ch32_pwm.hpp.

◆ channel_

uint16_t LibXR::CH32PWM::channel_
private

Definition at line 22 of file ch32_pwm.hpp.

◆ complementary_

bool LibXR::CH32PWM::complementary_
private

Definition at line 24 of file ch32_pwm.hpp.

◆ gpio_

GPIO_TypeDef* LibXR::CH32PWM::gpio_
private

Definition at line 26 of file ch32_pwm.hpp.

◆ pin_

uint16_t LibXR::CH32PWM::pin_
private

Definition at line 27 of file ch32_pwm.hpp.

◆ pin_remap_

uint32_t LibXR::CH32PWM::pin_remap_
private

Definition at line 28 of file ch32_pwm.hpp.

◆ tim_

TIM_TypeDef* LibXR::CH32PWM::tim_
private

Definition at line 21 of file ch32_pwm.hpp.


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