LCD Using pic16f628a

Thread Starter

Knightmare.BH

Joined May 30, 2014
7
This program to count the people in a lab ( max 9 people ). it has 2 sensors one for increment and the other for decrement.

Rich (BB code):
include<p16f628a.inc>
	CBLOCK	H'20'
	COUNT1	
	COUNT2	
	COUNT3
	LCD_POINTER
	LAB_COUNT
	endc	
#define	LCD_RS	PORTA,0
#define	LCD_RW	PORTA,1
#define	LCD_E	PORTA,2
#define	IN_	PORTA,3
#define	OUT_	PORTA,4
	clrf	PORTA
	clrf	PORTB
	clrf	COUNT1
	clrf	LAB_COUNT
	
	movlw	H'07'
	movwf	CMCON
	bsf	STATUS,RP0	
	movlw	b'11111000'
	movwf	TRISA
	movlw	b'00000000'
	movwf	TRISB
	bcf	STATUS,RP0
	call	Delay_L
	
	movlw	b'00001100'
	call	Send_CMD	
	movlw	b'00111000'
	call	Send_CMD	

	call	Text1
	call	Disp_C

Start
	btfsc	IN_
	goto	INC_LAB	
	btfsc	OUT_
	goto	DEC_LAB	
	goto	Start
	
INC_LAB
	incf	LAB_COUNT,f
	call	Disp_C
	goto	Start
DEC_LAB
	decf	LAB_COUNT,f
	call	Disp_C
	goto	Start



Disp_C	movlw	b'10000100'
	call	Send_CMD
	call	Delay_L	
	movf	LAB_COUNT,w
	iorlw	H'30'
	call	Send_CHR
	return



Text1
	clrf	LCD_POINTER
Text1L	movf	LCD_POINTER,w
	call	TextM1
	call	Send_CHR
	incf	LCD_POINTER,w
	xorlw	d'4'
	btfsc	STATUS,Z
	return
	incf	LCD_POINTER,f
	goto	Text1L	







Puls_E
	bsf	LCD_E
	nop
	bcf	LCD_E
	return	
Send_CMD
	bcf	LCD_RS
	bcf	LCD_RW
	movwf	PORTB
	call	Puls_E
	call	Delay_S
	return
Send_CHR
	bsf	LCD_RS
	bcf	LCD_RW
	movwf	PORTB
	call	Puls_E
	call	Delay_S
	return

Delay_S
Loop1	deCfsz	COUNT1,f
	goto	Loop1 
	return

Delay_L
Loop2	call	Delay_S
	deCfsz	COUNT2,f
	goto	Loop2 
	return


TextM1
	addwf	PCL,f
	dt	"LAB:",0


	end

The problem now is when it reach 9 and the increment sensor work it still count and when it reach 0 and the decrement sensor work it count also showing symbols.

I want to make it when it reach 9 and the sensor work it ignore it and still show 9
and the same with the 0
 
Last edited by a moderator:

ErnieM

Joined Apr 24, 2011
8,377
Simple: when you increment inside INC_LAB test the people count: if 9 don't increment it. If greater than 9 you may want to set it to 9.

Same with decrementing: if there are zero people in the room don't decrement the count.
 

atferrari

Joined Jan 6, 2004
4,770
Hola Knight

It is easier, by far, to discuss a flow diagram. It helps you to think in a more logic way.

I personally make sure my flow diagrama satisfies me and THEN I write code.
 

JohnInTX

Joined Jun 26, 2012
4,787
+2!
And..
Rich (BB code):
TextM1
addwf PCL,f
dt "LAB:",0
When you use a table lookup like this, you also must ensure that:

1) The value of W bounds-checked to make sure that the lookup will not jump off the end of the table

2) The table does not span 256 word program ROM pages unless you compute the jump as a 16 bit address.
Failure will have your program going out into the weeds. #2 is especially tricky since it can work reliably until you add some code above the table that pushes it down enough to span a bank.

I usually dedicate a page of ROM to tables with an ORG to a page boundary then put the tables at the beginning of the page.

EDIT: The code that sends the string could be better. Strings end with 00h as they should but the code tests the index for a fixed number of characters. This is not a good way to do it if you want messages of different lengths. A better way is to fetch the char, test for 00h as shown, and return on 00h.

I added a way to send more than one message as well. Use W as the index of the start of the message. The assembler will calculate the index automatically for you using $-MsgStart where $ is the ROM address of the start of a particular message and MsgStart is the ROM address of the start of the whole message table. In the example, MsgStart is at 701h and Msg2 is at 706h. 706h-701h = 5 which is the value of W that will fetch the first character of Msg2. Nice. The indexes are named using the EQU directive. To use, just movlw <name of message>. This will help (but not cure) the problem of bounds-checking the index as well. Note that the messages can be arbitrary lengths as long as they are terminated by 00h.

Finally, I put the message table on a ROM page boundary to help (but also not completely cure) the crossing a ROM page problem.

I didn't add bounds checking for the index in W because enough's enough for now. How would you add it?

