bldc/encoder.c

121 lines
3.1 KiB
C

/*
Copyright 2012-2015 Benjamin Vedder benjamin@vedder.se
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* encoder.c
*
* Created on: 7 mar 2015
* Author: benjamin
*/
#include "encoder.h"
#include "ch.h"
#include "hal.h"
#include "stm32f4xx_conf.h"
#include "hw.h"
// Private variables
static bool index_found;
static uint32_t enc_counts = 10000;
void encoder_init(uint32_t counts) {
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// Initialize variables
index_found = false;
enc_counts = counts;
palSetPadMode(HW_HALL_ENC_GPIO1, HW_HALL_ENC_PIN1,
PAL_MODE_ALTERNATE(HW_ENC_TIM_AF) |
PAL_STM32_OSPEED_HIGHEST |
PAL_STM32_PUDR_FLOATING);
palSetPadMode(HW_HALL_ENC_GPIO2, HW_HALL_ENC_PIN2,
PAL_MODE_ALTERNATE(HW_ENC_TIM_AF) |
PAL_STM32_OSPEED_HIGHEST |
PAL_STM32_PUDR_FLOATING);
// Enable timer clock
HW_ENC_TIM_CLK_EN();
// Enable SYSCFG clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
TIM_EncoderInterfaceConfig (HW_ENC_TIM, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising,
TIM_ICPolarity_Rising);
TIM_SetAutoreload(HW_ENC_TIM, enc_counts - 1);
TIM_Cmd (HW_ENC_TIM, ENABLE);
// Interrupt on index pulse
// Connect EXTI Line to pin
SYSCFG_EXTILineConfig(HW_ENC_EXTI_PORTSRC, HW_ENC_EXTI_PINSRC);
// Configure EXTI Line
EXTI_InitStructure.EXTI_Line = HW_ENC_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// Enable and set EXTI Line Interrupt to the highest priority
NVIC_InitStructure.NVIC_IRQChannel = HW_ENC_EXTI_CH;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
float encoder_read_deg(void) {
return ((float)HW_ENC_TIM->CNT * 360.0) / (float)enc_counts;
}
/**
* Reset the encoder counter. Should be called from the index interrupt.
*/
void encoder_reset(void) {
HW_ENC_TIM->CNT = 0;
index_found = true;
}
/**
* Set the number of encoder counts.
*
* @param counts
* The number of encoder counts
*/
void encoder_set_counts(uint32_t counts) {
if (counts != enc_counts) {
enc_counts = counts;
TIM_SetAutoreload(HW_ENC_TIM, enc_counts - 1);
index_found = false;
}
}
/**
* Check if the index pulse is found.
*
* @return
* True if the index is found, false otherwise.
*/
bool encoder_index_found(void) {
return index_found;
}