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:
Code: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:
Code: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?


		
		

Bookmarks