Thanks Luciano,
But it's the same program as in the datasheet...
Im now trying to write the decoding program in assembly..
Thanks Luciano,
But it's the same program as in the datasheet...
Im now trying to write the decoding program in assembly..
Rotary encoder in assembly for 16F84:
http://emp.byui.edu/fisherr/EET255/encdr.asm
Luciano
Luciano,
I added the code from the lin you posted..
I'm using interrupt on INT0 connected to channel A..
I'm able to count and detect directions..with 1 big problem
i cannot monitor or dispaly the counts either using LCDout or software serial to hyperterminal.
it's good for 2 seconds and then the whole LCD screen corrupts
...is it because the LCDout line is being interrupted by the encoder
...if i disable/enable interrupts within the LCDout line..i lose encoder counts
in the code..i use 2 leds connected to portB.6,7 to show direction.
LOOP is my main program
my code is below
Code:GoTo start ' Skip around interrupt handler DEFINE INTHAND display ' DEFINE INTERRUPT handler Asm display movwf wsave swapf STATUS, W clrf STATUS movwf ssave movf PCLATH, W movwf psave ;;;bsf _led ; Turn on LED (for example) ;new=PORTB & %11000000 ;Get intitial input from ENCODER & put the value in OLD. movf PORTB,W movlw _old ;Strip off all but the last 2 LSBs in OLD. movlw 0x03 ;Create bit mask for 2 LSBs (bits 6 & 7). 11000000 andwf _old,F ;Zero bits 0 thru 6. ;Read latest input from ENCODER & put the value in NEW. movf PORTB,W movwf _new ;Strip off all but the 2 LSBs in OLD. movlw 0x03 ;Create bit mask for 2 LSBs (bits 6 & 7). 11000000 andwf _new,F ;Zero bits 0 thru 6. movf _new,W ;Move the contents of NEW to TEMP and OLD to W movwf _temp ;in order to compare them with XOR. movf _old,W xorwf _temp,F ;XOR previous inputs (in W) with latest inputs ;(in TEMP) to see if they are equal. btfsc STATUS,Z ;Test result and skip next line if 0. GoTo rtrn ;Result is 0. Previous inputs equal latest ;inputs. Rotary encoder did not move. Return ;to loop ;Result is 1. Rotary encoder moved. Determine direction. bcf STATUS,C ;Clear the carry bit in the status register and rlf _old,F ;left shift it into OLD to align bit0 of OLD ;with bit 1 of NEW. movf _new,W ;Move the contents of NEW to W in order to XOR. xorwf _old,F ;XOR previous inputs (in OLD) with latest ;inputs (in W) to determine CW or CCW. btfsc _old,1 ;Test bit 1 of result (in OLD). Skip next line ;if it is 0 (direction is CCW). GoTo Up ;Bit is 1 (direction is CW). Go around Down Down ;Decrements COUNTER because encoder moved CCW. decf _enc_counter,F bsf _led GoTo rtrn ;Branch around UP. Up ;Increments COUNTER because encoder moved CW. incf _enc_counter,F bsf _led2 ;and increment counter. rtrn bcf intcon.1 ; clear interrupt flag ; Restore PCLATH, STATUS and W registers movf psave, W movwf PCLATH swapf ssave, W movwf STATUS swapf wsave, F swapf wsave, W retfie EndAsm start: 'SerOut PORTC.0,T9600,[#enc_counter,10,13] TRISB=%00111111 TRISC=%00000000 Low led Low led2 ' Turn LED off INTCON = %10010000 ' Enable INTERRUPT ON portb INT0 option_reg=%01110000 loop: 'INTCON = %00000000 'LCDOut $fe,1,DEC enc_counter 'Pause 4 'INTCON = %10010000 Low led Low led2 GoTo loop
Last edited by ice; - 11th May 2005 at 11:41.
Hi!
If you use INT0 you will lose encoder counts.
See my Incremental quadrature encoder direction drawing.
(File encoder.zip posted the 9th April 2005, 13:44).
The two encoder signals A/B have to be connected to two of
the PINs RB<7:4> which have an interrupt-onchange feature.
* * *
When I post a code sample, the code is well formatted and
there are no dead commented statements.(I do my best).
Do you think that people on this forum will spend time
reading your code if it is not formatted?
* * *
See thread LCDOUT & interrupts.
http://www.picbasic.co.uk/forum/show...dout+interrupt
* * *
Luciano
Luciano,
I switched to portB.6 and 7 for interrupt on change and modified the code
However i cannot decode direction now.I use LEDs to display direction..Now only one of them lights for both directions.Thanks.
**
i'm sorry abt my code being all garbled.Ive done my best this time.
**
Code:movf PORTB,W movlw _old ;Strip off all but the last 2 MSBs in OLD. movlw 0xc0 andwf _old,F ;Read latest input from ENCODER & put the value in NEW. movf PORTB,W movwf _new ;Strip off all but the 2 MSBs in NEW movlw 0xc0 andwf _new,F movf _new,W ;Move the contents of NEW to TEMP and OLD to W movwf _temp ;in order to compare them with XOR. movf _old,W xorwf _temp,F ;XOR previous inputs (in W) with latest inputs ;(in TEMP) to see if they are equal. btfss STATUS,Z ;Test result and skip next line if 0. GoTo rtrn ;Result is 0. Previous inputs equal latest ;inputs. Rotary encoder did not move. Return ;to loop bcf STATUS,C ;Clear the carry bit in the status register and rlf _old,F ;left shift it into OLD to align bit6 of OLD ;with bit7 of NEW. movf _new,W ;Move the contents ofNEW to W in order to XOR. xrwf _old,F ;XOR previous inputs (in OLD) with latest ;inputs (in W) to determine CW or CCW. btfss _old,7 ;Test bit 1 of result (in OLD). Skip next line ;if it is 0 (direction is CCW). GoTo Up ;Bit is 1 (direction is CW). Go around Down Down ;Decrements COUNTER because encoder moved CCW. decf _enc_counter,F bsf _led ;light CCW LED GoTo rtrn ;Branch around UP. Up ;Increments COUNTER because encoder moved CW. incf _enc_counter,F ;and increment counter. bsf _led2 ;light CW LED rtrn bcf intcon.0 ;clear interrupt flag on portBinT
Hi,
Below is one part of the interrupt assembly code.
(I have tested the code with the MPLAB simulator).
This is not the end of the difficulties.
I can help (the forum can help) if you do the following:
Write a PicBasic program that displays on the LCD the
rotary encoder count. The program will use an
interrupt-onchange in assembly for the encoder.
(Please write a new well formatted program).
The assembly code I have posted today is only one
part of the code you will need in the interrupt routine.
BEFORE my code you will have to save the processor context.
AFTER my code you will have to restore the processor context.
See PicBasic manual '9.3. Interrupts in Assembler' for
everything else you will need in order to use an interrupt
in assembly.
For now do not modify my code. Add everything, also the
two comment lines. (Cut & Paste).
(;====== BEGINNING OF THE ROTARY ENCODER CODE ========)
(;========= END OF THE ROTARY ENCODER CODE ===========)
If you like you can add the code for the two LEDs CCW and CW.
See comments in the code for the LEDs.
In my code I use 3 variables that you will have to declare
in your PicBasic program. These variables have new names.
(Not the same names you have used in your code).
I don't like names like 'new' because 'new' can be a
reserved word for some compiler.
The 3 variables are:
enc_new VAR BYTE
enc_old VAR BYTE
enc_counter VAR WORD
Set to 0 (zero) the variable enc_old when you power up
the PIC, before you enter the main loop of your PicBasic
program. This is not necessary but it will help you to
understand how this variable is used.
* * *
From your post of the 6th May 2005, 12:06
....im using a 16F873A,which has a 4K flash,meaning 4 banks...
according to the PBP manual, i have to define wsave,wsave1,wsave2,wsave3...
it takes in wsave and wsave1...but when i declare wsave2 and wsave3..it gives a RAM_END 255 error
From the PicBasic manual
2.2. Your First Program
If you don’t tell it otherwise, the PicBasic Pro Compiler defaults to
creating code for the PIC16F84. To compile code for PICmicro MCUs
other than the PIC16F84, simply use the -P command line option
described later in the manual to specify a different target processor. For
example, if you intend to run the above program, BLINK.BAS, on a
PIC16F877, compile it using the command:
PBP -p16f877 blink
So verify what you need for the 16F873A.
Luciano
Code:;====== BEGINNING OF THE ROTARY ENCODER CODE ======== ;The Rotary Encoder is connected to PORTB ;The A signal of the encoder connected to the PIN portB.7 ;The B signal of the encoder connected to the PIN portB.6 ; ;The 3 variables used are declared in the PicBasic code. ; ; enc_new VAR BYTE ; enc_old VAR BYTE ; enc_counter VAR WORD ; ;================================================ ;Read latest input from PORTB & put the value in _enc_new. movf PORTB,W movwf _enc_new ;Strip off all but the 2 MSBs in _enc_new. movlw B'11000000' ;Create bit mask (bits 7 & 6). andwf _enc_new,F ;Zero bits 5 thru 0. ;Determine the direction of the Rotary encoder. rlf _enc_old,F ;left shift it into _enc_old to align bit 6 of ;_enc_old with bit 7 of _enc_new. movf _enc_new,W ;Move the contents of _enc_new to W in order to XOR. xorwf _enc_old,F ;XOR previous inputs (in _enc_old) with latest ;inputs (in W) to determine CW or CCW. btfsc _enc_old,7 ;Test bit 7 of result (in _enc_old). Skip next line ;if it is 0 (direction is CCW). goto Up ;Bit is 1 (direction is CW). Go around Down ;and increment counter. Down ;Decrements _enc_counter because the rotary encoder moved CCW. ;Decrements _enc_counter (16 bit value), sets Z on exit. decf _enc_counter,F ; Decrement low byte incfsz _enc_counter,W ; Check for underflow incf _enc_counter+1,F ; Update decf _enc_counter+1,F ; Fixup movf _enc_counter,W iorwf _enc_counter+1,W ; Set Z bit ;Add here code for the CCW LED if needed. goto Continue ;Branch around UP. Up ;Increments _enc_counter because the rotary encoder moved CW. ;Increments _enc_counter (16 bit value), sets Z on exit. incfsz _enc_counter,W ; Add one to low byte decf _enc_counter+1,F ; No carry (negates next step) incf _enc_counter+1,F ; Add one to high byte movwf _enc_counter ; Store updated low byte back. iorwf _enc_counter+1,W ; Set Z flag ;Add here code for the CW LED if needed. Continue ;Assign the latest encoder inputs (in _enc_new) to _enc_old. movf _enc_new,W movwf _enc_old ;============ END OF THE ROTARY ENCODER CODE =====
Last edited by Luciano; - 12th May 2005 at 23:20.
Thank you so much Luciano...
The code is..
working good ,
direction decoding ok
counting on LCD[no garbage,dispays properly]
A few questions
1>You never clear the Int on PortB change flag in the interrupt.is it because your reading from portB,which is one of the ways to clear the flag.
2>retfie.. Neither is the retfie used to return from where the program left.
3>why didnt my program work ,when i used the INT0 interrupt.I cant figure it out.
4>I use CodeDesigner Lite as an IDE.I get t0 select the chip from a drop down menu.I select 16f873a.I even put the line PBP -p16F873A in the command line option,but the error on using wsave2 and wsave3,still persists.
Working with enc_counter on 16 bits is a bit difficult to work on the current project.I need 32 bits.so back to my code.
Bookmarks