Написал на Builder несколько ускоренную программу поиска коэффициентов файл "calc_presc.rar"
Функция на STM32F103 на 72 Мгц рассчитывает перебирает варианты за время около секунды.
CODE
#define MAX_PRESC 65535
#define MAX_PERIOD 256
//---------------------------------------------------------------------------
void calc_presc(int target_freq, unsigned short *presc_value, unsigned short *half_period_value)
{
int i, j;
float freq, best_calc_freq;
int presc, period;
// разница между заданой чаcтотой и рассчитаной
// в предыдущей итерации и а текущей
float prev_dif, cur_dif;
best_calc_freq=0;
for (i=0;i<MAX_PRESC; i++)
for (j=1; j<=MAX_PERIOD/2; j++)
{
prev_dif = cur_dif;
freq = (SYSCLK_FREQ_72MHz)/ ((1+i) * j*2);
/*
if (sign(target_freq - freq) == sign(target_freq - (SYSCLK_FREQ_72MHz)/ ((1+MAX_PRESC) * MAX_PERIOD)))
{
j = MAX_PERIOD/2;
}
*/
cur_dif = fabs(freq - target_freq);
if (cur_dif < fabs((best_calc_freq - target_freq)))
{
best_calc_freq = freq;
presc = i;
period =j;
}
else
{
if (j>1) // если уже есть с сравнивать
{
if (fabs(prev_dif) < fabs(cur_dif)) j=MAX_PERIOD/2; //результат ухудшается
}
}
}
*presc_value = presc;
*half_period_value = period;
}
Прескалер прямо пишется в регистры таймера, half_period_value прямо в CCR а удвоенное значение в элемент структуры TIM_Period
CODE
// Инициализация таймера управления катушкой
void coil_generator_init(int prescaller, int period)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitStructure.GPIO_Pin = COIL_MASK;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(COIL_PORT, &GPIO_InitStructure);
// Map TIM5 OC4 to PA3
GPIO_PinRemapConfig(GPIO_Remap_TIM5CH4_LSI,DISABLE);
// Init PWM TIM5
// Enable Timer1 clock and release reset
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, DISABLE);
TIM_InternalClockConfig(TIM5);
// Time base configuration
TIM_TimeBaseStructure.TIM_Prescaler = prescaller;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = period*2 -1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
// Channel 2 Configuration in PWM mode
//TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //vovka TIM_OCMode_Toggle
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0x00;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC4Init(TIM5,&TIM_OCInitStructure);
// Double buffered
TIM_ARRPreloadConfig(TIM5, ENABLE);
// TIM5 counter enable
TIM_Cmd(TIM5,ENABLE);
TIM5->CCR4 = period;
}
Перебор прескаллера 16 бит, периода 8 бит, так как для частот около 15..20гКц никакой выгоды от двух 16 битных коэффициентов нет.
Закомментированый кусок кода еще должен ускорить перебор, но в IAR нет функции Sign().
Но меня и такой вариант устраивает.
Сообщение отредактировал IgorKossak - Jun 25 2014, 19:56
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!