Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Команда Encoder в Баскоме-вопрос


Команда Encoder в Баскоме-вопрос

Сообщений 1 страница 30 из 47

1

В Баскоме есть команда
B = Encoder(pinb.0 , Pinb.1 , Links , Rechts , 1)
Раз'ясните, пожалуйста:
- переменная В, для чего она и куда её засунуть?
- wait (0 или 1) не пойму, что определяет?
Спасибо за терпение!

0

2

B - число щелчков, а вызываемые п/п должны как-то указывать или сообщать направление вращения. Возьми тестовую программу и проверь в "железе". Думаю она не понравится.
Вообще, это совершенно бесполезная функция. Энкодер обычно применяется с сложных системах и поэтому должен работать в фоновом режиме,  т.к. реальная программа не может бесконечно сидеть на его опросе. Кроме того, энкодер
может вращаться и медленно и очень быстро - до 1 кГц, и тогда его будет очень затруднительно
обрабатывать по опросу без пропусков щелчков.

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

Для статических энкодеров (такой нарисован в примере - это и все оптические) необходимо использовать прерывания
по каждому изменению уровня на обоих линиях. Т.е. можно использовать до четырех обычных прерываний,
например, INT0 \_, INT1 \_, INT2 _/, INT3 _/, соединив входы попарно - я делаю именно так. Зато в программе обработки
получается проще определить направление вращения. Можно использовать два прерывания по любому изменению уровня.
Или только одно по изменению уровня в порту. Но в последнем случае сложнее выделять направление ведь еще нужно
подавлять дребезг.

