Перейти к содержанию
    

stm32 аппаратная обработк энкодера

Доброго времени суток ув. форумчане

кто как обрабатывает данные снятые с таймера, который включен в режиме обработки энкодера?

у меня затык с тем, как определить направление вращения, что-бы прибавлять/вычитать значение к переменной

таймер инициализирую вот так:

	 //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;

Изменено пользователем Reystlin

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Доброго времени суток ув. форумчане

кто как обрабатывает данные снятые с таймера, который включен в режиме обработки энкодера?

у меня затык с тем, как определить направление вращения, что-бы прибавлять/вычитать значение к переменной

таймер инициализирую вот так:

 

Зачем Вам таймер? все делается на прерываниях от ножек. key2buf созраняет результат поворота на 1 деление.

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;
			}
		}

	}
}
}

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зачем Вам таймер? все делается на прерываниях от ножек.
Это смотря зачем энкодер нужен. Если на каждый шаг требуется действие - можно и на прерываниях. А если пользователь с помощью энкодера вводит какое-то число на экране и он физически не может реагировать на изменения на экране быстрее, чем за 20-30 мс, а экран физически не может обновляться чаще, то какой смысл грузить процессор прерываниями? Достаточно повесить энкодер на таймер и раз в эти 20 мс считывать накопленный результат.

Я не использую библиотеки, поэтому инициализация таймера у меня несколько короче:

	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, оно уже будет со знаком.

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

to Сергей Борщ

сделал вот так:

int16_t leftEnc = (int16_t)TIM3->CNT/2;

при кручении в обратную сторону в переменную leftEnc записывается значение 126 вместо -1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

to Сергей Борщ

сделал вот так:

int16_t leftEnc = (int16_t)TIM3->CNT/2;

при кручении в обратную сторону в переменную leftEnc записывается значение 126 вместо -1

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

 

Второй вопрос, а что в 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...

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ARR =0x00000100

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

 

int16_t leftEnc = (int16_t)TIM3->CNT/2;

 

Вы никак не получите. Чтобы оно работало ARR должно быть 0xFFFF;

Изменено пользователем Шаманъ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...