Вы не вошли.
Спасибо, теперь понял.
Если бы там было не умножение, а сдвиг, возможно додумался бы сам
да, и еще
вот так не лучше будет?
INTERRUPT(SIG_INPUT_CAPTURE1)
{
unsigned int CurrentTime;
CurrentTime = (256 * ICR1H) + ICR1L;
sprintf(buffer, "%06u rpm", (unsigned long)60E6 / (unsigned long)CurrentTime );
SetLCDPosition(3, 4);
ShowStr(buffer);
TCNT1 = 0;
}
на одну переменную и условие меньше ...
Вне форума
Думаю, что в таком варианте программа будет неработоспособной, так как нужно измерять время между двумя захватами, а не индицировать просто состояние счетчика в момент захвата.
Вне форума
2 Liv
Я Вам как-то письмо присылал, насчет валкодера. Не получали??
......There is someone in my head, but it's not me.......
Вне форума
Что-то у меня с почтой не то. И на Телесисах жалуются, что не отвечаю на письма. Пишите лучше в форум.
Вне форума
Что-то у меня с почтой не то. И на Телесисах жалуются, что не отвечаю на письма. Пишите лучше в форум.
А Вы e-mail сделайте на каком-нибудь русском сервере, mail.ru например, а на старом поставьте переадресацию на первое время. Х его з, что там с этим yahoo происходит.
Ну а я напишу тут, то, что было в том письме.
У меня опять есть к Вам вопросы. С управлением питанием слава Богу, разобрались, идем дальше.
Валкодер. Такой, как в старых шариковых мышках. Из колесика с прорезями и двух оптопар. Хочется мне разобраться, как его применить, например, для регулирования громкости. Самая большая трудность – определить направление вращения вала. Я тут разрисовал, как я понимаю ситуацию. Состояние, когда оптопара затемнена, будем считать единицей. Риски на оси t означают время изменения состояния оптопар (считаем, что вал вращают с постоянной скоростью, значит изменения происходят периодически с постоянной частотой).
Я думал, как определить направление и решил, что надо смотреть, какая из двух оптопар первой изменит состояние. В каком бы положении не находился вал, при вращении вправо первой изменит состояние оптопара А, затем Б. Если влево – то наоборот. Верно? Или есть другой способ? Один знакомый делал такую штуку на ПЛИС, так он для определения направления сдвигал один сигнал относительно другого на один такт и делал между ними xor. В результате xor получал при вращении вправо 1, влево – 0. Но то на ПЛИС, там он D-триггер поставил и один сигнал относительно другого сдвинул, в МК по-моему это не очень удобно. Что посоветуете??
И еще есть вопрос. Импульсы с фототранзисторов оптопар далеко не прямоугольны. Чтоб МК не сбоил и четко отделял 0 от 1 надо наверно какое-нибудь пороговое устройство поставить?? Триггеры Шмидта например?
Заранее спасибо!
Отредактировано Матроскин (18.10.2006 07:41:23)
......There is someone in my head, but it's not me.......
Вне форума
..Валкодер. Такой, как в старых шариковых мышках.. Что посоветуете??..
Полагаю будет уместно: www.vegalab.ru/index.php?option=com_con … &Itemid=54
В книжке в справочнике Э. Реда по ВЧ схемотехнике (издание не помню, есть не во всех) во вспомогательных устройствах опИсан принцип и приведен работающий оптический валкодер
А еще, тем же порядком можно сделать бойкий валкодер из шагового двигателя от старого дисковода, да и в принципе мз любого компактного униполярного:
ru3ga.qrz.ru/UZLY/encod.htm
Учите матчасть!
Вне форума
Все, что по этим ссылкам, я уже видел. Тут прикол вот в чем. Продаются готовые валкодеры, такие как в мыши. Выглядит как резик переменный. Дает такой же двухзначный код 00-01-11-10-00. Вот его я хочу использовать.
Из шаговика валкодер очень громоздкий будет, да и впомогательная схема сложновата. Можно программно сделать все с "мышиным" вариантом.
......There is someone in my head, but it's not me.......
Вне форума
Я использую энкодеры фирмы Bourns типа PEC-16. Обрабатываю энкодер и его кнопку в основном цикле программы. Если программа чем-то занята, то она всё равно не сможет отреагировать на вращение энкодера, а буферизовать проделанный поворот и откладывать его обрботку - это уже слишком. Обработка энкодера по прерываниям неудобна, так как требуется давить дребезг. Более того, чтобы корректно реализовать квадратурный декодер 1х (или 2х, 4х), прерывания должны происходить не по фронту или спаду одного из сигналов, а по любому изменению состояния энкодера. Отсюда следует порочность декодера типа "программный D-триггер, один сигнал энкодера на вход D, второй - на C". При такой реализации INC/DEC всегда происходит по фронту одного из сигналов энкодера, что есть неправильно. Если вал энкдера просто пошевелить на месте, может насчитаться куча импульсов. INC/DEC нужно делать по изменению состояния двух сигналов, чтобы и INC, и DEC происходили в одной и той же точке, но при её проходе с разными направлениями вращения. Информацию о построении правильных квадратурных декодеров можно почерпнуть из описания спец. микросхем, например, HCTL-2000. Если установить время подавления дребезга 5 мс, как советуют в даташит, то при быстром вращении импульсы пропускаются. Это воспринимается пользователем как глючная работа системы. Учитывая то, что на оборот у него 24 импульса, а на каждый импульс состояние выходов меняется 4 раза (именно на этом факте основаны так называемые 4-x квадратурные декодеры), то время подавления дребезга нужно сильно уменьшать. На практике приемлемым оказалось время подавления дребезга 300 мкс. С таким временем практически невозможно повернуть вал так, чтобы импульсы пропускались. С другой стороны, проблем с дребезгом тоже не обнаружено. Столь малые времена, к сожалению, не могут быть сформированы системным таймером как большинство других временных интервалов в программе. Поэтому приходится применять "тупую" задержку в виде цикла. Для таких малых интервалов это вполне допустимо, потери производительности процессора будут минимальными. Тем более, что обработка энкодера - это общение с пользователем, который всегда является самым медленным звеном системы Более того, если какая-то задача в основном цикле захочет временно забрать все ресурсы процессора (за вычетом потерь на прерывания), она сможет это сделать. В это время энкодер обслуживаться не будет. Для кнопки время подавления дребезга должно быть существенно большим, я использую 50 мс. Уж очень разные механические характеристики контактных групп кнопки и энкодера.
Программа построена следующим образом: в начале программы один раз вызывается инициализация энкодера iEnc. В основном цикле, который "крутится" с той частотой, которую позволяет процессор и его загрузка на данный момент, вызывается основная задача энкодера mEnc. Она в глобальной переменной Msg оставляет код события энкодера. Этот код передается всем задачам основного цикла, любая из них может его обработать. Функция mEnc вызывает функцию сканирования энкодера EScan, осуществляет подавление дребезга, реализует 1х квадратурный декодер и формирует код события. Квадратурный декодер большей кратности применить тоже можно, но для PEC-16 именно для декодера 1х на каждый щелчок приходится один инкремент/декремент.
Вот текст модуля поддержки энкодера:
;Encoder support module
;----------------------------------------------------------------------------
;Constantes:
.equ ENDEB = 300 ;encoder debounce delay, uS
.equ SWDEB = 50000 ;switch button debounce delay, uS
;----------------------------------------------------------------------------
;Derivated constantes:
.equ ENDEBV = ENDEB/100
.if ENDEBV > MAXBYTE
.error "out of range constant"
.endif
.equ SWDEBV = SWDEB/100
.if ENDEBV > MAXBYTE
.error "out of range constant"
.endif
;----------------------------------------------------------------------------
;Messages:
.equ msgNop = 0x00 ;no operation
.equ msgInc = 0x01 ;increment
.equ msgDec = 0x02 ;decrement
.equ msgKdn = 0x03 ;key down
.equ msgKup = 0x04 ;key up
;----------------------------------------------------------------------------
.DSEG ;Data segment
;----------------------------------------------------------------------------
.CSEG ;Code segment
;----------------------------------------------------------------------------
;Encoder subsystem init:
iEnc: ldi Msg,msgNop ;no operation
rcall EScan ;scan encoder
mov EncSt,temp ;save encoder state
ret
;----------------------------------------------------------------------------
;Encoder read:
mEnc: rcall EScan ;scan encoder
mov Cnt,temp ;save encoder state
eor temp,EncSt ;check for changes
breq no_ch ;return, no changes
ldi temp,ENDEBV ;debounce delay for encoder
bbrc temp,2,no_sw
ldi temp,SWDEBV ;debounce delay for switch button
no_sw: rcall Delay
rcall EScan ;scan encoder
cp temp,Cnt ;check encoder state
brne no_ch ;return, bounce
mov temp,EncSt ;previous encoder state
mov EncSt,Cnt ;save new encoder state
;Switch button check:
bbrc temp,2,s_0
bbrs Cnt,2,q1x ;no changes
ldi Msg,msgKdn ;key down message
rjmp e_ret
s_0: bbrc Cnt,2,q1x ;no changes
ldi Msg,msgKup ;key up message
rjmp e_ret
;1x quadrature decoder:
q1x: bbrc temp,0,a_0
a_1: bbrc Cnt,0,a_10
rjmp no_ch
a_0: bbrs Cnt,0,a_01
rjmp no_ch
a_01: bbrc Cnt,1,pls
rjmp no_ch
a_10: bbrc Cnt,1,min
rjmp no_ch
pls: ldi Msg,msgInc ;send increment message
rjmp e_ret
min: ldi Msg,msgDec ;send decrement message
rjmp e_ret
no_ch: ldi Msg,msgNop ;send no operation message
e_ret: ret
;----------------------------------------------------------------------------
;Scan encoder:
;Out: temp - encoder state
EScan: clr temp
Skip_if_Port_EF1_0
stbr temp,0
Skip_if_Port_EF2_0
stbr temp,1
Skip_if_Port_ESB_0
stbr temp,2
ret
;----------------------------------------------------------------------------
;Delay:
;Input: temp = delay [x100 uS]
Delay: push Cnt
de2: ldi Cnt,FCLK/100000
de1: dec Cnt ;1 +
nop ;1 +
nop ;1 +
nop ;1 +
nop ;1 +
nop ;1 +
nop ;1 +
nop ;1 +
brne de1 ;2 = 10
dec temp
brne de2
pop Cnt
ret
;----------------------------------------------------------------------------
Вот текст основного модуля программы:
;* Title : Encoder PEC-16 test
;* Version : 1.00
;* Target : ATmega8
;* Author : wubblick@yahoo.com
;----------------------------------------------------------------------------
.include "m8def.inc"
.include "macros.mac"
.include "Header.asm"
;------------------------- Interrupt Vectors: -------------------------------
.CSEG ;code segment
.org 0
rjmp Init ;reset vector
.org OC1Aaddr
rjmp Timer ;Timer1 OC vector
.org SPMaddr+1 ;skip vector table
;-------------------- Program Execution Starts Here: ------------------------
Init: ldy RAMEND
out SPL,YL ;locate stack
out SPH,YH
rcall iWdog ;start internal watchdog
rcall iPorts ;ports init
rcall iVar ;variables init
rcall iTimer ;system timer init
rcall iEnc ;encoder subsystem init
;...
sei ;interrupts enable
;Main loop:
Main: rcall mEnc ;read encoder
;process encoder messages
;...
rcall mWdog ;watchdog restart
rjmp Main ;loop
;------------------------- Subroutines area: --------------------------------
;Internal watchdog init:
iWdog: wdr
ldi temp,(1< out WDTCR,temp
ldi temp,(1< out WDTCR,temp ;watchdog enable, period 260 mS
;Internal watchdog restart:
mWdog: bbrc FLAGS,WUpd,nu
clbr FLAGS,WUpd
wdr ;internal watchdog restart
nu: ret
;----------------------------------------------------------------------------
;Ports init:
iPorts: ldi temp,PUPB
out PORTB,temp ;init PORTB and on/off pullup
ldi temp,DIRB
out DDRB,temp ;set PORTB direction
ldi temp,PUPC
out PORTC,temp ;init PORTC and on/off pullup
ldi temp,DIRC
out DDRC,temp ;set PORTC direction
ldi temp,PUPD
out PORTD,temp ;init PORTD and on/off pullup
ldi temp,DIRD
out DDRD,temp ;set PORTD direction
ret
;----------------------------------------------------------------------------
;Variables init:
iVar: clr FLAGS ;clear flags
ret
;----------------------------------------------------------------------------
;System timer init:
iTimer: ldi temp,0
out TCCR1A,temp ;OC disable, PWM disable
ldi temp,(1< out TCCR1B,temp ;CTC, CK/1
ldi temp,byte2(T1Div-1)
out OCR1AH,temp ;compare register load
ldi temp,byte1(T1Div-1)
out OCR1AL,temp
in temp,TIMSK
ori temp,(1< out TIFR,temp ;clear pending interrupts
out TIMSK,temp ;output compare interrupt enable
ret
;System timer interrupt:
Timer: push temp
in temp,SREG ;save status register
push temp
stbr Flags,WUpd ;set watchdog update flag
;...
pop temp
out SREG,temp ;restore status register
pop temp
reti
;----------------------------------------------------------------------------
.include "Encoder.asm" ;link encoder control module
;----------------------------------------------------------------------------
Вот заголовочный файл проекта:
;Project header file
;----------------------------------------------------------------------------
;Constantes:
.equ FCLK = 10000000 ;Fclk, Hz
.equ TSYS = 1000 ;time base, uS
;----------------------------------------------------------------------------
;Derivated constantes:
.equ MAXBYTE = 0xFF
.equ MAXWORD = 0xFFFF
.equ T1Div = ((((Fclk/1000)*Tsys)/100)+5)/10 ;CK/1
.if T1Div > MAXWORD
.error "out of range constant"
.endif
;----------------------------------------------------------------------------
;Port Definitions:
.equ DIRB = 0b11111111 ;Port B direction
.equ PUPB = 0b00000000 ;Port B pull-ups
.equ DIRC = 0b11001111 ;Port C direction
.equ PUPC = 0b00110000 ;Port C pull-ups
.equ EF2 = PC4 ; Encoder F2
.equ EF1 = PC5 ; Encoder F1
.macro Skip_if_Port_EF1_0 ;skip if EF1 = 0
sbic PINC,EF1
.endm
.macro Skip_if_Port_EF2_0 ;skip if EF2 = 0
sbic PINC,EF2
.endm
.equ DIRD = 0b11111110 ;Port D direction
.equ PUPD = 0b00000001 ;Port D pull-ups
.equ ESB = PD0 ; Encoder SB
.macro Skip_if_Port_ESB_0 ;skip if ESB = 0
sbic PIND,ESB
.endm
;----------------------------------------------------------------------------
;Global Register Variables:
;r0, r1 used with mul instruction
.def EncSt = r2 ;store encoder state
.def temp = r16 ;temporary register temp
.def Cnt = r17 ;temporary register Cnt
.def Msg = r18 ;message code
.def FLAGS = r25 ;flags
.equ WUpd = 0 ;watchdog update flag
;r26,r27 used as X-register
;r28,r29 used as Y-register
;r30,r31 used as Z-register
;----------------------------------------------------------------------------
Вот файл макросов, которые могут встречаться в данном проекте:
;***** Macros
.macro clbr ;clear bit in register
cbr @0,exp2(@1)
.endm
.macro stbr ;set bit in register
sbr @0,exp2(@1)
.endm
.macro bbrc ;branch if bit in register clear
sbrs @0,@1
rjmp @2
.endm
.macro bbrs ;branch if bit in register set
sbrc @0,@1
rjmp @2
.endm
.macro bbic ;branch if bit in I/O clear
sbis @0,@1
rjmp @2
.endm
.macro bbis ;branch if bit in I/O set
sbic @0,@1
rjmp @2
.endm
.macro addi ;add immediate
subi @0,-@1
.endm
.macro ldx ;load XL, XH with word
ldi XL,byte1(@0)
ldi XH,byte2(@0)
.endm
.macro ldy ;load YL, YH with word
ldi YL,byte1(@0)
ldi YH,byte2(@0)
.endm
.macro ldz ;load ZL, ZH with word
ldi ZL,byte1(@0)
ldi ZH,byte2(@0)
.endm
.macro table ;load Z pointer
ldi ZL,low (@0*2)
ldi ZH,high(@0*2)
.endm
.macro stdi ;store immediate indirect with displacement
ldi temp,@1
std @0,temp
.endm
.macro ldsx ;load XL, XH from memory
lds XL,@0+0
lds XH,@0+1
.endm
.macro ldsy ;load YL, YH from memory
lds YL,@0+0
lds YH,@0+1
.endm
.macro ldsz ;load ZL, ZH from memory
lds ZL,@0+0
lds ZH,@0+1
.endm
.macro stsx ;store XL, XH in memory
sts @0+0,XL
sts @0+1,XH
.endm
.macro stsy ;store YL, YH in memory
sts @0+0,YL
sts @0+1,YH
.endm
.macro stsz ;store ZL, ZH in memory
sts @0+0,ZL
sts @0+1,ZH
.endm
Отредактировано Liv (18.10.2006 21:40:43)
Вне форума
Спасибо!
Я использую энкодеры фирмы Bourns типа PEC-16. Обрабатываю энкодер и его кнопку в основном цикле программы.
А что за зверь?? мож ссылку дадите, а то я ничего не накопал. Я так понимаю, он контактный. Тут у нас вряд ли такое можно купить
Блин, не думал, что все так сложно. Ну чтож, будем копать. Хотя наверное попозже. Сечас занялся переделкой и переразводкой своего УМЗЧ ВВ. Хочется его в божеский вид привести.
......There is someone in my head, but it's not me.......
Вне форума
А что за зверь?? мож ссылку дадите, а то я ничего не накопал.
Я вот не понимаю таких вопросов. Вы где копали, в огороде, что-ли? Задаете в google PEC-16 и первая же ссылка - datasheet.
Вне форума
[ Сгенерировано за 0.245 сек, 7 запросов выполнено - Использовано памяти: 661.59 Кбайт (Пик: 711.96 Кбайт) ]