You have datasheet for that chip here:
https://ww1.microchip.com/downloads/en/DeviceDoc/PIC16(L)F18855-75-Data-Sheet-40001802H.pdfThe microcontroller has a built in voltage reference, which can be set to 1.024 , 2.048v , 4.096v
If you can afford to, set it to 4.096v and then your 10 bit ADC readings will give you 4mV per step ...
Look into staying away from floating point, the compiler has to add floating point stuff to your code because the controller doesn't have built in hardware floating point stuff.
So... don't use delay_ms 10 in your adc_read... just use a loop until it's not busy or something like that.
see 17.4 in your datasheet ... you need at least 200uS for a reading, then 200uS between consecutive readings... no need for 10ms
See 23.0 and 23.1 and 23.2 in datasheet for adc configuration ... you could set the adgo to 1 and then do something like while .adgo==1 asm("nop")
You can be smarter and figure out how much time each instruction would use and basically do a timeout.
For example each instruction uses 1 or more cycles, where a cycle is 4 Hz ... so at 32 Mhz that would be 8,000,000 cycles in a second or 8000 cycles in a ms, or 8 cycles in a uS ... if you want to timeout in 240uS, it would be enough to spend 8 x 240 cycles doing something.
See section 36 in datasheet ... you can see there decfsz uses 1 cycle or 2 if condition is met (it's used in while until value is 0) , goto uses 2 cycles so you could do something like
unsigned char n = 240;
do {
asm("goto $+1"); asm("goto $+1"); asm("nop");
// decrease if not zero - decfsz (1 cycle if !=0, 2 cycles otherwise)
// goto loop start = 2 cycles
} while(--n);
/// so that's 5 cycles for the goto commands + nop, plus 2 for the goto start , plus one for the decrement = 8 cycles and that gets repeated 240 times... you have your 240 x 8 cycles.
you could add in the do loop something like if (xxx.ADGO ==0) n=0; to exit loop as soon as done, or after 240 loops otherwise .... that would be a comparison and an assignment so you can calculate the cycles (it's probably 3 or 4 cycles but you can view the assembly code and see what instructions the compiler puts there and count the cycles based on instructions chosen by compiler.
Going back to the voltage reading... like I said... keep it in mV as much as possible.
And you could probably choose those resistor values better if you can, or just not use floating point, multiply everything by 10 for example
Your values : 982, 248.2 : 0.7982 My values : 9820 , 2482 : 9820 / 12302 keep it like this, don't even bother defining a float ratio value.
So let's say the ADC gives you 852 as a measurement ... that's 3408mV if you use a voltage reference of 4.096v
You can now do 3408 x 9820 / 12302 = 2720.416 and just round it to 2720 mV and print 2.720V on screen.
If possible, you could try tweaking your ratios to be multiples of 2 and then you can keep it integer and just shift bits...
For example, you can rewrite 9820 / 12302 as 817.447 / 1024 or 81744 / 102400 because 12302 = 12.013 x 1024
So now your measurement can be 3408 x 816.447 / 1024 = 3408 x 816447 / 1024 / 1000 = (2,782,451,376 >> 10 ) / 1000 = 2,717,237 / 1000 = 2717 mV ( 3mV error, close enough)
Same for your second cell ... 663 and 248.3 ... gives you 663 / 911.3 = rewrite it as 6640/9113 or as 745 / 1024 ( so you can shift 10 bits and be done with it)
and so on...
--
sprintf also adds up a lot of code. If you keep your voltage in mV all the way to the end, then it's just a matter of adding a dot before the last 3 digits.