dannyf, I have your initialization function for TIM2 running, from you previous post:
I will ask you to teach me how to use TIM2CH1toPIN()
The compiler complaints here:
Code: Select all
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; //enable AFIO
AFIO->MAPR = (AFIO->MAPR &~AFIO_MAPR_TIM2_REMAP) | (AFIO_MAPR_TIM2_REMAP & TIM2REMAP); //select the remap scheme
...but I think that some definitions here are not for the STM32F!03C8T6, but tomorrow I will Google the symbols and look for its equivalents in my core.
About the function, the neat, ordered coding is helping me to understand better what each bit does in the timer. The remapping is something very nice in this chip, but I will test it later.
Attached, is my working code with your function.
Now I need to concentrate on adding the interrupt to this PWM event.
Thank you for your help !
Roberto
Code: Select all
// https://www.stm32duino.com/viewtopic.php?p=12300#p12300
// the output on a given pin is enabled by the TIM2CHntoPIN() macros:
// #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:
// #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. dannyf
#define PWM_PR 50000
#define DUTY 5000
void setup()
{
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // clock to GPIOA
// Set PA0 as alternate function output push-pull
GPIOA->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_MODE0);
GPIOA->CRL |= GPIO_CRL_CNF0_1; /* 10: Alternate function output Push-pull */
GPIOA->CRL |= GPIO_CRL_MODE0_1; /* 10: Output mode, max speed 2 MHz. */
pwm2Init(1);
}
void loop()
{
TIM2->CCR1 = DUTY;
delay(500);
TIM2->CCR1 = DUTY*5;
delay(500);
}
//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->ARPE autoreload/preload ARR 1-> buffered, 0->ARPE 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) | //0->: update only OVF/UF generates 1-> update interrupt or DMA request if enabled.
(0<<1) | //0->UEV update enabled, 1->UEV update 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 affected 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
}