Ir ao conteúdo
  • Cadastre-se
poseidon22

Comportamento estranho da função delay!

Recommended Posts

Boa tarde amigos!

 

Recentemente eu comecei a usar a linguagem C para programar microcontroladores PIC. Estou utilizando o mplabX 3.40 junto com o compilador xc8 v1.38, ambos são as versões mais atualizadas desses programas! O código abaixo é para fazer um led blinking.

 

O problema é que a função "__delay_ms()" deveria fazer o uC esperar por "x" milissegundos, tal que 0 <= x <= 192, e no meu caso ela está fazendo o uC ficar um tempo muito superior a isso.

Repare que passando o valor 5 como argumento da função o meu led oscila aproximadamente em 1 segundo. Eu quero entender esse "bug" ,mas está difícil...

Eu já li o manual do compilador e vi que esse calculo é feito com base no #define do _XTAL_FREQ.

Eu já testei outras formas de delay como o "_delay()" que é equivalente ao NOP(); e em todos esses casos o delay é muito maior que o tempo que deveria ser

 

obs: Estou utilizando o pic18f1220, oscilador interno. 

 

#include <xc.h>
#define _XTAL_FREQ 4000000

void main(void) {
    TRISBbits.RB7 = 0x00;
    PORTBbits.RB7 = 0x00;
    while(1){
        
       PORTBbits.RB7 = !PORTBbits.RB7; // inverte rb7
       __delay_ms(5); 
    }
}

 

Editado por poseidon22
inclusão de tags

Compartilhar este post


Link para o post
Compartilhar em outros sites

Esse código está completo?

 

Digo isso porque estão faltando os fuses e declarar, para o programa, qual o PIC que tu está usando.

Nos fuses tu declara qual tipo de oscilador que está usando (interno, externo, HS, etc) e várias outras "configurações iniciais".

Abs.

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá amigo!

Segue o código completo! Implicitamente o mplabx ja faz o "include" de pic utilizado. Estou utilizando o oscilador interno de 4mhz do pic

 

// PIC18F1220 Configuration Bit Settings

// CONFIG1H
#pragma config OSC = INTIO2     // Oscillator Selection bits (Internal RC oscillator, port function on RA6 and port function on RA7)
#pragma config FSCM = ON        // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode enabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = ON         // Brown-out Reset Enable bit (Brown-out Reset enabled)
// BORV = No Setting

// CONFIG2H
#pragma config WDT = ON         // Watchdog Timer Enable bit (WDT enabled)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled, RA5 input pin disabled)

// CONFIG4L
#pragma config STVR = ON        // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Low-Voltage ICSP Enable bit (Low-Voltage ICSP enabled)

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (00200-0007FFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (000800-000FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (00200-0007FFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (000800-000FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (00200-0007FFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (000800-000FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from table reads executed in other blocks)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>
#define _XTAL_FREQ 4000000

void main(void) {
    TRISBbits.RB7 = 0x00;
    PORTBbits.RB7 = 0x00;
    while(1){
        
       PORTBbits.RB7 = !PORTBbits.RB7; // inverte rb7
       __delay_ms(5); 
    }
}

Eu estou baixando um versão mais antiga do compilador para ver se resolver meu problema

 

Edit: Acabei de testar com a versão 1.35 do compilador xc8 e o problema persiste :(

Editado por poseidon22

Compartilhar este post


Link para o post
Compartilhar em outros sites

ok

 

-mplab

-rode passo a passo inicialmente pra você sentir algo das entranhas do pic

-ache a função _delay e coloque um break point no começo e final dela com 5 ms como argumento

-mande rodar

-verifique quantos ciclos de máquina ocorreram e calcule se o tempo foi 5ms

-Também pode usar o logic analizer (ou algo assim) e verificar os pulsos do seu port

 

Mais opções:

 

-Crie seu próprio delay algo como

void delay(unsigned int d) //coloque um valor qualquer...

{

while (d--); //e verifique o tempo desta iteração com a técnica citada acima

}

-Use os timer´s

 

de nada...

adicionado 12 minutos depois

Ah sim, se for problema no hw, como pino de reset aberto, falha na alimentação, etc, receba um cascudo virtual.

Também observe o watch dog

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá amigo. Eu uso o mplabx também e eu sempre declaro qual o pic que estou usando no código.

Uso os fuses que ele gera só pra ter uma referência, mas geralmente eu que escrevo tudo.

Experimente fazer dessa rdem:

 

#include <pic18f1220.h>

#include <xc.h>

 

#pragma config

#pragma config  // aqui você coloca os fuses

#pragma config

 

#define _XTAL_FREQ 4000000

 

Já passei por esse tipo de problema e era essa ordem que me atrapalhava.

 

Outra coisa: Se não funcionar, tenta substituir a linha #define _XTAL_FREQ 4000000 por: 

 

OSCCONbits.IRCF2 = 1;

OSCCONbits.IRCF1 = 1;

OSCCONbits.IRCF0 = 0;

 

Isso faz tu configurar direto no registrador do oscilador interno para 4MHZ. 

Dá uma olhada no diagrama em blocos desse pic: Temq ue fazer configuração de postscaler do oscilador interno.

Diagrama-blocos-oscilador-696x761.jpg

Tu tem que configurar o postscaler. 

Não consegui ver a fundo porque estou na correria. Mas tente fazer com oscilador externo e ver se funciona, é uma opção.

 

 

 Abraço

Editado por Rafael Del Pino
  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

funcionou pourra!!!!!!!!!!!!!

 

eu realmente esqueci do configurar o OSCCON.

 

eu configurei o byte inteiro  para "OSCCON = 0b01100000"

 

agora deu certo :)

 

O lado bom é que eu aprendi que sempre devemos ler atentamente o datasheet o integrado que vamos utilizar.

 

Obrigado a todos que quiseram me ajudar!

 

 

@Rafael Del Pino te amo  (sem veadagi)

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×