Society of Robots - Robot Forum

Electronics => Electronics => Topic started by: ozirock on June 10, 2010, 03:13:42 AM

Title: LCD and PIC microchip assembly code
Post 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
Title: Re: LCD and PIC microchip assembly code
Post by: Razor Concepts on June 10, 2010, 03:29:06 AM
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.
Title: Re: LCD and PIC microchip assembly code
Post by: ozirock on June 10, 2010, 04:06:21 AM
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  :)
Title: Re: LCD and PIC microchip assembly code
Post by: ozirock on June 11, 2010, 12:03:08 PM
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?
Title: Re: LCD and PIC microchip assembly code
Post by: waltr on June 11, 2010, 01:26:14 PM
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.
Title: Re: LCD and PIC microchip assembly code
Post by: Soeren on June 11, 2010, 05:34:45 PM
Hi,

; WORKTIME.ASM [...]
;  Note: must add additional time digit to run over 99 hrs.
Do you at least get an extra lunch break?  ;D

Title: Re: LCD and PIC microchip assembly code
Post by: billhowl on June 12, 2010, 01:36:26 AM
Here is the basic code template for assembly code generation for PIC16F627
Code: [Select]
;**********************************************************************
;   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.



Title: Re: LCD and PIC microchip assembly code
Post by: TrickyNekro on June 14, 2010, 10:04:06 AM
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