Timer break - PIC18F4550

Asked

Viewed 400 times

5

Hello, I am a student of the Technical course in Mechatronics. My teacher passed a project to show the speed of a reduced CC motor, in RPM, in the Hyper Terminal. He said we need to use the timer interruption, however, I did not understand how to use the timer interruption in PIC18F4550. He gave us the base program to only modify to show speed. If anyone can help me, I would really appreciate it.

Follows the basic program:

/*
Exemplo para controle de Motor de Corrente Contínua
*/
#include <18F4550.h>
#use delay(clock = 20MHz)
#fuses HS, NOWDT, PUT, NOBROWNOUT, NOLVP
#use rs232(baud = 9600, parity = N, xmit = pin_c6, rcv = pin_c7, bits = 8)
#include <stdlib.h>                  // biblioteca de conversão de valores
#define led       pin_e2
// Definição de nomes para os canais do encoder. Para determinação do 
sentido de giro,
// ao menos um dos canais deve ser conectado à algum pino de interrupção                 
externa
#define CanalB    pin_b1
// Definição de nomes para a seleção de sentido de acionamento da Ponte H
#define PonteH_1  pin_d0
#define PonteH_2  pin_d1

// Definição de variável(is) global(is)
int1 i1_Sentido;
int16 i16_iPWM = 0, i16_pPWM = 0;
float f_Resolucao = 0, f_Angulo = 0, f_Posicao = 0;
char s_Resolucao[4], s_Posicao[10], s_pPWM[4];
signed int16 Contador = 0;

// Declaração de funções utilizadas no programa
void PiscaLed(void)
{
// Pisca-pisca para led
output_high(led);
delay_ms(250);
output_low(led);
delay_ms(250);
return;
}
void Inicializacao(void)
{  
// Inicialização para controle do motor cc
printf("Resolucao do Encoder [ppv = pulsos por volta] = ");
gets(s_Resolucao);               // após <enter>, lê o valor do tipo string 
digitado
printf("\n\r");
f_Resolucao = atof(s_Resolucao);   // converte string em número do tipo 
float
f_Resolucao = 360/f_Resolucao;
delay_ms(250);
return;
}

// Declaração das interrupções e suas respectivas funções
#int_EXT
void  EXT_isr(void) 
{
// Este pedaço de código será executado se a interrupção for acionada, ou 
seja, o Canal A do encoder
// passar de nível Alto para Baixo [H_TO_L], conforme configuração no 
programa principal [void main()]
if ( !input(CanalB) )            // Se o Canal B estiver em nível Baixo -> 
Sentido Horário
{
  Contador--;
}
if ( input(CanalB) )            // Se o Canal B estiver em nível Alto -> 
Sentido Anti-Horário
{
  Contador++;
}
return;
}

// Função principal
void main()
{
PiscaLed();

// Configuração da(s) Interrupção(ões) Externa(s)
disable_interrupts(GLOBAL);         // Desabilita todas as interrupções se 
estiverem habilitadas
enable_interrupts(INT_EXT);         // Habilita a interrupção externa 0
ext_int_edge(0, H_TO_L);         // Configuração da interrupção externa para 
borda de descida :: High TO Low [H_TO_L]
                          // Se fosse borda de subida :: Low TO High 
[L_TO_H]
enable_interrupts(GLOBAL);         // Habilita todas as interrupções

// Configuração do sinal PWM
setup_ccp1(CCP_PWM);            // Configura CCP1 como um PWM
//   O tempo de ciclo (período, T) será dado pela seguinte expressão:
//      T = (1/clock)*4*t2div*(período+1)
//   onde:
//      T = período (será dado em segundos)
//      clock = clock configurado em <#use delay(clock = #)>
//      t2div = número de vezes de oscilação do cristal por instrução (pode 
ser: T2_DIV_BY_1 ou T2_DIV_BY_4 ou T2_DIV_BY_16)
//      período = valor que determina quando o valor de clock será resetado 
(pode ser um inteiro de 0 a 255)
//   Neste programa o clock é de 20MHz = 20000000Hz, t2div será por 16 
(T2_DIV_BY_16) e o período selecionado será de 249. Assim,
//      T = (1/20000000)*4*16*(249+1) = 0.0008s = 800us :: f = 1/T = 
1/0.0008 = 1250Hz (aprox. 1,25kHz)
setup_timer_2(T2_DIV_BY_16, 249, 1);// Configura o período T do sinal PWM

// Inicialização de escrita na porta serial
printf("\n\n\n\r");
printf("::...[ Curso Tecnico em Mecatronica ]...::\n\r");
delay_ms(250);
printf("::         Controle de Motor CC         ::\n\r");
printf("\n\r");
delay_ms(250);

Inicializacao();               // Chama função de inicialização do motor

