How does you generate complementary PWM Outputs?
I would like to generate complementary PWM Outputs with adjustable dead time.
According to the STM32F401RE microcontroller datasheet
http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1577/LN1810/PF258797,
This was possible with Timer 1 (TIM1).
So far I has attempted to configure the timer myself using information available from the TIM HAL Driver from ST:
Http://developer.mbed.org/users/dreschpe/code/mbed-F401/docs/4e95b79aa640/stm32f4xx__hal__tim__ex_8c.html
And looking through an example of someone using the driver:
https://petoknm.wordpress.com/2015/01/05/rotary-encoder-and-stm32/.
Obviously, I do not want-a HAL sensor, but the closest example I can get-to-someone using the Advanced feat Ures of the timers.
thanks!
Damien
Edit:here is the code I went with the end:
voidCONFIGUREPWM (floatDuty_us,floatPeriod_us) {unsignedintvalue; floatnewval; //ensure power is turned on//grabbed from lines 54-57 of analogin_api.h, modified for PWM//This turns on the clock to Ports A, B, and CRcc->ahb1enr |= Rcc_ahb1enr_gpioaen | Rcc_ahb1enr_gpioben |Rcc_ahb1enr_gpiocen; //This turns on the clock to the time 1:Rcc->apb2enr |=Rcc_apb2enr_tim1en; //Set the GPIO Ports properly://PWM1 is connected to Pa_8//pwm1n is connected to pa_7//Set the PWM outputs to general output pins://This sets the pa_7 and pa_8 pins to Alternate Function pinsValue =0x8000+0x20000; Gpioa->moder |=value; //Set the PWM outputs to high speed:Value =0xc000+0x30000; Gpioa->ospeedr |=value; //Set PWM as outputs to the pins:Value = gpioa->afr[1]; //Reset the lowest four bits:Value &=0xfffffff0; //Configure pa_8 to AF:Value |=0x1; Gpioa->afr[1] =value; Value= gpioa->afr[0]; //Reset the 4 MSB:Value &=0x0fffffff; //Configure pa_7 to AF:Value |=0x10000000; Gpioa->afr[0] =value; //Set pull down resistors to PWM outputs:Value = gpioa->pupdr; //Clear the bits:Value &= ~ (GPIO_PUPDR_PUPDR7 |gpio_pupdr_pupdr8); //Set to pull down:Value |= Gpio_pupdr_pupdr7_1 |Gpio_pupdr_pupdr8_1; //Set The Register:Gpioa->pupdr =value; //Set the Prescale value to 1: TIM1->PSC = 0 ; //* * * TIM1 control Register 1:TIMX_CR1 * * *Value =0; //[9:8] Set CKD bits to zero for clock division of 1//[7] Timx_arr Register is buffered, set the Arpe bit to 1://value |= 0x80; //[6:5] Set CMS bits to zero for edge aligned mode//[6:5] Set CMS bits to ten for Center Aligned mode 2, up-down mode with flags Set when counter reaches the top. //value |= tim_cr1_cms_1; //[4] Set DIR bit to zero for upcounting//[3] Set OPM bit to zero so, the counter is not stopped at update event//[2] Set URS bit to zero so the anything can create an interrupt//[1] Set Udis bit to zero-generate an update event//[0] Set the CEN bit to zero to disable the counter//* Set the TIMX_CR1 Register: * TIM1->CR1 |= value; //* * * TIM1 control Register 2:TIMX_CR2 * * *Value =0; //Set OIS4 bit to zero, and the idle state of OC4 output//Set ois3n bit to zero, and the idle state of oc3n output//Set OIS3 bit to zero, and the idle state of OC3 output//[one] Set ois2n bit to zero, and the idle state of OC2N output//[ten] Set OIS2 bit to zero, the idle state of OC2 output//[9] Set ois1n bit to zero, the idle state of OC1N output//[8] Set OIS1 bit to zero, the idle state of OC1 output//[7] Set ti1s bit to zero, connecting only CH1 pin to TI1 input//[6:4] Set to 111:the oc4ref signal is used as trigger output (Trgo)//Value |= tim_cr2_mms_2 | Tim_cr2_mms_1 | Tim_cr2_mms_0; // Value |= Tim_cr2_mms_1 | Tim_cr2_mms_0; //[3] Set CCDS bit to zero, request sent when CCx event occurs//[2] Set CCUS bit to 1, Capture/compare control bits is updated by setting the COMG bit or when a rising edge occurs On Trgi// value |= 0x4; //[0] Set CCPC bit to 1, Ccxe, Ccxne and OCXM is update on a commutation event, or rising edge on Trgi// value |= 0x1; //* Set the TIMX_CR2 Register: * TIM1->CR2 = value; //* * * TIM1 Auto Reload Register:arr * * *Value =0; //[15:0] Set ARR bits to the frequency to being loaded in:newval = Ceil (period_us/Pwmstep_us); Value= (unsignedint) newval; //* Set the Timx_arr Register: Tim1->arr = value; //* * * TIM1 capture/compare Register 1:CCR1 * * *Value =0; //[15:0] Set the capture compare value to the duty cycle:newval = Ceil (duty_us/Pwmstep_us); Value= (unsignedint) newval; //* Set the TIMX_CCR1 Register: TIM1->CCR1 = value; //* * * TIM1 capture/compare Register 4:CCR4 * * *Value =0; //[15:0] Set the capture compare value to the duty cycle:newval = Ceil (duty_us/2.0f/Pwmstep_us); Value= (unsignedint) newval; //* Set the TIMX_CCR1 Register: TIM1->CCR4 = Tim1->arr- Ch4shift; //* * * TIM1 capture/compare mode register 2:CCMR2Value =0; //[[] Set oc4ce bit to 0, oc4ref are not affected by the ETRF input//[14-12] Set the oc4m bits to ' + ', PWM mode 1, which is what we want I think.Value |= tim_ccmr2_oc4m_2 |tim_ccmr2_oc4m_1; //[one] Set the OC4PE bit to 1, meaning read/write operations to the preload event require an update event.Value |=0x800; //Set the OC4FE bit to 0, the output compare fast enable is disabled//[9:8] Set the cc4s bits to 0, the channel is configured as an output. //* Set the TIMX_CCMR2 Register: * TIM1->CCMR2 = value; //* * * TIM1 capture/compare mode register 1:CCMR1Value =0; //[7] Set Oc1ce bit to 0, oc1ref are not affected by the ETRF input//[6-4] Set the oc1m bits to ' + ', PWM mode 1, which is what we want I think.Value |= tim_ccmr1_oc1m_2 |tim_ccmr1_oc1m_1; //[3] Set the OC1PE bit to 1, meaning read/write operations to the preload event require an update event.Value |=0x8; //[2] Set the OC1FE bit to 0, the output compare fast enable is disabled//[1:0] Set the cc1s bits to 0, the channel is configured as an output. //* Set the TIMX_CCMR1 Register: * TIM1->CCMR1 = value; //* * * TIM1 capture/compare enable Register:ccerValue =0; //[15:4]-Don ' t care://[3] Set CC1NP bit to zero for active high. //[2] Set cc1ne bit to 0, to de-activate the OC1N signal//value |= 0x4; //[1] Set the cc1p bit to zero for active high. //[0] Set the CC1E bit to 1, to de-activate the OC1 signal//value |= 0x1; //* Set the Tim1_ccer Register: * Tim1->ccer = value; //* * * TIM1 break and Dead-time REGISTER:BDTRValue =0; //Set MOE bit to 1 to enable the OC and OCN outputsValue |=0x8000; //[one] Set the OSSR bit such that the ouputs is forced to their idle mode is not running//value |= TIM_BDTR_OSSR; //[ten] Set Ossi bit such that the outputs is forced to their idle mode when MOE = 0Value |=Tim_bdtr_ossi; //* Set The TIM1_BDTR register: TIM1->BDTR = value; //* * * TIM1 dma/interrupt enable Register:dierValue =0; //[2] Set the Cc1ie bit to 1, to trigger an interrupt when counter 1 have a match-which should be half it through the Duty cycle.Value |=Tim_dier_cc4ie; //Set The Tim1_dier register: Tim1->dier |= value; //Set the UG bit in the EGR register to kick things off:Value =3; TIM1 ->egr = value; //Configure the interrupt:Nvic_setvector (TIM1_CC_IRQN, (uint32_t) &Tim1_cc_irqhandler); NVIC_ENABLEIRQ (TIM1_CC_IRQN); return; }
Stm32f4 How does you generate complementary PWM Outputs?