Ir ao conteúdo

Posts recomendados

Postado

Pessoal, acho que estou errando em algo que está na minha frente, mas infelizmente não estou enxergando. Configurei um Timer de 16bits para que ocorresse o estouro em 0,2 segundo. Depois implementei uma simples rotina de teste para checar o tempo, mas ele não bate de forma alguma. Não sei onde estou errando no código abaixo.

Fiz uma pequena tabela com os intervalos obtidos:

	counter		intervalo obtido (s)
	4			0,90
	3			0,65
	2			0,40

 

#include <16f73.h>
#fuses HS
#use fast_io(A)
// Ciclo de máquina de 500ns
#use delay(clock=8MHz,crystal=8MHz)

// Registrador do Timer1 (timer de 16bits)
#byte T1CON = 0x10

// Registradores de contagem do Timer1 (bytes mais e menos significativo)
#byte TMR1L = 0x0E
#byte TMR1H = 0x0F

// Valores de inicialização do Timer1 para estouro de 1 segundo: 15535 = 0x3CAF
// O Timer1 contará 50000, ou seja, de 15535 a 65535, o que dará 0,2 segundos a cada estouro
#define TMR1_INIT_H 0x3C
#define TMR1_INIT_L 0xAF


int ck;
unsigned int8 counter;

#INT_TIMER1
void TMR1_isr(void)
{
	// Timer1: com prescale de 1:8
	// Ciclo de máquina de 500E-9
  	// Estou ocorrendo a cada 0,2 segundos

  	// Começando o contador em zero, quando for igual a 4 terá transcorrido 1 segundo
	if ((counter == 4)){
	
  		// Liga/Desliga LED
		if (ck)
			output_high(pin_a0);
		else
			output_low(pin_a0);
		ck = !ck;
	
  		// Inicializa registradores de contagem do Timer1
		TMR1L = TMR1_INIT_L;
		TMR1H = TMR1_INIT_H;
		counter  = 0;
	}
  
  	counter++;
}


void main()
{
	ck = true;
	counter = 0;

	// Inicializa os registradores de contagem de tempo do Timer1
	// para que o estouro ocorra em 1 segundo
	TMR1L = TMR1_INIT_L;
	TMR1H = TMR1_INIT_H;

	// Seta o timer para trabalhar com prescale 1:8
	T1CON = 0x31;
  
	enable_interrupts(INT_TIMER1);
	enable_interrupts(GLOBAL);

	set_tris_a(0);
	output_low(pin_a0);

	while(true){
	}
}

Alguma dica?

 

 

  • Membro VIP
Postado

quebrar seu galho...

 

não vi o d.s. deste mc mas digamos que seu clock seja 8000000Hz e entra clk/4 no timer = 2000000, com prescaler/8 =250000, ao dividir por 50000 você vai ter 5Hz de interrput ou seus 0.2s..Até aí tudo bem Escrevi isso só pra acompanhar o raciocínio... No entanto percebi que você só realimenta o contador depois da condição if. Tente fazê-lo logo no início da interrupt. Penso também que é bom zerar o famigerado bit de flag de interrupt do timer.

-Confira (de novo) os valores de reload do timer e prescaler pois confiei que está correto, correto?

-Confira o valor do cristal

-Se estiver simulando no proteus ou mplab, confira o clock

-confira wdog off

-etc

 

1/2 ndv mas penso que se fizer if (counter>3) fica mais seguro. Vai que algum evento do além (ruídos, estática e afins) faz o counter>5... É.. variáveis principalmente vetores e ponteiros podem ter 'vida própria' ... mas ainda não é seu momento...

Postado

Olá @Isadora Ferraz

Fiz as modificações que você sugeriu, mas não surtiram efeito (para counter = 5, ainda t = 0,9s):

1- Realimentação do contador logo no início da função: de início imaginei que fosse isso certamente, mas não mudou o comportamento;

2- Zerar o bit da flag de estouro do Timer1;

3- Conferido o reload do Timer1 e Prescale;

4- Cristal OK. Até troquei por outro, de 20MHz, reajustei o que precisava no código, mas nada mudou (voltei 8MHz);

5- Estou com o circuito em protoboard;

6- Watch Dog Timer estava ligado (padrão deste uC), mas acrescentei um "#fuses HS, NOWDT";

7- A dica do uso do ">" em lugar de "==": sim, concordo plenamente. Aliás, como você observou, realmente não tive a infelicidade de passar por esse problema com microcontroladores ao usar ponteiros. Porém, anos atrás, quando os PCs começaram a receber processadores de dois ou mais núcleos, vários de meus programas que usavam ponteiros simplesmente enlouqueceram, pois não havia neles a proteção contra sobrescrita de memória (não havia necessidade). As vezes, no meio de um rotina, uma memória que estava bonitinha em uso, tinha seu valor alterado para outro qualquer...

 