while ( True )
{
  printf("\n\rDigite a posicao angular desejada: ");
  gets(s_Posicao);
  printf("\n\r");
  f_Posicao = atof(s_Posicao);
  delay_ms(250);

  printf("Digite o percentual de sinal PWM desejado [0 - 100]: ");
  gets(s_pPWM);
  printf("\n\n\r");
  i16_pPWM = atoi(s_pPWM);
  delay_ms(250);
  // Conversão do valor percentual de 0 a 100 para inteiro de 10bits
  i16_iPWM = i16_pPWM*10;         // 100% = 1000 :: 1000/100 = 10

  // Exemplo para uso do canal PWM: definição do tempo de ciclo ativo
  set_pwm1_duty(i16_iPWM);

  printf("PWM selecionado:  %5ld\n\r", i16_iPWM);
  printf("Posicao atual:    %5.1f\n\r", f_Angulo);
  printf("Posicao desejada: %5.1f\n\r", f_Posicao);
  if ( f_Posicao <= f_Angulo )
  {
     i1_Sentido = 0;
     printf("Sentido de giro:      Horario\n\r");
  }
  else
  {
     i1_Sentido = 1;
     printf("Sentido de giro: Anti-Horario\n\r");
  }

  if ( i1_Sentido == 0 )         // sentido horário
  {
     while ( f_Angulo > f_Posicao )
     {
        // Escrita/Acionamento do Motor CC
        output_high(PonteH_1);
        output_low(PonteH_2);
        f_Angulo = Contador*f_Resolucao;
        printf("Contador: %5ld :: Angulo: %5.1f\n\r", Contador, f_Angulo);
     }
     output_high(PonteH_1);
     output_high(PonteH_2);
  }

  if ( i1_Sentido == 1 )         // sentido anti-horário
  {
     while ( f_Angulo < f_Posicao )
     {
        // Escrita/Acionamento do Motor CC
        output_high(PonteH_2);
        output_low(PonteH_1);
        f_Angulo = Contador*f_Resolucao;
        printf("Contador: %5ld :: Angulo: %5.1f\n\r", Contador, f_Angulo);
     }
     output_high(PonteH_1);
     output_high(PonteH_2);
 }
 }
disable_interrupts(GLOBAL);         // Desabilita todas a interrupcoes 
externas se estiverem habilitadas
}

1 answer

1

In the PIC18F4550 we have 4 TIMERS embedded in it being the following:

  • Timer0 : 16-bit
  • Timer1 : 16-bit
  • Timer2 : 8-bit
  • Timer3 : 16-bit

Of the four timers in the PIC18F4550, show Timer1. The work of the other timers is the same. To generate a time delay using Timer1, we need to calculate a count of the desired time.

Steps to program the PIC18F4550 timer

  1. Configure the T1CON record.
  2. Clear TMR1IF Timer1 interrupt flag.
  3. Load the count into the 16-bit TMR1 or TMR1H (upper byte) and TMR1L (lower byte).
  4. Set TMR1ON to start Timer1 operation.
  5. Wait for TMR1IF = 1. Setting this bit to '1' shows that the Timer1 count exceeds 0xFFFF to 0x0000.

EXAMPLE

We will generate a delay of 1 ms using the Timer1.

#include "osc_config.h"     /* Configuration header file */
#include <pic18f4550.h>     /* Contains PIC18F4550 specifications */

#define Pulse LATB          /* Define Pulse as LATB to output on PORTB */

void Timer1_delay();

void main()
{
    OSCCON=0x72;        /* Configure oscillator frequency to 8MHz */
    TRISB=0;            /* Set as output port */
    Pulse=0xff;         /* Send high on PortB */

    while(1)
    {
        Pulse=~Pulse;       /* Toggle PortB at 500 Hz */ 
        Timer1_delay();     /* Call delay which provide desired delay */    
    }   
}

void Timer1_delay()
{
    /* Enable 16-bit TMR1 register, No pre-scale, internal clock,timer OFF */
    T1CON=0x80;  

    TMR1=0xf830;        /* Load count for generating delay of 1ms */
    T1CONbits.TMR1ON=1;     /* Turn ON Timer1 */
    while(PIR1bits.TMR1IF==0);  /* Wait for Timer1 overflow interrupt flag */
    TMR1ON=0;           /* Turn OFF timer */
    TMR1IF=0;           /* Make Timer1 overflow flag to '0' */
}

Steps to program the PIC18F4550 timer using interrupt

  1. Activate GIE, PEIE, TMR1IE.
  2. Configure the T1CON record.
  3. Clear TMR1IF Timer1 interrupt flag.
  4. Load the count into the 16-bit TMR1 or TMR1H (upper byte) and TMR1L (lower byte).
  5. Set TMR1ON to start the Timer1 operation. 6 . When TMR1IF = 1, the code jumps to the ISR to run it and, after the execution control, returns to the main program.

Program

#include <pic18f4550.h>
#include "Configuration_Header_File.h"

void Timer1_start();

#define Pulse LATB

void main()
{ 
    OSCCON=0x72;    /* Configure oscillator frequency to 8MHz */
    TRISB = 0;      /* Set as output Port */
    Pulse = 0xff;   /* Send high on PortB */
    Timer1_start();

    while(1);

}
/***************Interrupt Service Routine for Timer1******************/
void interrupt Timer1_ISR()
{

    TMR1=0xF856;
    Pulse = ~Pulse;     /* Toggle PortB at of 500 Hz */   
    PIR1bits.TMR1IF=0;  /* Make Timer1 Overflow Flag to '0' */
}

void Timer1_start()
{
    GIE=1;      /* Enable Global Interrupt */
    PEIE=1;         /* Enable Peripheral Interrupt */
    TMR1IE=1;       /* Enable Timer1 Overflow Interrupt */
    TMR1IF=0;

    /* Enable 16-bit TMR1 register,no pre-scale,internal clock, timer OFF */
    T1CON=0x80;     

    TMR1=0xF856;    /* Load Count for generating delay of 1ms */
    TMR1ON=1;       /* Turn ON Timer1 */
}

I hope I helped.

Site Fonte: electronicwings

Browser other questions tagged

You are not signed in. Login or sign up in order to post.