diff --git a/docs/mimxrt/quickref.rst b/docs/mimxrt/quickref.rst index cfd0605054a7b..34e0aa79f139f 100644 --- a/docs/mimxrt/quickref.rst +++ b/docs/mimxrt/quickref.rst @@ -193,7 +193,7 @@ PWM Constructor - *freq* should be an integer which sets the frequency in Hz for the PWM cycle. The valid frequency range is 15 Hz resp. 18Hz resp. 24Hz up to > 1 MHz. - - *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65536``. + - *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65535``. The duty cycle of a X channel can only be changed, if the A and B channel of the respective submodule is not used. Otherwise the duty_16 value of the X channel is 32768 (50%). @@ -231,7 +231,7 @@ is created by dividing the pwm_clk signal by an integral factor, according to th f = pwm_clk / (2**n * m) -with n being in the range of 0..7, and m in the range of 2..65536. pmw_clk is 125Mhz +with n being in the range of 0..7, and m in the range of 2..65535. pmw_clk is 125Mhz for MIMXRT1010/1015/1020, 150 MHz for MIMXRT1050/1060/1064 and 160MHz for MIMXRT1170. The lowest frequency is pwm_clk/2**23 (15, 18, 20Hz). The highest frequency with U16 resolution is pwm_clk/2**16 (1907, 2288, 2441 Hz), the highest frequency @@ -255,7 +255,7 @@ Use the :ref:`machine.ADC ` class:: from machine import ADC adc = ADC(Pin('A2')) # create ADC object on ADC pin - adc.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v + adc.read_u16() # read value, 0-65535 across voltage range 0.0v - 3.3v The resolution of the ADC is 12 bit with 10 to 11 bit accuracy, irrespective of the value returned by read_u16(). If you need a higher resolution or better accuracy, use diff --git a/docs/samd/quickref.rst b/docs/samd/quickref.rst index 25b5a8fc8ab2b..d57dc67908398 100644 --- a/docs/samd/quickref.rst +++ b/docs/samd/quickref.rst @@ -215,7 +215,7 @@ PWM Constructor - *freq* should be an integer which sets the frequency in Hz for the PWM cycle. The valid frequency range is 1 Hz to 24 MHz. - - *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65536``. + - *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65535``. - *duty_ns* sets the pulse width in nanoseconds. The limitation for X channels apply as well. - *invert*\=True|False. Setting a bit inverts the respective output. @@ -246,7 +246,7 @@ Use the :ref:`machine.ADC ` class:: from machine import ADC adc0 = ADC(Pin('A0')) # create ADC object on ADC pin, average=16 - adc0.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v + adc0.read_u16() # read value, 0-65535 across voltage range 0.0v - 3.3v adc1 = ADC(Pin('A1'), average=1) # create ADC object on ADC pin, average=1 The resolution of the ADC is 12 bit with 12 bit accuracy, irrespective of the diff --git a/ports/esp8266/machine_pwm.c b/ports/esp8266/machine_pwm.c index 25a2d6898f7c7..0d5ed595428e3 100644 --- a/ports/esp8266/machine_pwm.c +++ b/ports/esp8266/machine_pwm.c @@ -80,7 +80,7 @@ static void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, c pwm_set_duty(args[ARG_duty].u_int, self->channel); } if (args[ARG_duty_u16].u_int != -1) { - pwm_set_duty(args[ARG_duty_u16].u_int * 1000 / 65536, self->channel); + pwm_set_duty(args[ARG_duty_u16].u_int * 1000 / 65535, self->channel); } if (args[ARG_duty_ns].u_int != -1) { uint32_t freq = pwm_get_freq(0); @@ -164,13 +164,13 @@ static void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty) { static mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) { set_active(self, true); - return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel) * 65536 / 1024); + return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel) * 65535 / 1024); } static void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty) { set_active(self, false); self->duty_ns = -1; - pwm_set_duty(duty * 1024 / 65536, self->channel); + pwm_set_duty(duty * 1024 / 65535, self->channel); pwm_start(); } diff --git a/ports/mimxrt/hal/pwm_backport.c b/ports/mimxrt/hal/pwm_backport.c index 7732e0e8167c8..7815fd1dff57d 100644 --- a/ports/mimxrt/hal/pwm_backport.c +++ b/ports/mimxrt/hal/pwm_backport.c @@ -36,7 +36,7 @@ void PWM_UpdatePwmDutycycle_u16( // Setup the PWM dutycycle of channel A or B if (pwmSignal == kPWM_PwmA) { - if (dutyCycle >= 65536) { + if (dutyCycle >= PWM_FULL_SCALE) { base->SM[subModule].VAL2 = 0; base->SM[subModule].VAL3 = pulseCnt; } else { @@ -44,7 +44,7 @@ void PWM_UpdatePwmDutycycle_u16( base->SM[subModule].VAL3 = base->SM[subModule].VAL2 + pwmHighPulse; } } else { - if (dutyCycle >= 65536) { + if (dutyCycle >= PWM_FULL_SCALE) { base->SM[subModule].VAL4 = 0; base->SM[subModule].VAL5 = pulseCnt; } else { @@ -110,12 +110,8 @@ void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule, base->SM[subModule].OCTRL = (base->SM[subModule].OCTRL & ~PWM_OCTRL_POLX_MASK) | PWM_OCTRL_POLX(!invert); - // Switch the output on or off. - if (duty_cycle == 0) { - base->OUTEN &= ~(1U << subModule); - } else { - base->OUTEN |= (1U << subModule); - } + // Enable PWM output + base->OUTEN |= (1U << subModule); } #ifdef FSL_FEATURE_SOC_TMR_COUNT @@ -160,7 +156,7 @@ status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uin if (dutyCycleU16 == 0) { // Clear the output at the next compare reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ClearOnCompare)); - } else if (dutyCycleU16 >= 65536) { + } else if (dutyCycleU16 >= PWM_FULL_SCALE) { // Set the output at the next compare reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_SetOnCompare)); } else { diff --git a/ports/mimxrt/hal/pwm_backport.h b/ports/mimxrt/hal/pwm_backport.h index 04899173e20b3..9c9f6811add28 100644 --- a/ports/mimxrt/hal/pwm_backport.h +++ b/ports/mimxrt/hal/pwm_backport.h @@ -24,7 +24,7 @@ typedef struct _pwm_signal_param_u16 uint16_t deadtimeValue; // The deadtime value; only used if channel pair is operating in complementary mode } pwm_signal_param_u16_t; -#define PWM_FULL_SCALE (65536UL) +#define PWM_FULL_SCALE (65535UL) void PWM_UpdatePwmDutycycle_u16(PWM_Type *base, pwm_submodule_t subModule, pwm_channels_t pwmSignal, uint32_t dutyCycle, uint16_t center); diff --git a/ports/mimxrt/machine_pwm.c b/ports/mimxrt/machine_pwm.c index f9ae5e22edcc3..b68521281ae6c 100644 --- a/ports/mimxrt/machine_pwm.c +++ b/ports/mimxrt/machine_pwm.c @@ -45,6 +45,8 @@ typedef struct _machine_pwm_obj_t { mp_obj_base_t base; PWM_Type *instance; + const machine_pin_obj_t *pwm_pin; + const machine_pin_af_obj_t *pwm_pin_af_obj; bool is_flexpwm; uint8_t complementary; uint8_t module; @@ -255,6 +257,8 @@ static void configure_flexpwm(machine_pwm_obj_t *self) { PWM_SetupFaultDisableMap(self->instance, self->submodule, self->channel2, kPWM_faultchannel_1, 0); } + // clear the load okay bit for the submodules in case there is a pending load + PWM_SetPwmLdok(self->instance, 1 << self->submodule, false); if (self->channel1 != kPWM_PwmX) { // Only for A/B channels // Initialize the channel parameters pwmSignal.pwmChannel = self->channel1; @@ -283,6 +287,17 @@ static void configure_flexpwm(machine_pwm_obj_t *self) { self->instance->SM[self->submodule].CTRL &= ~(PWM_CTRL_DBLEN_MASK | PWM_CTRL_SPLIT_MASK); } } else { + if (self->duty_u16 == 0) { + // For duty_u16 == 0 just set the output to GPIO mode + if (self->invert) { + mp_hal_pin_high(self->pwm_pin); + } else { + mp_hal_pin_low(self->pwm_pin); + } + IOMUXC_SetPinMux(self->pwm_pin->muxRegister, PIN_AF_MODE_ALT5, 0, 0, 0, 0U); + } else { + IOMUXC_SetPinMux(self->pwm_pin->muxRegister, self->pwm_pin_af_obj->af_mode, 0, 0, 0, 0U); + } PWM_SetupPwmx_u16(self->instance, self->submodule, self->freq, self->duty_u16, self->invert, pwmSourceClockInHz); if (self->xor) { @@ -408,12 +423,16 @@ static void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, } self->center = center; } else { // Use alignment setting shortcut - if (args[ARG_align].u_int >= 0) { + uint32_t duty = self->duty_u16; + if (duty == VALUE_NOT_SET && self->duty_ns != VALUE_NOT_SET) { + duty = duty_ns_to_duty_u16(self->freq, self->duty_ns); + } + if (args[ARG_align].u_int >= 0 && duty != VALUE_NOT_SET && self->freq != VALUE_NOT_SET) { uint8_t align = args[ARG_align].u_int & 3; // limit to 0..3 if (align == PWM_BEGIN) { - self->center = self->duty_u16 / 2; + self->center = duty / 2; } else if (align == PWM_END) { - self->center = PWM_FULL_SCALE - self->duty_u16 / 2; + self->center = PWM_FULL_SCALE - duty / 2; } else { self->center = 32768; // Default value: mid. } @@ -515,6 +534,8 @@ static mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args // Create and populate the PWM object. machine_pwm_obj_t *self = mp_obj_malloc(machine_pwm_obj_t, &machine_pwm_type); + self->pwm_pin = pin1; + self->pwm_pin_af_obj = af_obj1; self->is_flexpwm = is_flexpwm; self->instance = af_obj1->instance; self->module = module; @@ -534,6 +555,8 @@ static mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args // Initialize the Pin(s). CLOCK_EnableClock(kCLOCK_Iomuxc); // just in case it was not set yet + // Configure PWMX channels to pin output mode to be prepared for duty_u16 == 0. + mp_hal_pin_output(pin1); IOMUXC_SetPinMux(pin1->muxRegister, af_obj1->af_mode, af_obj1->input_register, af_obj1->input_daisy, pin1->configRegister, 0U); IOMUXC_SetPinConfig(pin1->muxRegister, af_obj1->af_mode, af_obj1->input_register, af_obj1->input_daisy, diff --git a/ports/nrf/modules/machine/pwm.c b/ports/nrf/modules/machine/pwm.c index 8145509c76284..13d824e86674f 100644 --- a/ports/nrf/modules/machine/pwm.c +++ b/ports/nrf/modules/machine/pwm.c @@ -285,7 +285,7 @@ static mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self) { if (self->p_config->duty_mode[self->channel] == DUTY_PERCENT) { return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel]); } else if (self->p_config->duty_mode[self->channel] == DUTY_U16) { - return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel] * 100 / 65536); + return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel] * 100 / 65535); } else { return MP_OBJ_NEW_SMALL_INT(-1); } @@ -301,7 +301,7 @@ static mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) { if (self->p_config->duty_mode[self->channel] == DUTY_U16) { return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel]); } else if (self->p_config->duty_mode[self->channel] == DUTY_PERCENT) { - return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel] * 65536 / 100); + return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel] * 65535 / 100); } else { return MP_OBJ_NEW_SMALL_INT(-1); } @@ -365,7 +365,7 @@ static void machine_hard_pwm_start(const machine_pwm_obj_t *self) { if (self->p_config->duty_mode[i] == DUTY_PERCENT) { pulse_width = ((period * self->p_config->duty[i]) / 100); } else if (self->p_config->duty_mode[i] == DUTY_U16) { - pulse_width = ((period * self->p_config->duty[i]) / 65536); + pulse_width = ((period * self->p_config->duty[i]) / 65535); } else if (self->p_config->duty_mode[i] == DUTY_NS) { pulse_width = (uint64_t)self->p_config->duty[i] * tick_freq / 1000000000ULL; } diff --git a/ports/samd/machine_pwm.c b/ports/samd/machine_pwm.c index b2a383c21cba1..468e34a1653dd 100644 --- a/ports/samd/machine_pwm.c +++ b/ports/samd/machine_pwm.c @@ -54,7 +54,7 @@ typedef struct _machine_pwm_obj_t { #define PWM_CLK_READY (1) #define PWM_TCC_ENABLED (2) #define PWM_MASTER_CLK (get_peripheral_freq()) -#define PWM_FULL_SCALE (65536) +#define PWM_FULL_SCALE (65535) #define PWM_UPDATE_TIMEOUT (2000) #define VALUE_NOT_SET (-1) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy