реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Измерение частоты STM32F100
ELEKTROS
сообщение Sep 15 2011, 17:36
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 294
Регистрация: 29-06-11
Пользователь №: 65 952



Уже совсем незнаю что делать.
Вот прерывание по захвату канал 1 TIM2, диапазон частоты 0-1500Гц на входе, то правильно то неправильно меряет. TIM2 настроен с частотой 24МГц, захват по переднему фронту с нулевым фильтром, по идее TIM2 не будет переполняться при частоте больше 366Гц, при входном сигнале 150Гц, 30Гц заходит в условие if(perepolnenia_T2==0) когда perepolnenia_T2=0, что впринципе указавает на то что либо таймер не успевает переполниться, что ерунда какаято получается. Подскажите какая особенность может в работе с захватом? Ну погрешность потому что в прерывании таймер обнуляется, но не такая же.
CODE
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_CC1)!=RESET)
{
TIM2->SR = (uint16_t)~TIM_IT_CC1;
TIM2->CNT=0;
u32 temp_freq=freq;
count_deg_A=0;
count_deg_C=180;
if(perepolnenia_T2==0)
{
freq=(TIM2->CCR1)/10;
freq=FREQ_CPU/freq; }
}
else
{
temp_freq=(TIM2->CCR1)+0xFFFF*perepolnenia_T2;
temp_freq=temp_freq/10;
freq=(uint16_t)(FREQ_CPU/temp_freq);
}
perepolnenia_T2=0;
n_speed=6*freq/Z_ROTOR;
}

if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
{
TIM2->SR = (uint16_t)~TIM_IT_Update;
perepolnenia_T2++;
if(perepolnenia_T2>3001)
{
freq=0;
n_speed=0;
}

}
}

Или может есть у кого исходник для определения частоты сигнала в диапазоне 0-1500 Гц.

Может таймеры не так настраиваю:
CODE
TIM_TimeBaseInitStruct.TIM_Prescaler=0; // нужно будет менять несколько ступеней для всего диапазона для захвата TIM2
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; // настройка счёта вверх
TIM_TimeBaseInitStruct.TIM_Period=150;
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1; // предделитель тактирования таймера

/* Инициализация таймеров */
TIM_TimeBaseInit(TIM7, &TIM_TimeBaseInitStruct);

TIM_TimeBaseInitStruct.TIM_Prescaler=0;
TIM_TimeBaseInitStruct.TIM_Period=0xFFFF;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);

TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_CenterAligned3; // настройка счёта вверх
TIM_TimeBaseInitStruct.TIM_Prescaler=0;
TIM_TimeBaseInitStruct.TIM_Period=1200;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);

/* Заполнение полей структуры таймеров захвата */
TIM_ICInitStruct.TIM_Channel=TIM_Channel_1;
TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising;
TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;
TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;
TIM_ICInitStruct.TIM_ICFilter=0;

/* настройка захвата */
TIM_ICInit(TIM2, &TIM_ICInitStruct);

/* включение таймеров */
TIM_Cmd(TIM2,ENABLE);

/* Включение переферийных прерываний */
TIM2->SR = (uint16_t)~TIM_IT_Update;
TIM2->SR = (uint16_t)~TIM_IT_CC1;
TIM_ITConfig(TIM2, TIM_IT_Update | TIM_IT_CC1, ENABLE);// по захвату и обновлению - переполнению счётчика таймера

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // конфигурируем приоритетную группу

/* заполнение структуры модуля прерываний таймера 1 */
NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

/* заполнение структуры модуля прерываний таймера 2 */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);


Сообщение отредактировал IgorKossak - Sep 16 2011, 09:32
Причина редактирования: [codebox]
Go to the top of the page
 
+Quote Post
ELEKTROS
сообщение Sep 16 2011, 08:01
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 294
Регистрация: 29-06-11
Пользователь №: 65 952



Всё работает в том варианте что я привёл, только сделал фильтр по каналу равный 0xF(но думаю там и без этого работает), причина в том что ротор у меня дрыгался а не плавно вращался(вот наверно и ловило большие частоты иногда поэтому).
А теперь задача разбить частоту на 360 частей, т.е. мгновенно определять положение ротора с точностью в 1 электрический градус.
Делаю вот так таймер 7 прерывается с частотой 160кГц, но получаются разные результаты и 770 и 400, а должно быть скажем с учётом погрешности не больше 380:
CODE
void TIM7_IRQHandler(void)
{
if(TIM_GetITStatus(TIM7,TIM_IT_Update)!=RESET)
{
TIM7->SR = (uint16_t)~TIM_IT_Update;

if(freq==0)
{
start_fault++;
if(start_fault>1500000)
{
SETBIT_REG(flag_work_faza,0);
start_fault=0;
}
}
if(n_speed>N_SPEED_POROG_MIN)
{
u16 freq_temp=(TIM2->CNT);
u32 temp_freq=0;
u16 temp_deg=deg_imp;
if(freq>3670)//perepolnenia_T2==0)
{
if((TIM2->CCR1)!=0)freq_temp=FREQ_CPU*10/freq_temp;
}
else
{
temp_freq=0xFFFF*perepolnenia_T2;
temp_freq+=freq_temp;
temp_freq=temp_freq/10;
freq_temp=(uint16_t)(FREQ_CPU/temp_freq);
}
if(freq==0 || freq_temp==0) count_deg_A=0;
else count_deg_A=freq_temp*360/freq;
}
}
}

Суть этого куска кода чтоты определять частоту которую насчитал TIM2 когда произошло прерывание TIM7 и сравнить с частотой c датчика(частоту которого мы меряем) частоту с этого датчика принимаем за 360 электрических градусов, и по пропорции высчитываем сответствие "мгновенной" частоты электрическим градусам

Сообщение отредактировал IgorKossak - Sep 16 2011, 09:32
Причина редактирования: [codebox]
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 19:37
Рейтинг@Mail.ru


Страница сгенерированна за 0.01406 секунд с 7
ELECTRONIX ©2004-2016