Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ASM - LCD just displaying solid blocks on top row

Status
Not open for further replies.

Spadez

New Member
Hi,

Ive been working on my LCD code, which I had working at one point, on its own. I then tried to port this LCD code into the other code ive been working on and now all I get is solid boxes on the top row of the LCD.

Ive pasted my code below, can anyone see a reason why the LCD might be doing this? Any help or advise would be hugely appreciated.

Code:
;****************************************************************************
;
; TACHOMETER WITH LCD AND STEPPER MOTOR
;
;****************************************************************************

	PROCESSOR  PIC16F628
	INCLUDE    P16F628.INC

    RADIX DEC

	ERRORLEVEL -302,-305

#DEFINE	DATUM	PORTA		; PORT FOR LCD DATA.
#DEFINE	STEPP	PORTB		; PORT FOR STEPPER DATA.
#DEFINE	CONTROL	PORTB		; PORT FOR LCD CONTROL.

#DEFINE	CLKFRQ		4000	; CPU CLOCK FREQUENCY IN KHZ

#DEFINE LCD_PORT	PORTB
#DEFINE LCD_TRIS	TRISB
;LCD_PORT bits
DATA7		EQU	.7	; )
DATA6		EQU	.6	; )4 bit wide
DATA5		EQU	.5	; )data bus
DATA4		EQU	.4	; )
RS		EQU	.3	; Register select - data or commands
E		EQU	.2	; Chip enable

;RAM locations
SCREEN_DELAY_LOOP	EQU	0x20
SCREEN_DELAY_LOOP1	EQU	0x21
MESS_POINTER		EQU	0x22	; Message pointer
WORD_STORE		EQU	0x23	; Store for commands / data information
TEMP_PCLATH		EQU	0x24	; Temp store for PCLATH during screen string routine

; cywizard	begin
UNITS  	EQU   0X25
TENS  	EQU   0X26
HUNS  	EQU   0X27
; cywizard	end

 __CONFIG	_BODEN_ON&_WDT_OFF&_LVP_OFF&_PWRTE_ON&_HS_OSC

;============================================================================
; MACRO TO CREATE OFFSETS FOR FILE REGISTERS IN RAM
;============================================================================
BYTEADDR        SET 	32     ; USER FILE REGISTERS START HERE

BYTE            MACRO	BYTENAME
BYTENAME        EQU		BYTEADDR
BYTEADDR        SET		BYTEADDR+1
                ENDM

	BYTE	DATAL
	BYTE	REC_DATA

;============================================================================   
; MACRO STRING
;============================================================================
; Macro to call SEND_SCREEN_STRING, enables message strings to start beyond first 256 memory block
; and to cross block boundaries. Costs a few extra instructions per call, but greatly simplifies 
; string handling when dealing with > 256 bytes.

LCD_STRING	macro	lookup_address
		movf	PCLATH,W		; Store current value of PCLATH
		movwf	TEMP_PCLATH		; PCLATH may change below or in SEND_SCREEN_STRING
		if	high(lookup_address) != 0	; if start address of string is > 255
			movlw	high(lookup_address)
			movwf	PCLATH			; update PCLATH for string start address
		endif
		movlw	low(lookup_address)
		call	SEND_SCREEN_STRING
		movf	TEMP_PCLATH,W
		movwf	PCLATH			; Return PCLATH to original value
		endm

;============================================================================   
; RESET VECTOR
;============================================================================
   
	ORG	0
	GOTO 	MAIN			

;============================================================================
;                         SETUP 
;============================================================================

INITIALISE


	movlw	.20			; ~15ms delay after screen power up before send to it
	movwf	SCREEN_DELAY_LOOP1	; this delay is approx 15ms ( 20 x 256 x 3 us) @ 4MHz
	clrf	SCREEN_DELAY_LOOP

	decfsz	SCREEN_DELAY_LOOP,F
	goto	$-1
	decfsz	SCREEN_DELAY_LOOP1,F
	goto	$-3

	movlw	0x20			; set 4 bit data bus, at power up will be in 8 bit at this stage
	call	SEND_SCREEN_CMD		; will actually send 0x2? and 0x0? do D0-D3 float high/low
	movlw	0x28			; 4 bit, 2 line display
	call	SEND_SCREEN_CMD
	movlw	0x06			; Entry mode DD increment
	call	SEND_SCREEN_CMD
	movlw	0x0E			; Display & cursor on, not flashing
	call	SEND_SCREEN_CMD		; Cursor is usefull while debuging, 0x0C for no cursor
	call	CLEAR_SCREEN
	return

;============================================================================
;                         Clear Screen Macro
;============================================================================

CLEAR_SCREEN

	movlw	0x01			; Clear display, home cursor
	call	SEND_SCREEN_CMD

	movlw	.3			; needs >= 1.64ms delay before next screen send
	movwf	SCREEN_DELAY_LOOP1			; this delay is approx 2.3ms ( 3 x 256 x 3 us) @ 4MHz
	clrf	SCREEN_DELAY_LOOP
REP
	decfsz	SCREEN_DELAY_LOOP,F
	goto	REP
	decfsz	SCREEN_DELAY_LOOP1,F
	goto	REP
	return

