cancel
Showing results for 
Search instead for 
Did you mean: 

STM32f207 remapping pins problem

dbingle
Associate II
Posted on July 10, 2013 at 17:17

I'm not sure how to remap pins that do not line up correctly with the alternate functions specified in the datasheet. For example, the picture below shows the pin out of my microcontroller where OCx-LOW are pwm out and ICx are pwm in. Comparing it to the datasheet's alternate function listing, only some pins line up to timer channels. For example, OC1-LOW and OC2-LOW pin's alternate functions match up to timer 9 channel 2 and 1, but OC3-LOW and OC4-LOW don't match up to any timers on their alternate functions so I'm not sure how to use these pins with the timers for pwm out/in.

When they match, you can do something like the following, but not sure what to do when they don't line up.

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOI, &GPIO_InitStructure); 
/* Connect pins to TIM8 AF2 */
GPIO_PinAFConfig(GPIOI, GPIO_PinSource2, GPIO_AF_TIM8);

0690X00000604woQAA.png 0690X00000604lDQAQ.png Sorry if it's a simple solution, I've never programmed any microcontroller before.
20 REPLIES 20
dbingle
Associate II
Posted on July 23, 2013 at 17:54

You're a lifesaver.  This worked out perfectly.  Only note is that setting TIM_Prescaler = Prescaler - 1 will go to max 66535 value if prescaler is 0.  Just setting TIM_Prescaler = 0 fixes the issue in that case.

Posted on July 23, 2013 at 22:40

Yeah, sorry I should have had it set to 1 not 0.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dbingle
Associate II
Posted on August 13, 2013 at 19:41

Well thanks to your code, software controlled PWM outputs are working (within their reasonable limitations). I've been working on doing this with the PWM inputs, but having some trouble. Right now, it's set up to with external triggers and on an interrupt, gets the counter value from a timer running in the background. This sort of works, but there seems to be a lot of jumping around in the calculated duty cycle, especially when more than one inputs are running. For example, measuring a 25% duty cycle reads 1000 cycles high, 3000 low, but only for ~50% of the time. The other time, it would measure ~600 high/2400 low or 2100 high/1900 low, etc. Any suggestions? My code is below.

void PWM_Init_In(void) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_ICInitTypeDef TIM_ICInitStructure4;
TIM_ICInitStructure4.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure4.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure4.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure4.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure4.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &TIM_ICInitStructure4);
TIM_Cmd(TIM4, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Configure pin as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOH, &GPIO_InitStructure);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOH, EXTI_PinSource5);
EXTI_InitStructure5.EXTI_Line = EXTI_Line5;
EXTI_InitStructure5.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure5.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure5.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure5);
NVIC_Setup(EXTI9_5_IRQn, 0, ENABLE);
}
void EXTI9_5_IRQHandler(void) {
EXTI_ClearITPendingBit(EXTI_Line5);
TIM4_PH5[EXTI_LINE_5] = TIM_GetCounter(TIM4);
if (EXTI_LINE_5 == 0) {
EXTI_InitStructure5.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure5);
EXTI_LINE_5++;
} else if (EXTI_LINE_5 == 1) {
EXTI_InitStructure5.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructure5);
EXTI_LINE_5++;
} else if (EXTI_LINE_5 == 2) {
TIM4_PH5_RESULT[0]=calcPeriod(TIM4_PH5[0], TIM4_PH5[1]);
TIM4_PH5_RESULT[1]=calcPeriod(TIM4_PH5[1], TIM4_PH5[2]);
EXTI_LINE_5=0;
} else {
return;
}
}

Posted on August 13, 2013 at 20:38

Ok, so what should the numbers be based on the input signal being supplied? Have you tested this with a function generator and a logic analyzer? If I were trying to explain this I'd probably want to see the signal and the measurements in a contemporaneous fashion.

I don't see how the variables are defined, or how the delta is computed.

3 States? Basically measuring the duty of every other cycle.

I wouldn't be programming the timer in IC mode, you don't have an input for it, why not just program a timebase, or use a higher resolution 32-bit counter? I think I'd probably have done this differently, although I'd expect to see some latency/jitter in the measurements based on what the system was doing.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dbingle
Associate II
Posted on August 13, 2013 at 21:34

Doing an input capture using the one PWM input where the GPIO alternate function maps to a timer, I get a measurement of 997 high/2999 low - which is correct. 120MHz / ~4000 = 30 kHz signal with 25% duty cycle. Looking with an oscilloscope, this signal is correct and present at all the pins where I'm attempting to take measurements.

Sorry, I forgot to post the definitions and calcPeriod function.

static uint32_t TIM4_PH5[3];
static uint32_t TIM4_PH5_RESULT[2];
uint8_t EXTI_LINE_5=0;
void EXTI9_5_IRQHandler(void) { ... }
uint32_t calcPeriod(uint32_t T1, uint32_t T2) {
if (T1 > T2) {
return 65535-T1+T2;
} else {
return T2-T1;
}
}

You are correct about the 3 states. Waits for a rising edge, captures counter, waits for a falling edge, captures counter, waits for a rising edge, captures counter, skips next falling edge and waits for rising, etc. How would you have done this? I also just tried using a counter in my main while loop and then rather getting the timer counter at each interrupt, just get the counter I made, but I'm seeing weird results with it, like 1 cycle high, 49 low.
Posted on August 13, 2013 at 22:44

calcPeriod(0xFFFF,0x0000) != 1

delta = (b - a) & 0xFFFF; // Or ideally with 32-bit unsigned measurements with implicit masking

120 MHz? Are you sure, the TIM4 clock on APB1 (30 MHz) shouldn't be higher than 60 MHz

How are you publishing/printing the result? The result pair is volatile.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dbingle
Associate II
Posted on August 14, 2013 at 15:15

Good catch on being a cycle off for my delta calculation.

Yes you are correct about the timer clocks and I mixed up the information I posted.  The measurements for software driven calculations using TIM4 are ~500 high / 1500 low, but jump around a lot to ~150 high / 1850 low, etc.  The measurements for an actual timer input capture (not software driven) with TIM8 are steady at 997 high / 2999 low.  This would make TIM4 calculate to ~30kHz (60MHz / 2000), while TIM8 would calculate to ~30kHz (120MHz / 4000).

The 'TIM4_PH5_RESULT[2]' is a static class level variable.  I am 'watching' it in CrossStudio while the program is running to monitor its behavior.

Posted on August 14, 2013 at 20:36

Tried driving an F407 with an external 30 KHz @ 25/75 duty, a 128 sample snapshot showed a +/-1 tick variability. Mind you this was the sole task it was doing.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dbingle
Associate II
Posted on August 14, 2013 at 21:38

I also tried stripping it down to only doing one task - measuring the signal.  Measuring only the 25/75 duty, it did the same thing as yours and stayed within +/- 1 tick variability.   However, as soon as I added a second signal to measure on a different input pin, the variability increased to +/- 300 cycles, sometimes even more.  If this only spiked like 10% of the time, I wouldn't be as concerned, but it seems to only stay at the proper 25/75 duty reading about half of the time.  Could this simply be the chip not being able to handle the interrupts at the speed needed to keep accuracy while running multiple PWM inputs?

Posted on August 14, 2013 at 22:08

My inclination would be not to exceed interrupt rates of a few hundred KHz.

The jitter would be attributable to the amount of cycles spent in interrupt handlers. Pre-emption would mitigate that slightly at the expense of saturating the processor quicker.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..