Estou usando o kit EasyPic4. Configurei o kit corretamente e obtive algumas surpresas desagradáveis.
O aplicativo transmite uma string pela serial com 9 bytes (IN000000\r). \r é o retorno do carro.
O firmware transmite o valor da conversão via UART assíncrona, 8 bits de dados e 1 de stop. O CAD está configurado para 10 bits, com justificativa à direita.
O PIC é o 16F873A e o cristal é de 20MHz.
A linguagem é assembly.
O PIC identifica a string recebida do aplicativo, portanto a recepção pela UART está ok.
Como o valor da conversão estava aparecendo errado no aplicativo, comecei a pesquisar.
Isolei o CAD e entrei com outros dois registros, como suposto resultado da conversão. Chamei de BinH e BinL. Fiz estes registros variarem de 0 a 1023 em sequência crescente e estabelecendo um loop. A justificativa ficou à direita também. Igual ao CAD.
Converti o valor binário dos dois bytes em 5 bytes BCD, dos quais apenas 4 são utilizados (milhar, centena, dezena e unidade). Converti os bytes de BCD para ASCII e enviei para o transmissor da UART. O aplicativo mostrou todos os 1024 possíveis valores corretamente.
Isso prova que o erro está no CAD. Depois de inúmeras verificadas, juntamente com o manual do PIC, na rotina de configuração do CAD (AD_Config) e na rotina de conversão (AD_Converte), não encontrei erro algum. Aliás, já tinha usado estas rotinas antes, apenas com 8 bits e não 10.
O resultado da conversão sempre fornecia o registro menos significativo do CAD (ADRESL) com zero. Apenas os dois bits do registro mais significativo (ADRESH) funcionavam corretamente. Os 4 valores obtidos, ao se variar o potenciômetro, eram 0000, 0256, 0512 e 0768.
Primeiramente comecei a desconfiar do PIC. Troquei por outro e o byte menos significativo do CAD (ADRESL) passou a fornecer 4 constante. Os valores passaram para 0004, 0260, 0516 e 0772.
Isso certamente não poderia ocorrer. Mudar o PIC e obter resultados diferentes.

Apesar de grande parte do firmware estar funcionando corretamente (UART e lógicas), o CAD não estava.
Comecei a ler os capítulos do manual que elegi como possíveis candidatos ao problema.
Ao ler sobre a frequência máxima do cristal, encontrei 16MHz para os PICs comuns e 20MHz para os industriais. O meu é o comum.

PQP. Finalmente vislumbrei uma possibilidade de encontrar o problema.

Mudei o cristal para 10MHz e a configuração da UART.
O firmware apresentou o mesmo problema!!!

Seguem as rotinas principais que têm a ver com o problema:
- Código: Selecionar todos
; ******************************************************************************************************************
; Portas @
bsf banco
bcf STATUS,RP1
movlw b'10001011'
movwf TRISA ; Porta A.
movlw b'00000000'
movwf TRISB ; Porta B.
movlw b'10000000' ; RC7 como Rx da UART (entrada).
movwf TRISC ; Porta C.
bcf banco
...
; *******************************************************************************************************************
; Rotina AD_Config. Já incorpora as variáveis do CAD.
AD_Config:
; Configure as entradas analógicas como entradas no registro TRISA.
bsf banco ; Banco 1.
bsf TRISA,0 ; A0 é entrada.
bcf banco ; Banco 0.
; Configure o registro ADCON1 no banco 1.
; Neste ponto deve ser conhecida a sua opção de acordo com o seu sistema. Há 15 opções diferentes. Verifique no
; quadro “Register 11-2” na página 128 do manual PIC16F877A, qual a opção desejada. As opções são configuradas
; por meio dos bits 3, 2, 1 e 0 do registro ADCON1. Aqui será considerada a opção 1110, ou seja, apenas uma
; entrada analógica (AN0). A tensão de referência VRef conectada ao Vdd. (O Vdd não possui precisão).
; O tempo total para uma conversão é igual ao tempo de aquisição mais o tempo de conversão. Tmín >= TAcq + TConv
; Tmín >= 19,7us + 1,6us * FXtal >= 19,7us + 1,6us + 20e6 >= 32. NFOsc >= 32 -> NFOsc = 32.
bsf banco ; Banco 1.
movlw b'10001110' ; Resultado justificado à direita (10 bits), FOSC / 32, modo 14, apenas AN0 é entrada.
movwf ADCON1 ; analógica. VRef = Vdd.Todos os pinos restantes deixados como digitais.
bcf banco ; Banco 0.
; Configure o registro ADCON0 no banco 0.
movlw b'10000000' ; FOSC / 32, conectado o canal 0 (AN0), CAD não atuando (DONE) e
movwf ADCON0 ; desenergizado.
return
; *******************************************************************************************************************************************
; Rotina AD_Converte
AD_Converte:
; Pode-se aguardar o término da rotina AD_Converte, monitorando-se a bandeira de fim da conversão.
; bsf ADCON0,ADON ; Energize o módulo do CAD (ADCON0,ADON = 1). Neste caso a energização é externa à rotina.
btfsc ADCON0,GO ; Há conversão em curso? Aguarda o fim de conversão.
goto $-1
call T20us ; Aguarda pelo tempo de aquisição (Taq >= 19,7µs)
bsf ADCON0,GO ; Inicia a conversão. ADCON0, GO/DONEbarra = 1
btfsc ADCON0,GO ; Aguarda pelo término da conversão. Espera que ADCON0,GO = 0. As interrupções do CAD estão
goto $-1 ; desabilitadas. Aguarda o fim de conversão.
; bcf ADCON0,ADON ; Desenergize o módulo do CAD (ADCON0,ADON = 0). Neste caso a desenergização é externa à
return
Bom!
Cheguei no meu limite.

Talvez eu esteja passando pelo erro e não esteja enxergando.
Se alguém, que também use a linguagem assembly puder ajudar, ficarei grato.
[]'s
MOR_AL