;============================================================================
;                         Screen Macro
;============================================================================

SEND_SCREEN_CMD
	bcf	LCD_PORT,RS
	goto	SEND

SEND_SCREEN_DATA
	bsf	LCD_PORT,RS

SEND
	movwf	WORD_STORE	; Store all 8 bits of data
	movlw	B'00001111'
	andwf	LCD_PORT,F		; Clear data
	movf	WORD_STORE,W	; Collect data
	andlw	B'11110000'	; Strip bottom four bits
	iorwf	LCD_PORT,F		; Move data MSB Reg. B
	nop			; all nops to allow port settle prior to next change
	bsf	LCD_PORT,E		; Enable screen
	nop
	bcf	LCD_PORT,E
	movlw	B'00001111'
	andwf	LCD_PORT,F		; Clear data
	swapf	WORD_STORE,W	; Reverse nibbles of data
	andlw	B'11110000'	; Strip bottom four bits
	iorwf	LCD_PORT,F		; Move data LSB Reg. B
	nop
	bsf	LCD_PORT,E		; Enable screen
	nop
	bcf	LCD_PORT,E

	movlw	.12		; Delay between screen sends needs to be >= 40us
	movwf	SCREEN_DELAY_LOOP		; ~12 x 3 us + call & return etc > 40 us between screen sends

GO_ROUND_AGAIN
	decfsz	SCREEN_DELAY_LOOP,F
	goto	GO_ROUND_AGAIN

	return

;============================================================================
;                         Send String Macro
;============================================================================

SEND_SCREEN_STRING

	movwf	MESS_POINTER
	call	MESSAGE_DATA		; Fetch address command
	call	SEND_SCREEN_CMD		; Send address set command

NEXT_DATA 
	incfsz	MESS_POINTER,F		; Increment message pointer and check for overflow
	goto	NO_OVERFLOW
	incf	PCLATH,F		; inc PCLATH to move to next 256 memory block
NO_OVERFLOW
	call	MESSAGE_DATA		; fetch data
	addlw	.0			; add zero, if data was 0 then Z of status will be set
	btfsc	STATUS,Z		; Test for stop byte
	return				; This message finished, return
	call	SEND_SCREEN_DATA	; Display character
	goto	NEXT_DATA


;============================================================================
;                         Message Data Macro
;============================================================================

MESSAGE_DATA
; Screen lookup table.
; Each string starts with an address command byte and is terminated by a zero.
; DT means Define Table and is an assembler instruction, the assembler converts this to a
; series of retlw's, DT's are generally more readable except when defining chars.

	movf	MESS_POINTER,W
	movwf	PCL

;	org	0x0f6		; Debug only DELETE these 2 lines !!!!!!!!!!!!!!
;				; me testing macro !!!!!!!!!!!!!!!!!!!!!!!!!!!!!

user_defs
; User defined char 5 x 7 plus 1 cursor line
; three most significant bits are ignored by screen
; MSB set to 1 to avoid 0 end of string marker in mid string.

	retlw	0x48		; Start address of second character (1) in character generator ram.
;char 1				; The first character (0) is difficult to use as it can't be embedded
				; in a string as 0 is used as end of string marker.
	retlw	b'10001010'
	retlw	b'10000000'
	retlw	b'10000100'
	retlw	b'10000100'
	retlw	b'10000000'
	retlw	b'10010001'
	retlw	b'10001110'
	retlw	b'10000000'	; cursor line, sometimes separated from other 7 rows
;char 2
	retlw	b'10001010'	; 0x50 start address of char 2
	retlw	b'10000000'
	retlw	b'10000100'
	retlw	b'10000100'
	retlw	b'10000000'
	retlw	b'10001110'
	retlw	b'10010001'
	retlw	b'10000000'	; cursor line, sometimes separated from other 7 rows

	retlw	0		; 0 marks end of string

hello_world
	DT	0x80,"Hello World",0		; 0x80 is effective address of first char on first line

smiley						; 0xC0 is effective address of first char on second line
	DT	0xC0,"Userdef char ",.1,.2,0	; string followed by userdefined chars 1 & 2 as defined above

;============================================================================
;                         MAIN PROGRAM 
;============================================================================
MAIN        
	IFDEF	__16F628
	MOVLW	B'00000111'
	MOVWF	CMCON			; DISABLE COMPARATOR 
	ENDIF
	clrf	LCD_PORT
	bsf	STATUS,RP0	; Change to bank 1
	movlw	b'00000000'	; unused bits 0 & 1
	movwf	LCD_TRIS	; Set data / control lines to Output
	bcf	STATUS,RP0	; Go back to bank 0

	call	INITIALISE		; Set up port and screen ; NEW
	CLRF 	PORTA		        
	CLRF	PORTB
	MOVLW	B'11110000'		; SET PORTA DIRECTIONS
	TRIS	PORTA		        
	MOVLW	B'00000010'		; SET PORTB DIRECTIONS
	TRIS	PORTB	

