@@ -66,8 +66,6 @@ static LPC_CTxxBx_Type *Timers[4] = {
66
66
LPC_CT32B0 , LPC_CT32B1
67
67
};
68
68
69
- static unsigned int pwm_clock_mhz ;
70
-
71
69
void pwmout_init (pwmout_t * obj , PinName pin ) {
72
70
// determine the channel
73
71
PWMName pwm = (PWMName )pinmap_peripheral (pin , PinMap_PWM );
@@ -92,8 +90,6 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
92
90
/* Reset Functionality on MR3 controlling the PWM period */
93
91
timer -> MCR = 1 << 10 ;
94
92
95
- pwm_clock_mhz = SystemCoreClock / 1000000 ;
96
-
97
93
// default to 20ms: standard for servos, and fine for e.g. brightness control
98
94
pwmout_period_ms (obj , 20 );
99
95
pwmout_write (obj , 0 );
@@ -141,11 +137,18 @@ void pwmout_period_ms(pwmout_t* obj, int ms) {
141
137
// Set the PWM period, keeping the duty cycle the same.
142
138
void pwmout_period_us (pwmout_t * obj , int us ) {
143
139
int i = 0 ;
144
- uint32_t period_ticks = pwm_clock_mhz * us ;
140
+ uint32_t period_ticks = ( uint32_t )((( uint64_t ) SystemCoreClock * ( uint64_t ) us ) / ( uint64_t ) 1000000 ) ;
145
141
146
142
timer_mr tid = pwm_timer_map [obj -> pwm ];
147
143
LPC_CTxxBx_Type * timer = Timers [tid .timer ];
148
144
uint32_t old_period_ticks = timer -> MR3 ;
145
+
146
+ // for 16bit timer, set prescaler to avoid overflow
147
+ uint16_t high_period_ticks = period_ticks >> 16 ;
148
+ if ((high_period_ticks ) && (timer == LPC_CT16B0 || timer == LPC_CT16B1 )) {
149
+ timer -> PR = high_period_ticks ;
150
+ period_ticks /= (high_period_ticks + 1 );
151
+ }
149
152
150
153
timer -> TCR = TCR_RESET ;
151
154
timer -> MR3 = period_ticks ;
@@ -169,13 +172,14 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
169
172
}
170
173
171
174
void pwmout_pulsewidth_us (pwmout_t * obj , int us ) {
172
- uint32_t t_on = (uint32_t )(((uint64_t )SystemCoreClock * (uint64_t )us ) / (uint64_t )1000000 );
173
175
timer_mr tid = pwm_timer_map [obj -> pwm ];
174
176
LPC_CTxxBx_Type * timer = Timers [tid .timer ];
177
+ uint32_t t_on = (uint32_t )(((uint64_t )SystemCoreClock * (uint64_t )us ) / (uint64_t )1000000 / (timer -> PR + 1 ));
175
178
176
179
timer -> TCR = TCR_RESET ;
177
180
if (t_on > timer -> MR3 ) {
178
181
pwmout_period_us (obj , us );
182
+ t_on = (uint32_t )(((uint64_t )SystemCoreClock * (uint64_t )us ) / (uint64_t )1000000 / (timer -> PR + 1 ));
179
183
}
180
184
uint32_t t_off = timer -> MR3 - t_on ;
181
185
timer -> MR [tid .mr ] = t_off ;
0 commit comments