Society of Robots - Robot Forum
Electronics => Electronics => Topic started by: ozirock on June 10, 2010, 03:13:42 AM
-
Hello All,
I'm just wondering if anyone could point me in the right direction to find some examples of assembly code that can control a hitachi LCD screen.
Here is an example of the wiring I was going to use http://www.winpicprog.co.uk/pic_tutorial_lcd_board.htm (http://www.winpicprog.co.uk/pic_tutorial_lcd_board.htm)
And here is an example of the kind of information I have found which explains how to load the LCD http://www.josepino.com/?hitachi_displays (http://www.josepino.com/?hitachi_displays)
I'm new to using PIC microcontrollers and so far I've been using assembly language to program a pic 16f627, I was just wondering if anyone knew where to find an example of assembly code for this kind of situation?
Thanks
-
For future reference, the LCDs are referred to commonly as HD44780 displays and not Hitachi displays. This is probably why you didn't find any example code :D
Here is a link to some examples:
http://www.piclist.com/techref/io/lcd/pic.htm (http://www.piclist.com/techref/io/lcd/pic.htm)
Or search for "HD44780 pic assembly" for a lot more.
-
Thank you very much Razor Concepts, that is exactly what I was looking for, I see a stop watch tutorial that should get me off to a good start.
Thanks again :)
-
Ok I've been trying to get the code here http://www.piclist.com/techref/piclist/cheapic/worktime.htm (http://www.piclist.com/techref/piclist/cheapic/worktime.htm) to work for my PIC 16f627.
I didn't change a lot just what PIC it was and which include file to use so my code is:
;-------------------------------------------------------------------------;
; WORKTIME.ASM Pushbutton toggles clock keeping track of time on LCD ;
;-------------------------------------------------------------------------;
; Note: must add additional time digit to run over 99 hrs.
LIST P=16F627 ; 16F84 Runs at 4 MHz
INCLUDE "p16f627.inc"
__CONFIG _PWRTE_ON & _LP_OSC & _WDT_OFF ; uses 32.768 kHz crystal
ERRORLEVEL -224 ; supress annoying message because of tris
; Define Information
#DEFINE RS PORTA, 0
#DEFINE E PORTA, 1
#DEFINE TOGGLESW PORTB, 4
; Macro
EStrobe MACRO ; Strobe the "E" Bit
bsf E
bcf E
ENDM
CBLOCK 0CH
sec ; seconds digit
sec10 ; 10's of second digit
mins ; minutes digit
min10 ; 10's of minutes digit
hr ; hours digit
hr10 ; 10's of hours digit
highlim ; high limit + 1 of digit
w_temp ; holds W during interrupt
status_temp ; holds STATUS during interrupt
fsr_temp ; holds FSR during interrupt
Dlay ; 8 Bit Delay Variable
working ; working flag 0 not working, 1 working
ptr ; used in displaying message
Temp ; a temporary variable
bin ; a temporary variable
oset ; offset of time register
oldtime ; holds last value of sec
ENDC
ORG 0 ; start at location 0
goto main ; jump over to main routine
ORG 4
goto isr ; jump to interrupt routine
;-------------------------------------------------------------------------;
; High limit + 1 of digits at position W ;
;-------------------------------------------------------------------------;
sethi:
addwf PCL, f
dt H'A',H'6',H'A',H'6',H'A',H'A'
;-------------------------------------------------------------------------;
; Data for message to be output ;
;-------------------------------------------------------------------------;
shomsg ; Message to Output
addwf PCL, f ; Output the Characters
dt "Working Time:", 0
;-------------------------------------------------------------------------;
; Interrupt routine, increments time by one second (BCD) ;
;-------------------------------------------------------------------------;
isr:
movwf w_temp ; save W
swapf STATUS,W ; save status
movwf status_temp ; without changing flags
swapf FSR,W ; save FSR
movwf fsr_temp ; without changing flags
movf working, f ; check working flag
btfsc STATUS, Z ; if not zero then increment time
goto restore ; else get out of interrupt routine
movlw sec ; point at sec register
movwf FSR
newdigit: incf INDF, f ; current digit up one
movlw sec ; get difference between sec and FSR
subwf FSR, W
call sethi ; use to get high limit + 1
subwf INDF, W ; reached that number yet?
btfss STATUS, Z ; skip over if yes
goto restore ; else exit isr
clrf INDF ; set current digit to 0
incf FSR, f ; point at next digit
goto newdigit ; no, increment the next digit
restore:
swapf status_temp,W ; get original status back
movwf STATUS ; into status register
swapf fsr_temp,W ; get original fsr back
movwf FSR ; into status register
swapf w_temp,f ; old no flags trick again
swapf w_temp,W ; to restore W
bcf INTCON,T0IF ; clear the TMR0 interrupt flag
retfie ; finished reset GIE
;-------------------------------------------------------------------------;
; Initialize the ports ;
;-------------------------------------------------------------------------;
init:
clrf PORTA
clrf PORTB
movlw 0 ; Port A all outputs
tris PORTA
movlw B'00010000' ; RB4 input, others outputs
tris PORTB
movlw B'00000100' ; pull-ups enabled
; prescaler assigned to TMR0
; prescaler set to 1:32
; rolls over each second
option
movlw 0 ; zero out all registers
movwf hr10
movwf hr
movwf min10
movwf mins
movwf sec10
movwf sec
clrf working ; working flag to zero
movlw B'10100000' ; GIE set T0IE set, T0IF cleared
movwf INTCON
return
;-------------------------------------------------------------------------;
; Initialize the LCD ;
;-------------------------------------------------------------------------;
initlcd:
movlw D'40'
call nmsec ; Wait 40 msecs before Reset
bcf RS ; send an 8 bit instruction
movlw 0x03 ; Reset Command
call NybbleOut ; Send the Nybble
call Dlay5 ; Wait 5 msecs before Sending Again
EStrobe
nop
nop ; Wait 244 usecs before Sending the Second Time
EStrobe
nop
nop ; Wait 244 usecs before Sending the Third Time
bcf RS ; send an 8 bit instruction
movlw 0x02 ; Set 4 Bit Mode
call NybbleOut
nop
nop
movlw 0x028 ; 4 bit, 2 Line, 5x7 font
call SendINS
movlw 0x010 ; display shift off
call SendINS
movlw 0x001 ; Clear the Display RAM
call SendINS
call Dlay5 ; Note, Can take up to 4.1 msecs
movlw 0x006 ; increment cursor
call SendINS
movlw 0x00C ; display on cursor off
call SendINS
return
;-------------------------------------------------------------------------;
; Send the character in W out to the LCD ;
;-------------------------------------------------------------------------;
SendASCII
addlw '0' ; Send nbr as ASCII character
SendCHAR ; Send the Character to the LCD
movwf Temp ; Save the Temporary Value
swapf Temp, w ; Send the High Nybble
bsf RS ; RS = 1
call NybbleOut
movf Temp, w ; Send the Low Nybble
bsf RS
call NybbleOut
return
;-------------------------------------------------------------------------;
; Send an instruction in W out to the LCD ;
;-------------------------------------------------------------------------;
SendINS ; Send the Instruction to the LCD
movwf Temp ; Save the Temporary Value
swapf Temp, w ; Send the High Nybble
bcf RS ; RS = 0
call NybbleOut
movf Temp, w ; Send the Low Nybble
bcf RS
call NybbleOut
return
;-------------------------------------------------------------------------;
; Send the nibble in W out to the LCD ;
;-------------------------------------------------------------------------;
NybbleOut ; Send a Nybble to the LCD
movwf PORTB
EStrobe ; Strobe out the LCD Data
nop
nop
return
;-------------------------------------------------------------------------;
; Output the message on the LCD ;
;-------------------------------------------------------------------------;
OutMessage:
movwf FSR ; Point at first letter
OutLoop:
movf FSR, w ; Get pointer into W
incf FSR, f ; Set up for next letter
call shomsg ; Get character to output
iorlw 0 ; At the End of the Message?
btfsc STATUS, Z ; Skip if not at end
return ; Yes - Equal to Zero
call SendCHAR ; Output the ASCII Character
goto OutLoop ; Get the next character
;-------------------------------------------------------------------------;
; Wait until button is released ;
;-------------------------------------------------------------------------;
waitup:
btfss TOGGLESW ; test toggle switch
goto $ -1 ; ck again if pressed
movlw 20 ; wait 20 msec for debounce
call nmsec
btfss TOGGLESW ; check again, still up?
goto $ -4 ; no start over
return ; yes, finished
;-----------------------------------------------------------------------;
; Delay routine ;
;-----------------------------------------------------------------------;
Dlay5 movlw 5 ; delay for 5 milliseconds
nmsec: ; delay for # msec in W on entry
nop ; each nop is 0.122 milliseconds
nop
nop ; each total loop is 8 X 0.122 = 0.976 msec
nop
addlw H'FF' ; same as subtracting 1 from W
btfss STATUS, Z ; skip if result is zero
goto nmsec ; this is 2 X 0.122 msec
return ; back to calling point
;-------------------------------------------------------------------------;
; Display the Time ;
;-------------------------------------------------------------------------;
DispTime
MOVLW H'C0'
CALL SendINS
MOVF hr10, W
CALL SendASCII
MOVF hr, W
CALL SendASCII
MOVLW ":"
CALL SendCHAR
MOVF min10, W
CALL SendASCII
MOVF mins, W
CALL SendASCII
MOVLW ":"
CALL SendCHAR
MOVF sec10, W
CALL SendASCII
MOVF sec, W
CALL SendASCII
RETURN
;-------------------------------------------------------------------------;
; Toggle Work Flag ;
;-------------------------------------------------------------------------;
togglewk:
movf working, f ; set zero flag if zero
btfss STATUS, Z ; skip if working is zero
goto turnoff
incf working, f ; set working to 1
call waitup ; wait for button release
return
turnoff:
clrf working ; working set to zero
call waitup ; wait for button to be released
return
;-------------------------------------------------------------------------;
; The Main routine ;
;-------------------------------------------------------------------------;
main:
call init ; initialize ports, set up timer
call initlcd ; initialize the LCD
movlw 0 ; display 'Working Time:'
call OutMessage
ckbutton: ; check for a press of the TOGGLE button
btfss TOGGLESW ; skip if not pressed
call togglewk ; else change the mode of timer
movf oldtime, W ; is oldtime the same as sec?
subwf sec, W
btfsc STATUS, Z ; if not, skip over next instruction
goto ckbutton ; else continue checking
call DispTime ; sec has changed, display the time
movf sec, W ; make sec and oldsec the same
movwf oldtime
goto ckbutton ; and continue checking
end
I'm getting the errors as follows:
Warning[219] C:\VELLEMAN\K8048\OISIN ASM\LCD\CLOCK ONE - MODIFIED.ASM 70 : Invalid RAM location specified.
Warning[219] C:\VELLEMAN\K8048\OISIN ASM\LCD\CLOCK ONE - MODIFIED.ASM 72 : Invalid RAM location specified.
Warning[219] C:\VELLEMAN\K8048\OISIN ASM\LCD\CLOCK ONE - MODIFIED.ASM 93 : Invalid RAM location specified.
Warning[219] C:\VELLEMAN\K8048\OISIN ASM\LCD\CLOCK ONE - MODIFIED.ASM 97 : Invalid RAM location specified.
Warning[219] C:\VELLEMAN\K8048\OISIN ASM\LCD\CLOCK ONE - MODIFIED.ASM 98 : Invalid RAM location specified.
Warning[219] C:\VELLEMAN\K8048\OISIN ASM\LCD\CLOCK ONE - MODIFIED.ASM 124 : Invalid RAM location specified.
Warning[219] C:\VELLEMAN\K8048\OISIN ASM\LCD\CLOCK ONE - MODIFIED.ASM 264 : Invalid RAM location specified.
Warning[219] C:\VELLEMAN\K8048\OISIN ASM\LCD\CLOCK ONE - MODIFIED.ASM 296 : Invalid RAM location specified.
Warning[219] C:\VELLEMAN\K8048\OISIN ASM\LCD\CLOCK ONE - MODIFIED.ASM 302 : Invalid RAM location specified.
I haven't a clue how to fix this, does anyone know whats gone wrong?
-
Can you point to lines 70, 72, 93, 97, 98, 124, 264, 296 & 302 in your code?
Check the variable used on these lines and be sure that it is defined in cblock.
Look at the memory ram map in figure 3-2 of the data sheet. 0x0c is the SFR PIR1. Ram address 0x0d, 0x13, etc does not exist. You can also see this in the p16f627.inc file.
-
Hi,
; WORKTIME.ASM [...]
; Note: must add additional time digit to run over 99 hrs.
Do you at least get an extra lunch break? ;D
-
Here is the basic code template for assembly code generation for PIC16F627
;**********************************************************************
; This file is a basic code template for assembly code generation *
; on the PICmicro PIC16F627. This file contains the basic code *
; building blocks to build upon. *
; *
; If interrupts are not used all code presented between the ORG *
; 0x004 directive and the label main can be removed. In addition *
; the variable assignments for 'w_temp' and 'status_temp' can *
; be removed. *
; *
; Refer to the MPASM User's Guide for additional information on *
; features of the assembler (Document DS33014). *
; *
; Refer to the respective PICmicro data sheet for additional *
; information on the instruction set. *
; *
; Template file assembled with MPLAB V4.00.00 and MPASM V2.20.12 *
; *
;**********************************************************************
; *
; Filename: xxx.asm *
; Date: *
; File Version: *
; *
; Author: *
; Company: *
; *
; *
;**********************************************************************
; *
; Files required: *
; *
; *
; *
;**********************************************************************
; *
; Notes: *
; *
; *
; *
; *
;**********************************************************************
list p=16f627 ; list directive to define processor
#include <p16f627.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_ON & _BODEN_ON & _PWRTE_ON & _ER_OSC_CLKOUT & _MCLRE_ON & _LVP_ON
; '__CONFIG' directive is used to embed configuration data within .asm file.
; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
;***** VARIABLE DEFINITIONS
w_temp EQU 0x70 ; variable used for context saving
status_temp EQU 0x71 ; variable used for context saving
;**********************************************************************
ORG 0x000 ; processor reset vector
goto main ; go to beginning of program
ORG 0x004 ; interrupt vector location
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
; isr code can go here or be located as a call subroutine elsewhere
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
main
; remaining code goes here
END ; directive 'end of program'
PIC16F627 have four banks of general purpose registers start from locations 20-7Fh, A0h-FFh, 120h-14Fh, 170h-17Fh
and 1F0h-1FFh implemented as static RAM.
you can not just cut and pastes the codes without knowing what are the difference in registers, locations....etc.
PIC16F627 and 16F84 are two very difference used of registers, locations.
you may try to change "CBLOCK 0CH" to "CBLOCK 020H" but other registers and ports locations have to change too.
-
This should be helpful.... ;-)
http://home.iae.nl/users/pouweha/lcd/lcd.shtml (http://home.iae.nl/users/pouweha/lcd/lcd.shtml)
BTW, I got a 4bit mode library working for AVR in C as my first "big" program in C... It can't be that hard :P