Миландр

Ключевым подразделением нашей компании является Центр Проектирования интегральных микросхем
Текущее время: 2017-дек-15 13:18

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 10 ] 
Автор Сообщение
СообщениеДобавлено: 2016-авг-17 06:32 
Не в сети

Зарегистрирован: 2016-мар-05 21:08
Сообщения: 25
Здравствуйте.
Посоветуйте как реализовать обработку данных с энкодера.
Пробовал запустить example_project для 1986ВЕ1Т с сайта LDM.
Почему то ничего не заработало, хотя все верно настроено.
В STM32F4 с этим проблем не возникало, поскольку все реализовано аппаратно.
Здесь же мне интересен сам алгоритм:
1. Настройка портов.
2. Настройка таймера.
3. ...


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2016-авг-17 13:01 
Не в сети

Зарегистрирован: 2016-авг-17 12:45
Сообщения: 6
Как-нибудь вот так:
Encoder.h:
Код:
#ifndef ENCODER_H
#define ENCODER_H

#include <stdint.h>

typedef void (*encoderRotateCallback)(uint8_t position, uint8_t clockwise);

void encoderInit(encoderRotateCallback);

#endif // ENCODER_H


Encoder.c:
Код:
#include "encoder.h"
#include "MDR32F9Qx_config.h"
#include "MDR32F9Qx_port.h"
#include "MDR32F9Qx_timer.h"
#include "MDR32F9Qx_rst_clk.h"
#include "core_cm1.h"

static encoderRotateCallback ecbck;
static uint8_t prevPosition = 0x03;

static void initPort()
{
    PORT_InitTypeDef port;
    PORT_StructInit(&port);

    port.PORT_FUNC = PORT_FUNC_ALTER;
    port.PORT_MODE = PORT_MODE_DIGITAL;
    port.PORT_OE = PORT_OE_IN;
    port.PORT_SPEED = PORT_SPEED_FAST;
    port.PORT_Pin = PORT_Pin_10 | PORT_Pin_12;
    port.PORT_PULL_UP = PORT_PULL_UP_ON;

    PORT_Init(MDR_PORTA, &port);
}

void Timer4_IRQHandler()
{
    MDR_TIMER4->STATUS = 0;
    uint8_t currentPosition =
        ((MDR_PORTA->RXTX & PORT_Pin_12) ? 2 : 0) +
        ((MDR_PORTA->RXTX & PORT_Pin_10) ? 1 : 0);

    if(prevPosition == currentPosition)
        return;

    static uint8_t remap[4] = {0,1,3,2};
    uint8_t clockWise = ((remap[currentPosition]-remap[prevPosition]) & 0x3) == 1;
    prevPosition = currentPosition;
    ecbck(currentPosition,clockWise);
}

void encoderInit(encoderRotateCallback c)
{
    ecbck=c;

    RST_CLK_PCLKcmd(RST_CLK_PCLK_TIMER4 | RST_CLK_PCLK_PORTA, ENABLE);
    initPort();

    TIMER_CntInitTypeDef timerCnt;
    TIMER_CntStructInit(&timerCnt);

    timerCnt.TIMER_Period     = 0xFFFFFF;

    TIMER_CntInit(MDR_TIMER4, &timerCnt);

    TIMER_ChnInitTypeDef timerChn;
    TIMER_ChnStructInit(&timerChn);

    timerChn.TIMER_CH_Mode             = TIMER_CH_MODE_CAPTURE;
    timerChn.TIMER_CH_Number           = TIMER_CHANNEL3;
    timerChn.TIMER_CH_EventSource      = TIMER_CH_EvSrc_NE;
    TIMER_ChnInit(MDR_TIMER4, &timerChn);
    timerChn.TIMER_CH_Number = TIMER_CHANNEL4;
    TIMER_ChnInit(MDR_TIMER4, &timerChn);

    TIMER_ChnOutInitTypeDef chOut;
    TIMER_ChnOutStructInit(&chOut);

    chOut.TIMER_CH_Number = TIMER_CHANNEL3;
    TIMER_ChnOutInit(MDR_TIMER4, &chOut);
    chOut.TIMER_CH_Number = TIMER_CHANNEL4;
    TIMER_ChnOutInit(MDR_TIMER4, &chOut);

    TIMER_BRGInit(MDR_TIMER4, TIMER_HCLKdiv1);
    TIMER_ITConfig(MDR_TIMER4,
        TIMER_STATUS_CCR_CAP_CH3 |
        TIMER_STATUS_CCR_CAP_CH4 |
        TIMER_STATUS_CCR_CAP1_CH3 |
        TIMER_STATUS_CCR_CAP1_CH4,
        ENABLE);

    NVIC_EnableIRQ(TIMER4_IRQn);

    TIMER_Cmd(MDR_TIMER4, ENABLE);
}



Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2016-авг-18 16:02 
Не в сети

Зарегистрирован: 2016-мар-05 21:08
Сообщения: 25
Спасибо, но все же сделал немножко по своему)

