Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: stm32 аппаратная обработк энкодера
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Reystlin
Доброго времени суток ув. форумчане
кто как обрабатывает данные снятые с таймера, который включен в режиме обработки энкодера?
у меня затык с тем, как определить направление вращения, что-бы прибавлять/вычитать значение к переменной
таймер инициализирую вот так:
CODE
//Encoder TIM3 Init
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

TIM_Time_user.TIM_Prescaler = 0;
TIM_Time_user.TIM_CounterMode = TIM_CounterMode_Up;
TIM_Time_user.TIM_Period = 256;
TIM_Time_user.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseInit(TIM3, &TIM_Time_user);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_Cmd(TIM3, ENABLE);
TIM3->CNT=0;
//Encoder TIM2 Init
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_Time_user.TIM_Prescaler = 0;
TIM_Time_user.TIM_CounterMode = TIM_CounterMode_Up;
TIM_Time_user.TIM_Period = 256;
TIM_Time_user.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseInit(TIM2, &TIM_Time_user);
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI2, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_Cmd(TIM2, ENABLE);
//TIM2->CCMR1 = TIM_CCMR1_CC2S_0 | TIM_CCMR1_CC1S_0;
TIM2->CCER |= TIM_CCER_CC1P;
TIM3->CCER |= TIM_CCER_CC1P;
TIM2->CNT=0;
viakon
[quote name='Reystlin' post='1421264' date='Apr 22 2016, 09:59']Доброго времени суток ув. форумчане
кто как обрабатывает данные снятые с таймера, который включен в режиме обработки энкодера?
у меня затык с тем, как определить направление вращения, что-бы прибавлять/вычитать значение к переменной
таймер инициализирую вот так:

Зачем Вам таймер? все делается на прерываниях от ножек. key2buf созраняет результат поворота на 1 деление.
CODE
void EXTI15_10_IRQHandler(void)
{
if(EXTI->PR & EXTI_PR_PR14) // прерывание канал А энкодера
{
EXTI->PR = EXTI_PR_PR14; // сбросить прерывание
if(GPIOB->IDR & ENC1) // определение направления импульса
{
if(GPIOB->IDR & ENC2)
{
ENCState = 0;
}
}
else
{
switch(ENCState)
{
case 0:
{
if(GPIOB->IDR & ENC2)
{
ENCState = 1;
}
break;
}
case 2:
{
key2buf(18);
ENCState = 0;
break;
}
}
}
}
if(EXTI->PR & EXTI_PR_PR15)
{
EXTI->PR = EXTI_PR_PR15; // сбросить прерывание
if(GPIOB->IDR & ENC2)
{
if(GPIOB->IDR & ENC1)
{
ENCState = 0;
}
}
else
{
switch(ENCState)
{
case 0:
{
if(GPIOB->IDR & ENC1)
{
ENCState = 2;
}
break;
}
case 1:
{
key2buf(17);
ENCState = 0;
break;
}
}

}
}
}
Сергей Борщ
Цитата(viakon @ Apr 22 2016, 08:26) *
Зачем Вам таймер? все делается на прерываниях от ножек.
Это смотря зачем энкодер нужен. Если на каждый шаг требуется действие - можно и на прерываниях. А если пользователь с помощью энкодера вводит какое-то число на экране и он физически не может реагировать на изменения на экране быстрее, чем за 20-30 мс, а экран физически не может обновляться чаще, то какой смысл грузить процессор прерываниями? Достаточно повесить энкодер на таймер и раз в эти 20 мс считывать накопленный результат.
Я не использую библиотеки, поэтому инициализация таймера у меня несколько короче:
CODE
TIM3->PSC = 0; // TIM3CLK = PCLK/1
TIM3->ARR = 0xFFFF; // 16-bit resolution
TIM3->CNT = 0;
TIM3->CR1 = 0
| 0 * (TIM_CR1_CKD & -TIM_CR1_CKD) // Dead-time clock = timer clock
| 0 * TIM_CR1_ARPE // ARR not buffered
| 0 * (TIM_CR1_CMS & -TIM_CR1_CMS) // Unidirectional, not used
| 0 * TIM_CR1_DIR // Counting up, not used
| 0 * TIM_CR1_OPM // Counter not stopped at update event
| 0 * TIM_CR1_URS // Update request source, not used
| 1 * TIM_CR1_UDIS // Update event generation, 0 - enabled, 1 - disabled
| 1 * TIM_CR1_CEN // Counter enable
;

TIM3->SMCR = 0
| 0 * TIM_SMCR_ETP // External trigger polarity, not used
| 0 * TIM_SMCR_ECE // External clock mode 2 disabled
| 0 * (TIM_SMCR_ETPS & -TIM_SMCR_ETPS) // External trigger prescaler, not used
| 0 * (TIM_SMCR_ETF & -TIM_SMCR_ETF) // External trigger filter, not used
| 0 * TIM_SMCR_MSM // Master/slave mode, not used
| 0 * (TIM_SMCR_TS & -TIM_SMCR_TS) // Trigger selection, not used
| 3 * (TIM_SMCR_SMS & -TIM_SMCR_SMS) // Encoder mode, both edges
;

TIM3->CCMR1 = 0
// CC2 capture mode settings
| 1 * (TIM_CCMR1_IC2F & -TIM_CCMR1_IC2F) // IC2 Filter
| 0 * (TIM_CCMR1_IC2PSC & -TIM_CCMR1_IC2PSC) // IC2 Prescaler
| 1 * (TIM_CCMR1_CC2S & -TIM_CCMR1_CC2S) // Capture, TI1
// CC1 capture mode settings
| 1 * (TIM_CCMR1_IC1F & -TIM_CCMR1_IC1F) // IC1 Filter
| 0 * (TIM_CCMR1_IC1PSC & -TIM_CCMR1_IC1PSC) // IC1 Prescaler
| 1 * (TIM_CCMR1_CC1S & -TIM_CCMR1_CC1S) // Capture, TI1
;

значение TIM3->CNT достаточно явно привести к int16_t, оно уже будет со знаком.
Reystlin
to Сергей Борщ
сделал вот так:
int16_t leftEnc = (int16_t)TIM3->CNT/2;
при кручении в обратную сторону в переменную leftEnc записывается значение 126 вместо -1
Шаманъ
Цитата(Reystlin @ Apr 22 2016, 13:23) *
to Сергей Борщ
сделал вот так:
int16_t leftEnc = (int16_t)TIM3->CNT/2;
при кручении в обратную сторону в переменную leftEnc записывается значение 126 вместо -1

А сколько там изначально было? Может у Вас CNT у таймера было 127 sm.gif

Второй вопрос, а что в ARR? Ибо:
Цитата
Encoder interface mode acts simply as an external clock with direction selection. This
means that the counter just counts continuously between 0 and the auto-reload value in the
TIMx_ARR register (0 to ARR or ARR down to 0 depending on the direction). So you must
configure TIMx_ARR before starting. in the same way, the capture, compare, prescaler...


Reystlin
изначально там было 0
ARR =0x00000100
Шаманъ
Цитата(Reystlin @ Apr 22 2016, 13:56) *
ARR =0x00000100

Ну так, а что Вы хотите при ARR = 256 минус 1 в этом выражении

Цитата
int16_t leftEnc = (int16_t)TIM3->CNT/2;


Вы никак не получите. Чтобы оно работало ARR должно быть 0xFFFF;
Reystlin
Помогло, благодарюsm.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.