Skip to content

Commit f28131a

Browse files
toyowata0xc0170
authored andcommitted
[LPC812] Fixed PwmOut SCT bugs (ARMmbed#1656)
* [LPC812] Fixed PwmOut SCT bugs * Fixed 0% duty cycle output * Fixed pulse width 0 output * Remove unused comment-out code * Correct cast type for GCC toolchain * [LPC812] Fix incorrect duty cycle * The new PWM period now update existing PWM channels, so duty cycle is kept * Remove comment and unused code
1 parent f04e3dc commit f28131a

File tree

1 file changed

+34
-20
lines changed
  • libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC81X

1 file changed

+34
-20
lines changed

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC81X/pwmout_api.c

+34-20
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ static int get_available_sct() {
3737
// Find available output channel 0..3
3838
// Also need one Match register per channel
3939
for (i = 0; i < CONFIG_SCT_nOU; i++) {
40-
// for (i = 0; i < 4; i++) {
4140
if ((sct_used & (1 << i)) == 0)
4241
return i;
4342
}
@@ -47,7 +46,7 @@ static int get_available_sct() {
4746
// Any Port pin may be used for PWM.
4847
// Max number of PWM outputs is 4
4948
void pwmout_init(pwmout_t* obj, PinName pin) {
50-
MBED_ASSERT(pin != (uint32_t)NC);
49+
MBED_ASSERT(pin != (PinName)NC);
5150

5251
int sct_n = get_available_sct();
5352
if (sct_n == -1) {
@@ -72,8 +71,6 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
7271
LPC_SYSCON->PRESETCTRL |= (1 << 8);
7372

7473
// Two 16-bit counters, autolimit (ie reset on Match_0)
75-
//pwm->CONFIG &= ~(0x1);
76-
//pwm->CONFIG |= (1 << 17);
7774
pwm->CONFIG |= ((0x3 << 17) | 0x01);
7875

7976
// halt and clear the counter
@@ -90,9 +87,6 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
9087
// - clearing bit 2 of the CTRL register
9188
pwm->CTRL_U &= ~(1 << 2);
9289

93-
// Not using IRQs
94-
//NVIC_SetVector(PWM_IRQn, (uint32_t)pwm_irq_handler);
95-
//NVIC_EnableIRQ(PWM_IRQn);
9690
}
9791

9892
// LPC81x has only one SCT and 4 Outputs
@@ -157,6 +151,14 @@ void pwmout_write(pwmout_t* obj, float value) {
157151
// Match_0 is PWM period. Compute new endtime of pulse for current channel
158152
uint32_t t_off = (uint32_t)((float)(obj->pwm->MATCHREL[0].U) * value);
159153
obj->pwm->MATCHREL[(obj->pwm_ch) + 1].U = t_off; // New endtime
154+
155+
if (value == 0.0f) { // duty is 0%
156+
// Set CLR event to be same as SET event, makes output to be 0 (low)
157+
obj->pwm->OUT[(obj->pwm_ch)].CLR = (1 << 0);
158+
} else {
159+
// Use normal CLR event (current SCT ch + 1)
160+
obj->pwm->OUT[(obj->pwm_ch)].CLR = (1 << ((obj->pwm_ch) + 1));
161+
}
160162
}
161163

162164
// Get dutycycle (0.0 .. 1.0)
@@ -190,20 +192,26 @@ void pwmout_period_us(pwmout_t* obj, int us) {
190192
uint32_t t_period = obj->pwm->MATCHREL[0].U; // Current PWM period
191193
obj->pwm->MATCHREL[0].U = (uint32_t)us; // New PWM period
192194

193-
//Keep the dutycycle for the new PWM period
194-
//Should really do this for all active channels!!
195-
//This problem exists in all mbed libs.
196-
197-
//Sanity check
195+
// Sanity check
198196
if (t_period == 0) {
199-
return;
200-
// obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L = 0; // New endtime for this channel
197+
return;
198+
}
199+
else {
200+
int cnt = sct_used;
201+
int ch = 0;
202+
// Update match period for exising PWM channels
203+
do {
204+
// Get current pulse width
205+
uint32_t t_off = obj->pwm->MATCHREL[ch + 1].U;
206+
// Get the duty
207+
float v = (float)t_off/(float)t_period;
208+
// Update pulse width for this channel
209+
obj->pwm->MATCHREL[ch + 1].U = (uint32_t)((float)us * (float)v);
210+
// Get next used SCT channel
211+
cnt = cnt >> 1;
212+
ch++;
213+
} while (cnt != 0);
201214
}
202-
else {
203-
uint32_t t_off = obj->pwm->MATCHREL[(obj->pwm_ch) + 1].U;
204-
float v = (float)t_off/(float)t_period;
205-
obj->pwm->MATCHREL[(obj->pwm_ch) + 1].U = (uint32_t)((float)us * (float)v); // New endtime for this channel
206-
}
207215
}
208216

209217

@@ -219,7 +227,13 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms){
219227

220228
//Set pulsewidth
221229
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
222-
230+
if (us == 0) { // pulse width is 0
231+
// Set CLR event to be same as SET event, makes output to be 0 (low)
232+
obj->pwm->OUT[(obj->pwm_ch)].CLR = (1 << 0);
233+
} else {
234+
// Use normal CLR event (current SCT ch + 1)
235+
obj->pwm->OUT[(obj->pwm_ch)].CLR = (1 << ((obj->pwm_ch) + 1));
236+
}
223237
//Should add Sanity check to make sure pulsewidth < period!
224238
obj->pwm->MATCHREL[(obj->pwm_ch) + 1].U = (uint32_t)us; // New endtime for this channel
225239
}

0 commit comments

Comments
 (0)