Энкодер + atmega8 + CodeVisionAVR

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
AxiDim
Родился
Сообщения: 3
Зарегистрирован: Вс окт 14, 2012 22:31:20

Энкодер + atmega8 + CodeVisionAVR

Сообщение AxiDim »

Прошу помощи так как пока сам не могу разобраться.

Есть конечная задача сделать USB мультимедиа клавиатуру для Кар ПС. Состоять она будет из двух энкодеров и 4 кнопок.
Один энкодер должен регулировать громкость, второй - переключать треки. Ну а кнопки пока еще не определился.

Сам пытаюсь разобраться в CodeVisionAVR, но вот готовых примеров не нашел по обработке сигналов с энкодера, а написанные на чистом С не хотят работать у меня.

Помогите пожалуйста.
Энкодер подключаю к PB0 PB1 c подтяжкой через резисторы к +5в.
Реклама
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение Леонид Иванович »

Вот как пример:
Спойлер

Код: Выделить всё

//----------------------------------------------------------------------------

//Модуль поддержки энкодера.
//Энкодер подключается к портам ENC_F1 (фаза 1) и ENC_F2 (фаза 2).
//Функция Enc_Scan() вызывается в основном цикле.
//Результат обработки энкодера передается в основную программу
//через функцию OnEncoder().

//----------------------------- Константы: -----------------------------------

#define ENC_F2   (1 << PC1) //фаза энкодера F2
#define ENC_F1   (1 << PC2) //фаза энкодера F1

#define Pin_ENC_F2     (PINC & ENC_F2)
#define Pin_ENC_F1     (PINC & ENC_F1)

enum { State0, StateA, StateB, StateAB }; //состояния энкодера

enum { ENC_UP, ENC_DN }; //код шага вверх и шага вниз.

//----------------------------- Переменные: ----------------------------------

static char EncPrev;      //предыдущее состояние энкодера
static char EncPrevPrev;  //пред-предыдущее состояние энкодера

//----------------------- Инициализация энкодера: ----------------------------

void Encoder_Init(void)
{
  EncPrev = State0;       //инициализация предыдущего состояния
  EncPrevPrev = State0;   //инициализация пред-предыдущего состояния
}

//------------------------- Обработка энкодера: ------------------------------

void Encoder_Exe(void)
{
  char EncCur = 0;
  if(!Pin_ENC_F1) EncCur  = StateA; //опрос фазы 1 энкодера
  if(!Pin_ENC_F2) EncCur |= StateB; //опрос фазы 2 энкодера
  if(EncCur != EncPrev)             //если состояние изменилось,
  {
    if(EncPrev == StateAB &&        //если предыдущее состояние StateAB
       EncCur != EncPrevPrev )      //и текущее и пред-предыдущее не равны,
    {
      if(EncCur == StateB)          //если текущее состояние StateB,
        OnEncoder(ENC_UP);   //шаг вверх
      else                          //иначе
        OnEncoder(ENC_DN);   //шаг вниз
    }
    EncPrevPrev = EncPrev;          //сохранение пред-предыдущего состояния
    EncPrev = EncCur;               //сохранение предыдущего состояния
  }
}

//----------------------------------------------------------------------------
Реклама
Аватара пользователя
ua1arn
Встал на лапы
Сообщения: 81
Зарегистрирован: Вт май 08, 2012 23:15:45
Откуда: Санкт - Петербург

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение ua1arn »

Код: Выделить всё

static uint_fast8_t old_val;

void spool_encinterrupt(void)
{
	const uint_fast8_t new_val = hardware_get_encoder_bits();	/* Состояние фазы A - в бите с весом 2, фазы B - в бите с весом 1 */

	// dimensions are:
	// old_bits new_bits
	static const int_fast8_t graydecoder [4][4] =
	{
		{
			+0,		/* 00 -> 00 stopped				*/
			-1,		/* 00 -> 01 rotate left			*/
			+1,		/* 00 -> 10 rotate right		*/
			+0,		/* 00 -> 11 invalid combination */		
		},
		{
			+1,		/* 01 -> 00 rotate right		*/
			+0,		/* 01 -> 01 stopped				*/
			+0,		/* 01 -> 10 invalid combination */
			-1,		/* 01 -> 11 rotate left			*/
		},
		{
			-1,		/* 10 -> 00 rotate left			*/
			+0,		/* 10 -> 01 invalid combination */
			+0,		/* 10 -> 10 stopped				*/
			+1,		/* 10 -> 11 rotate right		*/
		},
		{
			+0,		/* 11 -> 00 invalid combination */
			+1,		/* 11 -> 01 rotate right		*/
			-1,		/* 11 -> 10 rotate left			*/
			+0,		/* 11 -> 11 stopped				*/
		},
	};


#if ENCODER_REVERSE
	position1 -= graydecoder [old_val][new_val];
#else
	position1 += graydecoder [old_val][new_val];
#endif
	old_val = new_val;
}


