Programação de Microcontroladores PIC: Guia Completo

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?

Principais Famílias PIC

PIC10F - Ultra Baixo Custo

PIC12F - Pequeno Formato

PIC16F - Meio de Gama (Mais Popular)

PIC18F - Alta Performance

Ambiente de Desenvolvimento

MPLAB X IDE (Recomendado)

IDE oficial da Microchip, baseado no NetBeans:

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:

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) { // Configurar porta B como saída 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

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 Important

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) { // Código da interrupção aqui 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:

#include <xc.h> #include <stdio.h> #define _XTAL_FREQ 4000000 // Variáveis globais unsigned int temperature; unsigned int fan_speed; void main(void) { // Inicializações 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

Otimização de Código

Debugging e Troubleshooting

Ferramentas de Debug

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:

  1. Pratique com projetos reais
  2. Estude protocolos de comunicação (SPI, I2C)
  3. Aprenda sobre RTOS para aplicações complexas
  4. Explore as famílias mais avançadas (PIC24, dsPIC)
  5. 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 Desenvolvimento Customizado?

A FIXTRON desenvolve soluções sob medida com microcontroladores PIC para automação industrial

Solicitar Orçamento Falar com Especialista