mpgmike
- 13th May 2018, 15:26
I am trying to use an all new PIC16F18426 for a personal project. I built a bench power supply, but the resolution on the LCD readout for Volts & Amps needed more resolution. The PIC16F18426 offers 12-bit ADC. However, since PBP3 cannot yet work with this new PIC, I'm trying my hand at ASM with MPLABX.
The challenge I'm facing in the software is converting the ADC values to decimal and isolating the digits to print to the LCD. The Basic code works like a charm on a PIC16F1824:
Get_Ch1: ;Get Channel 1 Values
ADCON0 = 000011 ;AN0, Volt1
DO
LOOP WHILE ADCON0.1 = 1
V1.HIGHBYTE = ADRESH
V1.LOWBYTE = ADRESL
ADCON0 = 000111 ;AN1, Amp1
DO
LOOP WHILE ADCON0.1 = 1
A1.HIGHBYTE = ADRESH
A1.LOWBYTE = ADRESL
IF (V1 = V1p) AND (A1 = A1p) THEN
RETURN
ENDIF
Volt1 = ((V1 + V1p) * 10) / 53
GOSUB Print_V1
V1p = V1
IF (A1 + A1p) > (V1 + V1p) THEN
Amp1 = (A1 + A1p) - (V1 + V1p)
ELSE
Amp1 = 0
ENDIF
GOSUB Print_A1
A1p = A1
RETURN
Print_A1: ;Amp1 Changed, Send to LCD, Line 2
RS = 0
LCD = $C0
GOSUB Send
RS = 1
pause 1
for b0 = 0 to 7
lookup b0, ["1-Amps: "], b1
LCD = b1
gosub Send
next b0
ARRAYWRITE Amp1a, [#Amp1]
IF Amp1 < 100 THEN
Amp1a[2] = Amp1a[1]
Amp1a[1] = Amp1a[0]
Amp1a[0] = " "
ENDIF
IF Amp1 < 10 THEN
Amp1a[2] = Amp1a[1]
Amp1a[1] = " "
Amp1a[0] = " "
ENDIF
FOR b0 = 0 TO 2
LCD = Amp1a[b0]
GOSUB Send
NEXT b0
FOR b0 = 0 TO 3
LOOKUP b0, [" mA "], b1
LCD = b1
GOSUB Send
NEXT b0
RETURN
The Assembly Code generated for Print_A1 is as follows:
Print_A1: ;Amp1 Changed, Send to LCD, Line 2
LABEL?L _Print_A1
MOVE?CT 000h, _RS ;RS = 0
MOVE?CB 0C0h, _LCD ;LCD = $C0
GOSUB?L _Send ;GOSUB Send
MOVE?CT 001h, _RS ;RS = 1
PAUSE?C 001h ;pause 1
MOVE?CB 000h, _b0 ;for b0 = 0 to 7
LABEL?L L00031
CMPGT?BCL _b0, 007h, L00032
LOOKUP?BCLB _b0, 008h, L00001, _b1 ;lookup b0, ["1-Amps: "], b1
LURET?C 031h
LURET?C 02Dh
LURET?C 041h
LURET?C 06Dh
LURET?C 070h
LURET?C 073h
LURET?C 03Ah
LURET?C 020h
LABEL?L L00001
MOVE?BB _b1, _LCD ;LCD = b1
GOSUB?L _Send ;gosub Send
NEXT?BCL _b0, 001h, L00031 ;next b0
LABEL?L L00032
ARRAYWRITENAME?B _Amp1a ;ARRAYWRITE Amp1a, [#Amp1]
ARRAYWRITECOUNT?C 000h
ARRAYWRITENUM?W _Amp1
ARRAYWRITEDEC?
CMPGE?WCL _Amp1, 064h, L00033 ;IF Amp1 < 100 THEN
MOVE?BB _Amp1a + 00001h, _Amp1a + 00002h ;Amp1a[2] = Amp1a[1]
MOVE?BB _Amp1a, _Amp1a + 00001h ;Amp1a[1] = Amp1a[0]
MOVE?CB 020h, _Amp1a ;Amp1a[0] = " "
LABEL?L L00033 ;ENDIF
CMPGE?WCL _Amp1, 00Ah, L00035 ;IF Amp1 < 10 THEN
MOVE?BB _Amp1a + 00001h, _Amp1a + 00002h Amp1a[2] = Amp1a[1]
MOVE?CB 020h, _Amp1a + 00001h ;Amp1a[1] = " "
MOVE?CB 020h, _Amp1a ;Amp1a[0] = " "
LABEL?L L00035 ;ENDIF
MOVE?CB 000h, _b0 ;FOR b0 = 0 TO 2
LABEL?L L00037
CMPGT?BCL _b0, 002h, L00038
AOUT?BBB _Amp1a, _b0, _LCD ;LCD = Amp1a[b0]
GOSUB?L _Send ;GOSUB Send
NEXT?BCL _b0, 001h, L00037 ;NEXT b0
LABEL?L L00038 ;FOR b0 = 0 TO 3
MOVE?CB 000h, _b0
LABEL?L L00039
CMPGT?BCL _b0, 003h, L00040
LOOKUP?BCLB _b0, 004h, L00002, _b1 ;LOOKUP b0, [" mA "], b1
LURET?C 020h
LURET?C 06Dh
LURET?C 041h
LURET?C 020h
LABEL?L L00002
MOVE?BB _b1, _LCD ;LCD = b1
GOSUB?L _Send ;GOSUB Send
NEXT?BCL _b0, 001h, L00039 ;NEXT b0
LABEL?L L00040
RETURN? ;RETURN
I tried copy/pasting the above code into MPLABX & pretty much all of it generated errors. I've tried numerous approaches but none have worked. Any ideas how to isolate decimal digits (1000s, 100s, 10s, 1s) from a larger value?
The challenge I'm facing in the software is converting the ADC values to decimal and isolating the digits to print to the LCD. The Basic code works like a charm on a PIC16F1824:
Get_Ch1: ;Get Channel 1 Values
ADCON0 = 000011 ;AN0, Volt1
DO
LOOP WHILE ADCON0.1 = 1
V1.HIGHBYTE = ADRESH
V1.LOWBYTE = ADRESL
ADCON0 = 000111 ;AN1, Amp1
DO
LOOP WHILE ADCON0.1 = 1
A1.HIGHBYTE = ADRESH
A1.LOWBYTE = ADRESL
IF (V1 = V1p) AND (A1 = A1p) THEN
RETURN
ENDIF
Volt1 = ((V1 + V1p) * 10) / 53
GOSUB Print_V1
V1p = V1
IF (A1 + A1p) > (V1 + V1p) THEN
Amp1 = (A1 + A1p) - (V1 + V1p)
ELSE
Amp1 = 0
ENDIF
GOSUB Print_A1
A1p = A1
RETURN
Print_A1: ;Amp1 Changed, Send to LCD, Line 2
RS = 0
LCD = $C0
GOSUB Send
RS = 1
pause 1
for b0 = 0 to 7
lookup b0, ["1-Amps: "], b1
LCD = b1
gosub Send
next b0
ARRAYWRITE Amp1a, [#Amp1]
IF Amp1 < 100 THEN
Amp1a[2] = Amp1a[1]
Amp1a[1] = Amp1a[0]
Amp1a[0] = " "
ENDIF
IF Amp1 < 10 THEN
Amp1a[2] = Amp1a[1]
Amp1a[1] = " "
Amp1a[0] = " "
ENDIF
FOR b0 = 0 TO 2
LCD = Amp1a[b0]
GOSUB Send
NEXT b0
FOR b0 = 0 TO 3
LOOKUP b0, [" mA "], b1
LCD = b1
GOSUB Send
NEXT b0
RETURN
The Assembly Code generated for Print_A1 is as follows:
Print_A1: ;Amp1 Changed, Send to LCD, Line 2
LABEL?L _Print_A1
MOVE?CT 000h, _RS ;RS = 0
MOVE?CB 0C0h, _LCD ;LCD = $C0
GOSUB?L _Send ;GOSUB Send
MOVE?CT 001h, _RS ;RS = 1
PAUSE?C 001h ;pause 1
MOVE?CB 000h, _b0 ;for b0 = 0 to 7
LABEL?L L00031
CMPGT?BCL _b0, 007h, L00032
LOOKUP?BCLB _b0, 008h, L00001, _b1 ;lookup b0, ["1-Amps: "], b1
LURET?C 031h
LURET?C 02Dh
LURET?C 041h
LURET?C 06Dh
LURET?C 070h
LURET?C 073h
LURET?C 03Ah
LURET?C 020h
LABEL?L L00001
MOVE?BB _b1, _LCD ;LCD = b1
GOSUB?L _Send ;gosub Send
NEXT?BCL _b0, 001h, L00031 ;next b0
LABEL?L L00032
ARRAYWRITENAME?B _Amp1a ;ARRAYWRITE Amp1a, [#Amp1]
ARRAYWRITECOUNT?C 000h
ARRAYWRITENUM?W _Amp1
ARRAYWRITEDEC?
CMPGE?WCL _Amp1, 064h, L00033 ;IF Amp1 < 100 THEN
MOVE?BB _Amp1a + 00001h, _Amp1a + 00002h ;Amp1a[2] = Amp1a[1]
MOVE?BB _Amp1a, _Amp1a + 00001h ;Amp1a[1] = Amp1a[0]
MOVE?CB 020h, _Amp1a ;Amp1a[0] = " "
LABEL?L L00033 ;ENDIF
CMPGE?WCL _Amp1, 00Ah, L00035 ;IF Amp1 < 10 THEN
MOVE?BB _Amp1a + 00001h, _Amp1a + 00002h Amp1a[2] = Amp1a[1]
MOVE?CB 020h, _Amp1a + 00001h ;Amp1a[1] = " "
MOVE?CB 020h, _Amp1a ;Amp1a[0] = " "
LABEL?L L00035 ;ENDIF
MOVE?CB 000h, _b0 ;FOR b0 = 0 TO 2
LABEL?L L00037
CMPGT?BCL _b0, 002h, L00038
AOUT?BBB _Amp1a, _b0, _LCD ;LCD = Amp1a[b0]
GOSUB?L _Send ;GOSUB Send
NEXT?BCL _b0, 001h, L00037 ;NEXT b0
LABEL?L L00038 ;FOR b0 = 0 TO 3
MOVE?CB 000h, _b0
LABEL?L L00039
CMPGT?BCL _b0, 003h, L00040
LOOKUP?BCLB _b0, 004h, L00002, _b1 ;LOOKUP b0, [" mA "], b1
LURET?C 020h
LURET?C 06Dh
LURET?C 041h
LURET?C 020h
LABEL?L L00002
MOVE?BB _b1, _LCD ;LCD = b1
GOSUB?L _Send ;GOSUB Send
NEXT?BCL _b0, 001h, L00039 ;NEXT b0
LABEL?L L00040
RETURN? ;RETURN
I tried copy/pasting the above code into MPLABX & pretty much all of it generated errors. I've tried numerous approaches but none have worked. Any ideas how to isolate decimal digits (1000s, 100s, 10s, 1s) from a larger value?