Página 1 de 1

Conversor AD PIC 18F2550

MensagemEnviado: 20 Jul 2009 23:23
por douglaslps
Olá amigos,

estou arriscando alguns testes com um PIC que tenho, porém, tenho tido alguns problemas com conceitos básicos como o conversor AD. Utilizo o mikroC.

Vou tentar resumir a história:

- 1° teste: Preparar a conversão manualmente, aguardar a conversão e utilizar os valores lidos utilizando potenciômetro em AN0 (Resultado: Funciona)

Código: Selecionar todos
void main()
org 0x800
{
    unsigned int valor ;

    // INIT ADC
    // AN0..AN2 analógicas[RA0..RA2]; VDD e VSS é ref de tensão - são 5V da alimentação
    ADCON1 = 0b00001100; 

    // selecciona TAD=64TOSC; tempo sampling =12TAD; formato resultado right justified
    ADCON2 = 0b10101110;

    // enable converter module
    ADCON0.ADON = 1;

    TRISA = 0x03;         // RA0..RA2 são input
    TRISB = 0x00;

    while(1)
    {
            ADCON0.CHS3 = 0; ADCON0.CHS2 = 0; ADCON0.CHS1 = 0; ADCON0.CHS0 = 0; // selecciona input AN0
            // 0000 - AN0; 0001 - AN1; 0010 - AN2
            ADCON0.GO_DONE=1;//   dá inicio à conversão
            while(ADCON0.GO_DONE) continue; //  aguarda fim da conversão
            PIR1.ADIF=0;
            valor=ADRESH*256+ADRESL; //  0.... 1023

            if (valor < 45)
            {
              PORTA.RA4 = 0;        // Turn OFF LEDs on PORTA
              PORTA.RA5 = 0;        // Turn OFF LEDs on PORTA
            }
            else
            {
              PORTA.RA4 = 1;        // Turn ON LEDs on PORTA
              PORTA.RA5 = 1;        // Turn ON LEDs on PORTA
            }
     }
}


- 2° teste: Preparar a conversão manualmente, aguardar a conversão e utilizar os valores lidos utilizando LM35 em AN1 (Resultado: NÃO Funciona)

Praticamente o mesmo código, somente alterando o input na primeira linha dentro do while:

Código: Selecionar todos
ADCON0.CHS3 = 0; ADCON0.CHS2 = 0; ADCON0.CHS1 = 0; ADCON0.CHS0 = 1; // selecciona input AN1


Estou conectando o a saída do sensor LM35 direto na entrada AN1 do PIC 18F2550, isso pode ser um problema?

Espero ter sido claro.
Aguardo qualquer sugestão.
Obrigado desde já.
Atenciosamente,
Douglas

MensagemEnviado: 21 Jul 2009 08:42
por fabim
unsigned int pega_adc(unsigned char canal_ad)
{
unsigned short temp;
unsigned int resultado;

temp = ADCON0 & 0b11000101;
ADCON0 = temp | ((canal_ad << 3) & 0b00111000);
Delay_Us(20);
ADCON0.GO_DONE = 1;
_asm nop;
while (ADCON0.GO_DONE);
((short *)&resultado)[1] = ADRESH;
((short *)&resultado)[0] = ADRESL;
return(resultado);
}

MensagemEnviado: 21 Jul 2009 08:47
por douglaslps
Obrigado Fabim, vou testar a noite e posto o resultado aqui.

Alguém sabe me dizer se posso utilizar a função Read_ADC() no lugar? Tentei substitur meu código por essa função, porém, o caso que funcionava parou de funcionar.

Obrigado pela atençao.

MensagemEnviado: 22 Jul 2009 19:25
por douglaslps
Olá,

acabei de fazer o teste. Infelizmente não funcionou. Veja como ficou meu código. Espero não ter feito nada errado:

Código: Selecionar todos
unsigned int pega_adc(unsigned char canal_ad)
{
unsigned short temp;
unsigned int resultado;

temp = ADCON0 & 0b11000101;
ADCON0 = temp | ((canal_ad << 3) & 0b00111000);
Delay_Us(20);
ADCON0.GO_DONE = 1;
_asm nop;
while (ADCON0.GO_DONE);
((short *)&resultado)[1] = ADRESH;
((short *)&resultado)[0] = ADRESL;
return(resultado);
}

