Sending 16-BIT number to an LCD

Discussion in 'General Electronics Chat' started by Siyom, Oct 15, 2012.

  1. Siyom

    Thread Starter Member

    Aug 9, 2012
    33
    0
    When programming with assembly,how do you send a 16 bit value to the LCD,do you need to break the numbers down,because in assembly you can only send single characters and a number like 8760 is a bit too much,even if i take it in binary i just don't see i can send it to LCD
     
  2. Dodgydave

    Distinguished Member

    Jun 22, 2012
    4,979
    744
    if its a dot matrix lcd, you use a full 8bit port to select the matrix address, 4bits row, 4bits column
     
  3. Papabravo

    Expert

    Feb 24, 2006
    10,138
    1,786
    Divide and conquer. The maximum nuber of decimal digits in a 16-bit unsigned number is 5. So

    1. Set DIVISOR to 10,000 = 10^4 and compute the QUOTIENT and the REMAINDER.
    2. Add the value of ASCII '0' to the QUOTIENT and send that to the display.
    3. Reduce the value of DIVISOR by a factor of 10 to 1000 = 10^3
    4. Compute the QUOTIENT and REMAINDER of the step 1. REMAINDER divided by DIVISOR.
    5. Add the value of ASCII '0' to the QUOTIENT and send that to the display.
    6. Reduce the value of DIVISOR by a factor of 10 to 100 = 10^2
    7. Compute the QUOTIENT and REMAINDER of the step 4. REMAINDER divided by DIVISOR.
    8. Add the value of ASCII '0' to the QUOTIENT and send that to the display.
    9. Reduce the value of DIVISOR by a factor of 10 to 10 = 10^1
    10. Compute the QUOTIENT and REMAINDER of the step 7. REMAINDER divided by DIVISOR.
    11. Add the value of ASCII '0' to the QUOTIENT and send that to the display.
    12. Add the value of ASCII '0' to the REMAINDER and send that to the display.

    I'm just curious -- how did you imagine it was done?
     
    Siyom likes this.
  4. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    Yes could divide.

    You can also maintain individual digit counters (each occupying 8 bits).
    Then you get rid of the division which is not so much desireable in assembler.
     
  5. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,024
    First, assuming you are working with binary numbers, you must convert the binary to BCD (binary coded decimal). For example, your value 8760 is 2238 hex. This won't do for displays so convert to BCD.

    The algorithm shown converts a 16 bit binary number in two registers (22h 38h in your case) and converts them to a packed BCD number (two digits 0-9 in each byte) in 3 registers (to hold the 5 digits required). So 22h 38h will convert to 00h 87h 60h.

    Next, you need to unpack the BCD since you will be outputting one digit at a time. The particular routine I grabbed does this for 4 individual digits but you get the idea. It could also be done on the fly.. These unpacked digits in 4 registers look like 08h 07h 06h 00h (the 5 MSdigit was unused in this project but its valid in R0).

    Finally, for each digit you'll have to convert it to agree with what the display wants. For 7 segment displays, each byte value can be used as as is as an index into a table of segment patterns. For a terminal UART or dot matrix LCDdisplay using the standard Hitachi 44780 or similar, you'll need to convert the unpacked BCD to ASCII which is done simply by adding 30h to each digit giving 38h 37h 36h 30h. Send these 4 to the display and it will read 8738 just like you want. Of course, there is more formatting you can do but I find this to be a good method regardless of the assembler / processor you use.

    Its also expandable to as many bits (24 or 32 or more) as you have RAM/time for. Also, its for a PIC but the basic algorithm will work on any processor.

    Code ( (Unknown Language)):
    1. ;***********************  BIN2BCD.asm  *****************************
    2.  
    3. ;********************************************************************
    4. ;                  Binary To BCD Conversion Routine
    5. ;      This routine converts a 16 Bit unsigned binary Number to a 5 Digit
    6. ; BCD Number.
    7. ;
    8. ;       The 16 bit binary number is input in locations H_Byte and
    9. ; L_Byte with the high byte in H_Byte.
    10.  
    11. ;        The BCD result is returned as packed BCD in R0-R1-R2 as 0d dd dd (R0 has MSdigit, R2 has 2 LSdigits)
    12.  
    13. ;       In this one, the lower 4 digits of the BCD number are returned UNPACKED in 4 bytes:
    14. ;    MSDcode-LSD code.  (PROJECT SPECIFIC but shows you how to do it)
    15. ;    Since the 4 umpacked bytes have the form 0d where d is 0h-9h, each can be used as an
    16. ;    index into a segment table (for 7-segment LEDs) or added to 30h to convert each
    17. ;    to an ASCII character for terminal UART or Hitachi LCD controllers.
    18.  
    19. ;   Calls: adjBCD  1 level
    20. ;   Uses FSR
    21. ;     Originally written for 16C5x
    22. ;
    23. ;*******************************************************************;
    24.  
    25. B_2unpakedBCD_1:
    26.           bcf     STATUS,0        ; clear the carry bit
    27.           movlw   .16
    28.           movwf   BitCount
    29.           clrf    R0
    30.           clrf    R1
    31.           clrf    R2
    32.  
    33.  ; Left shift binary and partial BCD.. R0-R1-R2-H_Byte-L_Byte
    34. loop16: rlf     L_Byte,F    
    35.           rlf     H_Byte,F  
    36.           rlf     R2,F  
    37.           rlf     R1,F  
    38.           rlf     R0,F  
    39.  
    40.           decfsz  BitCount,F    ; iff not 16 bits yet, adjust each 4 bit nibble  
    41.           goto    adjDEC
    42.  
    43.           goto    unpakit        ; else, done, packed BCD in R0,R1,R2 unpack it to 4 BCD
    44.  
    45. adjDEC:   movlw   R2ADDR        ; sets pointer to R2 in bank 1
    46.           call    adjBCD
    47.  
    48.           movlw   R1ADDR
    49.           call    adjBCD
    50.  
    51.           movlw   R0ADDR
    52.           call    adjBCD
    53.  
    54.           goto    loop16
    55.  
    56. adjBCD:  
    57.           movwf      FSR                
    58.           movlw   03h            ; BCD-adjust lower nibble in reg
    59.           addwf   INDF,W  
    60.           movwf   temp
    61.           btfsc   temp,3        ; test if result > 7 ( bit 3 == 1)
    62.           movwf   INDF            ; save it iff so.. else ignore it  
    63.           movlw   30h
    64.           addwf   INDF,W  
    65.           movwf   temp
    66.           btfsc   temp,7        ; test if result > 7 (bit 7 == 1)
    67.           movwf   INDF          ; save as MS nibble iff so
    68.           retlw   0
    69.  
    70.           ;********************  UNPACK BCD  ****************************
    71.           ; Unpacks BCD output from B2_BCD into overlayed Segment regs
    72.           ; as codes  Puts the 5th (MSD) digit in temp
    73.           ; Runs in bank 1, returns bank 0
    74.         ; NOTE THIS IS PROJECT-SPECIFIC..
    75.  
    76. unpakit:
    77.           movf    R0,W  
    78.           movwf   B2_BCD_5th_dig
    79.  
    80.           swapf   R1,W            ; copy lower 4 BCD to 4 RAM locations as 0d where d is the digit
    81.           andlw   0fh
    82.           movwf   MSDcode
    83.  
    84.           movf    R1,W  
    85.           andlw   0fh
    86.           movwf   MSDcode+1
    87.  
    88.           swapf   R2,W  
    89.           andlw   0fh
    90.           movwf   MSDcode+2
    91.  
    92.           movf    R2,W  
    93.           andlw   0fh
    94.           movwf   LSDcode
    95.           clrf    FSR
    96.           retlw   0
    97.  
    98.  
     
    Siyom likes this.
  6. Siyom

    Thread Starter Member

    Aug 9, 2012
    33
    0
    Thank you very much
     
Loading...