Ir ao conteúdo
  • Cadastre-se
Brunorichter

Delay sem precisão no PIC

Recommended Posts

Estou com um problema parecido do PAT0LINO, no tópico http://forum.clubedohardware.com.br/resolvido-delay-nao/882866

Escrevo sobre meu programa que serve como um PWM para controlar um servo motor. Uso CCS e um cristal de 4Mhz. Comecei a testar usando um simples delay_us e quando fui simular no proteus os tempos ficam todos errados. Um simples delay_ms(1000) demora 12 segundos para passar. Uso fuse XT, use delay=4000000. Assim que amanhecer posto meu código. Se alguém passou por isso alguma vez por favor, preciso de uma ajudinha!

Obs: PIC18F4550

Compartilhar este post


Link para o post
Compartilhar em outros sites

No PIC do proteus já está 4Mhz. Quando simulo no MPlab também da errado os calculos de tempo da interrupção e do delay. Acredito que seja o mesmo problema para os dois casos.

Segue abaixo o código.

A interrupção era para ocorrer a cada 50us e como repito 400x deveria gerar um sinal de periodo de 20ms mas não é o que ocorre.

#include <18f4550.h>

#FUSES NOWDT //No Watch Dog Timer
#FUSES hs //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES LVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
//#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOPROTECT //Code not protected from reading

#use delay(crystal=400000)
#define motor PIN_A0

unsigned int servo=0;
unsigned int ciclo=0;

#int_RTCC
void RTCC_isr(void)
{

output_high(pin_d2);
if(++ciclo >= 5 + servo) output_low(motor); // 50uS
if(ciclo == 400){ // 50uS * 400 = 20mS
ciclo = 0;
output_high(motor);
}
set_timer0(206);
}

void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_bit); //256 us overflow
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
servo=0;
//Example blinking LED program
while(true){
delay_ms(1000);
if(++servo==18) servo=0; // 5+17 ULTIMA POSIÇÃO
}

}

OBS:

Notem que coloquei #use delay(crystal=400000) que seria 400kHz

Assim ele se comporta proximo dos tempos que deveriam ocorrer. Isso até em uma placa de desenvolvimento que eu tenho. Com 4MHz um delay de 1s demora 12segundos.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Para que não tenha problemas futuros,recarregue o timer com precisão:

set_timer0(206 - get_timer0())

Pois o registrador do timer continua incrementando a cada cilco de clock e voce precisa 'descontar' esse tempo para um carregamento correto.

Compartilhar este post


Link para o post
Compartilhar em outros sites

vtrx, com essa modificação o período do sinal fica 46ms. antes estava em torno de 17ms. Tudo isso usando um cristal de 4MHz e colocando 400kHz no código

Abaixo código modificado. (fuse do cristal em XT)

#include <18f4550.h>

#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES LVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
//#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOPROTECT //Code not protected from reading

#use delay(crystal=400000)
#define motor PIN_A0

unsigned int servo=0;
unsigned int ciclo=0;

#int_RTCC
void RTCC_isr(void)
{

output_high(pin_d2);
if(++ciclo >= 5 + servo) output_low(motor); // 50uS
if(ciclo == 400){ // 50uS * 400 = 20mS
ciclo = 0;
output_high(motor);
}
set_timer0(206+get_timer0());
}

void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_bit); //256 us overflow
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
servo=0;
//Example blinking LED program
while(true){
delay_ms(1000);
if(++servo==18) servo=0; // 5+17 ULTIMA POSIÇÃO
}

}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Está montando no proteus ou na bancada?

Se for teste no Proteus, não confie. Melhor montar e testar de verdade. Tempos muito curtos assim, ele fica doidão.

Falou

Compartilhar este post


Link para o post
Compartilhar em outros sites

Obrigado vtrx! Agora esta bem próximo ao esperado!

Matheus, estou testando onde posso, no proteus, bancada, MPlab.

Na bancada o delay_ms(1000) demora aproximadamente 2,5 segundos agora.

Ao simular no MPLAB fazendo um debug a interrupção demora 178us para ocorrer, ao invés de 50us.

Já o delay_ms(1000) segundo o debug do MPLAB esta demorando 2,64 segundos. Praticamente o mesmo tempo que eu cronometro quando testo na bancada.

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

×