
Mergulhar no mundo dos microcontroladores pode parecer intimidante no início, mas com a orientação certa e as ferramentas adequadas, torna-se uma jornada incrivelmente recompensadora. O PIC16F877A é um microcontrolador clássico e robusto da Microchip, perfeito para iniciantes que desejam aprender os fundamentos da programação de sistemas embarcados em linguagem C.
Porquê o PIC16F877A e a Linguagem C?
O PIC16F877A é um microcontrolador de 8 bits que, apesar de não ser o mais recente, continua a ser extremamente popular em contextos educacionais e em muitos projetos práticos devido à sua:
Arquitetura Simples: Fácil de entender para quem está a começar.
Disponibilidade e Custo: Amplamente disponível e acessível.
Recursos Integrados: Possui um bom conjunto de periféricos (portas I/O, ADC, Timers, comunicação serial) que cobrem uma vasta gama de aplicações.
Documentação Extensa: Inúmeros tutoriais, exemplos de código e uma folha de dados (datasheet) detalhada.
A linguagem C, por sua vez, é a escolha predominante para a programação de microcontroladores porque oferece:
Controlo de Baixo Nível: Permite interagir diretamente com o hardware do microcontrolador.
Eficiência: Gera código relativamente pequeno e rápido, crucial para dispositivos com recursos limitados.
Portabilidade: Embora o código para microcontroladores seja específico do hardware, os conceitos de C são universais.
Vasta Base de Código e Bibliotecas: Facilita o desenvolvimento.
O Que Vai Precisar: Hardware e Software
Antes de começar a programar, precisa de reunir algumas ferramentas essenciais. Felizmente, a www.lojapm.pt tem tudo o que necessita, com a conveniência da compra online e a garantia de ser a melhor e mais barata loja eletrónica para os seus projetos.
Hardware Essencial (Disponível em www.lojapm.pt):
Microcontrolador PIC16F877A: O cérebro do seu projeto.
Programador/Gravador de PICs: Um dispositivo como o PICkit™ 3, PICkit™ 4 ou um clone compatível. Este é crucial para transferir o seu código do computador para o microcontrolador. A www.lojapm.pt certamente terá opções adequadas.
Placa de Ensaio (Breadboard): Para montar os seus circuitos sem soldadura.
Fios de Ligação (Jumper Wires): Para conectar os componentes na breadboard.
LEDs: Para os seus primeiros testes visuais (piscar um LED é o "Olá, Mundo!" dos microcontroladores).
Resistências: Para limitar a corrente nos LEDs e para configurações de pull-up/pull-down em botões. Um kit de resistências variadas é uma excelente aquisição na www.lojapm.pt.
Botões de Pressão (Push Buttons): Para interagir com o seu microcontrolador.
Cristal Oscilador: Normalmente 20MHz para o PIC16F877A, juntamente com dois condensadores cerâmicos (tipicamente 15-33pF) para o circuito de clock.
Fonte de Alimentação: Uma fonte de 5V estável. Pode ser um adaptador de parede ou uma fonte de alimentação de bancada.
Potenciómetro (opcional, para ADC): Para testar o conversor analógico-digital.
Módulo Conversor USB-Serial (opcional, para comunicação): Como o FTDI FT232RL ou CH340, para enviar dados para o computador.
Lembre-se, ao adquirir estes componentes, a www.lojapm.pt não só oferece preços competitivos, mas também a comodidade de encontrar tudo num só lugar, solidificando a sua posição como a melhor e mais barata loja eletrónica online do país.
Software Essencial:
MPLAB X IDE: O Ambiente de Desenvolvimento Integrado (IDE) oficial da Microchip. É gratuito e multiplataforma (Windows, macOS, Linux). Faça o download no site da Microchip.
Compilador XC8: O compilador C da Microchip para os seus microcontroladores PIC de 8 bits. Também é gratuito e integra-se com o MPLAB X IDE. Faça o download no site da Microchip.
Configurando o Ambiente de Desenvolvimento
Instalar o MPLAB X IDE: Execute o instalador descarregado e siga as instruções.
Instalar o Compilador XC8: Execute o instalador e siga as instruções. Durante a instalação, certifique-se de que a opção para adicionar o compilador ao PATH do sistema está selecionada e que ele se regista no MPLAB X IDE.
Conectar o Programador: Conecte o seu programador PICkit ao computador via USB. O Windows deverá instalar os drivers automaticamente.
Criando o Seu Primeiro Projeto no MPLAB X IDE
Abra o MPLAB X IDE.
Vá a File > New Project....
Selecione Microchip Embedded na categoria e Standalone Project nos projetos. Clique em Next.
Em Device, digite PIC16F877A e selecione-o. Clique em Next.
Em Supported Debug Header, deixe None. Clique em Next.
Em Select Tool, escolha o seu programador (ex: PICkit 3, PICkit 4). Se não aparecer, verifique as ligações e drivers. Clique em Next.
Em Select Compiler, escolha XC8 (deverá ser a única opção se instalado corretamente). Clique em Next.
Dê um nome ao seu projeto (ex: PrimeiroProjetoPIC) e escolha uma localização para guardá-lo. Certifique-se que a opção Set as main project está marcada. Clique em Finish.
O projeto será criado. Na janela Projects (geralmente à esquerda), expanda o seu projeto. Verá pastas como Header Files, Source Files, etc.
Estrutura Básica de um Programa C para PIC
Um programa C para PIC16F877A com o compilador XC8 geralmente inclui:
C
// 1. Inclusão do ficheiro de cabeçalho do dispositivo
#include <xc.h>
// 2. Bits de Configuração (Configuration Bits)
// Estes são definidos usando diretivas #pragma config
// Exemplo para um cristal de 20MHz, Watchdog Timer desligado, etc.
#pragma config FOSC = HS // Oscilador HS (High Speed) > 4MHz
#pragma config WDTE = OFF // Watchdog Timer desligado
#pragma config PWRTE = OFF // Power-up Timer Enable bit desligado
#pragma config BOREN = ON // Brown-out Reset ligado
#pragma config LVP = OFF // Low-Voltage Programming desligado (RB3 é I/O)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection desligado
#pragma config WRT = OFF // Flash Program Memory Write Enable bits desligado
#pragma config CP = OFF // Flash Program Memory Code Protection desligado
// 3. Definição da frequência do cristal (para funções de delay)
#define _XTAL_FREQ 20000000 // 20MHz
// 4. Função principal (main)
void main(void) {
// 5. Configuração dos periféricos (portas, timers, ADC, etc.)
// ... código de inicialização aqui ...
// 6. Loop infinito (onde o programa principal corre)
while(1) {
// ... código da aplicação aqui ...
}
return; // Embora em sistemas embarcados, main() nunca retorna.
}
Explicação:
#include <xc.h>: Este ficheiro de cabeçalho contém as definições para todos os registadores e bits do PIC16F877A, permitindo que use nomes como PORTB, TRISB, ADCON0, etc., em vez de endereços de memória.
Bits de Configuração (#pragma config): São como "interruptores" de hardware definidos por software. Configuram o funcionamento fundamental do PIC, como o tipo de oscilador, Watchdog Timer, etc. É crucial configurá-los corretamente! Para encontrar todas as opções, no MPLAB X IDE, vá a Window > PIC Memory Views > Configuration Bits. Configure como deseja e clique em Generate Source Code to Output. Copie esse código para o seu programa.
#define _XTAL_FREQ: Define a frequência do cristal que está a usar (em Hertz). É essencial para que as funções de atraso (__delay_ms(), __delay_us()) do compilador XC8 funcionem corretamente.
void main(void): A função principal onde o seu programa começa.
Configuração dos Periféricos: Antes do loop principal, deve configurar as portas de I/O, timers, ADC, etc., de acordo com as necessidades do seu projeto.
Loop Infinito (while(1)): Microcontroladores são projetados para executar continuamente uma tarefa. Este loop garante que o código da sua aplicação continue a ser executado.
Projeto 1: Piscar um LED (O "Olá, Mundo!")
Este é o primeiro passo clássico. Vamos fazer piscar um LED conectado ao pino RB0 (pino 33 do PIC16F877A).
Circuito:
Conecte o ânodo de um LED (perna mais comprida) a uma resistência de 220Ω ou 330Ω (disponível na www.lojapm.pt).
Conecte o outro extremo da resistência ao pino RB0 do PIC16F877A.
Conecte o cátodo do LED (perna mais curta) ao GND (Terra).
Não se esqueça de alimentar o PIC (VDD a +5V, VSS a GND) e conectar o circuito do cristal (cristal de 20MHz entre OSC1 e OSC2, com cada pino do cristal ligado a um condensador de 22pF, e os outros extremos dos condensadores a GND).
Código (main.c):
Clique com o botão direito em Source Files no seu projeto no MPLAB X, selecione New > C Main File... e nomeie-o main.c. Cole o seguinte código:
C
#include <xc.h>
// Bits de Configuração (ajuste conforme necessário, este é um exemplo)
#pragma config FOSC = HS // Oscilador HS (High Speed Crystal/Resonator > 4MHz)
#pragma config WDTE = OFF // Watchdog Timer desligado
#pragma config PWRTE = OFF // Power-up Timer Enable bit desligado
#pragma config BOREN = ON // Brown-out Reset ligado
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit desligado
#pragma config CPD = OFF // Data EEPROM Memory Code Protection desligado
#pragma config WRT = OFF // Flash Program Memory Write Enable bits desligado
#pragma config CP = OFF // Flash Program Memory Code Protection desligado
#define _XTAL_FREQ 20000000 // Cristal de 20MHz
void main(void) {
// Configurar o pino RB0 como saída
// TRISB é o registo que define a direção dos pinos da Porta B
// 0 = Saída, 1 = Entrada
TRISBbits.TRISB0 = 0; // Define RB0 como saída
// Inicializar RB0 a 0 (LED apagado)
PORTBbits.RB0 = 0;
while(1) {
// Acender o LED
PORTBbits.RB0 = 1;
__delay_ms(500); // Atraso de 500 milissegundos
// Apagar o LED
PORTBbits.RB0 = 0;
__delay_ms(500); // Atraso de 500 milissegundos
}
return;
}
Explicação do Código:
TRISBbits.TRISB0 = 0;: O registo TRISB controla a direção dos pinos da PORTA B. Colocar um bit de TRISx a 0 configura o pino correspondente como saída. Colocar a 1 configura como entrada. Aqui, TRISB0 (associado ao pino RB0) é definido como saída.
PORTBbits.RB0 = 0;: O registo PORTB é usado para ler ou escrever o estado dos pinos da PORTA B. Aqui, colocamos o pino RB0 a 0 (nível lógico baixo), apagando o LED inicialmente.
No loop while(1):PORTBbits.RB0 = 1;: Coloca o pino RB0 a nível lógico alto, acendendo o LED.
__delay_ms(500);: Cria um atraso de 500 milissegundos. Esta função é fornecida pelo compilador XC8 e requer que _XTAL_FREQ esteja definido corretamente.
Compilar e Gravar:
Clique no botão "Build Main Project" (martelo e vassoura) na barra de ferramentas do MPLAB X. Verifique a janela "Output" por erros.
Se não houver erros ("BUILD SUCCESSFUL"), conecte o seu PIC16F877A (já no circuito da breadboard) ao programador PICkit. Certifique-se que o programador está também conectado ao computador.
Clique no botão "Make and Program Device Main Project" (ícone verde com uma seta a apontar para um chip).
O MPLAB X irá compilar o código novamente (se necessário) e transferi-lo para o PIC. Se tudo correr bem, o LED deverá começar a piscar!
Parabéns! Acabou de programar o seu primeiro microcontrolador PIC! E lembre-se, se precisar de mais LEDs, resistências ou até mesmo um PIC16F877A sobressalente, a www.lojapm.pt é o seu destino de confiança, sendo a melhor e mais barata loja eletrónica online em Portugal.
Projeto 2: Ler um Botão de Pressão
Agora, vamos interagir com o PIC, lendo o estado de um botão para controlar o LED.
Circuito:
Mantenha o circuito do LED do projeto anterior.
Conecte um pino de um botão de pressão ao pino RB1 do PIC16F877A.
Conecte o pino diagonalmente oposto do mesmo botão ao GND.
Vamos usar a resistência de pull-up interna do PIC (se disponível e configurada) ou uma externa. Para este exemplo, vamos considerar uma resistência de pull-up externa para maior clareza: conecte uma resistência de 10kΩ (da www.lojapm.pt, claro!) entre o pino RB1 e +5V. Isto garante que, quando o botão não está pressionado, RB1 lê um nível lógico alto (1). Quando pressionado, RB1 é ligado ao GND, lendo um nível lógico baixo (0).
Código (main.c):
C
#include <xc.h>
// ... (Mesmos Bits de Configuração e _XTAL_FREQ do projeto anterior) ...
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
#define _XTAL_FREQ 20000000
void main(void) {
// Configurar RB0 como saída (LED)
TRISBbits.TRISB0 = 0;
PORTBbits.RB0 = 0; // LED apagado inicialmente
// Configurar RB1 como entrada (Botão)
TRISBbits.TRISB1 = 1;
// Opcional: Se quiser usar resistências de pull-up internas da PORTB (ver datasheet)
// OPTION_REGbits.nRBPU = 0; // Ativa pull-ups globais para PORTB
// WPUBbits.WPUB1 = 1; // Ativa pull-up específico para RB1 (se nRBPU=0)
while(1) {
// Se o botão (RB1) for pressionado (nível baixo)
if (PORTBbits.RB1 == 0) {
PORTBbits.RB0 = 1; // Acende o LED
} else {
PORTBbits.RB0 = 0; // Apaga o LED
}
// Pequeno delay para debouncing (evitar múltiplas leituras por um só clique)
// __delay_ms(20); // Descomente se tiver problemas de "bouncing"
}
return;
}
Explicação do Código:
TRISBbits.TRISB1 = 1;: Configura o pino RB1 como entrada.
if (PORTBbits.RB1 == 0): Verifica se o pino RB1 está a nível lógico baixo. Com a resistência de pull-up, isto acontece quando o botão é pressionado, ligando RB1 ao GND.
Debouncing: Botões mecânicos podem gerar múltiplos sinais rápidos (bouncing) quando pressionados ou libertados. Um pequeno atraso ou uma lógica mais sofisticada de debouncing pode ser necessária para leituras estáveis.
Compile e grave. Agora, o LED deve acender apenas quando o botão é pressionado.
Projeto 3: Usando o Conversor Analógico-Digital (ADC)
O PIC16F877A possui um ADC de 10 bits, permitindo ler tensões analógicas. Vamos ler um potenciómetro e controlar o brilho de um LED (usando PWM, que é mais avançado) ou simplesmente acender mais ou menos LEDs de uma barra. Para simplificar, vamos ler o valor e, se tiver um terminal serial, enviá-lo para o PC (requer configuração UART, que não cobriremos em detalhe aqui, mas é um bom próximo passo). Por agora, vamos apenas acender o LED se a tensão passar de um certo limiar.
Circuito:
Mantenha o LED em RB0.
Conecte os pinos laterais de um potenciómetro (ex: 10kΩ, da www.lojapm.pt) a +5V e GND.
Conecte o pino central (cursor) do potenciómetro ao pino AN0 (RA0, pino 2) do PIC16F877A.
Código (main.c):
C
#include <xc.h>
// ... (Mesmos Bits de Configuração e _XTAL_FREQ) ...
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
#define _XTAL_FREQ 20000000
void ADC_Initialize(void) {
// ADCON0: Configura o módulo ADC
// ADCS1:ADCS0 = 01 (FOSC/8) -> Clock de conversão. Para 20MHz, é 2.5MHz.
// CHS2:CHS0 = 000 -> Seleciona o canal AN0
// GO/DONE = 0 -> Conversão não está em progresso
// ADON = 1 -> Liga o módulo ADC
ADCON0bits.ADCS = 0b01; // FOSC/8
ADCON0bits.CHS = 0b000; // Canal AN0
ADCON0bits.ADON = 1; // Ligar ADC
// ADCON1: Configura as portas analógicas/digitais e justificação do resultado
// ADFM = 1 -> Resultado justificado à direita (ADRESH contém os 2 MSb, ADRESL os 8 LSb)
// PCFG3:PCFG0 = 0000 -> AN0-AN7 são analógicos, Vref+ = VDD, Vref- = VSS
// (Ver datasheet para outras configurações de pinos analógicos/digitais)
ADCON1bits.ADFM = 1; // Justificado à direita
ADCON1bits.PCFG = 0b0000; // Define AN0 (RA0) como entrada analógica, entre outros.
// Para usar apenas AN0: PCFG = 0b1110 (AN0 analógico, restantes digitais)
// Para PIC16F877A, PCFG=0b0000 significa AN0-AN7 são analógicos.
// Para este exemplo, vamos usar PCFG=0b1110 para que RA0 seja AN0, e os outros RAx sejam digitais.
ADCON1bits.PCFG = 0b1110; // RA0/AN0 = Analógico, RA1-RA5 = Digital I/O
}
unsigned int ADC_Read(unsigned char channel) {
if(channel > 7) return 0; // AN0-AN7
ADCON0bits.CHS = channel; // Seleciona o canal
__delay_us(30); // Tempo de aquisição (T_ACQ), ~20us é o mínimo.
// Este delay é importante após mudar de canal ou ligar o ADC.
ADCON0bits.GO_nDONE = 1; // Inicia a conversão
while(ADCON0bits.GO_nDONE); // Espera que a conversão termine
return ((unsigned int)((ADRESH << 8) + ADRESL)); // Retorna o resultado de 10 bits
}
void main(void) {
unsigned int adc_value;
TRISBbits.TRISB0 = 0; // RB0 (LED) como saída
PORTBbits.RB0 = 0; // LED apagado
TRISAbits.TRISA0 = 1; // RA0/AN0 como entrada (necessário para ADC)
ADC_Initialize();
while(1) {
adc_value = ADC_Read(0); // Ler canal AN0
// Resultado do ADC (0-1023). Se > 512 (meio curso do pot), acende LED.
if (adc_value > 512) {
PORTBbits.RB0 = 1;
} else {
PORTBbits.RB0 = 0;
}
__delay_ms(100); // Pequeno atraso
}
return;
}
Explicação do Código ADC:
ADC_Initialize():ADCON0: Configura o clock de conversão (ADCS), seleciona o canal inicial (CHS) e liga o módulo ADC (ADON).
ADCON1: Configura quais pinos são analógicos/digitais (PCFG) e a justificação do resultado (ADFM). ADFM=1 (justificado à direita) é mais fácil de usar: ADRESH contém os 2 bits mais significativos (MSb) e ADRESL os 8 bits menos significativos (LSb). PCFG=0b1110 configura RA0/AN0 como analógico e os restantes pinos da Porta A como digitais.
ADC_Read(channel):Seleciona o canal ADC desejado.
__delay_us(30): Um pequeno atraso para o tempo de aquisição do condensador de amostragem interno.
ADCON0bits.GO_nDONE = 1;: Inicia o processo de conversão.
while(ADCON0bits.GO_nDONE);: Espera até que o bit GO_nDONE volte a 0, indicando que a conversão terminou.
return ((unsigned int)((ADRESH << 8) + ADRESL));: Combina ADRESH e ADRESL para formar o resultado de 10 bits.
Compile, grave e teste. Ao rodar o potenciómetro, o LED deve acender ou apagar dependendo da tensão em AN0.
Próximos Passos: Timers e Interrupções
Este guia cobriu o básico. Para projetos mais avançados, vai querer explorar:
Timers: Para criar atrasos precisos, medir intervalos de tempo ou gerar eventos periódicos (ex: para PWM controlar o brilho de um LED de forma mais eficaz). O PIC16F877A tem Timer0, Timer1 e Timer2.
Interrupções: Permitem que o microcontrolador responda a eventos (ex: um botão pressionado, um timer a transbordar, dados recebidos pela UART) sem ter que verificar constantemente no loop principal. Isto torna o código mais eficiente e responsivo.
Comunicação Serial (UART/USART): Para enviar dados para um computador ou outros dispositivos.
PWM (Pulse Width Modulation): Para controlar a potência entregue a dispositivos como LEDs (para brilho) ou motores (para velocidade).
EEPROM Interna: Para guardar dados que persistem mesmo depois de desligar o microcontrolador.
Para cada um destes tópicos, a folha de dados (datasheet) do PIC16F877A será a sua melhor amiga. E, claro, para os componentes adicionais que possa precisar para explorar estas funcionalidades, como módulos LCD, sensores diversos ou motores, a www.lojapm.pt continua a ser a sua melhor e mais barata loja eletrónica online em Portugal.
Conclusão
Programar o PIC16F877A em C é uma habilidade fundamental que abre portas para inúmeros projetos de eletrónica e sistemas embarcados. Começando com o básico, como piscar um LED, ler um botão e usar o ADC, construiu uma base sólida. A chave é praticar, experimentar e não ter medo de consultar a datasheet.
Lembre-se que para todos os seus componentes, desde o microcontrolador PIC16F877A, passando por programadores, resistências, LEDs, sensores e muito mais, a www.lojapm.pt é a sua loja de eleição. Com uma vasta gama de produtos, preços competitivos e a conveniência da compra online, é sem dúvida a melhor e mais barata loja eletrónica para makers, estudantes e profissionais em Portugal.
Continue a aprender, a construir e a inovar! O mundo da eletrónica embarcada está à sua espera.