Для динамических енкодеров, такие делает BOURNS (ECW1J-B24-..., достаточно одного прерывания по спаду.

Аппаратно, для подавления дребезга обязательно нужно применить
RC-цепочку 10k+0.1mkF и 100 ом последовательно с замыкающим контактом :
                    10 k
   +5V <----====----------> Port
          /         100    |    |   
   |---/  ----====---   ===  0.1 мкФ   
                                   |
                                  __
Будут вопросы  - выложу текст программы.

+1

3

Я делаю так:

Код:
$regfile = "m16def.dat"                                     'подключаем файл заголовков для контроллера ATmega16
$crystal = 8000000                                          'частота кварцевого генератора

$baud = 9600                                                'настройка скорости передачи RS-232
$hwstack = 32                                               'аппаратный стек
$swstack = 10                                               'програмный стек
$framesize = 40                                             'размер фрейма

'настраиваем ЖКИ
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2
Config Lcd = 16 * 2                                         'ЖКИ 2 строки по 16 символов
Cursor Off                                                  'выключить курсор

'VALCODER________________________    выводы енкодера(валкодера)
Config Pind.3 = Input                                       'Valcoder A INT1
Valcod_a Alias Pind.3
Config Pina.4 = Input                                       'Valcoder B
Valcod_b Alias Pina.4
Set Portd.3
Set Porta.4

'объявляем переменные
Dim Valcod_param As Byte
Dim Valcod_cange As Bit

Config Int1 = Falling                                       'настраиваем внешнее прерывание INT1 на срабатывание при изменении из "1" в "0"
On Int1 Valcoder_change                                     'подпрограмма обработка прерывания Valcoder_change
Enable Int1                                                 'разрешаем работу прерывания  INT1
Enable Interrupts                                           'разрешаем глобальные прерывания

Cls                                                         'очищаем экран ЖКИ
Locate 1 , 10                                               'задаем позицию курсора
Lcd "Enc=" ; Valcod_param                                   'выводим переменную изменения значения енкодера(валкодера)

Do                                                          'начало цикла

If Valcod_cange = 1 Then                                    'если битовая переменна Valcod_cange = 1 (крутили енкодер(валкодер)
                       Locate 1 , 14                        'то задаем позицию курсора
                       Lcd Valcod_param ; "  "              'выводим переменную изменения значения енкодера(валкодера)
                       Reset Valcod_cange                   'сбрасываем битовую переменную Valcod_cange
                       Sound Buzer , 10 , 500               'генерим звук
End If

Loop                                                        'замыкаем цикл


Valcoder_change:                                            'подпрограмма обработки прерывания INT1
'*******************************************************************************
If Valcod_b = 1 Then                                        'если на линии B лог "1"
                  If Valcod_param <> 255 Then Incr Valcod_param       'то если  переменная Valcod_param не достигла значения 255 увеличиваем ее на 1
                Else                                        'если на линии B лог "0"
                  If Valcod_param <> 0 Then Decr Valcod_param       'то если  переменная Valcod_param не достигла значения 0 уменьшаем ее на 1
End If
Set Valcod_cange                                            'выставляем битовую переменную Valcod_cange
Return                                                      'возврат из подпрогрммы

End                                                         'конец программы

+1

4

Я пробовал в железе обрабатывать энкодер через Debounce. Принцип тот же, что и в Вашем коде. Работает ужасно. Наверное, потому что использовались два таймера в программе(часы и индикация LED)
А вот как раз Encoder работал стабильно. Через прерывания пока не пробывал. Так как в наше время приходится сначала разводить ПП, а потом под неё прошивку писать.(мега8, портD индикация)
Проверял я хелповский пример в железе. Ошибок- одна из пятнадцати. Переменная В меняется 1-3-2.
На количество щелчков не похоже. И что-же всётаки определяет "wait"? (Ну ни как этот англицкий не понять %-)

0

5

'----------------------------------------------------------------------------------
' демонстрационная программа применения энкодера
' расчитана на простые меги (только с Int0) и улучшенные с прерыванием по любом ножке
'----------------------------------------------------------------------------------
$map
'$regfile = "m8def.dat"
$regfile = "m168def.dat"
'$noramclear                             'не чистить память
$hwstack = 64                           'размер аппаратного стека
$swstack = 32                           'размер программного стека
$framesize = 32                         'размер области используемой для преобразований и временного хранения данных
                                         'Byte - 4 bytes, Integer - 7 bytes, Longs - 16 bytes, single - 24 bytes
                                         'String - длина слиния (монтажа) строк
                                         'Плюс локальные LOCAL переменные, плюс временные VALUE (BYVAL)
'----------------------------------------------
Dim Edat As Byte                        'признак "Есть новые данные енкодера"
Dim Ndat As Byte                        'признак "Есть новые данные для исполнения"
Dim R_cdec As Byte                      'СЧЕТЧИК ЩЕЛЧКОВ ВЛЕВО
Dim R_cinc As Byte                      'СЧЕТЧИК ЩЕЛЧКОВ ВПРАВО
Dim Tmpb As Byte                        'временные байтовые данные
Dim Ua As Single                        'временное значение
Dim Ub As Single                        'временное значение
Dim Bufa As String * 20                 'строка
Dim Bufb As String * 20                 'строка
Dim Bufz As String * 16                 'строка
'---------------------
' назначение векторов прерывания.
'On Int0 Int0_int Nosave                 'вектор внешнего прерывания 0
On Pcint0 Int0_int Nosave               'вектор внешнего прерывания 0
'---------------------
' инициализация оборудования.
'---------------------
$crystal = 20000000                     'кварц 20 МГц
'---------------------
Config Lcdpin = Pin , Db4 = Portc.1 , Db5 = Portc.2 , Db6 = Portc.3 , Db7 = Portc.4 , E = Portd.1 , Rs = Portd.0       'для индикатора M88
Config Lcd = 16 * 2                     'определить конфигурацию индикатора
'---------------------
'    СТОРОЖЕВОЙ ТАЙМЕР
'---------------------
$asm
    Wdr                                 'Reset Watchdog Timer
$end Asm
Mcusr = 0                               'сбросить WDRF в MCUSR и все остальное (m88)
Wdtcsr = &H1F                           'ЧТОБЫ ЗАПРЕТИТЬ WDT ТРЕБУЕТСЯ ВНАЧАЛЕ РАЗРЕШИТЬ (m88)
Wdtcsr = &H17                           'А ЗАТЕМ ЗАПРЕТИТЬ (m88)
'---------------------
Clkpr = &H80 : Clkpr = &H00             'коэффициент деления кварца: 1  Fкв = 20 МГц
'---------------------
'Smcr = &H01                             'разрешить режим Idle
'---------------------
'ATMEGA88,168
'Eicra = &B00000010                      'INT0 - по спаду
'Eimsk = &B00000001                      'INT0 - разрешить
Pcicr = &B00000001                      'разрешить прерывание по изменению уровня линий портов PCI0...PCI7
Pcmsk0 = &B00000100                     'а конкретно PBI2
Sei                                     'разрешить прерывания
'---------------------
'ATMEGA8
'Mcucr = &B10000010                      'IDLE - разрешить, INT0 - по спаду
'Gicr = &B01000000                       'INT0 - разрешить
'Sei                                     'разрешить прерывания
'---------------------
'    ПОРТЫ
'---------------------
Ddrb = &B00000000                      'направление линий порта B: 1 - на вывод
Portb = &B11111100                      'исходное состояние линий B: hhhhhhhh
'---------------------
Ddrc = &B00011110                      'направление линий порта C: 1 - на вывод
Portc = &B00000000                      'исходное состояние линий C:  zzz1111zb
'---------------------
Ddrd = &B11111111                      'направление линий порта D: 1 - на вывод
Portd = &B00000000                      'исходное состояние линий D: 00000000
'----------------------------------------------
' определение изображения дополнительных символов ЖКИ
    Deflcdchar 0 , 31 , 31 , 31 , 31 , 31 , 31 , 31 , 31       'блок
    Deflcdchar 1 , 4 , 4 , 10 , 10 , 17 , 17 , 31 , 32       'дельта
    Deflcdchar 3 , 4 , 32 , 4 , 32 , 4 , 32 , 4 , 32       'вертикальный разделитель
    Deflcdchar 6 , 2 , 6 , 15 , 31 , 15 , 6 , 2 , 32       'стрелка влево
    Deflcdchar 7 , 8 , 12 , 30 , 31 , 30 , 12 , 8 , 32       'стрелка вправо
    Cls                                 'обязательная операция.
    Cursor Off Noblink                  'сделать курсор невидимым
'---------------------
'время и дату компиляции записать в строку в европейском формате - DD-MM-YYYY hh:nn:ss
    Bufa = Version(1)                   'дата версии
    Bufa = Left(bufa , 10)
    Bufb = " v01:" + Bufa               'номер версии и дата
           '1234567890123456
    Bufa = " Encoder_Tester "           'стартовый заголовок
    Gosub Lcdbufs                       'все вывести
'---------------------
    Wait 2                              'будем отображать 2 с
    Ub = 5                              'установим начальное значение
    Edat = 0 : Ndat = 255               'и назначим отбображение текущего значения регулируемого параметра
    Cls                                 'очистить
'---------------------
'главный цикл - ждем событий
Mc:
    If Ndat <> 0 Then                   'Есть новые данные для исполнения?
       Ndat = 0 : Goto N_dat
    End If
    If Edat <> 0 Then                   'Есть новые данные енкодера?
       Edat = 0 : Gosub W_rot
    End If
    Waitms 200                          'задержка, чтобы индикатор не дергался слишком часто
Goto Mc
'---------------------
'   ----------------
'  | Adjusted Value:|
'  |     +XX.XX     |
'   ----------------
N_dat:
'первая строка
    Bufa = " Adjusted Value:"
'-----
'вторая строка
    Ua = Abs(ub)                        'делаем положительным, чтобы знак минус при форматировании не выскакивал впереди
    If Ua > 99.995 Then                 'предотвратим переполнение шкалы
       Cls : Lcd "   OVER_LOAD!" : Goto Mc
    End If
    Bufb = Fusing(ua , "##.##")         'форматируем по маске
    Bufz = Format(bufb , "00000")       'забиваем лидирующие нули, чтобы отображаемое значение было неподвижно на индикаторе
    If Ub < 0 Then                      'добавляем знак полярности
       Bufb = "     -" + Bufz
    Else
       Bufb = "     +" + Bufz
    End If
    Gosub Lcdbufs                       'вывод в индикатор сформированного изображения
Goto Mc
'----------------------------------------------
Const Onetik = 0.01                     'значение одного щелчка енкодера
'ОБРАБОТКА ЕНКОДЕРА
W_rot:
    Tmpb = 0                            'ОЧИСТИМ И СЧИТАЕМ КОД
    Swap Tmpb , R_cinc
    If Tmpb <> 0 Then                   'ПРОВЕРИМ СЧЕТЧИК ЩЕЛЧКОВ ВПРАВО
        Goto Wrotr                      'ЕСЛИ НЕ РАВЕН НУЛЮ - НА ОБРАБОТКУ
    End If
    Swap Tmpb , R_cdec
    If Tmpb <> 0 Then                   'АНАЛОГИЧНО СЧЕТЧИК ЩЕЛЧКОВ ВЛЕВО
        Goto Wrotl
    End If
Return
'--------
'ВРАЩЕНИЕ ЕНКОДЕРА ВЛЕВО
Wrotl:
    Ua = Tmpb                           'ПРЕОБРАЗОВАТЬ В ЧИСЛО С ПЛАВАЮЩЕЙ ТОЧКОЙ
    Ua = 0 - Ua                         'ОТРИЦАТЕЛЬНАЯ ПОЛЯРНОСТЬ
    Goto Wrot1
'--------
'ВРАЩЕНИЕ ЕНКОДЕРА ВПРАВО
Wrotr:
    Ua = Tmpb                           'ПРЕОБРАЗОВАТЬ В ЧИСЛО С ПЛАВАЮЩЕЙ ТОЧКОЙ
Wrot1:
    Ua = Ua * Onetik                    'вычисление приращения с учетом значения одного щелчка
    Ub = Ub + Ua                        'вычисление нового значения регулируемого параметра
    Ndat = 255                          'установить признак "Есть новые данные"
Return
'------------------------------------------
'вывод строковых буферов в индикатор
Lcdbufs:
    Gosub Lcd_bufa
Lcd_bufb:
    Locate 2 , 1 : Lcd Bufb : Return
'------------------------------------------
Lcd_bufa:
    Locate 1 , 1 : Lcd Bufa : Return
'----------------------------------------------------------------------------------
'ОБРАБОТКА ВНЕШНЕГО ПРЕРЫВАНИЯ 0 - ОТ ДВУХФАЗНОГО ИМПУЛЬСНОГО ЕНКОДЕРА
'ПРЕРЫВАНИЕ ПРОИСХОДИТ ПО СПАДУ НА ВХОДЕ P_CHA. ЗАТЕМ ПРОГРАММА ИНТЕГРИРУЕТ
' (ФИЛЬТРУЕТ) ЭТОТ УРОВЕНЬ, ДОЖИДАЯСЬ НАДЕЖНОГО УСТАНОВЛЕНИЯ "0". В МОМЕНТ
'ФИКСАЦИИ "0" НА ЛИНИИ P_cha РЕГИСТРИРУЕТСЯ УРОВЕНЬ P_chb , ПО КОТОРОМУ И
'ОПРЕДЕЛЯЕТСЯ НАПРАВЛЕНИЕ ВРАЩЕНИЯ. П/П РАБОТАЕТ ТАКЖЕ ПРИ ИСПОЛЬЗОВАНИИ
'ПРЕРЫВАНИЯ ОТ ЛЮБОГО ИЗМЕНЕНИЯ УРОВНЯ. НА СПАД СРАБАТЫВАЕТ, ФРОНТ ИГНОРИРУЕТ
'-------------------------------------------
P_cha Alias Pinb , 2                    'ОПРЕДЕЛЕНИЕ ПОРТОВ ВВОДА КОДА ЦИФРОВОЙ РУЧКИ,
P_chb Alias Pinb , 3                    'НО В АССЕМБЛЕРНОЙ ВСТАВКЕ ОНО НЕ РАБОТАЕТ
'-------------------------------------------
Const Con_irt = 30                      'КОНСТАНТА ИНТЕГРИРОВАНИЯ УРОВНЯ НА ВХОДЕ
Const Conirt1 = Con_irt * 1.5           'ПОЛТОРЫ КОНСТАНТЫ ИНТЕГРИРОВАНИЯ
Const Conirt2 = Con_irt * 2             'ДВЕ КОНСТАНТЫ ИНТЕГРИРОВАНИЯ
'---------
$asm
Int0_0:
    Inc R31                             'УРОВЕНЬ ВЫСОКИЙ - ОТКАТ СЧЕТЧИКА
    Cpi R31 , Conirt1                   'это Con_irt*1.5
    Brne Int0_1                         'ЕСЛИ ЖДЕМ СЛИШКОМ ДОЛГО - ВЫХОД
    Rjmp Int0_e
'---------
'ВНЕШНЕЕ ПРЕРЫВАНИЕ ОТ ЦИФРОВОЙ РУЧКИ
Int0_int:
    Push R31                            'сохраним регистры
    In R31 , Sreg
    Push R31
'-----
'ИНТЕГРИРУЮЩИЙ ФИЛЬТР (ФНЧ) ВХОДНОГО УРОВНЯ
    Ldi R31 , Con_irt                   'ПОСТОЯНАЯ ИНТЕГРИРОВАНИЯ В СЧЕТЧИК
Int0_1:
    Sbic PINb,2                         'ПРОВЕРИМ УРОВЕНЬ НА ВЫВОДЕ
    Rjmp Int0_15                        'ЕСЛИ НА НОЖКЕ "1" - ПЕРЕХОД
    Dec R31                             'ПОКА НЕ ОБНУЛИЛСЯ СЧЕТЧИК ЖДЕМ
    Brne Int0_1                         'МНОГОКРАТНОГО ПОДТВЕРЖДЕНИЯ НИЗКОГО УРОВНЯ
    Rjmp Int0_2
'-----
'ЕСЛИ УРОВНЬ ВЫСОКИЙ
Int0_15:
    Inc R31                             'УВЕЛИЧИВАЕМ СЧЕТЧИК
    Cpi R31 , Conirt2                   'ЕСЛИ НА "1" УСТАНОВЛЕНА СЛИШКОМ ДОЛГО
    Brne Int0_e                         'НА ВЫХОД
    Rjmp Int0_1
'---------------------------------------------
'ПРОГРАММА РАСЧИТАНА НА КОДОВЫЙ ПЕРЕКЛЮЧАТЕЛЬ
'С НОРМАЛЬНО РАЗОМКНУТЫМИ КОНТАКТАМИ, ЗАМЫКАЮЩИМИСЯ
'ТОЛЬКО В МОМЕНТ ЩЕЛЧКА. ЭТО ОЧЕНЬ УПРОЩАЕТ ЗАДАЧУ
'---------------------------------------------
'      |<----- ВРАЩЕНИЕ ВЛЕВО (ИЛИ НАОБОРОТ, В ЗАВИСИМОСТИ ОТ МОНТАЖА)
'chA---     ---------     ------ ОПРЕДЕЛЕНИЕ НАПРАВЛЕНИЯ
'      ¦   ¦  chA    ¦   ¦      ВРАЩЕНИЯ ЦИФРОВОГО КОДЕРА
'       ---           ---      ОСНОВАНО НА АНАЛИЗЕ СОСТОЯНИЯ
'chB-----  |  ---------     ---- КАНАЛА "B" В МОМЕНТ ЗАМЫКАНИЯ
'      | ¦ | ¦  chB    ¦   ¦    (ЩЕЛЧКА) В КАНАЛЕ "A"
'      |  ---           ---
'      |   |<------ ВРАЩЕНИЕ ВПРАВО
'---------------------------------------------
Int0_2:
'ОБРАБОТКА ИЗМЕНЕНИЯ УРОВНЯ
'---------
    Sbis PINb,3
    Rjmp Int0_3                         'ОПРЕДЕЛИМ НАПРАВЛЕНИЕ ВРАЩЕНИЯ
'---------
'ВРАЩЕНИЯ ВЛЕВО (УМЕНЬШЕНИЕ)
    Lds R31 , {r_cdec}                  'УВЕЛИЧИМ СЧЕТЧИК ЩЕЛЧКОВ ВЛЕВО
    Inc R31
    Sts {r_cdec} , R31
    Rjmp Int0_4
'---------
Int0_3:
'ВРАЩЕНИЯ ВПРАВО (УВЕЛИЧЕНИЕ)
    Lds R31 , {r_cinc}                  'УВЕЛИЧИМ СЧЕТЧИК ЩЕЛЧКОВ ВПРАВО
    Inc R31
    Sts {r_cinc} , R31
Int0_4:
    Ldi R31 , &HFF
    Sts {edat} , R31                    'поставить признак "НОВЫЕ ДАННЫЕ ЕНКОДЕРА"
'---------
Int0_e:
    Pop R31
    Out Sreg , R31
    Pop R31
    Reti
$end Asm
Return
'----------------------------------------------------------------------------------

+1

6

На редкость информативно, спасибо!
Асм только немного расстраивает, но подробное описание вселяет надежду (это я о себе)
Ещё раз спасибо, буду изучать.

0

7

ПОПРОБУЙ В ЖЕЛЕЗЕ. ПЕРЕДЕЛАТЬ ЕНКОДЕР НА ДРУГИЕ ЛИНИИ ПОРТОВ ОЧЕНЬ ПРОСТО -
НЕПОСРЕДСТВЕННОЕ УПОМИНАНИЕ ПОДКЛЮЧЕНИЯ ВСЕГО В ЧЕТЫРЕХ МЕСТАХ ПРОГРАММЫ.
НУ, И КОНЕЧНО ПОДКЛЮЧЕНИЕ ИНДИКАТОРА. ОЧЕНЬ РЕКОМЕНДУЮ ПРИМЕНИТЬ СХЕМУ
ПОДКЛЮЧЕНИЯ С RC-ЦЕПОЧКАМИ.
'        --------- + 5v
'       ¦       ¦      -------
'       -       -     ¦  AVR  ¦
'      | |10k  | |10k ¦       ¦
'       -       -     ¦       ¦
'  100n ¦       ¦     ¦       ¦
' |-||--+-------------¦PB2    ¦
'       ¦  100n ¦     ¦       ¦
'       ¦ |-||--+-----¦PB3    ¦
'       -       -     ¦       ¦
'      | |     | |    ¦       ¦
'       - 100   - 100  -------
'       ¦       ¦
'        /       /
'       /  ChA  / ChB
'       ¦       ¦
'      ---    ----

0

8

А если не вешать энкодер на ногу внешнего прерывания? Я попытался использовать команду "Encoder", она работает, но криво, перескакивает то по 2, то по 3 значения(чаще по 3). вот код, удалил все,  что ненужно в данный момент. оставил только энкодер и индикацию :

Код:
$regfile = "m8def.dat"
$crystal = 8000000

'----------------------------Псевдонимы---------------------------------------
Enc_1 Alias Pind.5                                'Энкодер вниз
Enc_2 Alias Pind.6                                'Энкодер вверх



'-------------------Конфигурирование портов-------------------------------------

Config Portc = Output                             'Индикаторы

Config Enc_1 = Input                              'Энкодер вниз
Config Enc_2 = Input                              'Энкодер вверх


'---------------------Конфигурирование таймеров---------------------------------
Config Timer0 = Timer , Prescale = 256
On Timer0 Din_indik

'----------------------Разрешаем прерывания-------------------------------------
Enable Interrupts
Enable Timer0


Start Timer0


Dim Tdes As Byte                                  'для десятичной части
Dim Tcel As Byte                                  'для целой части

Dim T1 As Single
Dim T2 As Byte

'-------------переменные для преобразования исходного числа---------------------
Dim N1 As Byte
Dim N2 As Byte
Dim N3 As Byte
Dim N4 As Byte
Dim N5 As Byte
Dim N6 As Byte
Dim N7 As Byte

Dim M1 As Long
Dim M2 As Long
Dim M3 As Long
Dim M4 As Long
Dim M5 As Long
Dim M6 As Long
Dim M7 As Long

'-------------------------------------------------------------------------------

Dim R As Byte                                     'для значений отправляемых в регистр


'-----------------Начало основного цикла----------------------------------------
Tcel = 50


Do
S = Encoder(pind.6 , Pind.5 , Enc_low , Enc_hi , 0)

Loop

End                                               'конец программы

'массив с кодами для семисегментника
'--------------Определения 7-ми сегментника (общ. аннод)----------------------
'
Numbers:
        ' FBGCdpDEA (в цифры полсе сегмента это разряд порта)
   Data &B00101000                                '0   ***A0***
   Data &B10101111                                '1   *      *
   Data &B10011000                                '2   F7     B6
   Data &B10001010                                '3   *      *
   Data &B00001111                                '4   ***G5***
   Data &B01001010                                '5   *      *
   Data &B01001000                                '6   E1     C4
   Data &B10101110                                '7   *      *
   Data &B00001000                                '8   ***D2***
   Data &B00001010                                '9             dp3
   Data &B11110111                                'точка
   Data &B01011000                                'E
   Data &B11011101                                'r
   Data &B00011100                                'P
   Data &B00001101                                'H
   Data &B01111101                                'I

'подпрограмма отправки данных в регистр
Registr:
Shiftout Portc.0 , Portc.2 , R , 1                'задвигаем данные
Pulseout Portc , 1 , 5                            'защелкиваем регистр
Waitus 700                                        'задержка переключений разрядов
Return

'подпрограмма работы с регистром переключающим аноды
Anod:
Shiftout Portc.3 , Portc.5 , R , 1
Pulseout Portc , 4 , 5

Return

Din_indik:

'раскладываем число на составляющие
M1 = Tcel
M2 = M1
'M3 = M1
M4 = M
M5 = M4
M6 = S
M7 = M6


M1 = M1 Mod 100
M1 = M1 / 10
N1 = Abs(m1)

M2 = M2 Mod 10
N2 = Abs(m2)

N3 = Tdes


M4 = M4 Mod 100
M4 = M4 / 10
N4 = Abs(m4)

M5 = M5 Mod 10
N5 = Abs(m5)

M6 = M6 Mod 100
M6 = M6 / 10
N6 = Abs(m6)

M7 = M7 Mod 10
N7 = Abs(m7)

R = &B00000001                                    ' первая цифра термометра
Gosub Anod
R = Lookup(n1 , Numbers)
Gosub Registr


R = &B00000010                                    ' вторая цифра термометра
Gosub Anod
R = Lookup(n2 , Numbers)
Gosub Registr

R = Lookup(10 , Numbers)
Gosub Registr

R = &B00000100                                    ' третья цифра термометра
Gosub Anod
R = Lookup(n3 , Numbers)
Gosub Registr



R = &B00001000                                    ' первая цифра таймера
Gosub Anod
R = Lookup(n4 , Numbers)
Gosub Registr

R = &B00010000                                    ' вторая цифра таймера
Gosub Anod
R = Lookup(n5 , Numbers)
Gosub Registr

R = &B00100000                                    ' третья цифра таймера
Gosub Anod
R = Lookup(n6 , Numbers)
Gosub Registr

R = &B01000000                                    ' четвертая цифра таймера
Gosub Anod
R = Lookup(n7 , Numbers)
Gosub Registr

Gifr = 128
Return

Enc_low:
Decr Tcel
'Waitms 5
Return

Enc_hi:
Incr Tcel
'Waitms 5
Return

0

9

kip написал(а):

- wait (0 или 1) не пойму, что определяет?

При Wait = 0 будет постоянно проверять наличие импульсов (этакий бесконечный опрос), при Wait = 1 программа остановится и будет ждать пока пока энкодер не будет повернут в ту или иную сторону, т.е. если его не крутить, то программа остановится.
LefLabel - это имя метки, которая будет вызвана при вращении влево, Соответственно RightLabel метка для правого поворота.
Еще условия:
· П/п, которая вызывается кодером должна заканчиваться оператором Return.
· Вывод, куда подключен энкодер должен работать в режиме ввода.
· Необходимо включить подтягивающие резисторы.

Отредактировано sva-don (2012-02-06 21:38:50)

0

10

Хрень честно говоря этот ENCODER. Он не может работать в подпрограммах, а это БОЛЬШОЙ минус....

0

11

Попробуйте так:

Код:
$regfile = "m32def.dat"                                     'определяем контроллер
$crystal = 8000000                                          'определяем частоту кварца/внутреннего генератора

Config Pind.3 = Input                                       'настройка пина d3 на вход(вывод A энкодера)
Valcod_a Alias Pind.3                                       'присваиваем пину d3 имя Valcod_a
Set Portd.3                                                 'включить внутренний подтягивающий резистор
Config Pind.4 = Input                                       'настройка пина d4 на вход(вывод B энкодера)
Valcod_b Alias Pind.4                                       'присваиваем пину d4 имя Valcod_b
Set Portd.4                                                 'включить внутренний подтягивающий резистор 

Config Int1 = Falling                                       'настраиваем внешнее прерывание INT1 на срабатывание при изменении из "1" в "0"
On Int1 Valcoder                                            'подпрограмма обработки прерывания Valcoder
Enable Int1                                                 'разрешаем работу прерывания  INT1
Enable Interrupts                                           'разрешаем глобальные прерывания

Valcoder:                                                   'подпрограмма обработки прерывания INT1
'*******************************************************************************
Select Case Menu
Case 1 : If Valcod_b = 1 Then                               'если на линии B лог "1"

Else                                                        'если на линии B лог "0"

End If
Case 2 : If Valcod_b = 1 Then                               'если на линии B лог "1"

Else                                                        'если на линии B лог "0"

End If
Case 3 : If Valcod_b = 1 Then                               'если на линии B лог "1"

Else                                                        'если на линии B лог "0"

End If
Case 4 : If Valcod_b = 1 Then                               'если на линии B лог "1"

Else                                                        'если на линии B лог "0"

End If
Case 5 : If Valcod_b = 1 Then                               'если на линии B лог "1"

Else                                                        'если на линии B лог "0"

End If
End Select
Return

Отредактировано max (2014-10-05 17:04:34)

0

12

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

0

13

max написал(а):

Config Int1 = Falling                                       'настраиваем внешнее прерывание INT1 на срабатывание при изменении из "1" в "0"

По идеи, у такого подхода есть один минус, энкодер не будет срабатывать при стартовом состоянии (чёт/нечет, если он замрет в положении "0" в "1"). Т.е. при первом шаге не будет отклика, если точность при старте не нужна, то - идеально.

0

14

Я решил свою проблему со своим энкодером (E40s6-2048-6-L-5) не используя прерываний int вот таким способом прерыванием по таймеру
в прерывании таймера опрашиваю состояния пинов и сравниваю их с предыдущим

$regfile = "m128def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 32
$framesize = 32
$baud = 38400

Dim Conl As Byte
Dim Con As Byte
Dim I As Dword
Dim Con_n As Dword

Config Portb.6 = Input : Config Portb.7 = Input   
Config Timer0 = Timer , Prescale = 8 
On Timer0 Tim0:
Enable Timer0
Enable Interrupts

Do
If I <> Con_n Then Print Con_n
I = Con_n
Loop

Tim0:
If Pinb.6 = 0 And Pinb.7 = 0 Then : Conl = 0 : End If
If Pinb.6 = 1 And Pinb.7 = 0 Then : Conl = 1 : End If
If Pinb.6 = 1 And Pinb.7 = 1 Then : Conl = 2 : End If
If Pinb.6 = 0 And Pinb.7 = 1 Then : Conl = 3 : End If
If Con = 0 And Conl = 1 Then : Incr Con_n : End If
If Con = 1 And Conl = 2 Then : Incr Con_n : End If
If Con = 2 And Conl = 3 Then : Incr Con_n : End If
If Con = 3 And Conl = 0 Then : Incr Con_n : End If
If Con = 0 And Conl = 3 Then : Decr Con_n : End If
If Con = 1 And Conl = 0 Then : Decr Con_n : End If
If Con = 2 And Conl = 1 Then : Decr Con_n : End If
If Con = 3 And Conl = 2 Then : Decr Con_n : End If
Con = Conl
Return

Отредактировано uh9cae (2014-10-21 00:08:44)

0

15

Лучше бы сделали по прерываниям от Int. Потому что 7812 прерываний в секунду от таймера, это уже перебор. Зря только тратятся ресурсы МК.
Кроме того, антидребезга нет.

0

16

int все заняты, это оптический энкодер в нём нет дребезга и этот энкодер даёт 4096 импульсов на оборот

Отредактировано uh9cae (2014-10-21 18:00:39)

0

17

Я вот понять не могу. B = Encoder(pinb.0 , Pinb.1 , Links , Rechts , 0) Использовал вот эту функцию. Выводы МК int0 int1. Мне не понятно почему энкодер так отвратно работает? Просто слов нет. Он можно сказать и не работает, только если ооооочень медленно вращать. Надо ли разрешать аппаратные или программные прерывания для этой функции? В чем может быть причина?

0

18

Запустить эту функцию с пристойной работой энкодера наверное маловероятно.

0

19

Вот так сюрприз. Может посоветуете как сделать лучше всего? Какой нибудь пример если не сложно покажите. Был бы очень благодарен)

