here is my code for pwm2
Code: Select all
//initialize pwm to TxCCP_PS (prescaler) and TxCCP_PR (period)
void pwm2Init(uint16_t TxCCP_PS) {
//route the clock to timer
//route the clock to timer
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
//source from internal clock -> disable slave mode
TIM2->SMCR &=~TIM_SMCR_SMS; //clear sms->use internal clock
//stop the timer to configure it
//TIM2->CR1 &=~TIM_CR1_CEN; //clear cen. 0=disable the timer, 1=enable the timer
//TIM2->CR1 &=~TIM_CR1_CKD; //clear CKD0..1. 0b00->1x clock; 0b01->2:1 clock, 0b10->4:1 clk; 0b11->reserved
//TIM2->CR1 &=~TIM_CR1_DIR; //clear DIR bit. 0=upcounter, 1=downcounter
//TIM2->CR1 &=~TIM_CR1_OPM; //clear opm bit. 0=periodic timer, 1=one-shot timer
//or to simply zero the register
//TIM2->CR1 = 0; //much easier
TIM2->CR1 = (0<<8) | //0->1:1 clock, 1->2:1 clock, 2->4:1 clock, 3->reserved
(0<<7) | //1->APR buffered, 0->APR not buffered
(0<<5) | //0->edge-aligned, 1->center-aligned mode 1, 2->center-aligned mode 2, 3->center-aligned mode 3
(0<<4) | //0->upcounter, 1->downcounter
(0<<3) | //0->continous mode, 1->one pulse mode
(0<<2) | //update request source
(0<<1) | //0->UEV enabled, 1->UEV disabled
(0<<0) | //0->counter disabled, 1->counter enabled
0x00;
TIM2->CR2 = 0; //default value
TIM2->SMCR= 0; //default value
//set the prescaler
TIM2->PSC = TxCCP_PS - 1; //set the prescaler
TIM2->RCR = 0; //repetition counter = 0 (=no repetition)
TIM2->ARR = PWM_PR; //auto reload register / period = 0; - need to change for downcounters
TIM2->CNT = 0; //reset the counter
//clear the status register bits for capture / compare flags
TIM2->SR &=~(TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF | TIM_SR_CC4IF | TIM_SR_UIF);
//disable the interrupt by clearing the enable bits
TIM2->DIER &=~(TIM_DIER_CC1IE | TIM_DIER_CC2IE | TIM_DIER_CC3IE | TIM_DIER_CC4IE | TIM_DIER_UIE);
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; //enable AFIO
AFIO->MAPR = (AFIO->MAPR &~AFIO_MAPR_TIM2_REMAP) | (AFIO_MAPR_TIM2_REMAP & TIM2REMAP); //select the remap scheme
//configure CCP1..4
//configure CCP1
TIM2->CCMR1 = (TIM2->CCMR1 &~0x00ff) |
(0<<7) | //0->OC1REF not affedted by ETRF, 1->OC1REF cleared by ETRF high
(6<<4) | //0->frozen (for time base), 1->active on match, 2->inactive on match, 3->toggle, 4->inactive, 5->active, 6->pwm mode 1, 7->pwm mode 2
(0<<3) | //0->preload disabled, 1->preload enabled
(0<<2) | //0->fast disabled, 1->fast enabled
(0<<0) | //0->ch1 as output, 1->ch1 as input, 2->ch1 as input, 3->ch1 as input
0x00;
TIM2->CCER = (TIM2->CCER &~(0x0f << 0)) |
(0<< 3) | //0->normal polarity for CC1N, 1->inverse polarity
(0<< 2) | //0->disable CC1N, 1->enable CC1N
(0<< 1) | //0->normal polarity for CC1, 1->inverse polarity
(1<< 0) | //1->enable CC1, 0->disable CC1
0x00;
TIM2->CCR1 = 0; //0% duty cycle
//configure gpio for pwm output
#if defined(TIM2CH1toPIN)
TIM2CH1toPIN();
#endif
//configure CCP2
TIM2->CCMR1 = (TIM2->CCMR1 &~0xff00) |
(0<<15) | //0->OC1REF not affedted by ETRF, 1->OC1REF cleared by ETRF high
(6<<12) | //0->frozen (for time base), 1->active on match, 2->inactive on match, 3->toggle, 4->inactive, 5->active, 6->pwm mode 1, 7->pwm mode 2
(0<<11) | //0->preload disabled, 1->preload enabled
(0<<10) | //0->fast disabled, 1->fast enabled
(0<<8) | //0->ch1 as output, 1->ch1 as input, 2->ch1 as input, 3->ch1 as input
0x00;
TIM2->CCER = (TIM2->CCER &~(0x0f << 4)) |
(0<< 7) | //0->normal polarity for CC2N, 1->inverse polarity
(0<< 6) | //0->disable CC2N, 1->enable CC2N
(0<< 5) | //0->normal polarity for CC2, 1->inverse polarity
(1<< 4) | //1->enable CC2, 0->disable CC2
0x00;
TIM2->CCR2 = 0; //0% duty cycle
//configure gpio for pwm output
#if defined(TIM2CH2toPIN)
TIM2CH2toPIN();
#endif
//configure CCP3
TIM2->CCMR2 = (TIM2->CCMR1 &~0x00ff) |
(0<<7) | //0->OC1REF not affedted by ETRF, 1->OC1REF cleared by ETRF high
(6<<4) | //0->frozen (for time base), 1->active on match, 2->inactive on match, 3->toggle, 4->inactive, 5->active, 6->pwm mode 1, 7->pwm mode 2
(0<<3) | //0->preload disabled, 1->preload enabled
(0<<2) | //0->fast disabled, 1->fast enabled
(0<<0) | //0->ch1 as output, 1->ch1 as input, 2->ch1 as input, 3->ch1 as input
0x00;
TIM2->CCER = (TIM2->CCER &~(0x0f << 8)) |
(0<<11) | //0->normal polarity for CC3N, 1->inverse polarity
(0<<10) | //0->disable CC3N, 1->enable CC3N
(0<< 9) | //0->normal polarity for CC3, 1->inverse polarity
(1<< 8) | //1->enable CC3, 0->disable CC3
0x00;
TIM2->CCR3 = 0; //0% duty cycle
//configure gpio for pwm output
#if defined(TIM2CH3toPIN)
TIM2CH3toPIN();
#endif
//configure CCP4
TIM2->CCMR2 = (TIM2->CCMR1 &~0xff00) |
(0<<15) | //0->OC1REF not affedted by ETRF, 1->OC1REF cleared by ETRF high
(6<<12) | //0->frozen (for time base), 1->active on match, 2->inactive on match, 3->toggle, 4->inactive, 5->active, 6->pwm mode 1, 7->pwm mode 2
(0<<11) | //0->preload disabled, 1->preload enabled
(0<<10) | //0->fast disabled, 1->fast enabled
(0<<8) | //0->ch1 as output, 1->ch1 as input, 2->ch1 as input, 3->ch1 as input
0x00;
TIM2->CCER = (TIM2->CCER &~(0x0f << 12)) |
(0<<15) | //0->normal polarity for CC4N, 1->inverse polarity
(0<<14) | //0->disable CC4N, 1->enable CC4N
(0<<13) | //0->normal polarity for CC4, 1->inverse polarity
(1<<12) | //1->enable CC4, 0->disable CC4
0x00;
TIM2->CCR4 = 0; //0% duty cycle
//configure gpio for pwm output
#if defined(TIM2CH4toPIN)
TIM2CH4toPIN();
#endif
TIM2->EGR = 0xff; //force an update
TIM2->BDTR |= TIM_BDTR_MOE; //enable MOE bit
//enable the timer.
TIM2->CR1 |= TIM_CR1_CEN; //enable the timer
}
the output on a given pin is enabled by the TIM2CHntoPIN() macros:
Code: Select all
#define TIM2CH1toPIN() TIM2CH1toPA0() //PA0, PA15
by commenting out this macro, you are muting the pwm output.
mapping the macro to "...toPA0()" or "...toPA15()" redirects the output.
In this case, TIM2CH1toPA0() is further defined as
Code: Select all
#define TIM2CH1toPA0() do {GIO_AFPP(GPIOA, 1<< 0); AFIO->MAPR = (AFIO->MAPR &~AFIO_MAPR_TIM2_REMAP) | (0x00 << 8);} while (0)
essentially enabling the right af function on a given pin.
the code will be different on different chips but the basic logic works.
hope it helps.