/* вызывается при запрещенных прерываниях */
void encoder_initialize(void)
{
	//rotate = backup_rotate = 0;
	//enchistindex = 0;
	//tichist [enchistindex] = 0;
	//enchist [enchistindex] = 0;
	//hardware_encoder_initialize(); // moved to main


	old_val = hardware_get_encoder_bits();	/* Состояние фазы A - в бите с весом 2, фазы B - в бите с весом 1 */
}

spool_encinterrupt вызывается по изменению уровня на выводах PD2 & PD3 (int0 и int1). Разрешить соответствующие прерывания по любому изменению уровня.
AxiDim
Родился
Сообщения: 3
Зарегистрирован: Вс окт 14, 2012 22:31:20

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение AxiDim »

Хорошо когда понимаешь, что написал.

Вообщем нашел модуль с таким кодом.
#ifndef _ENCODER_
#define _ENCODER_ 1
/*********************************************************************
Модуль программной поддержки контактного квадратурного энкодера
типа РЕС16 и аналогичных (без использования прерываний)

Copyright 2008 © ARV Research.

Внимание! Вы можете использовать данный модуль по своему усмотрению
в любых проектах. При любой публикации ваших проектов, использующих
этот модуль, следует указать ссылку на сайт http://arv.radioliga.com

Требуется компилятор WinAVR
**********************************************************************/

#define ENC_MAX_SPEED 100 /* максимальная "скорость" вращения энкодера */
#define ENC_BIG_STEP 98 /* "большой" шаг при быстром вращении */
#define ENC_FAST_ROTATE 90 /* константа "быстрого" вращения */

#define ENC_A_PIN 3 /* номер линии порта для сигнала А энкодера */
#define ENC_B_PIN 6 /* номер линии порта для сигнала B энкодера */
#define ENC_A_PORT PIND /* порт, к которому подключен сигнал А энкодера */
#define ENC_B_PORT PINB /* порт, к которому подключен сигнал B энкодера */

#define ENC_A_UP (ENC_A_PORT & (1<<ENC_A_PIN))
#define ENC_B_UP (ENC_B_PORT & (1<<ENC_B_PIN))
#define ENC_A_DN (!ENC_A_UP)
#define ENC_B_DN (!ENC_B_UP)

#define rotate_fast(x) (x > ENC_FAST_ROTATE)
#define DDR(x) (*(&x + 1))
#define PORT(x) (*(&x + 2))
/*
Использование модуля элементарно: в начале программы следует вызвать
функцию enc_init(), которая настроит нужные порты ввода-вывода.
Затем в основном цикле в нужном месте можно обратиться либо к
функции enc_rotate(), которая вернет значение, соответствующее направлению
вращения энкодера, либо функцию enc_delta(), которая кроме направления
возвратит и условную величину скорости вращения.
enc_rotate() позволяет использовать энкодер, как 2 кнопки "+1" и "-1"
enc_delta() уже может заменить 4 кнопки "+1", "+100", "-1" и "-100".
Функция способна отличать "рывки туда-сюда" от простого вращения в
одном направлении.

Нажатие встроенной кнопки энкодера НЕ ОБРАБАТЫВАЕТСЯ
*/


// инициализирует порты, к которым подключен энкодер
void enc_init(void);

/* возвращает направление и скорость вращения энкодера
параметр speed - указатель на переменную, в которую возвращается
условная скорость вращения (число от 0 до 100)

возвращает:
-1 - вращение влево (против часовой стрелки)
0 - нет вращения
1 - вращение вправо (по часовой стрелке)

ВНИМАНИЕ! функция выполняется достаточно длительное время:
максимально (при остановленном энкодере) ENC_MAX_SPEED миллисекунд,
при вращении возвращает управление раньше
*/
signed char enc_rotate(unsigned char * speed);

/* возвращает приращение энкодера:
1 или -1 при медленном вращении,
0 - при остановленном
ENC_BIG_STEP или -ENC_BIG_STEP при быстром вращении

ВНИМАНИЕ!!! Функция выполняется долго!!!
при быстром вращении возвращает управление только ПОСЛЕ ОСТАНОВКИ энкодера!
остановкой считается, если в течение 2*ENC_MAX_SPEED миллисекунд не было импульсов
с энкодера.
*/
signed char enc_delta(void);

