/* 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 . */ /* * 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; }