; NO WEAK PULLUPS, RB0 INT RISING EDGE, TMR0 ON RA4, PRESCALE 1:256 
    	MOVLW   B'11110111'		 
	OPTION  

; ------------------------------------
; Display Message
; ------------------------------------

	LCD_STRING	hello_world	; Use Macro to send string from lookup table to LCD

	LCD_STRING	user_defs	; Define "graphics" characters

	LCD_STRING	smiley		; Display user defined graphic characters
			

; ------------------------------------
; SET BAUD RATE TO COMMUNICATE WITH PC
; ------------------------------------
; BOOT BAUD RATE = 9600, NO PARITY, 1 STOP BIT
;
        MOVLW 0X19              ; 0X19=9600 BPS (0X0C=19200 BPS)
		BANKSEL SPBRG
        MOVWF SPBRG
        MOVLW B'00100100'       ; BRGH = HIGH (2)
	BANKSEL TXSTA
        MOVWF TXSTA             ; ENABLE ASYNC TRANSMISSION, SET BRGH

        BCF STATUS,RP0          ; RAM PAGE 0

        MOVLW B'10010000'       ; ENABLE ASYNC RECEPTION
	BANKSEL RCSTA
        MOVWF RCSTA
;
; ------------------------------------
; PROVIDE A SETTLING TIME FOR START UP
; ------------------------------------
;
        CLRF DATAL
SETTLE  DECFSZ DATAL,F
        GOTO SETTLE

		BANKSEL RCREG
        MOVF RCREG,W
        MOVF RCREG,W
        MOVF RCREG,W            ; FLUSH RECEIVE BUFFER

	;	CALL SERIAL_MESSAGE		;TO DELETE

START: 
	;cywizard	begin
	CALL	INITIALISE
	;cywizard	end

MAINLOOP:
	CALL	RECEIVE
	MOVWF	REC_DATA
	;cywizard	begin
	CALL	CONVERT
	MOVF	HUNS, W
	CALL	SEND_SCREEN_STRING
	MOVF	TENS, W
	CALL	SEND_SCREEN_STRING
	MOVF	UNITS, W
	CALL	SEND_SCREEN_STRING
	;cywizard	end
	GOTO	MAINLOOP

; 
; ------------------------------------------- 
; RECEIVE CHARACTER FROM RS232 AND STORE IN W 
; ------------------------------------------- 
; THIS ROUTINE DOES NOT RETURN UNTIL A CHARACTER IS RECEIVED. 
; 
RECEIVE 
	BANKSEL PIR1
	BTFSS PIR1,RCIF         ; (5) CHECK FOR RECEIVED DATA
        GOTO RECEIVE

	BANKSEL RCREG
        MOVF RCREG,W            ; SAVE RECEIVED DATA IN W
        RETURN
        
        
;cywizard	begin
; -------------------------------------------
; Convert to ASCII
; -------------------------------------------
CONVERT
	movf	REC_DATA, w
    movwf	UNITS
	movlw	'0'
    movwf	HUNS
    movwf	TENS

DO100S
 	movlw	.100
	subwf	UNITS,W
	btfss	STATUS,C
	goto	DO10S	
	movwf	UNITS
	incf	HUNS,F
	goto	DO100S

DO10S
	movlw	.10
	subwf	UNITS,W
	btfss	STATUS,C
	goto	ADJUST	
	movwf	UNITS
	incf	TENS,F
	goto	DO10S

ADJUST
	movlw	'0'
	addwf	UNITS,F     
	return
;cywizard	end   

	END
 
Last edited:
Hi

I cant read this code but i know that the problem will be in the initialisation of the LCD display. Not sure if this will help much.
 
I know that it will probably be the initialisation but I copied this code across from the old working code and when I ran through the code in MPLAB it seems to run through the initialise correctly
 
Last edited:
Check to see that your ported code agrees with the new hardware. Check again. The TRIS registers too.

Your are sharing the PORTB between the LCD control and the stepper motor. Make a copy of the program and comment or edit out all code for the steppers. Can you get the LCD to work without it?
 
I know that it will probably be the initialisation but I copied this code across from the old working code and when I ran through the code in MPLAB it seems to run through the initialise correctly

hi,
Ran your program in Oshonsoft, it initialises and displays correctly, BUT its running much faster than I would expect when using the programs real world delays for initialising.
I would guess that the LCD INIT delays are much too short a duration for a correct initialisation.

EDIT:
Further checks on your program show that the 15mS power on delay is OK, but the 40uS delay for writing the LCD commands is too short.

The LCD manual states 15mS, 4.1mS then more than 100uS for each delay in the initialise sequence before writing the set up commands
I usually write 0x38 after each one of these delays, then the init commands, never have any problems.
 

Attachments

  • AAesp01.gif
    AAesp01.gif
    6.4 KB · Views: 206
Last edited:
Hi,

Both the contrast and timing was taken over from the other circuit, with the same code sections, and that works, but in the interest of compliyngi with the correct timing I will alter. I still think there is something else causing it which hasnt been unearthed, and I wont be able to check on an compiler till Monday. Ive noted that there are two calls to "INITIALISE". I think there should only be one, is there a way that this could have caused the problem?
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top