augustinetez
Active Member
See previous (edited) post Mike - that was the problem although I put the turn on command at the end.
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
ISR MOVWF W_TEMP ; SAVE OFF CURRENT W REGISTER CONTENTS
MOVF STATUS,W ; MOVE STATUS REGISTER INTO W REGISTER
MOVWF STATUS_TEMP ; SAVE OFF CONTENTS OF STATUS REGISTER
BCF STATUS,RP0
BCF PIR1,TMR2IF
RLF previous,F
RLF previous,W
ANDLW 0X0C ;KEEP ONLY BITS 2 & 3
BTFSS PORTA,0 ;MOVE ENCODER BITS
IORLW 1 ;TO BITS 0 & 1
BTFSS PORTA,1
IORLW 2
MOVWF previous ;KEEP FOR NEXT TIME
CALL ENC_TABLE
ADDWF clicks,F
MOVLW 4
XORWF clicks,W
BTFSS STATUS,Z
GOTO CHECK_DOWN
CLRF clicks ;added this line
MOVLW high 10800 ;test if frequency has reached 108MHz
XORWF freqHigh,W
BTFSS STATUS,Z
GOTO DOINC ;high bytes don't match so do increment
MOVLW low 10800
XORWF freqLow,W
BTFSC STATUS,Z ;low bytes don't match so do increment
GOTO EXIT ;if it has, exit
DOINC INCF freqHigh,F ;if not then increment it
INCFSZ freqLow,F
DECF freqHigh,F
GOTO EXIT
CHECK_DOWN
MOVLW 0XFC ;-4
XORWF clicks,W
BTFSS STATUS,Z
GOTO EXIT
CLRF clicks ;added this line
MOVLW high 8700
XORWF freqHigh,W
BTFSS STATUS,Z
GOTO DODEC
MOVLW low 8700
XORWF freqLow,W
BTFSC STATUS,Z
GOTO EXIT
DODEC MOVF freqLow,F
SKPNZ
DECF freqHigh,F
DECF freqLow,F
;; GOTO EXIT ;;not needed
; RESTORE CONTEXT BEFORE RETURNING FROM INTERRUPT
EXIT MOVF STATUS_TEMP,W ; RETRIEVE COPY OF STATUS REGISTER
MOVWF STATUS ; RESTORE PRE-ISR STATUS REGISTER CONTENTS
SWAPF W_TEMP,F
SWAPF W_TEMP,W ; RESTORE PRE-ISR W REGISTER CONTENTS
RETFIE ; RETURN FROM INTERRUPT
busy_check
banksel TRISB ; Switch to bank for Tris operation
movlw b'00001111' ; Set ALL 4 to input, others outputs
movwf TRISB
banksel PORTB
bcf PORTB,LCD_rs ; Set up LCD for Read Busy Flag (RS = 0)
bsf PORTB,LCD_rw ; Set up LCD for Read (RW = 1)
bsf PORTB,LCD_e ; Set E high
LCD_is_busy
btfsc PORTB,LCD_busy ; Is Busy Flag (RB3) clear?
goto LCD_is_busy
bcf PORTB,LCD_e ; Set E low
banksel TRISB ; Switch to bank 1 for Tristate operation
clrf TRISB ; All pins (RB7..RB0) are back to outputs
banksel PORTB ; Switch to bank 0
RETURN
1, You have to read dummy first as the code will go from 00 to whatever..1. Occasionally when first powering up it will add or subtract a step without touching the encoder.
CLRF T2CON ; Stop Timer2, Prescaler = 1:1,
; Postscaler = 1:1
CLRF TMR2 ; Clear Timer2 register
CLRF INTCON ; Disable interrupts
BSF STATUS, RP0 ; Bank1
CLRF PIE1 ; Disable peripheral interrupts
BCF STATUS, RP0 ; Bank0
CLRF PIR1 ; Clear peripheral interrupts Flags
MOVLW 0x72 ; Postscaler = 1:15, Prescaler = 1:16
MOVWF T2CON ; Timer2 is off
BSF T2CON, TMR2ON ; Timer2 starts to increment <------------------------
Yes, the higher nibble has to be output but the bottom 4 bits must be input or they will fight with the LCD pins as both will be output.Re your previous about the busy routine and PORTB, some of it has to be outputs during the busy read as it carries the R/W, R/S & E lines as well as the data lines.
busy_check
banksel TRISB ;Switch to bank for Tris operation
movlw b'00001111' ;Set ALL 4 to input, others outputs
movwf TRISB
banksel PORTB
bcf PORTB,LCD_rs ;Set up LCD for Read Busy Flag (RS = 0)
bsf PORTB,LCD_rw ;Set up LCD for Read (RW = 1)
LCD_is_busy
bsf PORTB,LCD_e ;Set E high
NOP
movfw PORTB ;move busy flag into W
bcf PORTB,LCD_e ;Set E low
NOP
bsf PORTB,LCD_e ;perform dummy read
NOP
bcf PORTB,LCD_e ;Set E low
andlw 1<<LCD_busy
BTFSS STATUS,Z
GOTO LCD_is_busy
banksel TRISB ;Switch to bank 1 for Tristate operation
clrf TRISB ;All pins (RB7..RB0) are back to outputs
banksel PORTB ;Switch to bank 0
RETURN
;
; https://www.electro-tech-online.com/threads/st7066u-20x4-lcd-problems.160879/
;
list n=0,c=255
radix dec
errorlevel -302 ; Suppress the not in bank 0 warning message
processor 16F628A
;
; File: main.c
; Author: dan1138
; Target: PIC16F628A
;
; Created on March 2, 2021, 9:38 AM
; Description:
;
; This is an example of one way to implement the 4-bit parallel
; mode interface for a Hitachi HD44780 LCD module controller.
;
; PIC16F628A
; +----------:_:----------+
; <> 1 : RA2 RA1 : 18 <> ENCODER A
; <> 2 : RA3 RA0 : 17 <> ENCODER B
; <> 3 : RA4 OSC1/RA7 : 16 <>
; VPP -> 4 : RA5/VPP OSC2/RA6 : 15 <>
; GND -> 5 : VSS VDD : 14 <- 5v0
; LCD_D4 <> 6 : RB0/INT PGD/RB7 : 13 <> PGD/DLEN(SAA1057)
; LCD_D5 <> 7 : RB1/RX/DT PGC/RB6 : 12 <> PGC/LCD_RS
; LCD_D6/CLK(SAA1057) <> 8 : RB2/RX/CK RB5 : 11 <> LCD_RW
; LCD_D7/DAT(SAA1057) <> 9 : RB3/CCP PGM/RB4 : 10 <> LCD_E
; +-----------------------:
; DIP-18
;
; LCD display module is SC2004CULB-SO-GB-K
;
; SUNLIKE DISPLAY Model No: SC2004C
; https://electronlab.com.ua/files/_prod/Sunl_337/SC2004CULB-XH-GS.pdf
;
; Samsung KS0066 LCD controller
; https://www.lcd-module.de/eng/pdf/zubehoer/ks0066.pdf
;
; pin 1 - VSS Ground
; pin 2 - VDD +5
; pin 3 - Vo Contrast
; pin 4 - RS Register select
; pin 5 - RW Read/Write select
; pin 6 - E Enable active high strobe
; pin 7 - DB0 Data bit 0
; pin 8 - DB0 Data bit 1
; pin 9 - DB0 Data bit 2
; pin 10 - DB0 Data bit 3
; pin 11 - DB0 Data bit 4
; pin 12 - DB0 Data bit 5
; pin 13 - DB0 Data bit 6
; pin 14 - DB0 Data bit 7
;
; Definitions of target specific Special Function Registers
;
include <P16F628A.INC>
;
; Target specific configuration words
;
__config _CP_OFF&_LVP_OFF&_BODEN_OFF&_MCLRE_ON&_PWRTE_ON&_WDT_OFF& _INTOSC_OSC_NOCLKOUT
;
; Define macros to help with
; bank selection
;
#define BANK0 (h'000')
#define BANK1 (h'080')
#define BANK2 (h'100')
#define BANK3 (h'180')
;
; Macro to message from ROM to LCD display
;
Show_LCD_Message MACRO LCD_message
movlw LOW(LCD_message)
movwf pszLCD_RomStr
movlw HIGH(LCD_message)
movwf pszLCD_RomStr+1
call LCD_putrs
ENDM
;
; Constants used in application
;
; The StartFreq constant has units of MHz times 100
;
#define StartFreq (8700)
;
; Start address of each line on LCD module
;
#define LINE_ONE 0x00
#define LINE_TWO 0x40
#define LINE_THREE 0x14
#define LINE_FOUR 0x54
;
; Data used for ISR and LCD
;
cblock 0x70 ; memory present in all banks
WREG_save : 1
STATUS_save : 1
PCLATH_save : 1
LCD_Temp : 1
pszLCD_RomStr : 2
Sample_AB : 1
Valid_AB : 1
endc
cblock 0x60 ; memory present in bank 0
EncoderCount : 1
Last_AC : 1
endc
;
; Reset vector
;
org 0x000 ; processor reset vector
nop ; ICD2 needs this
goto Start ; go to beginning of program
;
; Interrupt vector
;
org 0x004
movwf WREG_save ; Save register that
movf STATUS,W ; must be restored to
movwf STATUS_save ; preserve the context
clrf STATUS ; Use BANK 0 as default
;
; This is the area where your interrupt service routines go
;
; KEEP THEIR EXECUTION TIME AS SHORT AS POSSIBLE.
; DO NOT DO WORK THAT SHOULD BE DONE IN THE APPLICATION LOOP!
;
btfss INTCON,TMR0IE
goto TMR0_Exit
btfss INTCON,TMR0IF
goto TMR0_Exit
bcf INTCON,TMR0IF
;
; Debounce quadrature encoder inputs
;
banksel PORTA
movf PORTA,W ; Sample quadrature encoder inputs
xorwf Sample_AB,W
andlw 3
xorwf Sample_AB,F ; Update sample, W = change of AB inputs
iorlw 0
movlw 3
btfss STATUS,Z ; Skip if inputs did not change since last sample
andwf Sample_AB,F ; reset debounce count
movlw 0x10
btfss Sample_AB,6 ; skip when debounce done
addwf Sample_AB,F ; increment debounce count
movf Sample_AB,W
andlw 3
btfsc Sample_AB,6 ; skip when debounce not done
movwf Valid_AB ; update debounced quadrature encoder inputs
TMR0_Exit:
movf STATUS_save,W
movwf STATUS
swapf WREG_save,F
swapf WREG_save,W
retfie
;
; Application start
;
Start:
clrf INTCON ; Disable all interrupt sources
banksel PIE1
clrf PIE1
banksel CMCON ; Make all GPIO use digital I/O
movlw 0x07
movwf CMCON
;
; Setup TIMER0 to assert an interrupt every 1.024 milliseconds
;
banksel OPTION_REG
movlw 0xC1 ; TIMER0 clock = FOSC/4, prescale = 1:4
movwf OPTION_REG
banksel TMR0
clrf TMR0
bcf INTCON,TMR0IF
bsf INTCON,TMR0IE
bsf INTCON,GIE
;
; Initialize the LCD module
;
call LCD_Init ; Initialize LCD module
;
; Show the initial LCD screen
;
movlw LINE_ONE
call LCD_SetPosition
Show_LCD_Message LCD_message1
movlw LINE_TWO
call LCD_SetPosition
Show_LCD_Message LCD_message2
movlw LINE_THREE
call LCD_SetPosition
Show_LCD_Message LCD_message3
movlw LINE_FOUR
call LCD_SetPosition
Show_LCD_Message LCD_message4
;
; Application loop
;
call QuadCheck ; Initialize quadrature decoder
banksel EncoderCount
clrf EncoderCount
AppLoop:
call QuadCheck
banksel EncoderCount
addwf EncoderCount,F
iorlw 0
skpnz
goto AppLoop
movlw LINE_FOUR+19
call LCD_SetPosition
movlw 0x3F
andwf EncoderCount,W
addlw '@'
call LCD_WriteData
goto AppLoop
;
; The current sample is AC.
; The previous sample is ac.
;
; Clockwise direction:
; c = a XOR b
; ab ac AC AC-ac
; 00 00 01 01
; 01 01 10 01
; 11 10 11 01
; 10 11 00 01
;
; Counter Clockwise direction:
; c = a XOR b
; ab ac AC AC-ac
; 00 00 11 11
; 10 11 10 11
; 11 10 01 11
; 01 01 00 11
;
;
; RA1 = A , RA0 = B
;
QuadCheck:
banksel Last_AC
movf Valid_AB,W ; Get debounced quadrature encoder inputs
btfsc Valid_AB,1 ; check of A input is one
xorlw 1 ; Make C = A xor B, Convert 2-bit Gray code to binary
andlw 3 ; mask for bits AC
xorwf Last_AC,W ; Use three XORs to swap the
xorwf Last_AC,F ; current sample with
xorwf Last_AC,W ; the last sample.
subwf Last_AC,W ; Calculate the difference (Current-Last)
andlw 3 ; W = 01 for CW step, W = 11 for CCW step
xorlw 1 ; Test for Clockwise step
btfsc STATUS,Z ; skip if not CW step
retlw +1
xorlw 2 ; Test for Counter Clockwise step
btfsc STATUS,Z ; skip if not CCW step
retlw -1
retlw 0
;
; LCD functions
;
#define LCD_PORT PORTB
#define LCD_DATA_BITS (0x0F)
#define LCD_RS PORTB,RB6
#define LCD_RW PORTB,RB5
#define LCD_E PORTB,RB4
;
;*****************************************************************
; Subroutine Name: LCD_Init
; Function: Initialize the LCD interface.
;
; Inputs: none
;
; Outputs: none
;
; Uses: WREG, STATUS
;
;*****************************************************************
LCD_Init:
call Delay_4us ; Used to test the timing
call Delay_40us ; of the delay functions
call Delay_5ms ; with the simulator.
call LCD_POR_Delay
banksel BANK1
movlw ~LCD_DATA_BITS ; Make GPIO bits for
andwf LCD_PORT,F ; LCD interface output bits
bcf LCD_E
bcf LCD_RW
bcf LCD_RS
banksel BANK0
andwf LCD_PORT,F
bcf LCD_E
bcf LCD_RW
bcf LCD_RS
;
; Force LCD module to 4-bit parallel mode
;
movlw 0x33
andlw LCD_DATA_BITS
movwf LCD_PORT
bsf LCD_E ; Assert LCD_E high
call Delay_4us
bcf LCD_E ; Assert LCD_E low
call Delay_5ms
bsf LCD_E ; Assert LCD_E high
call Delay_4us
bcf LCD_E ; Assert LCD_E low
call Delay_5ms
bsf LCD_E ; Assert LCD_E high
call Delay_4us
bcf LCD_E ; Assert LCD_E low
call Delay_5ms
movlw 0x22
andlw LCD_DATA_BITS
movwf LCD_PORT
bsf LCD_E ; Assert LCD_E high
call Delay_4us
bcf LCD_E ; Assert LCD_E low
call Delay_5ms
;
; Configure 20x4 LCD character module
;
movlw (0x28) ; 4-bit parallel, 5x7, multiline mode
call LCD_WriteCommand
movlw (0x08) ; Display off, cursor off, blink off
call LCD_WriteCommand
movlw (0x01) ; Clear display
call LCD_WriteCommand
movlw (0x0C) ; Display on, cursor off, blink off
call LCD_WriteCommand
movlw (0x13) ; Cursor shifts to the left
call LCD_WriteCommand
return
;
;*****************************************************************
; Subroutine Name: Delay_4us, Delay_20us, Delay_40us
; Function: provides a delay for 4, 20 or 40 microseconds
; Code relies on a 4MHz system oscillator
;
; Inputs: none
;
; Outputs: none
;
;*****************************************************************
Delay_40us:
call Delay_20us ; Wait at least 40 microseconds
Delay_20us: ; for command to complete.
call Delay_4us
call Delay_4us
call Delay_4us
call Delay_4us
goto Delay_4us
;
;*****************************************************************
; Subroutine Name: Delay_5ms
; Function: Provides a delay for at least 5 milliseconds
; Code relies on a 4MHz system oscillator
;
; Inputs: none
;
; Outputs: none
;
; Uses: WREG, STATUS
;
;*****************************************************************
Delay_5ms:
call Dly0
call Dly0
Dly0:
movlw 208 ; Magic number to get 5 milliseconds of delay
Dly1:
call Delay_4us
addlw -1
bnz Dly1
Delay_4us:
return
;
;*****************************************************************
; Subroutine Name: LCD_POR_Delay
; Function: provides a delay for at least 15 milliseconds
;
; Inputs: none
;
; Outputs: none
;
; Uses: WREG, STATUS
;
;*****************************************************************
LCD_POR_Delay:
call Delay_5ms
call Delay_5ms
goto Delay_5ms
;
;*****************************************************************
; Subroutine Name: LCD_WriteCommand
; Function: Set LCD_RS to command mode
; Write command byte to PORTB
; Pulse the LCD_E high for 4 microseconds
; Wait for 5 milliseconds
;
; Inputs: WREG Command to be sent to LCD module
;
; Outputs: none
;
; Uses: WREG, STATUS
;
;*****************************************************************
LCD_WriteCommand:
banksel LCD_PORT
bcf LCD_RW ; Assert LCD_RW low
bcf LCD_RS ; Assert LCD_RS low
call LCD_Write1
goto Delay_5ms
;
;*****************************************************************
; Subroutine Name: LCD_WriteData
; Function: Set LCD_RS to data mode
; Write command byte to PORTB
; Pulse the LCD_E high for 4 microseconds
; Wait for 40 microseconds
;
; Inputs: WREG Data to be sent to LCD module
;
; Outputs: none
;
; Uses: WREG, STATUS
;
;*****************************************************************
LCD_WriteData:
banksel LCD_PORT
bcf LCD_RW ; Assert LCD_RW low
bsf LCD_RS ; Assert LCD_RS high
LCD_Write1:
movwf LCD_Temp
if (LCD_DATA_BITS & 0x0F)
swapf LCD_Temp,F
movf LCD_Temp,W
endif
xorwf LCD_PORT,W
andlw LCD_DATA_BITS
xorwf LCD_PORT,F ; Write high nibble
bsf LCD_E ; Assert LCD_E high
call Delay_4us
bcf LCD_E ; Assert LCD_E low
call Delay_4us
swapf LCD_Temp,W
xorwf LCD_PORT,W
andlw LCD_DATA_BITS
xorwf LCD_PORT,F ; Write low nibble
bsf LCD_E ; Assert LCD_E high
call Delay_4us
bcf LCD_E ; Assert LCD_E low
goto Delay_40us
;
;*****************************************************************
; Subroutine Name: LCD_SetPosition
; Function: Set the position where character are to be
; written to the LCD display.
;
; Inputs: WREG Line and position on that lone
;
; Outputs: none
;
; Uses: WREG, STATUS
;
;*****************************************************************
LCD_SetPosition:
iorlw 0x80 ; Set position LCD module command
goto LCD_WriteCommand
;
;*****************************************************************
; Subroutine Name: LCD_putrs
;
; Function: This routine writes a string of bytes to the
; Hitachi HD44780 LCD controller.
;
; Inputs: pszLCD_RomStr: pointer to string;
;
; Outputs: none
;
; Uses: WREG, STATUS
;
;*****************************************************************
LCD_putrs:
call TableLookUp
iorlw 0
skpnz
return
call LCD_WriteData
incf pszLCD_RomStr,F
skpnz
incf pszLCD_RomStr+1,F
goto LCD_putrs
TableLookUp:
movfw pszLCD_RomStr+1
movwf PCLATH
movfw pszLCD_RomStr
movwf PCL
;
; ROM based LCD messages
;
LCD_message1:
dt "Ver 1.0 - 20x4 LCD",0
LCD_message2:
dt "Line 2 2021-MAR-04",0
LCD_message3:
dt "Line 3 20:00:29",0
LCD_message4:
dt " ",0
;
; Initialize EEPROM data
;
ORG 0x2100
;startup frequency bytes must be next 4 bytes of EEPROM
DATA StartFreq>>8 ; Most significant byte
DATA StartFreq&0xFF ; Least significant byte (87MHz)
DATA 0
DATA 0
END
There is at least one good thing in that the LCD code is working correctly on your 20x4 LCD module.Dan, attached photo is what I get with your code, as posted above.
View attachment 130126
Code builds without any errors.
No action from the encoder or indication on the LCD at line 4 pos 20.