Have fun!


Rich (BB code):
;*************** SEND STRING OF ARBITRARY LENGTH  *********************
; Send string from MsgStart[W] until 00h

Text_W:
    movwf    LCD_POINTER    ; save W as LCD_POINTER

Text1L:
    movf    LCD_POINTER,W    ; get index
    call    TextM1        ; get character to W
    
    iorlw    0        ; set flags on W to look for end of string
    skpnz            ; built in macro for btfsc STATUS,Z
    return            ; 0 found, done!

    call    Send_CHR    ; else, send character
    incf    LCD_POINTER,F    ; bump index
    goto    Text1L        ; next


    ;**************** EXAMPLE USE  ********************
Send1:
    movlw    Msg1
    call    Text_W
    return

Send2:    movlw    Msg2
    call    Text_W
    return

    ORG    700h        ; tables on page boundary (last page of ROM)
;************* MESSAGES IN LOOKUP TABLE  ****************
TextM1:    
    addwf    PCL,W ; still need to bounds-check W

MsgStart:               
Msg1 equ $-MsgStart ; Compute index for Msg1    
    dt    "LAB:",0

Msg2: equ $-MsgStart ; Compute index for Msg2
    dt    "MSG2 is Bigger",0
 
Last edited:

Thread Starter

Knightmare.BH

Joined May 30, 2014
7
Simple: when you increment inside INC_LAB test the people count: if 9 don't increment it. If greater than 9 you may want to set it to 9.

Same with decrementing: if there are zero people in the room don't decrement the count.
yeah i got ur point
but how can i test what's inside the register ?? it's not like a port i can test it if it on or off.

this is my first time with LCD so am newbie in it
 

JohnInTX

Joined Jun 26, 2012
4,787
To do tests and comparisons on a 16F, its necessary to do some arithmetic or logical operations on the value then testing the Z and/or C flags in STATUS.

Testing for zero (or non-zero) is easy:
Rich (BB code):
iorlw 0 ; will set the Z flag in STATUS if W was 0
iorwf aRAMbyte,F ; OR's a byte in RAM with itself and sets Z if it was zero.
  ; In both cases W/RAM is unchanged.
Comparing two values requires subtraction:
Rich (BB code):
sublw 2 ; does 2-W comparing W with the literal value 2. 
                        ;Z is set if they are equal, C is set if 2 > W etc .

movlw value
subwf value,W ; compares a RAM byte with 'value' in W. 
                       ;Flags are set as before.
Any instruction which affects the flags may be useful. For example:
Rich (BB code):
incf aRAMbyte,W ; will set Z if the byte in RAM was FFh (affects Z)
incfsz aRAMbyte,W ;will skip if the byte in RAM was FFh 
                              ;(without affecting flags)
decf(sz) ; likewise can be used to test for 01h etc. In the cases that affect the STATUS flags, the next instruction is a test and skip on the flag(s) that indicate the relation between the values.

All of the STATUS flag settings are described in the descriptions for each instruction in the manual. These should be committed to memory.

Have fun!
 
Last edited:

Thread Starter

Knightmare.BH

Joined May 30, 2014
7
To do tests and comparisons on a 16F, its necessary to do some arithmetic or logical operations on the value then testing the Z and/or C flags in STATUS.

Testing for zero (or non-zero) is easy:
Rich (BB code):
iorlw 0 ; will set the Z flag in STATUS if W was 0
iorwf aRAMbyte,F ; OR's a byte in RAM with itself and sets Z if it was zero.
  ; In both cases W/RAM is unchanged.
Comparing two values requires subtraction:
Rich (BB code):
sublw 2 ; does 2-W comparing W with the literal value 2. 
                        ;Z is set if they are equal, C is set if 2 > W etc .

movlw value
subwf value,W ; compares a RAM byte with 'value' in W. 
                       ;Flags are set as before.
Any instruction which affects the flags may be useful. For example:
Rich (BB code):
incf aRAMbyte,W ; will set Z if the byte in RAM was FFh (affects Z)
incfsz aRAMbyte,W ;will skip if the byte in RAM was FFh 
                              ;(without affecting flags)
decf(sz) ; likewise can be used to test for 01h etc. In the cases that affect the STATUS flags, the next instruction is a test and skip on the flag(s) that indicate the relation between the values.

All of the STATUS flag settings are described in the descriptions for each instruction in the manual. These should be committed to memory.

Have fun!
i didn't understand anything... am just a beginner

can u just fix the program then i will ask you what did u do after seeing it
that way will be easier
 

JohnInTX

Joined Jun 26, 2012
4,787
If you understand what you originally posted:
Rich (BB code):
incf    LCD_POINTER,w
xorlw    d'4' ; do a logical op on W and check Z     
btfsc    STATUS,Z     
return
..then you should be able to understand what I posted - do the logical/arithmetic operation and check the flags in STATUS.

I can't go much farther because
1) I don't know what you are trying to compare
2) this is basic stuff - you have to understand it before you can do anything.

