libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
hpm_pwm.cpp
1#include "hpm_pwm.hpp"
2
3using namespace LibXR;
4
5uint8_t HPMPWM::ResolveGptmrReloadCmpIndex(uint8_t duty_cmp_index)
6{
7 if (duty_cmp_index >= GPTMR_CH_CMP_COUNT)
8 {
9 return INVALID_CMP_INDEX;
10 }
11 return static_cast<uint8_t>(duty_cmp_index == 0u ? 1u : 0u);
12}
13
24HPMPWM::HPMPWM(LibXRHpmPwmType* pwm, clock_name_t clock, uint8_t pwm_index,
25 uint8_t cmp_index, Polarity polarity)
26 : pwm_(pwm),
27 gptmr_(reinterpret_cast<GPTMR_Type*>(pwm)),
28 clock_(clock),
29 pwm_index_(pwm_index),
30 cmp_index_(cmp_index),
31 invert_(polarity == Polarity::INVERTED),
32 reload_(0),
33 configured_(false)
34{
35}
36
38{
39 if (!configured_)
40 {
42 }
43
44 if (value < 0.0f)
45 {
46 value = 0.0f;
47 }
48 else if (value > 1.0f)
49 {
50 value = 1.0f;
51 }
52
53#if LIBXR_HPM_PWM_SUPPORTED
54 const float duty_percent = value * 100.0f;
55 if (pwm_update_duty_edge_aligned(pwm_, cmp_index_, duty_percent) != status_success)
56 {
57 return ErrorCode::FAILED;
58 }
59#elif LIBXR_HPM_GPTMR_PWM_FALLBACK
60 // GPTMR 比较值不允许落在 0 或 reload,避免输出退化成常高/常低。
61 // Keep compare away from 0/reload to avoid constant-high/constant-low output.
62 uint32_t cmp = static_cast<uint32_t>(static_cast<float>(reload_) * value);
63 if (cmp == 0u)
64 {
65 cmp = 1u;
66 }
67 else if (cmp >= reload_)
68 {
69 cmp = reload_ - 1u;
70 }
71 gptmr_update_cmp(gptmr_, pwm_index_, cmp_index_, cmp);
72#else
73 (void)value;
75#endif
76
77 return ErrorCode::OK;
78}
79
81{
82 if (config.frequency == 0u)
83 {
84 return ErrorCode::ARG_ERR;
85 }
86
87 const uint32_t clock_hz = clock_get_frequency(clock_);
88
89 if (clock_hz == 0u)
90 {
92 }
93
94 uint32_t reload = clock_hz / config.frequency;
95 if (reload == 0u || reload > 0xFFFFFFu)
96 {
98 }
99 reload_ = reload;
100
101#if LIBXR_HPM_PWM_SUPPORTED
102 pwm_stop_counter(pwm_);
103
104 pwm_config_t pwm_config{};
105 pwm_cmp_config_t cmp_config{};
106
107 pwm_get_default_pwm_config(pwm_, &pwm_config);
108 pwm_get_default_cmp_config(pwm_, &cmp_config);
109
110 pwm_config.enable_output = true;
111 pwm_config.invert_output = invert_;
112 pwm_config.dead_zone_in_half_cycle = 0;
113
114 pwm_set_reload(pwm_, 0, reload_);
115 pwm_set_start_count(pwm_, 0, 0);
116
117 cmp_config.mode = pwm_cmp_mode_output_compare;
118 cmp_config.cmp = reload_ + 1;
119 cmp_config.update_trigger = pwm_shadow_register_update_on_modify;
120
121 if (pwm_setup_waveform(pwm_, pwm_index_, &pwm_config, cmp_index_, &cmp_config, 1) !=
122 status_success)
123 {
124 return ErrorCode::INIT_ERR;
125 }
126
127 pwm_issue_shadow_register_lock_event(pwm_);
128#elif LIBXR_HPM_GPTMR_PWM_FALLBACK
129 if (gptmr_ == nullptr)
130 {
131 return ErrorCode::ARG_ERR;
132 }
133
134 const uint8_t reload_cmp_index = ResolveGptmrReloadCmpIndex(cmp_index_);
135 if (reload_cmp_index == INVALID_CMP_INDEX)
136 {
137 return ErrorCode::ARG_ERR;
138 }
139
140 // 重新配置前先停计数器,避免切换参数时输出毛刺。
141 // Stop counter before reconfiguration to avoid output glitches.
142 gptmr_stop_counter(gptmr_, pwm_index_);
143
144 gptmr_channel_config_t cfg;
145 gptmr_channel_get_default_config(gptmr_, &cfg);
146 cfg.mode = gptmr_work_mode_no_capture;
147 cfg.cmp_initial_polarity_high = invert_;
148 cfg.enable_cmp_output = true;
149 cfg.reload = reload_;
150 cfg.cmp[cmp_index_] = reload_ / 2u;
151 cfg.cmp[reload_cmp_index] = reload_;
152
153 if (gptmr_channel_config(gptmr_, pwm_index_, &cfg, false) != status_success)
154 {
155 return ErrorCode::INIT_ERR;
156 }
157 gptmr_channel_reset_count(gptmr_, pwm_index_);
158#else
160#endif
161
162 configured_ = true;
163 return ErrorCode::OK;
164}
165
167{
168 if (!configured_)
169 {
170 return ErrorCode::INIT_ERR;
171 }
172
173#if LIBXR_HPM_PWM_SUPPORTED
174 pwm_start_counter(pwm_);
175#elif LIBXR_HPM_GPTMR_PWM_FALLBACK
176 gptmr_start_counter(gptmr_, pwm_index_);
177#else
179#endif
180
181 return ErrorCode::OK;
182}
183
185{
186#if LIBXR_HPM_PWM_SUPPORTED
187 pwm_stop_counter(pwm_);
188#elif LIBXR_HPM_GPTMR_PWM_FALLBACK
189 gptmr_stop_counter(gptmr_, pwm_index_);
190#else
192#endif
193 return ErrorCode::OK;
194}
Polarity
输出极性 / Output polarity.
Definition hpm_pwm.hpp:35
HPMPWM(LibXRHpmPwmType *pwm, clock_name_t clock, uint8_t pwm_index, uint8_t cmp_index, Polarity polarity)
构造 HPM PWM 对象 / Construct an HPM PWM object.
Definition hpm_pwm.cpp:24
ErrorCode Disable() override
停止 PWM 输出 / Stop PWM output.
Definition hpm_pwm.cpp:184
ErrorCode SetDutyCycle(float value) override
设置占空比 / Set PWM duty cycle.
Definition hpm_pwm.cpp:37
ErrorCode Enable() override
启动 PWM 输出 / Start PWM output.
Definition hpm_pwm.cpp:166
ErrorCode SetConfig(Configuration config) override
配置 PWM 频率 / Configure PWM frequency.
Definition hpm_pwm.cpp:80
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ INIT_ERR
初始化错误 / Initialization error
@ NOT_SUPPORT
不支持 / Not supported
@ FAILED
操作失败 / Operation failed
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
PWM 配置参数 / Configuration parameters for PWM.
Definition pwm.hpp:23
uint32_t frequency
PWM 信号的频率(Hz) / PWM signal frequency in Hz.
Definition pwm.hpp:24