#endif
Пытаюсь вызвать его в основном коде, а при компилировании ругается на функцию enc_init().

Помогите как этот модуль заставить работать в моей программе.
Реклама
Эиком - электронные компоненты и радиодетали
takei
Нашел транзистор. Понюхал.
Сообщения: 181
Зарегистрирован: Пн янв 14, 2013 15:06:57
Откуда: Д.Вс.

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение takei »

Объяви в основном цикле enc_init();
А вообще код от ARV, как всегда гавно..
Реклама
AxiDim
Родился
Сообщения: 3
Зарегистрирован: Вс окт 14, 2012 22:31:20

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение AxiDim »

Так и делаю, но ошибка вылазит. В скобочках надо что нибудь указывать?
Реклама
Аватара пользователя
Flasher
Мудрый кот
Сообщения: 1802
Зарегистрирован: Ср сен 07, 2011 21:40:30

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение Flasher »

Вот странно-вылизанный код ЛИ даже не смотрится, а ищется какой-то говянный код...
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение ARV »

takei писал(а):А вообще код от ARV, как всегда гавно..
потрудитесь объясниться :twisted:
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение BCluster »

takei писал(а):Объяви в основном цикле enc_init();
А вообще код от ARV, как всегда гавно..
особенно, если учесть что приведен какой-то вообще шмат кода, очень разумно об этом судить.
ТС, там где-то в другом файле есть эти функции, найди их, и будет работать :))))
Аватара пользователя
VNN84
Грызет канифоль
Сообщения: 256
Зарегистрирован: Вт мар 11, 2008 06:22:36
Откуда: Волгоград

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение VNN84 »

Не программировал больше 2 лет, все напрочь забыл (((. Помогите, пжл, перевести код этого птичьего языка на читаемый. Мне надо его вставить в CodeVisionAVR. Энкодер висит на PINC.3 и PINC.2 c подтяжкой.
Код понравился этот: http://www.leniwiec.org/en/2014/04/28/r ... 2-168-328/ начитается с Gray’s code method

ОРИГИНАЛ
uint8_t read_gray_code_from_encoder(void )
{
uint8_t val=0;

if(!bit_is_clear(PIND, PD2))
val |= (1<<1);

if(!bit_is_clear(PIND, PD3))
val |= (1<<0);

return val;
}

ПЫТАЮСЬ ПЕРЕПИСАТЬ НА CodeVisionAVR
unsigned char read_gray_code_from_encoder (void)
{
unsigned char val=0;

if(!bit_is_clear(PINC.2)) val |= (1<<1); - РАСШИФРУЙТЕ ЭТО ПЖЛ, НА МОИ ПОРТЫ!

if(!bit_is_clear(PINC.3)) val |= (1<<0);

return val;
}

Дальше код из статьи вроде понятен.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение Аlex »

Код: Выделить всё

if(!bit_is_clear(PINC, 2))
    val |= (1<<1); 

if(!bit_is_clear(PINC, 3))
    val |= (1<<0);
bit_is_clear скорее всего, задефайнен как-нибудь так :

Код: Выделить всё

#define bit_is_clear(var, bit)       (((var)&(1<<bit))==0)
Либо, для CV-синтаксиса :

Код: Выделить всё

if(PINC.2)
    val |= (1<<1); 

if(PINC.3)
    val |= (1<<0);
Аватара пользователя
VNN84
Грызет канифоль
Сообщения: 256
Зарегистрирован: Вт мар 11, 2008 06:22:36
Откуда: Волгоград

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение VNN84 »

Да, спасибо. Запустил энкодер, крутит отлично. Но только вот на быстрое вращение не очень реагирует. Буду дальше разбираться.
Еще вопрос: val |= (1<<1) - можно это переписать в человеческий синтаксис? А то через пару месяцев опять буду смотреть как на китайскую грамоту )))
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

Re: Энкодер + atmega8 + CodeVisionAVR

Сообщение Zhuk72 »

VNN84 писал(а):Еще вопрос: val |= (1<<1) - можно это переписать в человеческий синтаксис? А то через пару месяцев опять буду смотреть как на китайскую грамоту )))
Выставить бит 1 в val. Иначе говоря, val |= 0b00000010 или val = val | 2.
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Ответить

Вернуться в «Разные вопросы по МК»