sexta-feira, 11 de novembro de 2016

Funções de tempo


 A medição de tempo é feita por contagem de ciclos de instrução (TCI), cujo valor, em segundos depende da frequência do oscilador de clock. O tempo correspondente ao ciclo de instrução (TCI), é dado pela equação:





Para uma frequência de 48MHz temos




xc.h

A bliblioteca xc.h disponibiliza alguma funções que permitem gerar atrasos.

É necessário "chamar" a biblioteca xc.h
#include <xc.h>

Para o correto funcionamento, uma vez que as funções são baseadas em ciclos de instrução do microcontrolador é necessário indicar a frequência em Hz de trabalho do microcontrolador
#define _XTAL_FREQ 48000000

Obs.: Nas funções e macros descritas a seguir o argumento a ser passado ("cycles" ou "x") não pode ser um valor elevado, pois o compilador "entende" que desta forma o programa poderia estar "travado" ou em loop infinito, então para obter tempos maiores, é necessário chamar várias vezes as funções ou realizar inteirações (laços de repetição como "for", "while").

 Fonte: Guia do Usuário do compilador XC8 - Microchip

_delay

Gera um atraso de um número de ciclos que é especificado como argumento "cycles"

Sintaxe:  void _delay(unsigned long cycles);

Uso: _delay(10);   // gera um atraso de 10 ciclos de instrução aproximadamente 833ns (10 x 83,3ns)


   

_delay3


Gera um atraso de 3 vezes o número de ciclos que é especificado como argumento "cycles"

Sintaxe:  void _delay3(unsigned char cycles);

Uso: _delay3(10); // atraso de 30 ciclos de instrução



__delayus


É uma macro baseada na função _delay e gera um atraso em us que é especificado no argumento "x"

Sintase: void __delay_us(x);

Uso: __delay_us(1);  // gera uma atraso de 1us



   __delayms


É uma macro baseada na função _delay e gera um atraso em ms que é especificado no argumento "x"

Sintase: void __delay_ms(x);

Uso: __delay_ms(1);  // gera uma atraso de 1ms   


Entendendo PWM



Datasheet capítulo 15 (PWM)

O que é PWM (MEC071)

Modulação por Largura de Pulso - UDESC

PULSE WIDTH MODULATION CONCEITOS E CIRCUITO-EXEMPLO

EletrônicaDigital PWM - Modulação Por Largura de Pulso - Mecaweb





Exemplo de funcionamento




Código de exemplo para acionamento das saídas 1 e 2



/*
 * File:   PWM_1_exemplo.c
 * Author: Pilger
 *
 * Created on 16 de Novembro de 2017, 08:35
 */

#define _XTAL_FREQ 48000000
#define TMR2PRESCALE 16

// relação de frequencia x prescaler para xtal de 48M
// para reslução de 1000 -> 2^10 = 1023
// ps   F pwm
// 1    48KHz
// 4    12KHz
// 16    3 KHz

#include <xc.h>
#include "C:\h\config_PIC18F4550.h"

//variáveis globais
long freq;

// protótipos de funções
void delay_ms(int i);
int PWM_Max_Duty(void);
void PWM1_Init(long fre);
void PWM2_Init(long fre);
void PWM1_Duty(unsigned int duty);
void PWM2_Duty(unsigned int duty);
void PWM1_Start(void);
void PWM1_Stop(void);
void PWM2_Start(void);
void PWM2_Stop(void);


void main(){
  unsigned int i=0,j=0;
  PWM1_Init(3000);
  PWM2_Init(3000);
  TRISD = 0xFF;
  TRISC = 0;
  PWM1_Duty(0);
  PWM2_Duty(0);
  PWM1_Start();
  PWM2_Start();
  while (1)  {
    if(PORTDbits.RD0 == 0 && i<1000){
        while(PORTDbits.RD0==0);  
      i=i+100;
    }
    if(PORTDbits.RD1 == 0 && i>0){
        while(PORTDbits.RD1==0);
      i=i-100;
    }
    if(PORTDbits.RD2 == 0 && j<1000){
        while(PORTDbits.RD2==0);
      j=j+100;
    }
    if(PORTDbits.RD3 == 0 && j>0){
      while(PORTDbits.RD3==0);
        j=j-100;
    }
    PWM1_Duty(i);
    PWM2_Duty(j);
    delay_ms(10); // 10ms  
  }
}