Build the code. Fire up MPSIM (MPLAB's simulator) and step through the code. Open a WATCH window, type in the names of some variables and watch what they do when the various instructions are executed. Try a few of the examples and it will all become clear.

Did you write the code or is it from a book/site?
 

Thread Starter

Knightmare.BH

Joined May 30, 2014
7
If you understand what you originally posted:
Rich (BB code):
incf    LCD_POINTER,w
xorlw    d'4' ; do a logical op on W and check Z     
btfsc    STATUS,Z     
return
..then you should be able to understand what I posted - do the logical/arithmetic operation and check the flags in STATUS.

I can't go much farther because
1) I don't know what you are trying to compare
2) this is basic stuff - you have to understand it before you can do anything.

Build the code. Fire up MPSIM (MPLAB's simulator) and step through the code. Open a WATCH window, type in the names of some variables and watch what they do when the various instructions are executed. Try a few of the examples and it will all become clear.

Did you write the code or is it from a book/site?

i didn't write it..
the teacher wrote it and he said to make it cant count more than 9
and cant count less than zero..
like when it reach 9 and the sensor work it must stay on 9 only if the 2nd sensor work it will count down to 8
 

JohnInTX

Joined Jun 26, 2012
4,787
OK. Well, ErnieM in #2 said what has to be done and in #7 the first code snippet shows 2 ways of testing for zero and the second one shows 2 ways of testing / comparing to an arbitrary value (9 in your case).

So, revise the code, get it to assemble with no errors and run it up on MPSIM. Any problems will become obvious. If you can't resolve the questions, post your revised code and we can look at it from there.
 

Thread Starter

Knightmare.BH

Joined May 30, 2014
7
OK. Well, ErnieM in #2 said what has to be done and in #7 the first code snippet shows 2 ways of testing for zero and the second one shows 2 ways of testing / comparing to an arbitrary value (9 in your case).

So, revise the code, get it to assemble with no errors and run it up on MPSIM. Any problems will become obvious. If you can't resolve the questions, post your revised code and we can look at it from there.

i already tried it it didn't do anything:

DEC_LAB
iorlw 0
iorwf LAB_COUNT,f
decf LAB_COUNT,f
call Disp_C
goto Start
 

JohnInTX

Joined Jun 26, 2012
4,787
I showed various ways to test for 0 depending on the program. You can't just copy all of them and hope for the best. I picked the middle one.

Rich (BB code):
DEC_LAB:
 iorwf LAB_COUNT,F  ; set STATUS,Z if LAB_COUNT == 0
 btfss STATUS,Z ; TEST RESULT OF iorwf, SKIP NEXT INSTRUCTION IF Z IS SET
 decf LAB_COUNT,F ; if NZ, this is not skipped so LAB_COUNT is decremented, result is left in LAB_COUNT (not W)
  ; the updated value of LAB_COUNT is in RAM, move to W if necessary
  call Disp_C ; update display
  goto Start
How did you test your code?
 

Thread Starter

Knightmare.BH

Joined May 30, 2014
7
I showed various ways to test for 0 depending on the program. You can't just copy all of them and hope for the best. I picked the middle one.

Rich (BB code):
DEC_LAB:
 iorwf LAB_COUNT,F  ; set STATUS,Z if LAB_COUNT == 0
 btfss STATUS,Z ; TEST RESULT OF iorwf, SKIP NEXT INSTRUCTION IF Z IS SET
 decf LAB_COUNT,F ; if NZ, this is not skipped so LAB_COUNT is decremented, result is left in LAB_COUNT (not W)
  ; the updated value of LAB_COUNT is in RAM, move to W if necessary
  call Disp_C ; update display
  goto Start
How did you test your code?
what is the STATUS,Z ??
never used it before

and i test my code using isis
 

JohnInTX

Joined Jun 26, 2012
4,787
what is the STATUS,Z ??
never used it before
Seriously?

Read sections 3.0, 4.2.2.1 and 15.0 in the datasheet. Then go back and read sections 1 through 5 and 14. Then read some of the tutorial info in Max's #9. There are lots of application notes on microchip.com that have code examples - like this one. Pick a few and read the code until you understand what's going on.

When you have it in hand, write the 'increment to 9' code, test it on ISIS then post it with problems. Until then, there isn't much more I can do for you.

Its probably time to visit with your teacher on this as well.

Good luck!
 

Thread Starter

Knightmare.BH

Joined May 30, 2014
7
Seriously?

Read sections 3.0, 4.2.2.1 and 15.0 in the datasheet. Then go back and read sections 1 through 5 and 14. Then read some of the tutorial info in Max's #9. There are lots of application notes on microchip.com that have code examples - like this one. Pick a few and read the code until you understand what's going on.

When you have it in hand, write the 'increment to 9' code, test it on ISIS then post it with problems. Until then, there isn't much more I can do for you.

Its probably time to visit with your teacher on this as well.

Good luck!
i just need the code for tomorrow but u wont write it..
so never mind
 
Top