void main()
org 0x800
{
    unsigned int valor ;
    unsigned int temp;

    // INIT ADC
    // AN0..AN2 analógicas[RA0..RA2]; VDD e VSS é ref de tensão - são 5V da alimentação
    ADCON1 = 0b00001100;

    // selecciona TAD=64TOSC; tempo sampling =12TAD; formato resultado right justified
    ADCON2 = 0b10101110;

    // enable converter module
    ADCON0.ADON = 1;

    TRISA = 0x03;         // RA0..RA2 são input
    TRISB = 0x00;

    while(1)
    {
            valor=pega_adc(0);

            if (valor < 45)
            {
              PORTA.RA4 = 0;        // Turn OFF LEDs on PORTA
              PORTA.RA5 = 0;        // Turn OFF LEDs on PORTA
            }
            else
            {
              PORTA.RA4 = 1;        // Turn ON LEDs on PORTA
              PORTA.RA5 = 1;        // Turn ON LEDs on PORTA
            }
     }
}


Aguardo comentários,
Obrigado.

MensagemEnviado: 22 Jul 2009 20:49
por fabim
unsigned int pega_adc(unsigned char canal_ad)
{
unsigned short temp;
unsigned int resultado;

temp = ADCON0 & 0b00000001;
ADCON0 = temp | ((canal_ad << 2) & 0b00111100);
ADCON0.GO_DONE = 1;
while (ADCON0.GO_DONE);
((short *)&resultado)[1] = ADRESH;
((short *)&resultado)[0] = ADRESL;
return(resultado);
}

void main( void ) {
unsigned int valor, temp ;


ADCON1 = 0b00001100;

ADCON2 = 0b10111110;

ADCON0.ADON = 1;

CMCON = 0x07;

TRISA = 0b00000111; // RA0..RA2 são input
TRISB = 0x00;

while(1)
{
valor=pega_adc();

if (valor < 45)
{
LATA.F4 = 0; // Turn OFF LEDs on PORTA
LATA.F4 = 0; // Turn OFF LEDs on PORTA
}
else
{
LATA.F5 = 1; // Turn ON LEDs on PORTA
LATA.F5 = 1; // Turn ON LEDs on PORTA
}
delay_ms(500)
}
}


testado, e funcionando perfeitamente..

MensagemEnviado: 22 Jul 2009 20:59
por douglaslps
Fabim.

muito obrigado pela ajuda. Acredito que seu código funcione mesmo.
Acho que descobri o problema.
Minha PIC está protegida contra gravação do endereço 0 ao 0x800 (onde está o bootloader).
Portanto todo meu código deve estar depois disso. O problema é que quando eu crio uma nova função ela insiste em ir para o começo da memória. Observe que eu forço o meu main() no endereço 0x800.

Você sabe uma forma de eu indicar para o compilador que o código deve estar depois do endereço 0x800 sem ter que colocar em cada função o endereço de início?

Obrigado.

MensagemEnviado: 23 Jul 2009 08:19
por fabim
cara muito estranho esse boot.
99% dos boot ficam nos 128..256 bytes finais do uC, e não de 0 a 800!! :shock:
Isso não é um boot é um bootão!!rs

zóia, qual compilador que tu esta utilizando ?

Fabim

MensagemEnviado: 23 Jul 2009 08:44
por douglaslps
Deve ser um bootão mesmo :)

Estou utilizando o MikroC. Ontem a noite fiz uma busca rápida pra ver se resolvia o problema, mas só encontrei soluções para versões antigas do MikroC.

Você sabe me indicar como faço para o código iniciar depois do 0x800 no mikroC?

Obrigado novamente,
Douglas

MensagemEnviado: 25 Jul 2009 00:41
por douglaslps
Fabim,

gostaria de agradecer mais uma vez. O código que você me passou funcionou perfeitamente.

Pessoal,

para fixar o início de origem do seu código e assim, não sobrescrever o bootloader, utilize a seguinte instrução na primeira linha do seu código fonte:

#pragma orgall "endereço inicial do seu programa"

No meu caso:

#pragma orgall 0x800

Resolvido. <Créditos para o Fabim>