Теперь у меня другая проблема. Заключается она в следующем.
Почему то значение переменной сбрасывается в ноль.
Даже если просто создать переменную и инкрементировать ее каждую секунду, то в определенный момент она сбрасывается и счет опять начинается с нуля. Сброс происходит рандомно. Значение переменной может увеличится и до 55, и до 15 и т.д.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2016-авг-22 11:27 
Не в сети

Зарегистрирован: 2016-авг-17 12:45
Сообщения: 6
newfag писал(а):
Почему то значение переменной сбрасывается в ноль.
Даже если просто создать переменную и инкрементировать ее каждую секунду, то в определенный момент она сбрасывается и счет опять начинается с нуля. Сброс происходит рандомно. Значение переменной может увеличится и до 55, и до 15 и т.д.


Вопрос непонятен.
Про какую переменную речь? Как и где создаете и инкрементируете?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2016-авг-22 12:53 
Не в сети

Зарегистрирован: 2016-мар-05 21:08
Сообщения: 25
JTzar писал(а):
newfag писал(а):
Почему то значение переменной сбрасывается в ноль.
Даже если просто создать переменную и инкрементировать ее каждую секунду, то в определенный момент она сбрасывается и счет опять начинается с нуля. Сброс происходит рандомно. Значение переменной может увеличится и до 55, и до 15 и т.д.


Вопрос непонятен.
Про какую переменную речь? Как и где создаете и инкрементируете?



Переменная типа uint8_t, создаю вне main и инкрементирую в главном цикле.

Создал другой проект. Там ничего не сбрасывается. Теперь ищу проблему в старом проекте, т.к. все переписывать не охота.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2016-авг-22 14:14 
Не в сети

Зарегистрирован: 2016-авг-17 12:45
Сообщения: 6
При такой мистике нужно предполагать самое худшее - неверная работа с памятью.
Причин может быть много:
1) Перекрываются регионы памяти.
2) Ошибка в алгоритме выделения памяти в куче.
3) Если используется RTOS, может недастаточно памяти для стека под некоторую задачу.
4) Арифметические операции с указателями.
и др.

В общем я посоветвал просмотреть все места в программе, где что-либо инициализируется нулем, и поизменять на другие значения.
Удачи.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2016-авг-23 10:34 
Не в сети

Зарегистрирован: 2016-мар-05 21:08
Сообщения: 25
Все же решил уточнить, целесообразно ли применять такой простой алгоритм?
Открыть Код
Код:
void TIMER4_IRQHandler()     //Микроконтроллер уходит в прерывание по отрицательному фронту
{
  if (PORT_ReadInputDataBit(MDR_PORTA,PORT_Pin_10) == 0){    // Проверяем уровень сигнала на вывода PA10
      MDR_TIMER4->CNT = 1;                                        // Если 0, то обнуляем счетчик
      while (MDR_TIMER4->CNT < 400){}                           // И ждем пока досчитает до 400 (число подобрано опытным путем)
      if (PORT_ReadInputDataBit(MDR_PORTA,PORT_Pin_12) == 0){   // Проверяем уровень сигнала на вывода PA12
         iPer++;                     // Если 0, то инкремент переменной iPer
      } else if (PORT_ReadInputDataBit(MDR_PORTA,PORT_Pin_12) == 1){
         iPer--;                     // Если 1, то декремент переменной iPer
      }
      MDR_TIMER4->STATUS = 0;                     
   }
}
Закрыть

Ну а дальше значение переменной iPer можно использовать для изменения других параметров


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2016-авг-23 14:10 
Не в сети

Зарегистрирован: 2016-авг-17 12:45
Сообщения: 6
newfag писал(а):
Все же решил уточнить, целесообразно ли применять такой простой алгоритм?

Нет.

Если нужно абсолютное значение положения, используйте вышеприведенный код вот так:
Код:
void encoderRotate(uint8_t position, uint8_t clockwise)
{
    if(clockwise)
        iPer++;
    else
        iPer--;
}

encoderInit(encoderRotate);


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2016-авг-25 09:02 
Не в сети

Зарегистрирован: 2016-мар-05 21:08
Сообщения: 25
JTzar писал(а):
newfag писал(а):
Все же решил уточнить, целесообразно ли применять такой простой алгоритм?

Нет.

Если нужно абсолютное значение положения, используйте вышеприведенный код вот так:
Код:
void encoderRotate(uint8_t position, uint8_t clockwise)
{
    if(clockwise)
        iPer++;
    else
        iPer--;
}

encoderInit(encoderRotate);



Спасибо.
А как устранить дребезг контактов? При повороте энкодера в один щелчок значение переменной изменяется на +-4. Насколько я понимаю, эта проблема должна решатся путем задания значений цифрового фильтра на входе (поля ETR FILTER[3:0] регистра BRKETR_CNTRL ), но при изменении значений ничего не происходит.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2016-авг-26 15:35 
Не в сети

Зарегистрирован: 2016-авг-17 12:45
Сообщения: 6
JTzar писал(а):
При повороте энкодера в один щелчок значение переменной изменяется на +-4


Так и задумывалось. При повороте на один щелчок энкодер переходит через 3 промежуточных состояния. Вдруг эта инфа понадобится.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 10 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB