PDA

View Full Version : 4bit hex decoder w/LCD



rangerdoc
- 10th May 2008, 03:02
I'm trying to write code for some hardware I'm going to build. With two purposes:
1) I have a 4-bit hex rotary encoder that will be inputs to the lower 4 bits of portA. I want the LCD to display an ASCII of the HEX encoder value.
2) I also have 4 momentary switches. They will be the lower 4 bits of portB. I have 4 LEDs on portC. When I press a momentary switch on portB, I want the cooresponding LED on portC to light & latch. When any other button is pressed, I want the first LED to go low and the new LED to go high and latch. Basically, I want portC to output & latch any value of portB other than 0.
All MCU inputs are optically isolated from the hardware they are operating.

I'm really new at this & this is my first code other than simple LED out type programs. Here is what I have:



'program for integrated firing panel
'portA = hexadecimal rotary encoder input (value to be displayed as an ASCII on LCD)
'portB = 4bit bank select momentary switches input
'portC = 4bit output to bank LEDs
'message = LCD display of portA (hex switch) value

'initialize device
@ device pic16f737, INTRC_OSC_NOCLKOUT, MCLR_OFF
OSCCON = $60 '4mhz internal oscillator

'initialize ports
TRISB = $10 'make all portB pins outputs except B.4
TRISC = 0 'Make portC outputs
PORTC = 0 'Make sure portC pins start low

'initialize variables
TxPin var PORTB.4 'alias pin B.4 to "TxPin"
rotary_in var word 'create variable "rotary_in"
banks var word 'create variable "banks"
rotary_in = PORTA & $0f 'isolate lower 4 bits of portA & write to "rotary_in"
banks = PORTB & $0f 'isolate lower 4 bits of portB & write to "banks"
LEDs var PORTC 'alias PORTC as "LEDs"

'Initialize Display
Pause 1000 'pause 1 sec to let LCD initialize
serout TxPin,4, [22] 'turn display on, no cursor
serout TxPin,4, [17] 'turn backlight on
serout TxPin,4, ["Firing Panel v1"]
serout TxPin,4, [148] 'move to line 2
serout TxPin,4, [2] 'display custom character 3
pause 5000
serout TxPin,4, [22] 'clear the screen
pause 2000

message:
serout TxPin,4, [22] 'Clear LCD
serout TxPin,4, [128] 'move cursor to beginning of first line
serout TxPin,4, ["Panel Selected:"]
serout TxPin,4, [199] 'cursor to middle of second line
serout TxPin,4, [#rotary_in] 'display ASCII of portA lower 4 bits on LCD
END

leds:
If banks > 0 Then 'for all port B.0 thru B.3 values, except 0,
banks = PORTC 'write value of portB to portC
Endif

goto message 'loop LCD forever

End



The whole thing compiles fine except for Error Line 44: Syntax Error. Is this line 44 of the PBP or the ASM code? Does that include blank lines and comments as a line? In other words: which is line 44?
Any help would be appreciated. I know most of you could find much better ways of writing this, but I need to keep it simple, even if it isn't the most efficient way of doing this. That way I can continue to work with it and learn from it in the future. The inputs and outputs will be so slow that speed isn't an issue.
One thing I don't like is that in the "leds:" routine, I'm writing a binary value to the whole portC when portC.4 is TxPin. Not sure if this will create problems.
Attached is the assembly file created by PBP.

Thanks

Jerson
- 10th May 2008, 05:27
The errror you see on line 44(BAS file) is that you have re-declared the variable LEDs as a label. PBP is case in-sensitive.

Second, you read the switches and rotary encoder just once at the start and then keep displaying that value. Is that what you intended?

Your Leds code is never reached.

rangerdoc
- 10th May 2008, 12:53
OK, pretty simple.
I've renamed the label & removed "END" from the message routine. It compiles OK now. I'll build it on a breadboard and see how it works.

Thanks for the help.

rangerdoc
- 13th May 2008, 04:02
Once I changed to mode 8 instead of mode 4 for Serout, everything worked up to line 28 of the code below.
It worked briefly, but begins to lag. Almost instantly, I notice a considerable delay in the response time between a hex value in and the coresponding ASCII display. The delay gets longer after several seconds, then crashes all together. I tried adding a 3 second delay to the loop of this function to reduce the number of serial transmissions to the lcd, but it still doesn't work. The display is erratic. Sometimes when going from bit 16 high to bit 32 high, it will briefly display the sum of the two & after a few seconds delay, then the proper value of "32" is displayed. And the lower 4 bits don't work at all. The display always reads "none" if any of the lower 4 bits is high.
Do I need a debounce? Should I use a standard LCD instead of the Parallax serial LCD? Or am I likely to have the same problems with a 44780 controlled LCD also? Possibly I need to use interrupts instead of looping the same data over and over until there is a change in state?

Here's a simplified version of the code with just the LCD functions:



'program for integrated firing panel
'portA = hexadecimal rotary encoder input (value to be displayed as an ASCII on LCD)
'portB.1 = serial Tx

'initialize device
@ device pic16f747, INTRC_OSC_NOCLKOUT, MCLR_OFF
OSCCON = $60 '4mhz internal oscillator

'initialize variables
TxPin var PORTB.1 'alias pin B.1 to "TxPin"

'Initialize Display
Pause 1000 'pause 1 sec to let LCD initialize
serout TxPin,8, [22] 'turn display on, no cursor
serout TxPin,8, [17] 'turn backlight on
serout TxPin,8, ["Firing Panel v1"]
pause 5000
serout TxPin,8, [22] 'Clear LCD
serout TxPin,8, [128] 'move cursor to beginning of first line
serout TxPin,8, ["Panel Selected:"]

message:

serout TxPin,8, [199] 'cursor to line 1, position 8
IF PORTA = 0 then
serout TxPin,8, ["None"]
Else
serout TxPin,8, [#PORTA] 'display ASCII of portA on LCD
Endif
pause 3000
goto message 'loop LCD forever

End

Archangel
- 13th May 2008, 08:48
You might find something useful here:
http://www.picbasic.co.uk/forum/showthread.php?t=7529

rangerdoc
- 18th May 2008, 03:53
OK, Thanks Joe,

I finally got time to sit down and go through the post thoroughly. It makes sense, so I'll try to implement the code into my project.

skimask
- 18th May 2008, 05:17
It worked briefly, but begins to lag. Almost instantly, I notice a considerable delay in the response time between a hex value in and the coresponding ASCII display.
Maybe your serial LCD is getting bogged down, not enough time between individual characters.
Try some character pacing. It's in the PBP manual.

rangerdoc
- 21st May 2008, 06:29
That did the trick Joe. Thanks.
Here's the final product:



'initialize device
@ device pic16f737, INTRC_OSC_NOCLKOUT, MCLR_OFF, WDT_OFF
OSCCON = $60 'internal 4mHz oscillator

'Initialize ports
TRISA = 0 ' RA0 to RA3 inputs for DIP switch, RA4 - RA7 for pushbuttons
PORTA = 0
TRISC = $FF

'initialize variables
Tx var PORTB.1
Index var byte
X var word
switches var byte

'Initialize LCD
Pause 1000 'pause 1/2 sec to let LCD initialize
serout Tx,10, [22] 'turn display on, no cursor
serout Tx,10, [17] 'turn backlight on
serout Tx,10, [12] 'Clear screen
pause 5
serout Tx,10, ["Panel Selected:"]
pause 1000

loop:
Index = PORTc & $0F ' Read DIP switch AND mask lsb
LOOKUP2 Index,[1,3,3,4,5,6,7,8,9,10,11,12,13,14,15,16],X
serout Tx,10, [154," ",154] ' clear previous entry
serout Tx, 10, [#X]
pause 50

LEDS:
switches = (PORTC>>4) & $0F 'take msb & save as "switches"
if switches > 0 then
porta = switches 'enter value "switches" to portA
endif

Goto loop:

END