Вт сен 04, 2012 14:40:49
Вт сен 04, 2012 14:57:54
;----------
; Перекодировка и вывод данных на индикаторы
; Первым идёт последний бит большого индикатора
; Направление данных | Адреса в буфере
; |
; >----------> |
; | |
; ^----------< | 08 09 0A 0B 0C 0D
; | |
; >----------^ | 00 01 02 03 04 05 06 07
;----------
print:
; первые 6 байт читаем без инверсии, остальные инвертируем
ldi r16,14 ; Счетчик байт
ldiX display_buf+14 ; В X адрес буфера индикаторов (на конец)
lds r19,point_maskH ; Берём маски точек
lds r20,point_maskL
pr0:
ld r17,-X ; Читаем байт и декрементируем указатель X
ldi2Z digits ; В Z указатель на таблицу перекодировки
add16Z r17 ; Смещение по таблице перекодировки
lpm r17,Z ; Читаем "рисунок" символа
mov r21,r19 ; Накладываем маску с точками
andi r21,0b10000000
or r17,r21
cpi r16,9 ; Прошли 6 символов?
brcc pr1
com r17 ; Если да - инвертируем
pr1:
ldi r18,8 ; Счетчик битов
pr2:
cbi ds_port,ds_bit ; Линию данных в 0
rol r17 ; Бит в C
brcc pr3 ; Если бит = 0 перепрыгиваем
sbi ds_port,ds_bit ; Иначе линию в 1
pr3:
push_sh_cp ; Сдвиговый импульс
dec r18
brne pr2 ; Не прошло 8 бит? Зацикливаем
rol r20 ; Сдвигаем временные регистры с масками
rol r19 ; с учётом переноса
dec r16 ; Не прошло 14 байт? Зацикливаем
brne pr0
push_st_cp ; Все данные прошли, дёргаем защёлку
ret
Вт сен 04, 2012 15:02:55
Вт сен 04, 2012 15:11:15
Вт сен 04, 2012 15:16:34
#define Enc PINC.3 // ВХОД енкодера
// INT1
interrupt [EXT_INT1 void ext_int1_isr(void) // прерывание от ЭНКОДЕРА
{
if (Enc==0)
{
if (Enc==0)
{
ваш код (у меня if(OCR0<235) {OCR0+=1;} )
}
}
if (Enc==1)
{
if (Enc==1)
{
ваш код ( у меня if(OCR0>2) {OCR0-=1;})
}
}
}
Вт сен 04, 2012 19:10:51
sbi sh_cp_port,sh_cp_bit #Выставили бит на порт
nop #Пропустили такт
cbi sh_cp_port,sh_cp_bit #Сняли бит
Ср сен 05, 2012 00:46:37
//Глобальные переменные
volatile static char EncValue = 0; /*значение увеличения\уменьшения енкодера*/
//обработка прерывания, частота вызова 1000 Гц. (или циклический вызов из основной программы)
#define EncoderPort PINC /*порт чтения енкодера*/
#define EncoderPin0 (1<<3) /*пины чтения енкодера*/
#define EncoderPin1 (1<<4) /*пины чтения енкодера*/
#define EncLockCntrMax 3 /*количество циклов опроса для фиксации шага енкодера (2-10) */
void encoder (void)
{
static unsigned char EncLockCntr0 = 0; //счетчик защелки канала 0
static unsigned char EncLockCntr1 = 0; //счетчик защелки канала 1
static unsigned char EncFlags = 0; //байт флагов
#define bEncLock0 (1<<0) /*бит защелки фазы 0 енкодера*/
#define bEncLock1 (1<<1) /*бит защелки фазы 1 енкодера*/
//обработка фазы 1
if (EncoderPort & EncoderPin0){ //контакт разомкнут (лог 1)?
if (EncLockCntr0 < EncLockCntrMax) //защелка досчитала?
EncLockCntr0 ++; //инкремент защелки
else
EncFlags |= bEncLock0; //установить бит защелки
}
else{ //контакт разомкнут
if (EncLockCntr0) //защелка обнулилась?
EncLockCntr0 --; //декремент защелки
else
if (EncFlags & bEncLock0){
EncFlags &= ~bEncLock0; //сбросить бит защелки
if (~EncFlags & bEncLock1) //если второй канал уже обнулен, обновить значение глобального счетчика
EncValue --;
}
}
//обработка фазы 2
if (EncoderPort & EncoderPin1){ //контакт разомкнут (лог 1)?
if (EncLockCntr1 < EncLockCntrMax) //защелка досчитала?
EncLockCntr1 ++; //инкремент защелки
else
EncFlags |= bEncLock1; //установить бит защелки
}
else{ //контакт разомкнут
if (EncLockCntr1) //защелка обнулилась?
EncLockCntr1 --; //декремент защелки
else
if (EncFlags & bEncLock1){
EncFlags &= ~bEncLock1; //сбросить бит защелки
if (~EncFlags & bEncLock0) //если второй канал уже обнулен, обновить значение глобального счетчика
EncValue ++;
}
}
}
Ср сен 05, 2012 01:56:02
#define ENC_A RB0
#define ENC_B RB1
extern void EncoderScan(void);
extern signed int Enc_Get_Val(void);
#include "enc.h"
static char EncState;
static volatile signed int EncValRet=0;
/***********************************************************/
void EncoderScan(void){
char New = (char)(ENC_A) + ((char)ENC_B<<1);
switch(EncState){
case 0:
if(New == 2) EncValRet++;
if(New == 1) EncValRet--;
break;
case 1:
if(New == 0) EncValRet++;
if(New == 3) EncValRet--;
break;
case 2:
if(New == 3) EncValRet++;
if(New == 0) EncValRet--;
break;
case 3:
if(New == 1) EncValRet++;
if(New == 2) EncValRet--;
break;
}
EncState = New; // Записываем новое значение
}
/***********************************************************/
signed int Enc_Get_Val(void){
signed int ret;
ret = EncValRet;
EncValRet=0;
return ret;
}
Ср сен 05, 2012 02:24:20
ketrosi писал(а):У меня так сделано (CVAVR)
- Код:
#define Enc PINC.3 // ВХОД енкодера
// INT1
interrupt [EXT_INT1 void ext_int1_isr(void) // прерывание от ЭНКОДЕРА
{
if (Enc==0)
{
if (Enc==0)
{
ваш код (у меня if(OCR0<235) {OCR0+=1;} )
}
}
if (Enc==1)
{
if (Enc==1)
{
ваш код ( у меня if(OCR0>2) {OCR0-=1;})
}
}
}
энкодер подключеный одним выводом на INT1, другой вывод Enc (пин необходимого вам порта настроенный на ввод)
защита от дребезга имеется в виде конденсаторов на 0,1 и еще програмная.
INT0 можно задействовать на кнопку энкодера или подключить еще один энкодер при необходимости.
Ср сен 05, 2012 08:17:01
if (enc && flags_enc) // ловим импульс
{
if(enc1) // вправо
{
right();
}
else // влево
{
left();
}
flags_enc=0;
}
if(!(enc)) flags_enc=1; // сбрасываем флаг
Ср сен 05, 2012 08:20:21
ploop писал(а):Измерил. Идут посылки по 8 бит с небольшими паузами (пауза из-за условий для инверсии, смотрите код). Между группами, после того, как передадутся 112 бит, паузы довольно большие (10-20 мс). Выглядит так (ch1 - такт, ch2 - данные):
Реализовано так:
- Код:
sbi sh_cp_port,sh_cp_bit #Выставили бит на порт
nop #Пропустили такт
cbi sh_cp_port,sh_cp_bit #Сняли бит
Ср сен 05, 2012 08:30:43
Пт апр 18, 2014 21:57:30
ketrosi писал(а):ketrosi писал(а):У меня так сделано (CVAVR)
- Код:
#define Enc PINC.3 // ВХОД енкодера
// INT1
interrupt [EXT_INT1 void ext_int1_isr(void) // прерывание от ЭНКОДЕРА
{
if (Enc==0)
{
if (Enc==0)
{
ваш код (у меня if(OCR0<235) {OCR0+=1;} )
}
}
if (Enc==1)
{
if (Enc==1)
{
ваш код ( у меня if(OCR0>2) {OCR0-=1;})
}
}
}
энкодер подключеный одним выводом на INT1, другой вывод Enc (пин необходимого вам порта настроенный на ввод)
защита от дребезга имеется в виде конденсаторов на 0,1 и еще програмная.
INT0 можно задействовать на кнопку энкодера или подключить еще один энкодер при необходимости.
также можно обрабатывать прерыванием INT1 еще и кнопку подключив ее через диод ко входу INT1 и
прямым подключением ко входу нужного порта.
Таким образом одно прерывание обрабатывает один энкодер (кнопку и крутилку), и упрощается сама программа.
Много чего можно обслуживать по одному прерыванию используя диоды по схеме монтажное или.
срабатывает прерывание , в нем проверяются пины портов, определяется по какому произошла сработка, далее выполняются нужные действия.
Пт апр 18, 2014 22:26:30
Сб май 07, 2016 14:09:32
Вс май 08, 2016 01:58:05
Вс май 08, 2016 07:37:17
Gerik_PP писал(а):...
Вт май 10, 2016 19:52:29
Пт июл 22, 2016 23:21:20
ploop писал(а):Да дребезг программно нормально отсекается. Если сами не придумаете, вот алгоритм Леонида Ивановича, раскомментирован до нельзя...Спойлер
- Код:
//----------
//Модуль поддержки энкодера
//Энкодер подключается к портам ENC_F1 (фаза 1) и ENC_F2 (фаза 2).
//Для подавления дребезга используется анализ двух последовательных
//состояний. Это позволяет обойтись без временных задержек.
//Функция Encoder_Init() должна вызываться один раз в начале программы.
//Функция Encoder_Exe() должна вызываться в основном цикле.
//При повороте энкодера на шаг вправо или влево вызываются функции
//To_Do_Step_Up() и To_Do_Step_Dn() соответственно.
.......................