Rotary encoder timer interrupt - STM32F103C8T6

Generic boards that are not Maple or Maple mini clones, and don't contain the additional USB reset hardware
Post Reply
vib
Posts: 12
Joined: Wed May 03, 2017 7:35 pm

Rotary encoder timer interrupt - STM32F103C8T6

Post by vib » Thu Jun 29, 2017 8:05 pm

Hi Everyone,
I'm struggling to make a timer interrupt for my rotary encoder
I only use keil with my STM32F103C8T6 (aka blue pill ?)

If it was working properly, I would expect my variable codeur to increase and the value to written on the LCD

Do you have any idea where it comes from?
(everything else ie LCD and stepper motor are working well)

Thank you

Code: Select all

#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_exti.h"
#include "delay.h"
#include "lcd16x2.h"
#include <stdio.h>

// LCD custom char
uint8_t bar[][8] = 
{ 
	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
	{ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
	{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 },
	{ 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C },
	{ 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E },
	{ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }
};
/*
volatile uint8_t last_enc_val_a_B;		//broach
volatile uint8_t last_enc_val_b_B;		//broach
volatile uint8_t last_enc_val_a_M; 	 	//motor
volatile uint8_t last_enc_val_b_M;		//motor
volatile int enc_cnt_B;								//broach
volatile int enc_cnt_M;								//motor
char enc_cnt_buf_B[8];								//broach
char enc_cnt_buf_M[8];								//motor
*/
int CW = 0;
int CCW = 500;
volatile int valeur_moteur = 0;	
int pitch_100 = 0;
int codeur = 0;
char codeur_buf[8];

void init_lcd(void);
void intro_LCD(void);
void lcd_update(void);
void init_motor(void);
void test_motor_CW(void);
void test_motor_CCW(void);
void init_timer(void);


int main(void)
{
	DelayInit();
	init_lcd();
	intro_LCD();
	init_motor();
	
	while (1)
	{
		lcd_update();
		
		for(CW; CW<500; CW++)
		{
			test_motor_CW();
		}	
		DelayMs(500);
		for(CCW; CCW>0; CCW--)
		{
			test_motor_CCW();
		}	
	}
}


void init_timer()
{

	// Step 1: Initialize GPIO as input for rotary encoder
	// PB6 (encoder pin A), PB5 (encoder pin B)
	GPIO_InitTypeDef GPIO_InitStruct;	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM4 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
 
/* TIM4 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 500; // 1 MHz down to 1 KHz (1 ms)
TIM_TimeBaseStructure.TIM_Prescaler = 4000; // 24 MHz Clock down to 1 MHz (adjust per your clock)
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
	
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);	// TIM IT enable 
TIM_Cmd(TIM4, ENABLE); // TIM4 enable counter
}

void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
codeur++;
}
}
void test_motor_CW()
{
	GPIO_WriteBit(GPIOA, GPIO_Pin_3, 0);
	DelayUs(250);
	GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
	DelayUs(250);
	GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
	DelayUs(250);
}

void test_motor_CCW()
{
	GPIO_WriteBit(GPIOA, GPIO_Pin_3, 1);
	DelayUs(250);
	GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
	DelayUs(250);
	GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
	DelayUs(250);
}


void init_motor()
	{
	GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_2;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
	GPIO_WriteBit(GPIOA, GPIO_Pin_3, 0);
	}
	
void init_lcd()
{
	uint8_t i;
	
	// Initialize LCD
	lcd16x2_init(LCD16X2_DISPLAY_ON_CURSOR_OFF_BLINK_OFF);
	
	// Fill custom char
	for (i = 0; i < 8; i++)
	{
		lcd16x2_create_custom_char(i, bar[i]);
	}
}


void lcd_update()
{
	lcd16x2_clrscr();
	lcd16x2_gotoxy(0, 0);
	lcd16x2_puts("test");
	lcd16x2_gotoxy(0, 1);
	sprintf(codeur_buf, "%i", codeur);
	lcd16x2_puts(codeur_buf);
	DelayMs(250);
	
}

void intro_LCD()
{
	lcd16x2_clrscr();
	lcd16x2_gotoxy(0, 0);
	lcd16x2_puts("xxx");
	lcd16x2_gotoxy(0, 1);
	lcd16x2_puts("x");
	lcd16x2_gotoxy(0, 2);
	lcd16x2_puts("Module filetage V0.1");
	DelayMs(1000);
}

dannyf
Posts: 103
Joined: Wed May 11, 2016 4:29 pm

Re: Rotary encoder timer interrupt - STM32F103C8T6

Post by dannyf » Tue Jul 04, 2017 5:20 pm

it is not clear from your code what you want to do. it seems that you are firing up tim4 to increment codeur but i don't seen anything about a rotary encoder.

zmemw16
Posts: 1380
Joined: Wed Jul 08, 2015 2:09 pm
Location: St Annes, Lancs,UK

Re: Rotary encoder timer interrupt - STM32F103C8T6

Post by zmemw16 » Tue Jul 04, 2017 8:21 pm

@vib
a possible way out is use CubeMX to configure tim4 as an encoder, export the code and 'backport' it to whichever library you're using or at least to compare with how it does it against your code.
stephen

Post Reply