// função que gera atraso em mlisegundos
void delay_ms(int i){
    for ( int x = 0; x < i; x++ )     { 
    __delay_ms(1); 
    }
}

int PWM_Max_Duty(void){
  return(_XTAL_FREQ/(freq*TMR2PRESCALE);
}

void PWM1_Init(long fre){
  PR2 = (_XTAL_FREQ/(fre*4*TMR2PRESCALE)) - 1;
  freq = fre;
}

void PWM2_Init(long fre){
  PR2 = (_XTAL_FREQ/(fre*4*TMR2PRESCALE)) - 1;
  freq = fre;
}

void PWM1_Duty(unsigned int duty){
  if(duty<1024) {
    duty = ((float)duty/1023)*PWM_Max_Duty();
    CCP1CONbits.DC1B1 = duty & 2;
    CCP1CONbits.DC1B0 = duty & 1;
    CCPR1L = duty>>2;
  }
}

void PWM2_Duty(unsigned int duty){
  if(duty<1024) {
    duty = ((float)duty/1023)*PWM_Max_Duty();
    CCP2CONbits.DC2B1 = duty & 2;
    CCP2CONbits.DC2B0 = duty & 1;
    CCPR2L = duty>>2;
  }
}

void PWM1_Start(void) {
    CCP1CONbits.CCP1M3 = 1;
    CCP1CONbits.CCP1M2 = 1;
  #if TMR2PRESCALE == 1
      T2CONbits.T2OUTPS0 = 0;
      T2CONbits.T2OUTPS1 = 0 ;
  #elif TMR2PRESCALE == 4
      T2CONbits.T2OUTPS0 = 1;
      T2CONbits.T2OUTPS1 = 0 ;
  #elif TMR2PRESCALE == 16
      T2CONbits.T2OUTPS0 = 1;
      T2CONbits.T2OUTPS1 = 1 ;
  #endif
  T2CONbits.TMR2ON = 1;
  TRISCbits.TRISC2 = 0;
}

void PWM1_Stop(void) {
    CCP1CONbits.CCP1M3 = 0;
    CCP1CONbits.CCP1M2 = 0;
}

void PWM2_Start(void){
    CCP2CONbits.CCP2M3 = 1;
    CCP2CONbits.CCP2M2 = 1;
  #if TMR2PRESCALE == 1
      T2CONbits.T2OUTPS0 = 0;
      T2CONbits.T2OUTPS1 = 0;
  #elif TMR2PRESCALE == 4
      T2CONbits.T2OUTPS0 = 1;
      T2CONbits.T2OUTPS1 = 0;    
  #elif TMR2PRESCALE == 16
      T2CONbits.T2OUTPS0 = 1;
      T2CONbits.T2OUTPS1 = 1;
  #endif
  T2CONbits.TMR2ON = 1;
  TRISCbits.TRISC1 = 0;
}

void PWM2_Stop(void){
    CCP2CONbits.CCP2M3 = 0;
    CCP2CONbits.CCP2M2 = 0;
}




Atividade 1


1.1 Entendendo o PWM 

  • Criar um projeto e compilar o exemplo
  • Observar no simulador
  • Colocar no hardware
  • Ligar um led na saída e observar
  • Ligar um osciloscópio e analisar a saída

1.2 Adicionando recursos de informação 

  • Modificar o programa para
  • Adicionar o módulo LCD e indicar o percentual de PWM em cada sinal
  • Modificar o incremento e decremento para saltos de 1%

1.3 Ligando uma carga 



  • Ligar uma carga em uma das saídas, um motor DC de 12V (pode ser uma ventoinha de fonte de computador)