2016-06-19 07:46 AM
Hello to everyone, i am building an old project with STM32F107 now.
I am trying to calculate the SVPWM values on the fly but seems like compiler's code is so long.I am running on 72MHz.The fuction below needs around 60-65 usec,which is too much to fit on 20Khz timing.I am using KEIL uvision 5 and 3lvl optimization.float THETA;int SECTOR=0;float Ua=0;float Ub=0;float Uc=0;float PI=3.14;float T=0.0000625; // 16kHzfloat MAXMODINDEX = 2250;volatile float n=0;volatile float i=0;float FREF =50;int MAXn;//--------------------------------//void SVPWM(int count){__disable_irq(); THETA= 2*PI*FREF*count*T;SECTOR = THETA/(PI/3); Ua = (FREF/50)*sinf((PI/3)-(THETA-SECTOR*(PI/3)));Ub = (FREF/50)*sinf(THETA-SECTOR*(PI/3));Uc = 1.0-Ua-Ub;switch(SECTOR) { case 0: TIM3->CCR1 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(Ub + 0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(0.5*Uc); break; case 1: TIM3->CCR1 = MAXMODINDEX*(Ua + 0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(0.5*Uc); break; case 2: TIM3->CCR1 = MAXMODINDEX*(0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(Ub + 0.5*Uc); break; case 3: TIM3->CCR1 = MAXMODINDEX*(0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(Ua + 0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); break; case 4: TIM3->CCR1 = MAXMODINDEX*(Ub + 0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); break; case 5: TIM3->CCR1 = MAXMODINDEX*(Ua + Ub + 0.5*Uc); TIM3->CCR2 = MAXMODINDEX*(0.5*Uc); TIM3->CCR3 = MAXMODINDEX*(Ua + 0.5*Uc); break; default: break; } __enable_irq(); }2016-06-19 07:59 AM
The F107 is a Cortex M3, without FPU , so every floating point operation needs to be emulated.
Even the FPU (in the F3/F4/F7 parts) does not support trigonometric functions (sinf(), cosf() ...). Better use scaled math, and integer variables.2016-06-19 08:17 AM
Yeah i know F107 doesnt support FPU but 60-65usec is still too much.
2016-06-19 09:12 AM
Try measure the timing for sinf() calls, and for mult./div. operations.
You can also step through the disassembly code ... I used a integer-based approach with a sin/cos table (also integer) to create a realtime modulation of two frequencies (output via DAC). That took about 10us per cycle on a F100 (24MHz).2016-06-19 10:37 AM
There are likely a number of significant ways to optimize your code, Keil doesn't understand the algorithms, and especially where you have variables with global scope rather than constants. Multiplication is faster than division.
The F1 series also has no caching, prefetching, or optimization of the very slow Flash memory. Consider also using a proper version of PI, and using methods where you are not constantly rehashing the same math.2016-06-19 10:53 AM
2016-06-19 11:03 AM
If i use constants i see time being increased.
Could other compiler has much more optimized code;2016-06-19 01:19 PM
Take a look at this book ''Math Toolkit for Real-Time Programming'' might be useful.
2016-06-19 01:51 PM
2016-06-19 05:27 PM
something like this should be faster
#define PI 3.141592654f
// ...
Ua = (FREF * (1.0f/0f))*sinf((PI/3.0f) - (THETA - (float)SECTOR * (PI/3.0f)));
Ub = (FREF * (1.0f/0f))*sinf(THETA - (float)SECTOR * (PI/3.0f));