0

20

Код:
$regfile = "m8adef.dat"
$crystal = 8000000

Encoder1 Alias Pinb.1
Encoder2 Alias Pinb.2
Knopka Alias Pinb.0

Config Int0 = Falling
Enable Int0
Enable Interrupts
On Int0 Radiost

Делал настройку частоты в приемничке(надо было вращать энкодер шустрей):
это в основном цикле
If  Encoder1 = 0 And Encoder2 = 1 Then
Waitms 50
Frequenz = Frequenz + 0.1
End If
If Encoder1 = 1 And Encoder2 = 0 Then
Waitms 50
Frequenz = Frequenz - 0.1
End If

это переключение настроенных радиостанций(здесь быстро вращать энкодер не понадобилось)
Radiost:
If B = 2 And Encoder1 = 0 And Encoder2 = 1 Then
Set Portb.7
Start Timer0
Waitms 100
Sound , Portb.6 , 75 , 300
A = A + 1
End If
If B = 2 And Encoder1 = 1 And Encoder2 = 0 Then
Set Portb.7
Start Timer0
Sound , Portb.6 , 75 , 300
Waitms 100
A = A - 1
End If

Подключал так:
http://sa.uploads.ru/t/xTv28.jpg

может пригодится.

Отредактировано Sergik07 (2014-12-08 19:53:57)

