diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c index 1dc6775..c497b6b 100644 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -104,9 +104,23 @@ It is recommended to enable the timer in the following order: */ void analogWrite(uint32_t PinNumber, uint32_t writeVal) { - if (digitalPinHasPWM(PinNumber)) + if (writeVal > WriteValMax) writeVal = WriteValMax; + + if (digitalPinPwmIsOn(PinNumber) > 0) // pin has pwm and pwm is already on { - if (writeVal > WriteValMax) writeVal = WriteValMax; + // we can only change writeVal if it is differ from current value + TIMER32_TypeDef* timer = pwmPinToTimer(PinNumber); + uint32_t newOCR = (uint32_t) (((uint64_t)pwmTopVal * writeVal) / WriteValMax); + if (timer->CHANNELS[pwmPinToTimerChannel(PinNumber)].OCR != newOCR) + { + // if new ocr differs from current, set new ocr + timer->CHANNELS[pwmPinToTimerChannel(PinNumber)].OCR = newOCR; + } + } + else if (digitalPinPwmIsOn(PinNumber) == 0) // pin has pwm and pwm is off + { + // init pin as pwm + uint32_t OCRval = (uint32_t) (((uint64_t)pwmTopVal * writeVal) / WriteValMax); // initialization of the required timer htimer32.Instance = pwmPinToTimer(PinNumber); @@ -127,7 +141,7 @@ void analogWrite(uint32_t PinNumber, uint32_t writeVal) htimer32_channel.PWM_Invert = TIMER32_CHANNEL_NON_INVERTED_PWM; htimer32_channel.Mode = TIMER32_CHANNEL_MODE_PWM; htimer32_channel.CaptureEdge = TIMER32_CHANNEL_CAPTUREEDGE_RISING; - htimer32_channel.OCR = (uint32_t) (((uint64_t)pwmTopVal * writeVal) / WriteValMax); + htimer32_channel.OCR = OCRval; htimer32_channel.Noise = TIMER32_CHANNEL_FILTER_OFF; HAL_Timer32_Channel_Init(&htimer32_channel); @@ -137,7 +151,7 @@ void analogWrite(uint32_t PinNumber, uint32_t writeVal) HAL_Timer32_Start(&htimer32); pwmIsInited++; // increase inited channels qty } - else + else // pin doesn't have pwm ErrorMsgHandler("analogWrite(): invalid pwm pin number"); } @@ -168,14 +182,17 @@ It is recommended to turn off the timer in the following order: - Write 0 to the INT_CLEAR register; - Set TIM_EN to 0. */ +// use only if digitalPinPwmIsOn(PinNumber) > 0 void analogWriteStop(uint32_t PinNumber) { - if (digitalPinHasPWM(PinNumber) && (pwmIsInited > 0) && digitalPinPwmIsOn(PinNumber)) + if ((pwmIsInited > 0)) { // load the timer address and channel number corresponding to the specified pin htimer32.Instance = pwmPinToTimer(PinNumber); - htimer32_channel.TimerInstance = htimer32.Instance; htimer32_channel.ChannelIndex = pwmPinToTimerChannel(PinNumber); + htimer32.Instance->CHANNELS[htimer32_channel.ChannelIndex].OCR = 0; + htimer32_channel.TimerInstance = htimer32.Instance; + // deinit channel HAL_Timer32_Channel_DeInit(&htimer32_channel); pwmIsInited--; // decrease inited channels qty