O código atualizado da rotina do Timer1 ficou assim:

#INT_TIMER1
void TMR1_isr(void)
{
	// Limpa a flag de indicação de estouro do Timer1
	PIR1_TMR1IF = 0;
	// Reload do Timer1/Prescale (não sei se foi isso que você quis dizer...)
	// bits 5-4 => Prescale 1:8 e bit 0 => Timer1 ON
	T1CON = 0x31;
	// Reinicia os registradores de contagem do Timer1 (fora do if)
	TMR1L = TMR1_INIT_L;
	TMR1H = TMR1_INIT_H;

	counter++;

	if ((counter > 4)){	
		if (ck)
			output_high(pin_a0);
		else
			output_low(pin_a0);
		
		ck = !ck;
		counter  = 0;
	}
}

 

 

  • Membro VIP
Postado

Não conheço este mc como deveria mas verifique se ele tem alguma configuração adicional de clock como pll ou algo assim

Bem, além da tradicional ausência de palavras mágicas  que acho que já me acostumei, você não mencionou se o cod atualizado te atendeu.

 

Bem isso não deve fazer muita diferença mas tente algo como
 

if (counter>4)
{
counter=0;
RA0^=1; //hás de descobrir como seu compilador acessa o pino
//if (ck)// nem precisa disso
//ck=!ck;// e nem disso
}

É que fica + enxuto/elegante e percebi que você gosta de entender bit a bit o mc e isso é legal

 

+ tarde dou +1 analisada quiçá simulando

 

Postado

Opa!

2 horas atrás, Isadora Ferraz disse:

você não mencionou se o cod atualizado te atendeu.

 

18 horas atrás, wBB disse:

Fiz as modificações que você sugeriu, mas não surtiram efeito (para counter = 5, ainda t = 0,9s):

Deveria ter contado exatamente um segundo, mas está dando menos, e pior, está defasando em +50ms a cada nova interação conforme mostra a tabela lá do início.

 

2 horas atrás, Isadora Ferraz disse:

verifique se ele tem alguma configuração adicional de clock como pll ou algo assim

Não tem.

 

Fiz a modificação que você sugeriu, retirando a variável "ck", mas também não mudou os tempos. Realmente fica melhor assim em relação ao código.

Estou tentando outras coisas aqui, mas sem muito sucesso...

 

Obrigado pela atenção.

  • Membro VIP
Postado

esqueci de perguntar.. como/onde está medindo estes 0.9S? Poderia ser seu instrumento? Mas se for na simulação, continue quebrando a cabeça. Este mc só tem 1 vetor de interrupt. Por acaso outra interrupt não está zoando? Tipo aquela do pino? Neste caso tente

if (PIR1_TMR1IF)

{

//...

}

Postado

Estou medindo o tempo por meio de um contador/temporizador externo, mas que é bem preciso. Estou sem osciloscópio aqui. Deixo executar 100 interrupções do Timer e depois divido o tempo obtido por 100.

Fiz a modificação do código incluindo a checagem da flag, porém não houve mudança. Até acredito que poderia estar sendo zoada mesmo a interrupção desse timer por causa de outra interrupção, porém criei um programa para teste apenas com o Timer1 habilitado e sem mais nada conectado ao microcontrolador...

Ficou assim:

#INT_TIMER1
void TMR1_isr(void)
{
	if (PIR1_TMR1IF) {
		// Limpa a flag de indicação de estouro do Timer1
		PIR1_TMR1IF = 0;
		// Reload do Timer1/Prescale
		// bits 5-4 => Prescale 1:8 e bit 0 => Timer1 ON
		T1CON = 0x31;
		// Reinicia os registradores de contagem do Timer1
		TMR1L = TMR1_INIT_L;
		TMR1H = TMR1_INIT_H;
	
		counter++;
	
		if (counter > 4){
			PORTAA_RA0 = !PORTAA_RA0;
			//PORTAA_RA0 ^= 1;
			counter  = 0;
		}
	}
}

 

adicionado 0 minutos depois

vou tentar simular no Proteus (que ainda não mexi...)

adicionado 40 minutos depois

Parece um castigo....

Não tem o PIC16F73 na biblioteca do Proteus. Existe biblioteca de microcontroladores para download?

Postado

@Isadora Ferraz  lhe devo desculpas. O mc, o cristal e as configurações estavam sempre todos certos, mas meu código estava errado (como eu imaginava e até comentei isso na abertura do tópico...). Eu estava fazendo simplesmente a contagem errada e nada mais. Para o código acima, "counter" tem que ser "> 5" e não "> 4". Se "counter++" estivesse depois do "if", aí sim seria "if (counter > 4)"... Me desculpe e obrigado novamente!

 

De qualquer forma ainda tenho interesse em simular o PIC16F73 no Proteus. Existe LIB para baixar de algum lugar?

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades 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

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!