+1

21

Даже и не знаю, но у меня работает нормально. Правда висит одна нога на прерывании. И ни каких секретов нет.  И без прерывания, тоже нормално работает :dontknow:

0

22

Sergik07 спасибо! Будем пробовать))))

0

23

kip я так понимаю у тебя код не большой совсем. Тогда да, будет работать корректно. Но если код большой, то обязательно начнутся проблемы.

0

24

У меня часы на меге8 на асинхронном таймере со светодиодным индикатором. Задействованы все таймеры ( индикация + яркость) и sound. Точнее - это кухонный таймер с функцией часов. При повороте энкодера включается установка таймера, и далее он запускается. Энкодер выдрал с автомагнитолы. Кроме того, код у меня попросил один человек(?) через мыло. И у него не пошёл энкодер. Выяснилось, что много шелчков у него. Я переделал прошивку, и при включении он настраивал энкодер под себя. Я просто добавил делитель. К сожалению быстрый поиск на компьютере не дал результатов. Попробую получше поискать. А таймер работает до сих пор. Могу видео заснять. Уверяю Вас, использовал "баскомовскую" команду

0

25

Ну не знаю. Может быть что то не так сделал. Но вроде все как в примере. Ладно попробую, там видно будет. Отпишу тогда.
Пичаль что нет нормального энкодера для протеуса. Приходиться кнопки ставить обычные. А сам модэли еще не умею делать.

