Introdução aos Microcontroladores PIC
Os microcontroladores PIC (Peripheral Interface Controller) da Microchip são amplamente utilizados na automação industrial devido à sua versatilidade, confiabilidade e custo-benefício. Este guia aborda desde conceitos básicos até técnicas avançadas de programação.
Por Que Escolher PIC?
- Baixo consumo: Ideal para aplicações battery-powered
- Arquitetura Harvard: Processamento eficiente
- Abundante I/O: Muitos pinos disponíveis
- Periféricos integrados: ADC, PWM, UART, SPI, I2C
- Preço acessível: Relação custo-benefício excelente
- Amplo suporte: Ferramentas e documentação
Principais Famílias PIC
PIC10F - Ultra Baixo Custo
- 6-8 pinos, limitado mas muito barato
- Aplicações: sensores simples, controle de LED
- Exemplo: PIC10F200
PIC12F - Pequeno Formato
- 8 pinos, ideal para espaços reduzidos
- PWM interno, ADC
- Exemplo: PIC12F675, PIC12F1840
PIC16F - Meio de Gama (Mais Popular)
- 14-64 pinos, equilíbrio ideal
- Periféricos avançados
- Exemplos: PIC16F877A, PIC16F1938
PIC18F - Alta Performance
- 18-100 pinos, para aplicações complexas
- Multiplicador hardware, USB
- Exemplos: PIC18F4520, PIC18F46K22
Ambiente de Desenvolvimento
MPLAB X IDE (Recomendado)
IDE oficial da Microchip, baseado no NetBeans:
- Gratuito e multiplataforma
- Debugger integrado
- Simulador completo
- Suporte a todos os compiladores
Compiladores Disponíveis
| Compilador | Linguagem | Licença | Observações |
|---|---|---|---|
| XC8 | C | Gratuito/PRO | Oficial Microchip |
| MPASM | Assembly | Gratuito | Máximo controle |
| CCS | C | Comercial | Muitas bibliotecas |
Primeiro Programa: "Hello World" com LED
Hardware Necessário:
- PIC16F877A ou similar
- Cristal 4MHz + capacitores 22pF
- LED + resistor 330Ω
- Fonte 5V regulada
- Programador (PICkit 3/4)
Código em C (XC8):
// Configuração dos fuses
#pragma config FOSC = HS // Cristal externo
#pragma config WDTE = OFF // Watchdog desabilitado
#pragma config PWRTE = ON // Power-up timer
#pragma config BOREN = ON // Brown-out reset
#pragma config LVP = OFF // Low voltage programming
#include <xc.h>
#define _XTAL_FREQ 4000000 // Frequência 4MHz
void main(void) {
TRISB = 0x00; // Todos pinos como saída
PORTB = 0x00; // Inicializar em 0
while(1) {
PORTB = 0xFF; // Ligar todos LEDs
__delay_ms(500); // Aguardar 500ms
PORTB = 0x00; // Desligar todos LEDs
__delay_ms(500); // Aguardar 500ms
}
}
Conceitos Fundamentais
Registradores Essenciais
- TRIS: Direção dos pinos (0=saída, 1=entrada)
- PORT: Estado atual dos pinos
- LAT: Latch de saída (evita read-modify-write)
- ANSEL: Seleção analógico/digital
- OPTION_REG: Configurações gerais
- INTCON: Controle de interrupções
Configuração de I/O
// Configurar RB0 como entrada e RB1 como saída
TRISB0 = 1; // RB0 = entrada
TRISB1 = 0; // RB1 = saída
// Ou usando máscaras
TRISB = 0b00000001; // RB0=entrada, resto=saída
// Ler entrada e controlar saída
if (PORTBbits.RB0 == 1) {
LATBbits.LATB1 = 1; // Liga LED
} else {
LATBbits.LATB1 = 0; // Desliga LED
}
Trabalhando com Periféricos
ADC (Conversor Analógico-Digital)
// Configurar ADC para RA0
void ADC_Init(void) {
TRISA0 = 1; // RA0 como entrada
ANS0 = 1; // RA0 como analógica
ADCON0 = 0b00000001; // Canal 0, ADC ON
ADCON1 = 0b10000000; // Resultado justificado à direita
}
// Ler valor ADC
unsigned int ADC_Read(void) {
ADCON0bits.GO = 1; // Iniciar conversão
while(ADCON0bits.GO); // Aguardar término
return ((ADRESH << 8) + ADRESL); // Retornar resultado
}
PWM (Modulação por Largura de Pulso)
// Configurar PWM no CCP1 (RC2)
void PWM_Init(void) {
TRISC2 = 0; // RC2 como saída
PR2 = 255; // Período PWM
CCP1CON = 0x0C; // Modo PWM
T2CON = 0x04; // Timer2 ON, prescaler 1:1
}
// Ajustar duty cycle (0-1023)
void PWM_SetDuty(unsigned int duty) {
if (duty < 1024) {
CCPR1L = duty >> 2; // 8 bits mais significativos
CCP1CONbits.DC1B = duty & 3; // 2 bits menos significativos
}
}
Interrupções
Dica Importante
Interrupções são fundamentais para sistemas responsivos. Use-as para eventos críticos como comunicação serial ou sinais de emergência.
Configuração Básica de Interrupção
// Configurar interrupção externa INT0
void Interrupt_Init(void) {
TRISB0 = 1; // RB0 como entrada
INTCON = 0b10010000; // GIE=1, INTE=1
OPTION_REGbits.INTEDG = 1; // Interrupção na borda de subida
}
// Rotina de interrupção
void __interrupt() ISR(void) {
if (INTCONbits.INTF) {
LATBbits.LATB1 ^= 1; // Toggle LED
INTCONbits.INTF = 0; // Limpar flag
}
}
Comunicação Serial UART
// Configurar UART a 9600 baud (4MHz crystal)
void UART_Init(void) {
TRISC6 = 0; // TX como saída
TRISC7 = 1; // RX como entrada
SPBRG = 25; // 9600 baud @ 4MHz
TXSTA = 0x20; // Transmissor habilitado
RCSTA = 0x90; // Receptor habilitado
}
// Enviar um caractere
void UART_Send(char data) {
while(!TXSTAbits.TRMT); // Aguardar buffer vazio
TXREG = data;
}
// Receber um caractere
char UART_Receive(void) {
while(!PIR1bits.RCIF); // Aguardar recepção
return RCREG;
}
Projeto Prático: Controle de Temperatura
Vamos criar um sistema que:
- Lê temperatura via sensor LM35
- Controla ventilador via PWM
- Exibe dados no LCD
- Envia dados via UART
#include <xc.h>
#include <stdio.h>
#define _XTAL_FREQ 4000000
unsigned int temperature;
unsigned int fan_speed;
void main(void) {
ADC_Init();
PWM_Init();
UART_Init();
LCD_Init();
while(1) {
// Ler temperatura (LM35 em RA0)
temperature = ADC_Read();
temperature = temperature * 500 / 1024; // Converter para °C
// Controlar ventilador baseado na temperatura
if (temperature < 25) {
fan_speed = 0; // Desligado
} else if (temperature < 35) {
fan_speed = 512; // 50% velocidade
} else {
fan_speed = 1023; // 100% velocidade
}
PWM_SetDuty(fan_speed);
// Atualizar display
LCD_Clear();
LCD_SetCursor(0, 0);
LCD_Print("Temp: %d C", temperature);
LCD_SetCursor(1, 0);
LCD_Print("Fan: %d%%", (fan_speed * 100) / 1023);
// Enviar dados via UART
printf("T:%d,F:%d\r\n", temperature, fan_speed);
__delay_ms(1000);
}
}
Dicas de Otimização
Economia de Energia
- Use modos sleep quando possível
- Desabilite periféricos desnecessários
- Reduza frequência do clock
- Use watchdog timer para wake-up
Otimização de Código
- Evite divisões e multiplicações desnecessárias
- Use operações bit-wise quando apropriado
- Minimize uso de variáveis float
- Prefira lookup tables para cálculos complexos
Debugging e Troubleshooting
Ferramentas de Debug
- MPLAB SIM: Simulador integrado
- PICkit Debugger: Debug in-circuit
- Logic Analyzer: Para sinais digitais
- Osciloscópio: Para sinais analógicos
Problemas Comuns
| Problema | Causa Provável | Solução |
|---|---|---|
| PIC não executa | Configuração de clock incorreta | Verificar #pragma config FOSC |
| I/O não funciona | TRIS incorreto | Verificar direção dos pinos |
| ADC lê valores errados | ANSEL não configurado | Configurar pinos como analógicos |
| PWM não gera sinal | Timer2 desabilitado | Habilitar Timer2 |
Próximos Passos
Para se aprofundar na programação PIC:
- Pratique com projetos reais
- Estude protocolos de comunicação (SPI, I2C)
- Aprenda sobre RTOS para aplicações complexas
- Explore as famílias mais avançadas (PIC24, dsPIC)
- Considere migrar para PIC32 para aplicações que exigem mais performance
Conclusão
Os microcontroladores PIC oferecem uma excelente plataforma para automação industrial. Com as técnicas apresentadas neste guia, você pode desenvolver soluções robustas e eficientes para diversas aplicações.
Precisa de Assistência Técnica Especializada?
A FIXTRON INDUSTRIAL oferece diagnóstico, reparo e manutenção de equipamentos eletrônicos industriais.