Continue to Site

### Welcome to our site!

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
You said:
of course it won't, Basic can't do negative numbers...
It can, but you need to control it.
I have indicators written in Oshon and I provide the logic glue..

Last edited:

#### augustinetez

##### Active Member
Edit, I assumed the default radix is decimal, if not I can produce the table anyway you like.
Thanks Mike, yes default is decimal (although I tend to mix and match depending on what part of the program I'm writing).

#### augustinetez

##### Active Member
After hours playing with a calculator following on from Mikes post #19
2. if above 491 calculate ADC-492 - this allows for the dead zone.
3. if below 483 calculate 482-ADC
4. if neither 2 or 3 true then calculated value=0
5. if not zero then lookup value in a table.
I think I might have a near enough solution:

Do 1-4 as above, but instead of running in to a look up table, multiply the result from 1 or 2 by 56 and divide by 10.

It will give direct numbers that are close enough to 10 - 2500 for the project at hand (any fractions generated should be ignored if integer computation is used).

#### Pommie

##### Well-Known Member
Had some time this morning and thought I'd take a trip down memory lane and do some asm programming.

If you do decide to go the table route, this code will provide a value as you described,
Code:
        radix       dec
errorlevel     -207    ;Skip found label after column 1
errorlevel     -302    ;Skip out of bank nuisance messages
errorlevel     -303    ;Skip program word too large. Truncated to core size
;
; *******************************************************************************
; * Configuration fuse information for 16F1827:                    *
; *******************************************************************************
;
include   <P16LF1827.INC>

__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF

CBLOCK    0x20
flags
ENDC

CBLOCK    0x70
acc:2                ;in common memory so can be accessed from bank 3 (where flash registers are)
ENDC

ORG     0x0000
goto    start

ORG     0x0004

;--------------------------------------------------------------------------------

start
banksel OSCCON
movlw     b'01101000'
movwf   OSCCON
banksel    0
call    getValue
goto    $#define valueADC 35 #define center 487 getValue ;first do ADC-487 to discover direction bcf flags,0 ;clear the negative flag movlw low(valueADC) movwf acc movlw high(valueADC) movwf acc+1 movlw high(center) subwf acc+1,f movlw low(center) subwf acc,f btfss STATUS,C decf acc+1,f btfss acc+1,7 ;is it negative goto notNeg ;need to negate acc bsf flags,0 ;set the negative flag movlw 0xff xorwf acc,f xorwf acc+1,f incf acc,f btfsc STATUS,Z incf acc+1,f notNeg ; have now got a valid lookup value ;and a flag to tell us if above or below 487 banksel EEADRL ;Select Bank for EEPROM registers movfw acc ; movwf EEADRL movfw acc+1 addlw 0x0e movwf EEADRH bcf EECON1,CFGS ;Do not select Configuration Space bsf EECON1,EEPGD ;Select Program Memory bsf EECON1,RD ;Initiate read NOP ;required 2 x NOPs NOP ;EEDAT will now contain 0 - 2500 ;and flags,0 will be set if below center goto$

org 0xe00
;note, dead band incorporated into table
DW     0,0,0,0,0,5,11,16,22,27,33,39,44,50,55,61,67,72,78,83,89
DW  95,100,106,111,117,123,128,134,139,145,151,156,162,167,173,178
DW  184,190,195,201,206,212,218,223,229,234,240,246,251,257,262,268
DW  274,279,285,290,296,302,307,313,318,324,329,335,341,346,352,357
DW  363,369,374,380,385,391,397,402,408,413,419,425,430,436,441,447
DW  453,458,464,469,475,480,486,492,497,503,508,514,520,525,531,536
DW  542,548,553,559,564,570,576,581,587,592,598,604,609,615,620,626
DW  631,637,643,648,654,659,665,671,676,682,687,693,699,704,710,715
DW  721,727,732,738,743,749,755,760,766,771,777,782,788,794,799,805
DW  810,816,822,827,833,838,844,850,855,861,866,872,878,883,889,894
DW  900,906,911,917,922,928,934,939,945,950,956,961,967,973,978,984
DW  989,995,1001,1006,1012,1017,1023,1029,1034,1040,1045,1051,1057,1062,1068,1073
DW  1079,1085,1090,1096,1101,1107,1112,1118,1124,1129,1135,1140,1146,1152,1157,1163
DW  1168,1174,1180,1185,1191,1196,1202,1208,1213,1219,1224,1230,1236,1241,1247,1252
DW  1258,1263,1269,1275,1280,1286,1291,1297,1303,1308,1314,1319,1325,1331,1336,1342
DW  1347,1353,1359,1364,1370,1375,1381,1387,1392,1398,1403,1409,1414,1420,1426,1431
DW  1437,1442,1448,1454,1459,1465,1470,1476,1482,1487,1493,1498,1504,1510,1515,1521
DW  1526,1532,1538,1543,1549,1554,1560,1565,1571,1577,1582,1588,1593,1599,1605,1610
DW  1616,1621,1627,1633,1638,1644,1649,1655,1661,1666,1672,1677,1683,1689,1694,1700
DW  1705,1711,1717,1722,1728,1733,1739,1744,1750,1756,1761,1767,1772,1778,1784,1789
DW  1795,1800,1806,1812,1817,1823,1828,1834,1840,1845,1851,1856,1862,1868,1873,1879
DW  1884,1890,1895,1901,1907,1912,1918,1923,1929,1935,1940,1946,1951,1957,1963,1968
DW  1974,1979,1985,1991,1996,2002,2007,2013,2019,2024,2030,2035,2041,2046,2052,2058
DW  2063,2069,2074,2080,2086,2091,2097,2102,2108,2114,2119,2125,2130,2136,2142,2147
DW  2153,2158,2164,2170,2175,2181,2186,2192,2197,2203,2209,2214,2220,2225,2231,2237
DW  2242,2248,2253,2259,2265,2270,2276,2281,2287,2293,2298,2304,2309,2315,2321,2326
DW  2332,2337,2343,2348,2354,2360,2365,2371,2376,2382,2388,2393,2399,2404,2410,2416
DW  2421,2427,2432,2438,2444,2449,2455,2460,2466,2472,2477,2483,2488,2494,2500,2500
DW  2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500
DW  2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500
DW  2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500
DW  2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500
end
You could use the code above the label notNeg to get the value to be multiplied by 56 and divided by 10.
Note, this will not make an allowance for the dead zone.

Mike.

#### augustinetez

##### Active Member
That looks interesting Mike, will give it a bash in a PIC tomorrow (with EEDAT data shown on the display for testing).

#### Pommie

##### Well-Known Member
One thing to bear in mind, the DW table only uses half a K of flash. You still have 3.5K for the rest of your code. I assume the original code fitted in a smaller pic so this might be a viable alternative.

Mike.

#### augustinetez

##### Active Member
The original code was in a 12F629 so plenty of room in the 16F1827.

Only extra to add will to check if anything has changed since the last ADC read and skip it if nothings changed.

Hopefully this will be that last part of the puzzle.

#### augustinetez

##### Active Member
Wrote quick test program to test code for display on LCD - doesn't work in Oshonsoft simulator (could be a problem of the simulator) - won't have time to test it in an actual PIC for a few days (shows 000 instead of table values).

Code below if anybody wants to mess around with it.

C-like:
;
;********************************************************************************
;
; Target Controller        PIC16F1827
;                          __________
;          -----------RA3 |2       17| RA0---------
;          -----------RA4 |3       16| RA7---------
;          -----------RA5 |4       15| RA6---------
;     Ground----------Vss |5       14| VDD---------+5 V
;     LCD D4----------RB0 |6       13| RB7---------
;     LCD D5----------RB1 |7       12| RB6---------LCD_rs  (LCD Pin 4)
;     LCD D6----------RB2 |8       11| RB5---------LCD_rw  (LCD Pin 5)
;     LCD D7----------RB3 |9       10| RB4---------LCD_e   (LCD Pin 6)
;                          ----------
;
; *******************************************************************************
; * Device type and options                            *
; *******************************************************************************
;
processor 16F1827
errorlevel -207    ; Skip found label after column 1
errorlevel -302    ; Skip out of bank nuisance messages
errorlevel -303    ; Skip program word too large. Truncated to core size
;
; *******************************************************************************
; * Configuration fuse information for 16F1827:                    *
; *******************************************************************************
;
include   <P16F1827.INC>

__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
;
; *******************************************************************************
; Info for power-up display. Why was it done this way instead of with a table -
; because it is easier for beginners to visualise where the characters will
; appear on the LCD.

SIGN_ON_1    equ ' '        ; Position 1 on LCD - left most position
SIGN_ON_2    equ 'V'
SIGN_ON_3    equ 'K'
SIGN_ON_4    equ '5'
SIGN_ON_5    equ 'T'
SIGN_ON_6    equ 'M'
SIGN_ON_7    equ ' '
SIGN_ON_8    equ 'A'
SIGN_ON_9    equ 'D'
SIGN_ON_10    equ 'C'
SIGN_ON_11    equ ' '
SIGN_ON_12    equ 'T'
SIGN_ON_13    equ 'E'
SIGN_ON_14    equ 'S'
SIGN_ON_15    equ 'T'
SIGN_ON_16    equ ' '        ; Position 16 on LCD - right most position
;
; *******************************************************************************
; * General equates.                                *
; *******************************************************************************
;
#define center 487
;
; *******************************************************************************
; * Assign names to IO pins.                            *
; *******************************************************************************
;
LCD_busy equ    0x03        ; LCD busy bit
LCD_e    equ     0x04        ; 0=disable, 1=enable
LCD_rw    equ     0x05        ; 0=write, 1=read
LCD_rs    equ     0x06        ; 0=instruction, 1=data
;
;
;    16F1827 Oscillator setup
; OSCCON - Oscillator control reg.
; ---------------------------------
; SPLLEN b7 enable PLL x4
; 1 = enabled 0 = disabled
; IRCF | b6-3 frequency selection
; 1111 = 16MHz HF
; 1110 = 8 or 32MHz HF
; 1101 = 4MHz HF
; 1100 = 2MHz HF
; 1011 = 1MHz HF
; 1010 = 500kHz HF
; 1001 = 250kHz HF
; 1000 = 125kHz HF
; 0111 = 500kHz MF (default)
; 0110 = 250kHz MF
; 0101 = 125kHz MF
; 0100 = 62.5kHz MF
; 0011 = 31.25kHz HF
; 0010 = 31.25kHz MF
; 000x = 31.25kHz LF
; Reserved B2 reserved, 0
; SCS      B1 0-: 1x = int. OSC.
; 01 = Timer1 oscillator
; 00 = determined by FOSC <2:0> in Configuratio
; POR default 00111-00 500 kHz (POR = Power On Reset)
OSCCONVAL EQU b'01101000'    ; 4MhZ CLOCK
;
; *******************************************************************************
; *           Allocate variables in general purpose register space        *
; *******************************************************************************
;
CBLOCK    0x20        ; Start Data Block
TenK
Thou
Hund
Tens
Ones
freq_0
freq_1
freq_2
freq_3
byte2send        ;
LCD_char        ; Character being sent to the LCD
rs_value        ; The LCD rs line flag value
timer1            ; Used in delay routines
timer2            ;   "
count            ; loop counter  (gets reused)
temp            ; General reusable register
CounterA
CounterB
CounterC
CounterD
CounterE
flags
ENDC            ; End of Data Block

CBLOCK    0x70
acc:2
NumH
NumL
ENDC            ; End of Data Block
;
; *******************************************************************************
; * The 16F1827 resets to 0x00.                            *
; * The Interrupt vector is at 0x04.                        *
; *******************************************************************************
;
ORG    0x0000

ORG    0x0004
;
; *******************************************************************************
; *                                        *
; * Purpose:  This is the start of the program.                    *
; *                                        *
; *******************************************************************************
;
start
BANKSEL    PORTA
clrf    PORTA
clrf    PORTB

; Set PIC oscillator frequency
banksel    OSCCON        ; Select OSCCON
movlw    OSCCONVAL    ;
movwf    OSCCON        ; Loads the wanted value
banksel    PORTA

; Configures all I / O as digital
Banksel    ANSELA
bsf    ANSELA,ANSA2    ; set ra2 to analog
clrf    ANSELB

; Disable all wakeup pull-ups
Banksel    WPUA
clrf    WPUA
clrf    WPUB

BANKSEL    OPTION_REG
clrf    OPTION_REG    ;
;
movlw   b'00110111'    ; PORTA (RA0:2,4:5 inputs, RA3,6:7 outputs)
movwf   TRISA        ;
clrf    TRISB        ; Set port B to all outputs

movlw    b'11000000'    ; right justify, FOSC/4 vdd and vss vref

movlw    b'00001001'    ; select channel an2 & turn adc on

BANKSEL    PORTA;
call    init_LCD    ; Initialize the LCD
call    busy_check    ; Wait for LCD to finish initialising
call    display_version    ; Display title and version
;
; *******************************************************************************
; *                                        *
; * Purpose:      This is the Main Program Loop.                    *
; *                                        *
; *******************************************************************************
;
main
movlw    100
call    wait        ; acquisiton delay & loop delay

goto    $-1 ; no, test again BANKSEL ADRESH movf ADRESH,w ; read upper 2 bits movlb 0 movwf valueADC ; store in gpr space BANKSEL ADRESL movf ADRESL,w ; read lower 8 bits movlb 0 movwf valueADC+1 ; store in gpr space call getValue call bin2BCD call show_bcd goto main ; Continue main loop ; getValue ;first do ADC-487 to discover direction bcf flags,0 ; clear the negative flag movlw low(valueADC) movwf acc movlw high(valueADC) movwf acc+1 movlw high(center) subwf acc+1,f movlw low(center) subwf acc,f btfss STATUS,C decf acc+1,f btfss acc+1,7 ; is it negative goto notNeg ;need to negate acc bsf flags,0 ; set the negative flag movlw 0xff xorwf acc,f xorwf acc+1,f incf acc,f btfsc STATUS,Z incf acc+1,f notNeg ; have now got a valid lookup value ; and a flag to tell us if above or below 487 BANKSEL EEADRL ; Select Bank for EEPROM registers movfw acc ; movwf EEADRL movfw acc+1 addlw 0x0e movwf EEADRH bcf EECON1,CFGS ; Do not select Configuration Space bsf EECON1,EEPGD ; Select Program Memory bsf EECON1,RD ; Initiate read NOP ; required 2 x NOPs NOP ; EEDAT will now contain 0 - 2500 ; and flags,0 will be set if below center movf EEDATH,w movwf NumH ; for BCD conversion routine movf EEDATL,w movwf NumL ; for BCD conversion routine movlb 0 return ; ; ******************************************************************************* ; * Purpose: * ; * This subroutine converts a 16 bit binary number to decimal in * ; * TenK, Thou, Hund, Tens, Ones * ; ******************************************************************************* ; bin2BCD ; Takes number in NumH:NumL and returns decimal in TenK:Thou:Hund:Tens:Ones ; Fast 16-Bit Binary to Decimal by Peter Hemsley ; Input: 16-bit binary in NumH and NumL ; Output: Decimal (BCD) digits in TenK,Thou,Hund,Tens,Ones ; No temporary variables required ; Code size: 46 instructions ; Execution time: Variable, approx 150 to 170 cycles Bin2DecFast movf NumH,w ;Hex Digit 0X00 (H2) iorlw 0xF0 ;w=H2-16 movwf Ones ;Ones=H2-16 movwf Tens ;Tens=H2-16 addwf Tens,f ;Tens=H2*2-32 addwf Tens,f ;Tens=H2*3-48, C=1 movwf Hund ;Hund=H2-16 rlf Hund,f ;Hund=H2*2-31 swapf NumH,w ;Hex Digit X000 (H3) iorlw 0xF0 ;w=H3-16 addwf Hund,f ;Hund=H3+H2*2-47 Done! movwf Thou ;Thou=H3-16 addwf Thou,f ;Thou=H3*2-32 addlw D'52' ;w=H3+36 addwf Ones,f ;Ones=H3+H2+20 swapf NumL,w ;Hex Digit 00X0 (H1) iorlw 0xF0 ;w=H1-16 addwf Tens,f ;Tens=H2*3+H1-64 addwf Ones,f ;Ones=H3+H2+H1+4, C=1 rlf Ones,f ;Ones=(H3+H2+H1)*2+9, C=0 comf Ones,f ;Ones=-(H3+H2+H1)*2-10 rlf Ones,f ;Ones=-(H3+H2+H1)*4-20 movf NumL,w ;Hex Digit 000X (H0) andlw 0x0F ;w=H0 addwf Ones,f ;Ones=H0-(H3+H2+H1)*4-20 Done! rlf Tens,f ;C=0, Tens=H2*6+H1*2-128 Done! movlw D'7' movwf TenK ;TenK=7 addlw D'3' ;w=10, C=0 rlf Thou,f ;Thou=H3*4-64 Done! mod0 addwf Ones,f ;D(X)=D(X)mod10 decf Tens,f ;D(X+1)=D(X+1)+D(X)div10 skpc goto mod0 mod1 addwf Tens,f decf Hund,f skpc goto mod1 mod2 addwf Hund,f decf Thou,f skpc goto mod2 mod3 addwf Thou,f decf TenK,f skpc goto mod3 return ; ; ******************************************************************************* ; * Display data on the LCD. * ; ******************************************************************************* ; show_bcd movlw 0xC1 ; Point the LCD to digit location call cmnd2LCD ; Send digit location to LCD movf Thou,f ; Test if 'file'is 0 or 1 btfss STATUS,Z ; The Z or Zero bit is set to "1" when the result goto not_zero ; of an arithmetic or logical operation is zero movlw ' ' ; Thou = 0, insert space call data2LCD ; Send byte in W to LCD goto show_Hund not_zero movfw Thou ; Thou is not 0, insert number addlw 0x30 ; Convert to ASCII character call data2LCD ; Send to LCD - rinse and repeat until all characters sent show_Hund movfw Hund addlw 0x30 call data2LCD movfw Tens addlw 0x30 call data2LCD movfw Ones addlw 0x30 call data2LCD return ; ; ******************************************************************************* ; * * ; * Purpose: Send Command or Data byte to the LCD * ; * Entry point cmnd2LCD: Send a Command to the LCD * ; * Entry Point data2LCD: Send a Data byte to the LCD * ; * * ; * Input: W has the command or data byte to be sent to the LCD. * ; * * ; ******************************************************************************* ; cmnd2LCD ; ****** Entry point for commands ****** clrf rs_value ; Remember to clear RS (clear rs_value) goto write2LCD ; Go to common code data2LCD ; ****** Entry point for data ******** bsf rs_value,0 ; Remember to set RS (set bit 0 of rs_value) write2LCD movwf LCD_char ; Save byte to write to LCD call busy_check ; Check to see if LCD is ready for new data movlw 2 ; movwf count ; SET UP LOOP COUNTER write2LCD2 swapf LCD_char,f ; SWAP MS & LS NIBBLES movf LCD_char,w andlw 15 ; MAKE TOP 4 BITS OF W 0 movwf PORTB ; SEND MS NIBBLE bcf PORTB,LCD_rs ; Guess RS should be clear - command mode btfsc rs_value,0 ; Should RS be clear? (is bit 0 == 0?) bsf PORTB,LCD_rs ; No, set RS - data mode nop bsf PORTB,LCD_e ; SET E HIGH nop bcf PORTB,LCD_e ; SET E LOW decfsz count,F goto write2LCD2 ; GO BACK AND SEND LS NIBBLE return ; ; ******************************************************************************* ; * * ; * Purpose: Check if LCD is done with the last operation. * ; * This subroutine polls the LCD busy flag to determine if * ; * previous operations are completed. * ; * * ; ******************************************************************************* ; busy_check clrf PORTB ; Clear all outputs on PORTB banksel TRISB ; Switch to bank for Tris operation movlw b'00001000' ; Set RB3 input, others outputs movwf TRISB ; banksel PORTB bcf PORTB,LCD_rs ; Set up LCD for Read Busy Flag (RS = 0) nop bsf PORTB,LCD_rw ; Set up LCD for Read (RW = 1) LCD_is_busy bsf PORTB,LCD_e ; Set E high nop bcf PORTB,LCD_e ; Drop E again btfss PORTB,LCD_busy ; Is Busy Flag (RB3) clear? goto not_busy ; Yes - exit nop ; No nop ; Wait a while bsf PORTB,LCD_e ; Pulse E high (dummy read of lower nibble), nop ; wait, bcf PORTB,LCD_e ; and drop E again goto LCD_is_busy ; If not, it is busy so jump back not_busy banksel TRISB ; Switch to bank 1 for Tristate operation clrf TRISB ; All pins (RB7..RB0) are back to outputs banksel PORTB ; Switch to bank 0 clrf PORTB ; Clear all of Port B (inputs and outputs) return ; ; ; ; ******************************************************************************* ; * * ; * Purpose: Power on initialization of Liquid Crystal Display. The LCD * ; * controller chip must be equivalent to an Hitachi 44780. * ; * * ; ******************************************************************************* ; init_LCD movlw 100 call wait ; Wait for LCD to power up ; Put 4-bit command on RB3..RB0 ; PIC's RB3..RB0 lines connect to LCD's DB7..DB4 lines movlw 0x03 ; LCD init instruction (First) movwf PORTB ; Send to LCD via RB3..RB0 bsf PORTB,LCD_e ; Set the LCD E line high, movlw 100 call wait ; wait a "long" time, bcf PORTB,LCD_e ; and then Clear E movlw 0x03 ; LCD init instruction (Second) movwf PORTB ; Send to LCD via RB3..RB0 bsf PORTB,LCD_e ; Set E high, movlw 32 call wait ; wait a while, bcf PORTB,LCD_e ; and then Clear E movlw 0x03 ; LCD init instruction (Third) movwf PORTB ; Send to LCD via RB3..RB0 bsf PORTB,LCD_e ; Set E high, movlw 32 call wait ; wait a while, bcf PORTB,LCD_e ; and then Clear E movlw 0x02 ; 4-bit mode instruction movwf PORTB ; Send to LCD via RB3..RB0 bsf PORTB,LCD_e ; Set E high, movlw 16 call wait ; wait a while, bcf PORTB,LCD_e ; and then Clear E movlw 0x28 ; 1/16 duty cycle, 5x8 matrix call cmnd2LCD ; Send command in w to LCD movlw 0x08 ; Display off, cursor and blink off call cmnd2LCD ; Send command to LCD movlw 0x01 ; Clear and reset cursor call cmnd2LCD ; Send command in w to LCD movlw 0x06 ; Set cursor to move right, no shift call cmnd2LCD ; Send command in w to LCD movlw 0x0E ; Display on, cursor on and blink off ; movlw 0x0F ; Display on, cursor on and blink on ; movlw 0x0C ; Display on, cursor and blink off call cmnd2LCD ; Send command in w to LCD return ; ; ; ******************************************************************************* ; * * ; * Function: clear_lcd * ; * * ; * Purpose: Clears the LCD and homes the cursor. * ; * * ; * Input: None * ; * * ; * Output: None * ; * * ; * Revisions: Ver 2.0: Added function for convenience and to reduce code * ; * space 4-4-04 W3CD. * ; * * ; ******************************************************************************* ; clear_lcd movlw 0x01 ; Prepare to display a new message on LCD call cmnd2LCD ; by clearing the current one return ; ; ******************************************************************************* ; * * ; * Purpose: Display version and other info on LCD for 1 second * ; * upon power-up * ; * * ; * Input: SIGN_ON_1 through SIGN_ON_16 * ; * * ; * Output: LCD displays info * ; * * ; ******************************************************************************* ; display_version call clear_lcd movlw SIGN_ON_1 ; digit 1 call data2LCD ; movlw SIGN_ON_2 ; digit 2 call data2LCD ; movlw SIGN_ON_3 ; digit 3 call data2LCD ; movlw SIGN_ON_4 ; digit 4 call data2LCD ; movlw SIGN_ON_5 ; digit 5 call data2LCD ; movlw SIGN_ON_6 ; digit 6 call data2LCD ; movlw SIGN_ON_7 ; digit 7 call data2LCD ; movlw SIGN_ON_8 ; digit 8 call data2LCD ; movlw SIGN_ON_9 ; digit 9 call data2LCD ; movlw SIGN_ON_10 ; digit 10 call data2LCD ; movlw SIGN_ON_11 ; digit 11 call data2LCD ; movlw SIGN_ON_12 ; digit 12 call data2LCD ; movlw SIGN_ON_13 ; digit 13 call data2LCD ; movlw SIGN_ON_14 ; digit 14 call data2LCD ; movlw SIGN_ON_15 ; digit 15 call data2LCD ; movlw SIGN_ON_16 ; digit 16 call data2LCD ; call wait_a_sec ; Wait one second return ; ; ******************************************************************************* ; * * ; * Purpose: Delay routines * ; * * ; ******************************************************************************* ; wait_a_sec ;PIC Time Delay = 0.99999900 s with Osc = 4000000 Hz movlw D'6' movwf CounterC movlw D'19' movwf CounterB movlw D'172' movwf CounterA loop decfsz CounterA,f goto loop decfsz CounterB,f goto loop decfsz CounterC,f goto loop return wait_100us ;PIC Time Delay = 0.00009800 s with Osc = 4MHz movlw D'31' movwf CounterA loop2 decfsz CounterA,1 goto loop2 return wait ; Enter with 'w' holding number of times to execute 1mS delay routine movwf timer1 ; Set up counter call wait_1ms ; Go to wait loops decfsz timer1,f goto$-2
return

wait_1ms     ;PIC Time Delay = 0.00099800 s with Osc = 4MHz
movlw    D'2'
movwf    CounterD
movlw    D'74'
movwf    CounterE
loop1
decfsz    CounterE,f
goto    loop1
decfsz    CounterD,f
goto    loop1
return
;
org 0xe00
;note, dead band incorporated into table
DW  0,0,0,0,0,5,11,16,22,27,33,39,44,50,55,61,67,72,78,83,89
DW  95,100,106,111,117,123,128,134,139,145,151,156,162,167,173,178
DW  184,190,195,201,206,212,218,223,229,234,240,246,251,257,262,268
DW  274,279,285,290,296,302,307,313,318,324,329,335,341,346,352,357
DW  363,369,374,380,385,391,397,402,408,413,419,425,430,436,441,447
DW  453,458,464,469,475,480,486,492,497,503,508,514,520,525,531,536
DW  542,548,553,559,564,570,576,581,587,592,598,604,609,615,620,626
DW  631,637,643,648,654,659,665,671,676,682,687,693,699,704,710,715
DW  721,727,732,738,743,749,755,760,766,771,777,782,788,794,799,805
DW  810,816,822,827,833,838,844,850,855,861,866,872,878,883,889,894
DW  900,906,911,917,922,928,934,939,945,950,956,961,967,973,978,984
DW  989,995,1001,1006,1012,1017,1023,1029,1034,1040,1045,1051,1057,1062,1068,1073
DW  1079,1085,1090,1096,1101,1107,1112,1118,1124,1129,1135,1140,1146,1152,1157,1163
DW  1168,1174,1180,1185,1191,1196,1202,1208,1213,1219,1224,1230,1236,1241,1247,1252
DW  1258,1263,1269,1275,1280,1286,1291,1297,1303,1308,1314,1319,1325,1331,1336,1342
DW  1347,1353,1359,1364,1370,1375,1381,1387,1392,1398,1403,1409,1414,1420,1426,1431
DW  1437,1442,1448,1454,1459,1465,1470,1476,1482,1487,1493,1498,1504,1510,1515,1521
DW  1526,1532,1538,1543,1549,1554,1560,1565,1571,1577,1582,1588,1593,1599,1605,1610
DW  1616,1621,1627,1633,1638,1644,1649,1655,1661,1666,1672,1677,1683,1689,1694,1700
DW  1705,1711,1717,1722,1728,1733,1739,1744,1750,1756,1761,1767,1772,1778,1784,1789
DW  1795,1800,1806,1812,1817,1823,1828,1834,1840,1845,1851,1856,1862,1868,1873,1879
DW  1884,1890,1895,1901,1907,1912,1918,1923,1929,1935,1940,1946,1951,1957,1963,1968
DW  1974,1979,1985,1991,1996,2002,2007,2013,2019,2024,2030,2035,2041,2046,2052,2058
DW  2063,2069,2074,2080,2086,2091,2097,2102,2108,2114,2119,2125,2130,2136,2142,2147
DW  2153,2158,2164,2170,2175,2181,2186,2192,2197,2203,2209,2214,2220,2225,2231,2237
DW  2242,2248,2253,2259,2265,2270,2276,2281,2287,2293,2298,2304,2309,2315,2321,2326
DW  2332,2337,2343,2348,2354,2360,2365,2371,2376,2382,2388,2393,2399,2404,2410,2416
DW  2421,2427,2432,2438,2444,2449,2455,2460,2466,2472,2477,2483,2488,2494,2500,2500
DW  2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500
DW  2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500
DW  2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500
DW  2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500
;
END

#### rjenkinsgb

##### Well-Known Member
You may need to use different instructions to read the table?
eg.

Also, the table could be bytes rather than words, as you need every value a multiple of ten. That could save some program space, if it's tight?
eg. Divide all by ten so you have 0-250 range in single bytes, then multiply the result by ten.

#### Pommie

##### Well-Known Member
Also, the table could be bytes rather than words,
Absolutely no point storing it as bytes as they're 14 bit flash words, so still 1 location per entry - I.E. same size.
The DW table is simply constructed from the excel sheet I did that calculates the value as requested.
You may need to use different instructions to read the table?
The code was run (albeit in simulation) on the chip mentioned and referring to the datasheet for that chip. It works.
as you need every value a multiple of ten.
I suspect this was done as an attempt to simplify the code and not an actual requirement.

Mike.
Edit, the values increase by ~5.6 per step, far from the 10 multiple.

Last edited:

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
When I sim that code... The LCD busy craps out too fast.. If the busy come on fast, it misses the second nibble read and the RW bit is never cleared...

I will work on it later as now I have a LCD written while busy error..

#### augustinetez

##### Active Member
In the Oshonsoft Sim I set the LCD setup values to 1 to stop it messing up.

I think it's just the Oshon sim doesn't understand the DW instruction.

If you use the Breakpoints manager and look at the code, it either says 'unrecognised' against parts of the table or lines of gibberish in amongst the table:-

The MPlab listing file is fine without any of the above garbage.

As for size, it only takes a total of 521 bytes.

#### augustinetez

##### Active Member
Edit, the values increase by ~5.6 per step, far from the 10 multiple.
That's not a problem, the 10 multiple was a preferred option but this works just as well - the main thing was an even(ish) spread of values.

#### augustinetez

##### Active Member
have NEVER had much luck with busy read on 4 bit interfaces...
And I've never had any problem (bar once) since I started using the busy read with 4 bit interfaces - must have something to do with the obtuseness of animate objects

#### augustinetez

##### Active Member
Below code is a combination of various peoples input on this forum re ADC scaling, 16x8 multiply & 16x8 divide (from other thread viz AN617 problems) plus various other possibly useful bits.

It takes the ADC value, defines a center point and tells you whether the returned value is above or below the center.

That value is then multiplied by 56 and divided by 10 to scale it to a range of values between ~5 and 2500.

Thankyou to all for your input.

Note to Nigel - the divide routine came from Piclist

Code:
; *                                        *
; *******************************************************************************
; *    ADC scaling,16x8 multiply & 16x8 divide routines            *
; *    Plus various other bits of possibly useful bits of code            *
; *******************************************************************************
;
;********************************************************************************
;
; Target Controller        PIC16F1827
;                          __________
;          -----------RA3 |2       17| RA0---------
;          -----------RA4 |3       16| RA7---------
;          -----------RA5 |4       15| RA6---------
;     Ground----------Vss |5       14| VDD---------+5 V
;     LCD D4----------RB0 |6       13| RB7---------
;     LCD D5----------RB1 |7       12| RB6---------LCD_rs  (LCD Pin 4)
;     LCD D6----------RB2 |8       11| RB5---------LCD_rw  (LCD Pin 5)
;     LCD D7----------RB3 |9       10| RB4---------LCD_e   (LCD Pin 6)
;                          ----------
;
; *******************************************************************************
; * Device type and options                            *
; *******************************************************************************
;
processor 16F1827
errorlevel -207    ; Skip found label after column 1
errorlevel -302    ; Skip out of bank nuisance messages
errorlevel -303    ; Skip program word too large. Truncated to core size
;
; *******************************************************************************
; * Configuration fuse information for 16F1827:                    *
; *******************************************************************************
;
include   <P16F1827.INC>

__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
;
; *******************************************************************************
; Info for power-up display. Why was it done this way instead of with a table -
; because it is easier for beginners to visualise where the characters will
; appear on the LCD.

SIGN_ON_1    equ ' '        ; Position 1 on LCD - left most position
SIGN_ON_2    equ 'V'
SIGN_ON_3    equ 'K'
SIGN_ON_4    equ '5'
SIGN_ON_5    equ 'T'
SIGN_ON_6    equ 'M'
SIGN_ON_7    equ ' '
SIGN_ON_8    equ 'A'
SIGN_ON_9    equ 'D'
SIGN_ON_10    equ 'C'
SIGN_ON_11    equ ' '
SIGN_ON_12    equ 'T'
SIGN_ON_13    equ 'E'
SIGN_ON_14    equ 'S'
SIGN_ON_15    equ 'T'
SIGN_ON_16    equ ' '        ; Position 16 on LCD - right most position
;
; *******************************************************************************
; * General equates.                                *
; *******************************************************************************
;
#define center 486        ; For ADC scaling routine
;
; *******************************************************************************
; * Assign names to IO pins.                            *
; *******************************************************************************
;
LCD_busy equ    0x03        ; LCD busy bit
LCD_e    equ     0x04        ; 0=disable, 1=enable
LCD_rw    equ     0x05        ; 0=write, 1=read
LCD_rs    equ     0x06        ; 0=instruction, 1=data
;
;
; 16F1827 Oscillator setup
; OSCCON - Oscillator control reg.
; ---------------------------------
; SPLLEN b7 enable PLL x4
; 1 = enabled 0 = disabled
; IRCF | b6-3 frequency selection
; 1111 = 16MHz HF
; 1110 = 8 or 32MHz HF
; 1101 = 4MHz HF
; 1100 = 2MHz HF
; 1011 = 1MHz HF
; 1010 = 500kHz HF
; 1001 = 250kHz HF
; 1000 = 125kHz HF
; 0111 = 500kHz MF (default)
; 0110 = 250kHz MF
; 0101 = 125kHz MF
; 0100 = 62.5kHz MF
; 0011 = 31.25kHz HF
; 0010 = 31.25kHz MF
; 000x = 31.25kHz LF
; Reserved B2 reserved, 0
; SCS      B1 0-: 1x = int. OSC.
; 01 = Timer1 oscillator
; 00 = determined by FOSC <2:0> in Configuratio
; POR default 00111-00 500 kHz (POR = Power On Reset)
OSCCONVAL EQU b'01101000'    ; 4MhZ CLOCK
;
; *******************************************************************************
; *           Allocate variables in general purpose register space        *
; *******************************************************************************
;
CBLOCK    0x20        ; Start Data Block
TenK
Thou
Hund
Tens
Ones
byte2send        ;
LCD_char        ; Character being sent to the LCD
rs_value        ; The LCD rs line flag value
timer1            ; Used in delay routines
count            ; loop counter  (gets reused)
CounterA
CounterB
CounterC
CounterD
CounterE
flags
r1
r2
r3
t
ENDC            ; End of Data Block

CBLOCK    0x70
NumH
NumL
ENDC            ; End of Data Block
;
; *******************************************************************************
; * The 16F1827 resets to 0x00.                            *
; * The Interrupt vector is at 0x04.                        *
; *******************************************************************************
;
ORG    0x0000

ORG    0x0004
;
; *******************************************************************************
; *                                        *
; * Purpose:  This is the start of the program.                    *
; *                                        *
; *******************************************************************************
;
start
BANKSEL    PORTA
clrf    PORTA
clrf    PORTB

; Set PIC oscillator frequency
banksel    OSCCON        ; Select OSCCON
movlw    OSCCONVAL    ;
movwf    OSCCON        ; Loads the wanted value
banksel    PORTA

; Configures all I / O as digital
Banksel    ANSELA
bsf    ANSELA,ANSA2    ; set ra2 to analog
clrf    ANSELB

; Disable all wakeup pull-ups
Banksel    WPUA
clrf    WPUA
clrf    WPUB

BANKSEL    OPTION_REG
clrf    OPTION_REG    ;
;
movlw   b'00110111'    ; PORTA (RA0:2,4:5 inputs, RA3,6:7 outputs)
movwf   TRISA        ;
clrf    TRISB        ; Set port B to all outputs

movlw    b'11000000'    ; right justify, FOSC/4 vdd and vss vref

movlw    b'00001001'    ; select channel an2 & turn adc on

BANKSEL    PORTA;
call    init_LCD    ; Initialize the LCD
call    busy_check    ; Wait for LCD to finish initialising
call    display_version    ; Display title and version
;
; *******************************************************************************
; *                                        *
; * Purpose:      This is the Main Program Loop.                    *
; *                                        *
; *******************************************************************************
;
main
movlw    100
call    wait        ; acquisiton delay & loop delay

goto    $-1 ; no, test again movf ADRESH,w ; read upper 2 bits movwf NumH ; store in gpr space movf ADRESL,w ; read lower 8 bits movwf NumL ; store in gpr space movlb 0 call getValue call bin2BCD call show_bcd goto main ; Continue main loop ;-------------------------------------------------------------------------------- ; ADC scaling routine ;-------------------------------------------------------------------------------- getValue ;first do ADC-487 to discover direction bcf flags,0 ; clear the negative flag movlw high(center) subwf NumH,f movlw low(center) subwf NumL,f btfss STATUS,C decf NumH,f btfss NumH,7 ; is it negative goto notNeg ;need to negate acc bsf flags,0 ; set the negative flag movlw 0xff xorwf NumL,f xorwf NumH,f incf NumL,f btfsc STATUS,Z incf NumH,f notNeg ; 'flags' tells us if above or below center value ;-------------------------------------------------------------------------------- ; Multiply by 56 (multiplier is in register 't') ;-------------------------------------------------------------------------------- clrf r3 clrf r2 clrf r1 bsf r1,7 ; used to count to 8 movlw 56 ; value to multiply by movwf t mult_loop rrf t,f btfss STATUS,C goto noAdd movfw NumL addwf r2,f movfw NumH btfsc STATUS,C incfsz NumH,w ; w = w+1 addwf r3,f noAdd rrf r3,f rrf r2,f ; r2 is high byte of word rrf r1,f ; r1 is low byte of word btfss STATUS,C goto mult_loop ;-------------------------------------------------------------------------------- ; Divide by 10 (divisor is in 'w')- remainder is not calculated ;-------------------------------------------------------------------------------- movlw 16 movwf count movlw 10 ; keep divisor value in accumulator clrf r3 ; temporary register divide rlf r1,f ; shift next msb into temporary rlf r2,f rlf r3,f rlf count,f ; carry has 9th bit of temporary ; copy carry to counter subwf r3,f ; substract Y (in w) from temporary skpnc ; if no borrow, set Counter.0 bsf count,0 btfss count,0 ; if Counter.0 clear (borrow) restore temporary addwf r3,f clrc ; restore counter rrf count,f ;at this point carry is the next bit of result decfsz count,f ; repeat 16 times to find integer part goto divide rlf r1,f rlf r2,f movfw r2 movwf NumH movfw r1 movwf NumL return ; ; ******************************************************************************* ; * Takes number in NumH:NumL and returns decimal in TenK:Thou:Hund:Tens:Ones * ; * Fast 16-Bit Binary to Decimal by Peter Hemsley * ; * Input: 16-bit binary in NumH and NumL * ; * Output: Decimal (BCD) digits in TenK,Thou,Hund,Tens,Ones * ; * No temporary variables required * ; * Code size: 46 instructions * ; * Execution time: Variable, approx 150 to 170 cycles * ; ******************************************************************************* ; bin2BCD Bin2DecFast movf NumH,w ;Hex Digit 0X00 (H2) iorlw 0xF0 ;w=H2-16 movwf Ones ;Ones=H2-16 movwf Tens ;Tens=H2-16 addwf Tens,f ;Tens=H2*2-32 addwf Tens,f ;Tens=H2*3-48, C=1 movwf Hund ;Hund=H2-16 rlf Hund,f ;Hund=H2*2-31 swapf NumH,w ;Hex Digit X000 (H3) iorlw 0xF0 ;w=H3-16 addwf Hund,f ;Hund=H3+H2*2-47 Done! movwf Thou ;Thou=H3-16 addwf Thou,f ;Thou=H3*2-32 addlw D'52' ;w=H3+36 addwf Ones,f ;Ones=H3+H2+20 swapf NumL,w ;Hex Digit 00X0 (H1) iorlw 0xF0 ;w=H1-16 addwf Tens,f ;Tens=H2*3+H1-64 addwf Ones,f ;Ones=H3+H2+H1+4, C=1 rlf Ones,f ;Ones=(H3+H2+H1)*2+9, C=0 comf Ones,f ;Ones=-(H3+H2+H1)*2-10 rlf Ones,f ;Ones=-(H3+H2+H1)*4-20 movf NumL,w ;Hex Digit 000X (H0) andlw 0x0F ;w=H0 addwf Ones,f ;Ones=H0-(H3+H2+H1)*4-20 Done! rlf Tens,f ;C=0, Tens=H2*6+H1*2-128 Done! movlw D'7' movwf TenK ;TenK=7 addlw D'3' ;w=10, C=0 rlf Thou,f ;Thou=H3*4-64 Done! mod0 addwf Ones,f ;D(X)=D(X)mod10 decf Tens,f ;D(X+1)=D(X+1)+D(X)div10 skpc goto mod0 mod1 addwf Tens,f decf Hund,f skpc goto mod1 mod2 addwf Hund,f decf Thou,f skpc goto mod2 mod3 addwf Thou,f decf TenK,f skpc goto mod3 return ; ; ******************************************************************************* ; * Display data on the LCD. * ; ******************************************************************************* ; show_bcd movlw 0xC1 ; Point the LCD to digit location call cmnd2LCD ; Send digit location to LCD ; movf Thou,f ; Test if 'file'is 0 or 1 ; btfss STATUS,Z ; The Z or Zero bit is set to "1" when the result ; goto not_zero ; of an arithmetic or logical operation is zero ; ; movlw ' ' ; Thou = 0, insert space ; call data2LCD ; Send byte in W to LCD ; goto show_Hund movfw TenK ; Thou is not 0, insert number addlw 0x30 ; Convert to ASCII character call data2LCD ; Send to LCD - rinse and repeat until all characters sent not_zero movfw Thou ; Thou is not 0, insert number addlw 0x30 ; Convert to ASCII character call data2LCD ; Send to LCD - rinse and repeat until all characters sent show_Hund movfw Hund addlw 0x30 call data2LCD movfw Tens addlw 0x30 call data2LCD movfw Ones addlw 0x30 call data2LCD return ; ; ******************************************************************************* ; * * ; * Purpose: Send Command or Data byte to the LCD * ; * Entry point cmnd2LCD: Send a Command to the LCD * ; * Entry Point data2LCD: Send a Data byte to the LCD * ; * * ; * Input: W has the command or data byte to be sent to the LCD. * ; * * ; ******************************************************************************* ; cmnd2LCD ; ****** Entry point for commands ****** clrf rs_value ; Remember to clear RS (clear rs_value) goto write2LCD ; Go to common code data2LCD ; ****** Entry point for data ******** bsf rs_value,0 ; Remember to set RS (set bit 0 of rs_value) write2LCD movwf LCD_char ; Save byte to write to LCD call busy_check ; Check to see if LCD is ready for new data movlw 2 ; movwf count ; SET UP LOOP COUNTER write2LCD2 swapf LCD_char,f ; SWAP MS & LS NIBBLES movf LCD_char,w andlw 15 ; MAKE TOP 4 BITS OF W 0 movwf PORTB ; SEND MS NIBBLE bcf PORTB,LCD_rs ; Guess RS should be clear - command mode btfsc rs_value,0 ; Should RS be clear? (is bit 0 == 0?) bsf PORTB,LCD_rs ; No, set RS - data mode nop bsf PORTB,LCD_e ; SET E HIGH nop bcf PORTB,LCD_e ; SET E LOW decfsz count,F goto write2LCD2 ; GO BACK AND SEND LS NIBBLE return ; ; ******************************************************************************* ; * * ; * Purpose: Check if LCD is done with the last operation. * ; * This subroutine polls the LCD busy flag to determine if * ; * previous operations are completed. * ; * * ; ******************************************************************************* ; busy_check clrf PORTB ; Clear all outputs on PORTB banksel TRISB ; Switch to bank for Tris operation movlw b'00001000' ; Set RB3 input, others outputs movwf TRISB ; banksel PORTB bcf PORTB,LCD_rs ; Set up LCD for Read Busy Flag (RS = 0) nop bsf PORTB,LCD_rw ; Set up LCD for Read (RW = 1) LCD_is_busy bsf PORTB,LCD_e ; Set E high nop bcf PORTB,LCD_e ; Drop E again btfss PORTB,LCD_busy ; Is Busy Flag (RB3) clear? goto not_busy ; Yes - exit nop ; No nop ; Wait a while bsf PORTB,LCD_e ; Pulse E high (dummy read of lower nibble), nop ; wait, bcf PORTB,LCD_e ; and drop E again goto LCD_is_busy ; If not, it is busy so jump back not_busy banksel TRISB ; Switch to bank 1 for Tristate operation clrf TRISB ; All pins (RB7..RB0) are back to outputs banksel PORTB ; Switch to bank 0 clrf PORTB ; Clear all of Port B (inputs and outputs) return ; ; ; ; ******************************************************************************* ; * * ; * Purpose: Power on initialization of Liquid Crystal Display. The LCD * ; * controller chip must be equivalent to an Hitachi 44780. * ; * * ; ******************************************************************************* ; init_LCD movlw 100 call wait ; Wait for LCD to power up ; Put 4-bit command on RB3..RB0 ; PIC's RB3..RB0 lines connect to LCD's DB7..DB4 lines movlw 0x03 ; LCD init instruction (First) movwf PORTB ; Send to LCD via RB3..RB0 bsf PORTB,LCD_e ; Set the LCD E line high, movlw 100 call wait ; wait a "long" time, bcf PORTB,LCD_e ; and then Clear E movlw 0x03 ; LCD init instruction (Second) movwf PORTB ; Send to LCD via RB3..RB0 bsf PORTB,LCD_e ; Set E high, movlw 32 call wait ; wait a while, bcf PORTB,LCD_e ; and then Clear E movlw 0x03 ; LCD init instruction (Third) movwf PORTB ; Send to LCD via RB3..RB0 bsf PORTB,LCD_e ; Set E high, movlw 32 call wait ; wait a while, bcf PORTB,LCD_e ; and then Clear E movlw 0x02 ; 4-bit mode instruction movwf PORTB ; Send to LCD via RB3..RB0 bsf PORTB,LCD_e ; Set E high, movlw 16 call wait ; wait a while, bcf PORTB,LCD_e ; and then Clear E movlw 0x28 ; 1/16 duty cycle, 5x8 matrix call cmnd2LCD ; Send command in w to LCD movlw 0x08 ; Display off, cursor and blink off call cmnd2LCD ; Send command to LCD movlw 0x01 ; Clear and reset cursor call cmnd2LCD ; Send command in w to LCD movlw 0x06 ; Set cursor to move right, no shift call cmnd2LCD ; Send command in w to LCD movlw 0x0E ; Display on, cursor on and blink off ; movlw 0x0F ; Display on, cursor on and blink on ; movlw 0x0C ; Display on, cursor and blink off call cmnd2LCD ; Send command in w to LCD return ; ; ; ******************************************************************************* ; * * ; * Function: clear_lcd * ; * * ; * Purpose: Clears the LCD and homes the cursor. * ; * * ; ******************************************************************************* ; clear_lcd movlw 0x01 ; Prepare to display a new message on LCD call cmnd2LCD ; by clearing the current one return ; ; ******************************************************************************* ; * * ; * Purpose: Display version and other info on LCD for 1 second * ; * upon power-up * ; * * ; * Input: SIGN_ON_1 through SIGN_ON_16 * ; * * ; * Output: LCD displays info * ; * * ; ******************************************************************************* ; display_version call clear_lcd movlw SIGN_ON_1 ; digit 1 call data2LCD ; movlw SIGN_ON_2 ; digit 2 call data2LCD ; movlw SIGN_ON_3 ; digit 3 call data2LCD ; movlw SIGN_ON_4 ; digit 4 call data2LCD ; movlw SIGN_ON_5 ; digit 5 call data2LCD ; movlw SIGN_ON_6 ; digit 6 call data2LCD ; movlw SIGN_ON_7 ; digit 7 call data2LCD ; movlw SIGN_ON_8 ; digit 8 call data2LCD ; movlw SIGN_ON_9 ; digit 9 call data2LCD ; movlw SIGN_ON_10 ; digit 10 call data2LCD ; movlw SIGN_ON_11 ; digit 11 call data2LCD ; movlw SIGN_ON_12 ; digit 12 call data2LCD ; movlw SIGN_ON_13 ; digit 13 call data2LCD ; movlw SIGN_ON_14 ; digit 14 call data2LCD ; movlw SIGN_ON_15 ; digit 15 call data2LCD ; movlw SIGN_ON_16 ; digit 16 call data2LCD ; ; call wait_a_sec ; Wait one second nop ; for sim return ; ; ******************************************************************************* ; * * ; * Purpose: Delay routines * ; * * ; ******************************************************************************* ; wait_a_sec ;PIC Time Delay = 0.99999900 s with Osc = 4000000 Hz movlw D'6' movwf CounterC movlw D'19' movwf CounterB movlw D'172' movwf CounterA loop decfsz CounterA,f goto loop decfsz CounterB,f goto loop decfsz CounterC,f goto loop return wait_100us ;PIC Time Delay = 0.00009800 s with Osc = 4MHz movlw D'31' movwf CounterA loop2 decfsz CounterA,1 goto loop2 return wait ; Enter with 'w' holding number of times to execute 1mS delay routine movwf timer1 ; Set up counter call wait_1ms ; Go to wait loops decfsz timer1,f goto$-2
return

wait_1ms     ;PIC Time Delay = 0.00099800 s with Osc = 4MHz
movlw    D'2'
movwf    CounterD
movlw    D'74'
movwf    CounterE
loop1
decfsz    CounterE,f
goto    loop1
decfsz    CounterD,f
goto    loop1
return
;
END

#### augustinetez

##### Active Member
Further on the "Good news front", I finally managed to get some time on the workbench and tried Mike's table code (posts #24 & #28) in an actual PIC.

It works , thankyou Mike - I will actually use that in the project as it provides a better dead zone than the straight multiply/divide option I came up with.

#### Pommie

##### Well-Known Member
I intended to ask (at some time) if you had tried it in an actual pic.
Glad to hear it's now all working.
Wonder why the Oshonsoft simulator didn't like it?
It works fine in the MPLAB (NOT X) simulator.
BTW, if you want the spreadsheet (along with the VBA that produces the DW table), so you can tweek values, let me know.

Mike.

#### augustinetez

##### Active Member

Re Oshonsoft sim, there are quite a few things it doesn't understand or can't decipher properly (like programs longer than 2048 words), really needs a massive overhaul to make it more useful.

#### Pommie

##### Well-Known Member
Attached is the excel spreadsheet that produces the DW table. It's a txt file as the board won't allow xls files (and definitely not xlsm files), rename to a .xlsm file and the macro builtIt produces the table in the immediate window.
It does have a spurious comma at the end of the data but just delete it.
I think it's self explanatory but any questions just ask.

Mike.
P.S. Alt-F11 will activate the VB window to see the code.
Edit, I'm using excel 2013 so anything after 2007 should work.

#### Attachments

33.8 KB · Views: 60
Last edited:

Replies
11
Views
858
Replies
14
Views
936
Replies
12
Views
1K
Replies
4
Views
2K
Replies
5
Views
1K