Отредактировано Atmel (2014-12-11 12:59:39)

0

26

Блин. Не работает. Точнее работает, но гораздо хуже чем было О_о. Надо разбираться в коде. Что то тут не так...

0

27

В протеусе есть двигатель с энкодером. Я его использовал и включал в нужную сторону

0

28

Спасибо, но про движок знаю. Жудко неудобная хреновина))))

0

29

Atmel написал(а):

Жудко неудобная хреновина

Интересно, неудобная чем?

Модель здесь

0

30

обрабатываю импульсы от оптического энкодера ЛИР-158 (1000 импульсов на оборот)

Код:
  $regfile = "m8def.dat"
$crystal = 12000000
$hwstack = 32
$swstack = 32
$framesize = 32
$baud = 57600


Dim I As Word
Dim W As Word
Dim N As Word

Config Pind.5 = Input
Config Pind.6 = Input
Config Pind.7 = Input
Config Portc.4 = Output

Config Timer0 = Timer , Prescale = 8
On Timer0 Tim0:
Enable Timer0

Config Int0 = Falling     ' прерывание INT0 по нисходящему фронту (c + на -)
On Int0 Encod

Enable Interrupts
Enable Int0


Do

 If I <> W Then Print W
I = W


Loop

Encod:              ' тут узнаем в каком направлении вращают ручку энкодера
                    ' ждем пока утихнет дребезг контактов
  If Pind.6 = 0 Then                                        ' если на ноге единица (импульс не пришел) тогда
  Incr W                    ' инкременируем переменную (увеличиваем на 1)
  N = W
 If N = 1000 Then W = 0
  Else                      ' в обратном случае
  Decr W                    ' декрементируем переменную (уменьшаем на 1)
  N = W
 If N = 0 Then W = 1000
  End If



  Gifr = 64



  Return

 Tim0:
If Pind.5 = 0 Then W = 0
If Pind.5 = 0 Then Print W


Return

девайс цепляется через переходник USB-UART  к компу и в LabView считываются импульсы.

В чем проблема: не смог к коду привязать кнопку сброса счетчиков импульсов (переменная W), кнопка сидит на Pind.5. как сейчас происходит-при вращени по часовой,значение переменной увеличивается от 0 до 1000,нажимаешь на кнопку,переменная сбрасывается в 0, если дальше вращать по часовой, то все ОК, а вот если против (после нажатия кнопки) то переменная становится =65535 (Word) и далее уменьшается.

как решить?сильно не пинайте...

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Команда Encoder в Баскоме-вопрос