Conversor AD PIC 18F2550

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Conversor AD PIC 18F2550

Mensagempor douglaslps » 20 Jul 2009 23:23

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
douglaslps
Bit
 
Mensagens: 7
Registrado em: 02 Jul 2008 14:22

Mensagempor fabim » 21 Jul 2009 08:42

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);
}
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor douglaslps » 21 Jul 2009 08:47

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.
douglaslps
Bit
 
Mensagens: 7
Registrado em: 02 Jul 2008 14:22

Mensagempor douglaslps » 22 Jul 2009 19:25

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.
douglaslps
Bit
 
Mensagens: 7
Registrado em: 02 Jul 2008 14:22

Mensagempor fabim » 22 Jul 2009 20:49

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..
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor douglaslps » 22 Jul 2009 20:59

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.
douglaslps
Bit
 
Mensagens: 7
Registrado em: 02 Jul 2008 14:22

Mensagempor fabim » 23 Jul 2009 08:19

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
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor douglaslps » 23 Jul 2009 08:44

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
douglaslps
Bit
 
Mensagens: 7
Registrado em: 02 Jul 2008 14:22

Mensagempor douglaslps » 25 Jul 2009 00:41

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>
douglaslps
Bit
 
Mensagens: 7
Registrado em: 02 Jul 2008 14:22


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Google [Bot] e 1 visitante

cron

x