Microcontroladores PIC - emc.ufg.brjwilson/Micro_Parte_3_(PIC_Pratica).pdf · •String (conjunto...
Transcript of Microcontroladores PIC - emc.ufg.brjwilson/Micro_Parte_3_(PIC_Pratica).pdf · •String (conjunto...
MICROCONTROLADORES PICPRÁTICA
MSc. Gustavo Souto de Sá e Souza
INTRODUÇÃO
Para fins de avaliação e estudo prático, usaremos os microcontroladores dafamília PIC18, mais especificamente o PIC18F45K20.
É importante lembrar que as informações contidas aqui podem variar paraoutras famílias PIC ou até mesmo para outros chips da mesma família.
LINGUAGEM C – COMPILADOR XC8
Inicialização da variável “variavel”:
• Bit ou boolean: bit variavel;
• Valor inteiro: int variavel;
• Valor inteiro com sinal (positivo ou negativo): signed int variavel;
• Caractere: char variavel;
• String (conjunto de, digamos, 10 caracteres): char variavel[10];
• Valor flutuante: float variavel;
LINGUAGEM C – COMPILADOR XC8
Definição de variável:
• Decimal: variavel = 100;
• Binário: variavel = 0b1100100;
• Hexadecimal: variavel = 0x64;
• Caractere: variavel = “d”;
LINGUAGEM C – COMPILADOR XC8
Operações:
• Definição de variável: variavel = 255;
• Soma: variavel = 15 + b;
• Subtração: variavel = 15 - b;
• Multiplicação: variavel = 15 * b;
• Divisão: variavel = 15 / b;
• Rotação de N bits para esquerda: variavel = variavel << N;
• Rotação de N bits para a direita: variavel = variavel >> N;
LINGUAGEM C – COMPILADOR XC8
Operações:
• Operação E: variavel = variavel & 55;
• Operação OU: variavel = variavel | 55;
• Operação NÃO (inverte apenas 1 bit): variavel = !variavel;
• Incrementar em 1: variavel++;
• Decrementar em 1: variavel--;
LINGUAGEM C – COMPILADOR XC8
Condições (retornam 1 se verdadeiro, 0 se falso):
• Verificar se é igual: (variavel == b);
• Verificar se é diferente: (variavel != b);
• Verificar se é maior: (variavel > b);
• Verificar se é menor: (variavel < b);
• Verificar se é maior ou igual: (variavel >= b);
• Verificar se é menor ou igual: (variavel <= b);
• Condição E: (variavel <= b && variavel != 0);
• Condição OU: (variavel <= b || variavel != 0);
LINGUAGEM C – COMPILADOR XC8
Definições:
• Define “_constante” como 5: #define _constante 5
• Define “PINO_DO_LED” como LATD1: #define PINO_DO_LED LATD1
Inclusões de bibliotecas:
• Inclui biblioteca do compilador: #include <stdlib.h>
• Inclui biblioteca da pasta local: #include “lcd.h”
LINGUAGEM C – COMPILADOR XC8
Se:
• if:
if (variavel == 10) {
// executa se condição for verdadeira
} else {
// executa se condição for falsa
}
LINGUAGEM C – COMPILADOR XC8
Se:
• if:
if (variavel == 10) {
// executa se condição for verdadeira
} else {
// executa se condição for falsa
}
Condição
LINGUAGEM C – COMPILADOR XC8
Loops:
• While:
while (variavel != 0) {
// código em loop
}
LINGUAGEM C – COMPILADOR XC8
Loops:
• While:
while (variavel != 0) {
// código em loop
}
Condição (executa enquanto for 1)
LINGUAGEM C – COMPILADOR XC8
Loops:
• for:
for (variavel = 1; variavel < 100; variavel++) {
// código em loop
}
LINGUAGEM C – COMPILADOR XC8
Loops:
• for:
for (variavel = 1; variavel < 100; variavel++) {
// código em loop
}
Valor inicial
LINGUAGEM C – COMPILADOR XC8
Loops:
• for:
for (variavel = 1; variavel < 100; variavel++) {
// código em loop
}
Condição (executa enquanto for 1)
LINGUAGEM C – COMPILADOR XC8
Loops:
• for:
for (variavel = 1; variavel < 100; variavel++) {
// código em loop
}
Incremento
LINGUAGEM C – COMPILADOR XC8
Loops:
• break:
for (variavel = 1; variavel < 100; variavel++) {
// código em loop
if (variavel < 0) {
break;
}
}
LINGUAGEM C – COMPILADOR XC8
Loops:
• break:
for (variavel = 1; variavel < 100; variavel++) {
// código em loop
if (variavel < 0) {
break;
}
}
Finaliza e sai do loop aqui
LINGUAGEM C – COMPILADOR XC8
Funções:
• Principal:
void main (void) {
// Código principal do programa vem aqui
}
LINGUAGEM C – COMPILADOR XC8
Funções:
• Interrupção:
void interrupt int_func (void) {
// Código da interrupção
}
LINGUAGEM C – COMPILADOR XC8
Funções:
• Interrupção de baixa prioridade:
void interrupt low_priority int_low_funcao (void) {
// Código da interrupção de baixa prioridade
}
LINGUAGEM C – COMPILADOR XC8
Funções:
• Secundárias:
void LigaTimer (void) {
TMR0ON = 1;
}
LINGUAGEM C – COMPILADOR XC8
Funções:
• Secundárias com valores de entrada e saída:
int SomaDez (int valor_de_entrada) {
valor_de_entrada = valor_de_entrada + 10;
return valor_de_entrada;
}
LINGUAGEM C – COMPILADOR XC8
Chamando Funções:
LigaTimer();
variavel = SomaDez(variavel);
LINGUAGEM C – COMPILADOR XC8
Função de atraso por milissegundo:
__delay_ms(tempo_em_milissegundos);
!!! Requer que a velocidade do oscilador seja definido antes, por meio da linha
#define _XTAL_FREQ 1000000 (para um oscilador de 1 MHz)
Também requer a library xc.h incluída por meio da linha:
#include <xc.h>
Pode causar erro se o valor de entrada for muito grande, relativo à velocidade do oscilador.
LINGUAGEM C – COMPILADOR XC8
Comentando o código:
TRISA = 0; // A parte comentada vem depois de
// duas barras
/* Ou você pode comentar
todo um trecho do código
usando asterisco e barra */
ok++;
LINGUAGEM C – COMPILADOR XC8
sprintf: imprime e manipula strings e caracteres. Requer que a biblioteca “stdio.h” seja incluída.
#include <stdio.h>
char linha1[16];
sprintf(linha1, “Hello, world!”);
// Grava o texto ‘Hello, world!’ na variável linha1
LINGUAGEM C – COMPILADOR XC8
char linha1[16];
contador = 15;
sprintf(linha1, “Contagem: %i”, contador);
// Grava o texto ‘Contagem: 15’ na variável linha1
// %i imprime um número inteiro
LINGUAGEM C – COMPILADOR XC8
char linha1[16];
contador = 15;
sprintf(linha1, “Contagem: %3.2i”, contador);
// Grava o texto ‘Contagem: 15.00’ na variável
linha1
// %X.Yi imprime um número inteiro com X casas fixas
// antes do separador decimal e Y fixas casas depois
LINGUAGEM C – COMPILADOR XC8
char linha1[16];
temperatura = 37.52;
sprintf(linha1, “Graus: %2.2f”, temperatura);
// Grava o texto ‘Graus: 37.52’ na variável linha1
// %f imprime um número de ponto flutuante
LINGUAGEM C – COMPILADOR XC8
char linha1[16];
caractere_U = 0x55;
sprintf(linha1, “Letra U: %c”, caractere_U);
// Grava o texto ‘Letra U: U’ na variável linha1
// %c imprime um caractere correspondente à tabela
// ASCII
LINGUAGEM C – COMPILADOR XC8
Definindo bits de Configuração:
#pragma config LVP = OFF; // Desabilita o bit ICSP de
fonte de alimentação simples (única)
LINGUAGEM C – COMPILADOR XC8
Bits de Configuração essenciais:
• FOSC: // Frequência do oscilador
Define a origem do oscilador principal do microcontrolador. Mais usados:
#pragma config FOSC = INTIO; (oscilador interno)
#pragma config FOSC = XT; (cristal externo)
#pragma config FOSC = HS; (cristal externo rápido)
LINGUAGEM C – COMPILADOR XC8
Bits de Configuração essenciais:
• WDTEN:
Watchdog Timer enable. Habilita o reset automático do Watchdog Timer. Caso o comando ClrWdt() não seja executado num dado número de instruções, o microcontrolador será ressetado:
#pragma config WDTEN = OFF;
#pragma config WDTPS = 32768;
No PIC18F4550:
#pragma config WDT = OFF; // desabilita watchdog timer
#pragma config WDTPS = 32768;
LINGUAGEM C – COMPILADOR XC8
Bits de Configuração essenciais:
• MCLRE:
Master Clear enable. Habilita ou desabilita o pino de reset no microcontrolador.
#pragma config MCLRE = OFF;
LINGUAGEM C – COMPILADOR XC8
Bits de Configuração essenciais:
• PBADEN:
Habilita ou desabilita o conversor Analógico-Digital na porta B. Caso for utilizar interrupção na porta B ou usá-la como entrada/saída digital, este deve estar desabilitado. Por padrão é habilitado:
#pragma config PBADEN = OFF;
LINGUAGEM C – COMPILADOR XC8
Bits de Configuração não tão essenciais (podem ficar no valor padrão):
• PWRT:
Aguarda um tempo depois de ligar para iniciar o programa. Habilitá-lo evita instabilidade no programa devido a oscilações na alimentação e oscilador:
#pragma config PWRT = ON;
LINGUAGEM C – COMPILADOR XC8
Bits de Configuração não tão essenciais (podem ficar no valor padrão):
• BOREN:
Brown-out reset enable. Habilita o reset automático em caso de baixa tensão de alimentação:
#pragma config BOREN = SBORDIS;
LINGUAGEM C – COMPILADOR XC8
Registradores essenciais:
• OSCCON: Byte que define a frequência do oscilador interno do PIC18F45K20:
OSCCON=0b01110000; // Frequência: 16 MHz
OSCCON=0b01100000; // Frequência: 8 MHz
OSCCON=0b01010000; // Frequência: 4 MHz
OSCCON=0b00110000; // Frequência: 1 MHz (padrão)
LINGUAGEM C – COMPILADOR XC8
Registradores essenciais:
• OSCCON: Byte que define a frequência do oscilador interno do PIC18F4550:
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
IDLEN IRCF2 IRCF1 IRCF0 OSTS IOFS SCS1 SCS0
Bits de seleção da frequência
OSCCON=0b01110000; // Frequência: 8 MHz
OSCCON=0b01100000; // Frequência: 4 MHz
OSCCON=0b01010000; // Frequência: 2 MHz
OSCCON=0b01000000; // Frequência: 1 MHz (padrão)
OSCCON=0b00110000; // Frequência: 500 kHz
OSCCON=0b00100000; // Frequência: 250 kHz
LINGUAGEM C – COMPILADOR XC8
Registradores importantes - interrupção:
• GBIE: bit que habilita a interrupção global:
GBIE = 1; // Habilita interrupção
• PBIE: bit que habilita a interrupção de periféricos (timer2, adc):
PBIE = 1; // Habilita interrupção de periféricos
• INTXIE: bit que habilita a interrupção externa X (X = 0, 1 ou 2):
INT0IE = 1; // Habilita interrupção externa 0
LINGUAGEM C – COMPILADOR XC8
Registradores importantes - interrupção:
• ADIF: bit que habilita a interrupção do conversor AD:
ADIF = 1; // Habilita interrupção do ADC
• TXIE: bit que habilita a interrupção de transmissão da serial:
TXIE = 1; // Habilita interrupção do TX da serial
• RCIE: bit que habilita a interrupção de recepção da serial:
RCIE = 1; // Habilita interrupção do RX da serial
LINGUAGEM C – COMPILADOR XC8
Registradores importantes - interrupção:
• TMRXIE: bit que habilita o timer X (X pode ser 0, 1, 2 ou 3):
TMR3IE = 1; // Habilita interrupção do TMR3
LINGUAGEM C – COMPILADOR XC8
Registradores importantes – interrupção (flags):
• INTXIF: bit que sinaliza a flag da interrupção externa X (X=0, 1, 2):
INT0IF = 0; // Limpa a flag do INT0
• TMRXIF: bit que sinaliza a flag de interrupção do timer X (X=0, 1, 2, 3):
TMR3IF = 0; // Limpa a flag do TMR3
• ADIF: bit que sinaliza a flag de interrupção do ADC:
ADIF = 0; // Limpa a flag do ADC
LINGUAGEM C – COMPILADOR XC8
Registradores importantes – ADC :
• ADCON0bits.GO: bit que inicia a conversão analógica:
ADCON0bits.GO = 1; // Inicia a conversão AD
• ADCON0bits.DONE: flag que sinaliza o fim da conversão analógica:
while (!ADCON0bits.DONE) {
} // Aguarda finalização da conversão AD
LINGUAGEM C – COMPILADOR XC8
Registradores importantes – ADC :
• ANSEL e ANSELH: bytes que selecionam quais canais analógicos ficam ativos:
ANSEL = 0b00010100; // Habilita ADC nas portas
// AN2 e AN4
ANSELH = 0b00011111; // Habilita ADC nas portas
// AN8 até AN12
LINGUAGEM C – COMPILADOR XC8
Registradores importantes – ADC (PIC18F4550):
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
X X CHS3 CHS2 CHS1 CHS0 GO/DONE\ ADON
Bits de seleção do Canal AnalógicoStatus da conversão
Habilita ADC
ADCON0: Registrador de Controle do ADC
ADCON0bits.CHS = 0b0000 Seleção do Canal AN0
ADCON0bits.CHS = 0b0001 Seleção do Canal AN1
ADCON0bits.ADON = 1 Liga o ADC
ADCON0bits.GO = 1 Inicia a conversão A/D
LINGUAGEM C – COMPILADOR XC8
Registradores importantes – ADC (PIC18F4550):
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
X X VCFG1 VCFG0 PCFG3 PCFG2 PCFG1 PCFG0
Bits de configuração da
tensão de referência
ADCON1: Registrador de Controle do ADC
ADCON1bits.VCFG = 0b00; Tensões de referência: Vss e Vdd
LINGUAGEM C – COMPILADOR XC8
Registradores importantes – ADC (PIC18F4550):
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
ADFM - ACQT2 ACQT1 ACQT0 ADCS2 ADCS1 ADCS0
Formato do resultado
Bits de seleção do Tempo de Aquisição de dados
Bits de seleção do Clock de conversão
ADCON2: Registrador de Controle do ADC
ADCON2bits.ADCS = 0b110 Clock do AD: Fosc/64
ADCON2bits.ACQT = 0b010 Tempo de aquisição: 4 TAD
ADCON2bits.ADFM = 0b1 Formato do resultado: justificado à direita
LINGUAGEM C – COMPILADOR XC8
Registradores importantes – ADC :
• ADRESL: byte que guarda os 8 bits menos significativos da conversão AD:
• ADRESH: byte que guarda os 8 bits mais significativos da conversão AD:
valor_convertido = (ADRESH * 0x0100) + ADRESL;
// guarda o valor da conversão AD na variável
// de 16 bits “valor_convertido”
LINGUAGEM C – COMPILADOR XC8
Registradores importantes – PWM:
• CCPR2L: byte que define o duty cycle do PWM2:
CCPR2L = 26; // Define PWM com duty-cycle de 10%
CCPR2L = 255; // Define PWM com duty-cycle de 100%
CCPR2L = 128; // Define PWM com duty-cycle de 50%
CCPR2L = 77; // Define PWM com um duty-cycle de 30%
EXEMPLO – PISCAR LED
Inicio
Configuração Inverte sinal do pino D0Atrasa 100 ms
EXEMPLO – PISCAR LED#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void main(void) {
OSCCON = 0b01100000; // Define velocidade do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
while(1) { // Inicia loop infinito
LATDbits.LATD0 = !LATDbits.LATD0; // Inverte sinal do pino D0
__delay_ms(100); // Atraso de 100 ms
}
}
Fim de Código
EXEMPLO – PISCAR LED – 1 SEGUNDO
Inicio
Configuração Inverte sinal do pino D0 Atrasa 100 vezes 10 ms
EXEMPLO – PISCAR LED – 1 SEGUNDO#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void SuperDelay(long counter) { // Função com valor de entrada “counter”
counter = counter / 10; // Divide o valor informado por 10
for (long i = 1; i <= counter; i++) { // E usa o resultado como base
__delay_ms(10); // Para repetir uma contagem de 10 ms
}
}
void main(void) {
OSCCON = 0b01010000; // Define velocidade do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
EXEMPLO – PISCAR LED – 1 SEGUNDOwhile(1) { // Inicia loop infinito
LATDbits.LATD0 = !LATDbits.LATD0; // Inverte sinal do pino D0
SuperDelay(1000); // Atraso de 1 s
}
}
Fim de Código
EXEMPLO – ROTACIONAR LEDInicio
Configuração Rotaciona para a esquerda
LED aceso na borda
esquerda?Rotaciona para a direita
LED aceso na borda direita?
não
não
sim
sim
EXEMPLO – ROTACIONAR LED#define _XTAL_FREQ 1000000 // Oscilador de 4 MHz
#include <xc.h>
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void main(void) {
TRISA = 0b00000000; // Habilita porta A como saída
LATA = 1; // Liga o primeiro pino da porta A
while(1) { // Inicia loop infinito
while(LATA != 0b00000001) {
LATA = (LATA >> 1 | LATA << 7); // Rotacionando com estilo pra esquerda
__delay_ms(100); // Atraso de 100 ms
}
while(LATA != 0b10000000) {
LATA = (LATA << 1 | LATA >> 7); // Rotacionando com estilo pra direita
__delay_ms(100); // Atraso de 100 ms
}
}
}
Fim de Código
EXEMPLO – ROTACIONAR LED - EXPLICAÇÃODigamos que LATA = 0b00000001
LATA >> 1 retorna o seguinte valor: 0b00000000, pois rotacionou o “1” para a direita e
ele caiu fora dos 8 bits. O oitavo bit é preenchido com 0.
LATA << 7 retorna o seguinte valor: 0b10000000, pois rotacionou o “1” um total de sete
bits para a esquerda e ele ficou no lugar do oitavo bit. Os 7 primeiros bits são
preenchidos com 0.
Fazendo a operação OU entre ambos, temos (LATA >> 1 | LATA << 7) = 0b10000000;
Continuemos com LATA = 0b10000000
LATA >> 1 retorna o seguinte valor: 0b01000000, pois rotacionou o “1” para a direita e
ele caiu no lugar do sétimo bit. O oitavo bit é preenchido com 0.
LATA << 7 retorna o seguinte valor: 0b00000000, pois rotacionou o “1” um total de sete
bits para a esquerda e ele saiu do espaço dos bits. Os 7 primeiros bits são preenchidos
com 0.
Fazendo a operação OU entre ambos, temos (LATA >> 1 | LATA << 7) = 0b01000000;
EXEMPLO – LCD
Inicio
Configuração Adiciona 1 em contador
Atualiza LCD com valor de contador
EXEMPLO – LCD#define _XTAL_FREQ 1000000
#include <xc.h>
#define RS LATD2 // < Pinos do LCD
#define EN LATD3
#define D4 LATD4
#define D5 LATD5
#define D6 LATD6
#define D7 LATD7 // Pinos do LCD >
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#include "lcd.h"
#include <stdio.h>
EXEMPLO – LCDchar linha1[16]; // Variável linha1 com 16 caracteres
char linha2[16]; // Variável linha2 com 16 caracteres
int contador = 0; // Variável contador com valor inicial 0
void main(void) {
TRISD = 0; // Define porta D inteira como saída
Lcd_Init(); // Inicia o LCD
sprintf(linha1, "Hello world! "); // Grava texto em linha1
Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1
Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD
while(1) {
sprintf(linha2, "Contador: %i ",contador); // Grava texto em linha2
contador ++; // Incrementa contador
Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1
Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD
}
}
Fim de Código
EXEMPLO – LCD + CONTADOR FLOAT
Inicio
Configuração Adiciona 1 em contador
Atualiza LCD com valor de contador
EXEMPLO – LCD + CONTADOR FLOAT#define _XTAL_FREQ 1000000
#include <xc.h>
#define RS LATD2 // < Pinos do LCD
#define EN LATD3
#define D4 LATD4
#define D5 LATD5
#define D6 LATD6
#define D7 LATD7 // Pinos do LCD >
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#include "lcd.h"
#include <stdio.h>
EXEMPLO – LCD + CONTADOR FLOATchar linha1[16]; // Variável linha1 com 16 caracteres
char linha2[16]; // Variável linha2 com 16 caracteres
float contador = 0.0; // Variável contador com valor inicial 0.0
void main(void) {
TRISD = 0; // Define porta D inteira como saída
Lcd_Init(); // Inicia o LCD
sprintf(linha1, "Hello world! "); // Grava texto em linha1
Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1
Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD
while(1) {
sprintf(linha2, "Contador: %3.2f",contador); // Grava texto em linha2
contador = contador + 0.01; // Incrementa contador em 0.01
Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1
Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD
}
}
Fim de Código
EXEMPLO – INTERRUPÇÃO (INT0)Inicio
Configuração Aguarda interrupção
Interrupção ativada?
Inverte sinal do LEDnão sim
EXEMPLO – INTERRUPÇÃO (INT0)#define _XTAL_FREQ 1000000
#include <xc.h>
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#pragma config PBADEN = OFF // Conversor AD da porta B desligado
void setupInt(void) {
GIE = 1; // Habilita interrupção global
INT0IE = 1; // Interrupção da INT 0
INT0F = 0; // Flag de interrupção da INT 0
INTEDG0 = 1; // Interrupção por borda crescente.
}
EXEMPLO – INTERRUPÇÃO (INT0)void interrupt interrupcao(void) { // Função de interrupção
if (INT0F) { // Caso a flag da INT0 esteja habilitada
LATAbits.LA0 = !LATAbits.LA0; // Inverte o sinal no pino A0
INT0F = 0; // Desabilita a flag da INT0
}
}
void main(void) {
TRISA = 0x00; // Porta A com todos pinos de saída
TRISB = 0x01; // Somente pino B1 como entrada (INT0)
setupInt(); // Função de inicializar Interrupção
while(1) { // Loop infinito
}
}
// O código acima inverte o sinal no pino A0 a cada pressionar de um botão ligado à INT0
Fim de Código
EXEMPLO – TEMPORIZADOR 0Inicio
Configuração(temporizador
configurado para gerar interrupção
a cada 50 ms)
Aguarda interrupção
Interrupção ativada?
Inverte sinal do LEDnão sim
EXEMPLO – TEMPORIZADOR 0#define _XTAL_FREQ 4000000 // Oscilador a 4 MHz. O número de instruções por
// segundo é de 1 milhão. O tempo para executar uma
#include <xc.h> // instrução (e do tick do timer) é de 1 us.
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void setupInt(void) {
GIE = 1; // Habilita interrupção global
TMR0IE = 1; // interrupção do Timer 0
}
void setupTmr0() {
T08BIT = 0; // Modo 16 bits
T0CS = 0; // Source do clock
PSA = 1; // Desabilita Prescaler
TMR0H = 0x3C; // Começa a contar de 15535
TMR0L = 0xAF; // até 65535 (conta 50 mil vezes)
TMR0ON = 1; // Liga o timer
EXEMPLO – TEMPORIZADOR 0}
void interrupt interrupcao(void) { // Função de interrupção
if (TMR0IF) { // Caso a flag do temporizador esteja ativa
LATAbits.LA0 = !LATAbits.LA0; // Inverte pino A0
TMR0H = 0x3C; // Começa a contar de 15535
TMR0L = 0xAF; // até 65535 (conta 50 mil vezes)
TMR0IF = 0; // Flag do timer 0 em 0
}
}
void main(void) {
OSCCON = 0b01010000; // Oscilador a 4 MHz (1 tick do timer = 1 us)
setupInt(); // Função de habilitar interrupção
setupTmr0(); // Função de configurar timer 0
TRISA = 0x00; // Porta A como saída
while(1) { // Loop infinito
}
}
// O código acima inverte o sinal do pino A0 a cada 50000 us, via temporizador 0.
Fim de Código
EXEMPLO – TEMPORIZADOR 0 + PRESCALERInicio
Configuração(temporizador
configurado para gerar interrupção
a cada 1s)
Aguarda interrupção
Interrupção ativada?
Inverte sinal do LEDnão sim
EXEMPLO – TEMPORIZADOR 0 + PRESCALER#define _XTAL_FREQ 4000000 // Oscilador a 4 MHz. O número de instruções por
// segundo é de 1 milhão. O tempo para executar uma
#include <xc.h> // instrução (e do tick do timer) é de 1 us.
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void setupInt(void) {
GIE = 1; // Habilita interrupção global
TMR0IE = 1; // interrupção do Timer 0
}
void setupTmr0() {
T08BIT = 0; // Modo 16 bits
T0CS = 0; // Source do clock
PSA = 0; // Habilita Prescaler
T0PS0 = 0; // Multiplicador Prescaler
T0PS1 = 0; // 32 vezes
T0PS2 = 1; // 32 x 31250 us = 1 segundo
EXEMPLO – TEMPORIZADOR 0 + PRESCALERTMR0H = 0x85; // Começa a contar de 34285
TMR0L = 0xED; // até 65535 (conta 31250 vezes)
TMR0ON = 1; // Liga o timer
}
void interrupt interrupcao(void) { // Função de interrupção
if (TMR0IF) { // Caso a flag do temporizador esteja ativa
LATAbits.LA0 = !LATAbits.LA0; // Inverte pino A0
TMR0H = 0x85; // Começa a contar de 34285
TMR0L = 0xED; // até 65535 (conta 31250 vezes)
TMR0IF = 0; // Flag do timer 0 em 0
}
}
void main(void) {
OSCCON = 0b01010000; // Oscilador a 4 MHz (1 tick do timer = 1 us)
setupInt(); // Função de habilitar interrupção
setupTmr0(); // Função de configurar timer 0
TRISA = 0x00; // Porta A como saída
while(1) { // Loop infinito
EXEMPLO – TEMPORIZADOR 0 + PRESCALER}
}
// O código acima inverte o sinal do pino A0 a cada 1 s, via temporizador 0.
Fim de Código
EXEMPLO – TEMPORIZADOR 2Inicio
Configuração(temporizador
configurado para gerar interrupção
a cada 10 ms)
Aguarda interrupção
Interrupção ativada?
Inverte sinal do LEDnão sim
EXEMPLO – TEMPORIZADOR 2#define _XTAL_FREQ 4000000 // Oscilador a 4 MHz. O número de instruções por
// segundo é de 1 milhão. O tempo para executar uma
#include <xc.h> // instrução (e do tick do timer) é de 1 us.
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void setupInt(void) {
GIE = 1; // Habilita interrupção global
PEIE = 1; // Timer 2 exige interrupção de periféricos habilitada
TMR2IE = 1; // interrupção do Timer 2
}
void setupTmr2() {
T2CKPS0 = 1; // Prescaler x 4
T2CKPS1 = 0; //
T2OUTPS0 = 0; // Postscaler x 10
T2OUTPS1 = 1; //
T2OUTPS2 = 0; // Conta 250 (PR2, abaixo) x 4 (prescaler) x 10 (postscaler) vezes
T2OUTPS3 = 1; // totalizando 10000 vezes (~10 ms) por interrupção
EXEMPLO – TEMPORIZADOR 2TMR2 = 0x00; // Começa a contar de 0
PR2 = 249; // até 249 (conta 250 vezes + recarga automatica)
TMR2ON = 1; // Liga o timer
}
void interrupt interrupcao(void) { // Função de interrupção
if (TMR2IF) { // Caso a flag do temporizador esteja ativa
LATAbits.LA0 = !LATAbits.LA0; // Inverte pino A0
TMR2IF = 0; // Flag do timer 2 em 0
}
}
void main(void) {
OSCCON = 0b01100000; // Oscilador a 4 MHz (1 tick do timer = 1 us)
setupInt(); // Função de habilitar interrupção
setupTmr2(); // Função de configurar timer 0
TRISA = 0x00; // Porta A como saída
while(1) { // Loop infinito
}
} // O código acima inverte o valor do pino A0 a cada 10 ms usando o Timer 2.
Fim de Código
EXEMPLO – CONVERSOR ANALÓGICO-DIGITALInicio
ConfiguraçãoInicia leitura da tensão
no pino A0
Finalizou leitura?
Grava valor da leitura nos bits da porta C e D
não sim
EXEMPLO – CONVERSOR ANALÓGICO-DIGITAL#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void main(void) {
OSCCON = 0b01100000; // Define velocidade do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
TRISC = 0b00000000; // Habilita porta C como saída
TRISA = 0x00000001; // Habilita pino A0 como entrada
ADCON2 = 0b10101111; //
ADCON1 = 0b00000000; // Tensões de referência: Vss e Vdd
ANSEL = 0x00000001; // Seleciona o canal AN0
EXEMPLO – CONVERSOR ANALÓGICO-DIGITAL
ADCON0bits.ADON = 1; // Habilita o conversor AD
while(1) { // Inicia loop infinito
ADCON0bits.GO = 1; // Inicia a conversão
while (!ADCON0bits.GODONE) { // Aguarda fim da conversão
}
LATD = ADRESL; // Transfere valor para porta D
LATC = ADRESH; // Transfere valor para porta C
__delay_ms(100); // Atraso de 100 ms
}
}
Fim de Código
EXEMPLO – ADC + LCDInicio
ConfiguraçãoInicia leitura da tensão
no pino A0
Finalizou leitura?
Calcula tensão no pino e exibe valor lido e
tensão calculada no LCD
não sim
EXEMPLO – ADC + LCD#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#define RS LATD2 // < Pinos do LCD
#define EN LATD3
#define D4 LATD4
#define D5 LATD5
#define D6 LATD6
#define D7 LATD7 // Pinos do LCD >
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#include "lcd.h"
#include <stdio.h>
char linha1[16]; // Variável linha1 com 16 caracteres
char linha2[16]; // Variável linha2 com 16 caracteres
EXEMPLO – ADC + LCD
int contador = 0; // Variável contador com valor inicial 0
float tensao = 0.0; // Variável tensao com valor inicial 0.0
void setupADC(void) {
TRISA = 0b00000001; // Habilita pino A0 como entrada
ADCON2bits.ADCS = 0b111; // Tempo de aquisição: 4 Tad
ADCON2bits.ACQT = 0b110; // Clock do AD: Fosc/64
ADCON2bits.ADFM = 0b1; // Formato: à direita
ADCON1bits.VCFG = 0b00; // Tensões de referência: Vss e Vdd
ANSEL = 0x00000001; // Seleciona o canal AN0
ADCON0bits.ADON = 1; // Liga o AD
}
void main(void) {
OSCCON = 0b01010000; // Define velocidade do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
EXEMPLO – ADC + LCDsetupADC();
Lcd_Init(); // Inicia o LCD
while(1) { // Inicia loop infinito
ADCON0bits.GO = 1; // Inicia a conversão A/D
while (!ADCON0bits.GODONE) { // Aguarda fim da conversão
}
contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável
tensao = ((5 * contador) * 0.0009765625); // Calcula tensão real
sprintf(linha1, "Conversor: %4i ", contador); // Grava texto em linha1
sprintf(linha2, "Tensao: %1.2f ",tensao); // Grava texto em linha2
Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1
Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD
Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1
Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD
}
}
Fim de Código
EXEMPLO – ADC + LCD + DOIS CANAISInicio
Configuração Lê tensão no pino A0
Atualiza LCD com valor lido
Atualiza LCD com valor lido
Lê tensão no pino A1
EXEMPLO – ADC + LCD + DOIS CANAIS#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#define RS LATD2 // < Pinos do LCD
#define EN LATD3
#define D4 LATD4
#define D5 LATD5
#define D6 LATD6
#define D7 LATD7 // Pinos do LCD >
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#include "lcd.h"
#include <stdio.h>
char linha1[16]; // Variável linha1 com 16 caracteres
char linha2[16]; // Variável linha2 com 16 caracteres
EXEMPLO – ADC + LCD + DOIS CANAIS
int contador = 0; // Variável contador com valor inicial 0
float tensao1 = 0.0; // Variável tensao com valor inicial 0.0
float tensao2 = 0.0; // Variável tensao com valor inicial 0.0
void setupADC(void) {
TRISA = 0b00000011; // Habilita pinos A0 e A1 como entrada
ADCON2bits.ADCS = 0b111; // Tempo de aquisição: 4 Tad
ADCON2bits.ACQT = 0b110; // Clock do AD: Fosc/64
ADCON2bits.ADFM = 0b1; // Formato: à direita
ADCON1bits.VCFG = 0b00; // Tensões de referência: Vss e Vdd
ANSEL = 0b00000011; // Habilita canais AN0 e AN1 como AD
ADCON0bits.ADON = 1; // Liga o circuito AD
}
void main(void) {
OSCCON = 0b01010000; // Define velocidade do oscilador para 4MHz
EXEMPLO – ADC + LCD + DOIS CANAIS
TRISD = 0b00000000; // Habilita porta D como saída
setupADC();
Lcd_Init(); // Inicia o LCD
while(1) { // Inicia loop infinito
ADCON0bits.CHS = 0b0000; // Seleciona canal AN0
ADCON0bits.GO = 1; // Inicia a conversão
while (!ADCON0bits.GODONE) { // Aguarda fim da conversão
}
contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável
tensao1 = ((5 * contador) * 0.0009765625); // Calcula tensão real
ADCON0bits.CHS = 0b0001; // Seleciona canal AN1
ADCON0bits.GO = 1; // Inicia a conversão
while (!ADCON0bits.GODONE) { // Aguarda fim da conversão
EXEMPLO – ADC + LCD + DOIS CANAIS
}
contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável
tensao2 = ((5 * contador) * 0.0009765625); // Calcula tensão real
sprintf(linha1, "Tensao 1: %1.2f ",tensao1); // Grava texto em linha1
sprintf(linha2, "Tensao 2: %1.2f ",tensao2); // Grava texto em linha2
Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1
Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD
Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1
Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD
}
}
Fim de Código
EXEMPLO – ADC + LCD + 4 CANAIS#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#define RS LATD2 // < Pinos do LCD
#define EN LATD3
#define D4 LATD4
#define D5 LATD5
#define D6 LATD6
#define D7 LATD7 // Pinos do LCD >
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#include "lcd.h"
#include <stdio.h>
char linha1[16]; // Variável linha1 com 16 caracteres
char linha2[16]; // Variável linha2 com 16 caracteres
EXEMPLO – ADC + LCD + 4 CANAIS
Inicio
Configuração
Atualiza LCD(chama rotina que lê
tensão nos pinos A0 a A4 automaticamente)
EXEMPLO – ADC + LCD + 4 CANAIS
void setupADC(void) {
TRISA = 0b00001111; // Habilita pinos A0 a A3 como entrada
ADCON2bits.ADCS = 0b1111; // Clock do AD: Fosc/64
ADCON2bits.ACQT = 0b110; // Tempo de aquisição automático: 16 Tad
ADCON2bits.ADFM = 0b1; // Formato: à direita
ADCON1bits.VCFG = 0b00; // Tensões de referência: Vss e Vdd
ANSEL = 0b00001111; // Habilita canais AN0 a AN3 como AD
ADCON0bits.ADON = 1; // Liga o circuito AD
}
float leTensao(int canal_adc) {
ADCON0bits.CHS = canal_adc; // Seleciona canal
ADCON0bits.GO = 1; // Inicia a conversão
while (!ADCON0bits.GODONE) { // Aguarda fim da conversão
}
int contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável
EXEMPLO – ADC + LCD + 4 CANAISfloat tensao = ((5 * contador) * 0.0009765625); // Calcula tensão real
return tensao;
}
void main(void) {
OSCCON = 0b01010000; // Define velocidade do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
setupADC();
Lcd_Init(); // Inicia o LCD
while(1) { // Inicia loop infinito
sprintf(linha1, "T0: %1.1f T1: %1.1f", leTensao(0), leTensao(1));
// Grava texto em linha1
sprintf(linha2, "T2: %1.1f T3: %1.1f", leTensao(2), leTensao(3));
// Grava texto em linha2
Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1
Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD
Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1
Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD
}
}
Fim de Código
EXEMPLO – ADC + LCD + 8 CANAIS + INTInicio
Configuração(x = 0)
Atualiza LCDcom as variáveis tensão[0] a
tensão[7];Inicia leitura do pino ANx
Leitura finalizada?
Atualiza variável
tensão[x] com o valor da
tensão no pino Ax;
Incrementa x
não sim x é maior que 7?
sim
x = 0
não
EXEMPLO – ADC + LCD + 8 CANAIS + INT#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#define RS LATD2 // < Pinos do LCD
#define EN LATD3
#define D4 LATD4
#define D5 LATD5
#define D6 LATD6
#define D7 LATD7 // Pinos do LCD >
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#include "lcd.h"
#include <stdio.h>
char linha1[16]; // Variável linha1 com 16 caracteres
char linha2[16]; // Variável linha2 com 16 caracteres
EXEMPLO – ADC + LCD + 8 CANAIS + INT
int canal = 0; // Variável que diz qual canal é lido atualmente
float tensao[8]; // Vetor que guarda a tensão em cada um dos canais
bit atualizado; // Flag que indica se todos canais já foram lidos
void setupADC(void) {
TRISA = 0b00101111; // Habilita pinos A0 a A3 e A5 como entrada
TRISE = 0b00000111; // Habilita pinos E0 a E2 como entrada
// São os pinos relativos a AN0 a AN7
ADCON2bits.ADCS = 0b1111; // Clock do AD: Fosc/64
ADCON2bits.ACQT = 0b110; // Tempo de aquisição automático: 16 Tad
ADCON2bits.ADFM = 0b1; // Formato: à direita
ADCON1bits.VCFG = 0b00; // Tensões de referência: Vss e Vdd
ANSEL = 0b11111111; // Habilita canais AN0 a AN7 como AD
ADCON0bits.ADON = 1; // Liga o circuito AD
}
EXEMPLO – ADC + LCD + 8 CANAIS + INTvoid setupInterrupcao(void) {
GIE = 1; // Habilita interrupção global
PEIE = 1; // ADC exige interrupção de periféricos habilitada
ADIE = 1; // Liga interrupção pelo AD
}
void interrupt adc_interrupt(void) {
if (ADIF) {
int contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável
tensao[canal] = ((5 * contador) * 0.0009765625); // Calcula tensão real
if (canal == 7) { // Verificação para alternar
canal = 0; // o canal lido a cada interrupcao
ADCON0bits.CHS = canal; // Seleciona canal
atualizado = 1; // Marca a flag caso ja leu os 4 canais
} else {
canal++; // Atualiza o canal
ADCON0bits.CHS = canal; // Seleciona canal
ADCON0bits.GO = 1; // Inicia a conversão
}
ADIF = 0; // Desmarca flag da interrupção ADC
EXEMPLO – ADC + LCD + 8 CANAIS + INT
}
}
void main(void) {
OSCCON = 0b01010000; // Define velocidade do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
Lcd_Init(); // Inicia o LCD
setupADC(); // Configura o ADC
setupInterrupcao(); // Configura a interrupção
atualizado = 0; // Marca a flag para atualizar os 8 canais
ADCON0bits.CHS = canal; // Seleciona canal
ADCON0bits.GO = 1; // Inicia a conversão
while(1) { // Inicia loop infinito
sprintf(linha1, "1:%1.0f 2:%1.0f 3:%1.0f 4:%1.0f",
tensao[0], tensao[1], tensao[2], tensao[3]); // Grava texto em linha1
sprintf(linha2, "5:%1.0f 6:%1.0f 7:%1.0f 8:%1.0f",
tensao[4], tensao[5], tensao[6], tensao[7]); // Grava texto em linha2
EXEMPLO – ADC + LCD + 8 CANAIS + INT
Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1
Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD
Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1
Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD
atualizado = 0; // Marca a flag para atualizar os 4 canais
ADCON0bits.GO = 1; // Inicia a conversão
}
}
Fim de Código
EXEMPLO – ADC + LCD + TIMERInicio
Configuração(configura timer para interromper
a cada 10 ms)
Atualiza LCD com o valor da variável “tensão” e
“contador”
Grava tensão do pino AN0 na variável “tensão”;
Incrementa “contador”;
não simInterrupção do conversor AD?
Interrupção do timer?
simInicia leitura no conversor AD
EXEMPLO – ADC + LCD + TIMER#define _XTAL_FREQ 4000000
#define RS LATD2 // < Pinos do LCD
#define EN LATD3
#define D4 LATD4
#define D5 LATD5
#define D6 LATD6
#define D7 LATD7 // Pinos do LCD >
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#include <xc.h>
#include "lcd.h"
#include <stdio.h>
char linha1[16]; // Variável linha1 com 16 caracteres
char linha2[16]; // Variável linha2 com 16 caracteres
int contador = 0; // Variável contador com valor inicial 0
EXEMPLO – ADC + LCD + TIMER
float tensao = 0.0; // Variável que guarda a tensão lida no conversor AD
long contagem = 10000; // Variável que define quantos us serão contados a cada conversão
void interrupt interrupcao() {
if (ADIF) {
int leitura_adc = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável
tensao = ((5 * leitura_adc) * 0.0009765625); // Calcula tensão real
contador++; // Incrementa contador
ADIF = 0; // Desmarca flag da interrupção ADC
}
if (TMR3IF) {
TMR3H = (0xFFFF - contagem) >> 8; // Cálculo do valor inicial do TMR3
TMR3L = ((0xFFFF - contagem) & 0xFF); // Cálculo do valor inicial do TMR3
LATDbits.LD0 = !LATDbits.LD0; // Inverte sinal no pino D0
TMR3IF = 0; // Limpa a Flag da interrupção
ADCON0bits.GO = 1; // Inicia conversao AD
}
}
EXEMPLO – ADC + LCD + TIMER
void setupTmr3() {
T3CKPS0 = 0; // Prescaler
T3CKPS1 = 0; // Prescaler
TMR3CS = 0; // Clock origina do clock interno
TMR3H = (0xFFFF - contagem) >> 8; // Cálculo do valor inicial do TMR3
TMR3L = ((0xFFFF - contagem) & 0xFF); // Cálculo do valor inicial do TMR3
TMR3ON = 1; // Liga o timer
}
void setupADC(void) {
TRISA = 0b00000001; // Habilita pino A0entrada
ADCON2bits.ADCS = 0b1111; // Clock do AD: Fosc/64
ADCON2bits.ACQT = 0b110; // Tempo de aquisição automático: 16 Tad
ADCON2bits.ADFM = 0b1; // Formato: à direita
ADCON1bits.VCFG = 0b00; // Tensões de referência: Vss e Vdd
EXEMPLO – ADC + LCD + TIMER
ANSEL = 0b00000001; // Habilita canal AN0
ADCON0bits.ADON = 1; // Liga o circuito AD
}
void setupInt(void) {
GIE = 1; // Habilita interrupção global
PEIE = 1; // Habilita interrupção de periféricos
TMR3IE = 1; // Interrupção do timer 3
ADIE = 1; // Habilita interrupção do ADC
}
void main(void) {
OSCCON = 0b01010000; // Oscilador interno a 4 MHz
TRISA = 1; // A0 como entrada
TRISD = 0; // Define porta D inteira como saída
setupADC(); // Configuração do ADC
setupInt(); // Configuração da Interrupção
EXEMPLO – ADC + LCD + TIMER
setupTmr3(); // Configuração do Timer 3
Lcd_Init(); // Inicia o LCD
while(1) {
sprintf(linha1, "N: %i", contador); // Grava texto em linha1
Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1
Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD
sprintf(linha2, "Tensao: %3.2f", tensao); // Grava texto em linha2
Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1
Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD
}
}
Fim de Código
EXEMPLO – PWM
Inicio
Configuração(configura
temporizador e PWM)
. . . É, não faz nada.
EXEMPLO – PWM#define _XTAL_FREQ 4000000
#pragma config FOSC = INTIO // Oscilador interno
#pragma config WDT = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#pragma config CCP2MX = PORTC // Saída do PWM na porta C
#include <xc.h>
void setupTmr2() {
TMR2 = 0x00; // Começa a contar de 0
PR2 = 249; // até 250 (conta 250 vezes + recarga automatica)
}
void setupPWM (void) {
TRISCbits.RC1 = 1; // "desliga" bit de saída
setupTmr2(); // Configura timer 2
CCP2CONbits.CCP2M = 0b1100; // Modo PWM ativo
CCPR2L = 128; // Configura % do PWM (0 - 255), portanto 128 = 50%
EXEMPLO – PWM
TMR2IF = 0; // Limpa flag do TMR2
TMR2ON = 1; // Dispara o timer
TRISCbits.RC1 = 0; // "liga" bit de saída
}
void main(void) {
OSCCON = 0b01010000; // Oscilador interno a 4 MHz
setupPWM();
while(1) {
}
}
// Gera um sinal PWM na saída do pino RC1
Fim de Código
EXEMPLO – PWM + ADCInicio
ConfiguraçãoInicia conversão AD no pino
AN0
Atualiza valor do “duty cycle” do PWM baseado no valor de
tensão lido no pino AN0
não simInterrupção do conversor AD?
EXEMPLO – PWM + ADC#define _XTAL_FREQ 4000000
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#pragma config CCP2MX = PORTC // Saída do PWM na porta C
#include <xc.h>
long contagem = 0; // Variável auxiliar
void interrupt interrupcao() {
if (ADIF) {
contagem = (ADRESH * 0x100) + ADRESL; // Transfere a leitura do AD para a
contagem = contagem >> 2; // variavel 'contagem'
CCPR2L = contagem; // % é igual aos 8 MSB do ADC
ADIF = 0; // Desmarca flag da interrupção ADC
}
if (TMR2IF) { // Caso a flag do temporizador esteja ativa,
TMR2IF = 0; // desmarca a mesma
EXEMPLO – PWM + ADC
}
}
void setupTmr2() {
TMR2 = 0x00; // Começa a contar de 0
PR2 = 249; // até 250 (conta 250 vezes + recarga automatica)
}
void setupADC(void) {
TRISA = 0b00000001; // Habilita pino A0entrada
ADCON2bits.ADCS = 0b1111; // Clock do AD: Fosc/64
ADCON2bits.ACQT = 0b110; // Tempo de aquisição automático: 16 Tad
ADCON2bits.ADFM = 0b1; // Formato: à direita
ADCON1bits.VCFG = 0b00; // Tensões de referência: Vss e Vdd
ANSEL = 0b00000001; // Habilita canal AN0
EXEMPLO – PWM + ADC
ADCON0bits.ADON = 1; // Liga o circuito AD
}
void setupInt(void) {
GIE = 1; // Habilita interrupção global
PEIE = 1; // Habilita interrupção de periféricos
TMR2IE = 1; // Interrupção do timer 1
ADIE = 1; // Habilita interrupção do ADC
}
void setupPWM (void) {
TRISCbits.RC1 = 1; // "desliga" bit de saída
setupTmr2(); // Configura timer 2
CCP2CONbits.CCP2M = 0b1100; // Modo PWM ativo
CCPR2L = 128; // Configura % do PWM (0 - 255)
TMR2IF = 0; // Limpa flag do TMR2
TMR2ON = 1; // Dispara o timer
EXEMPLO – PWM + ADC
TRISCbits.RC1 = 0; // "liga" bit de saída
}
void main(void) {
OSCCON = 0b01010000; // Oscilador interno a 4 MHz
TRISD = 0; // Define porta D inteira como saída
LATD = 1; // Acende o primeiro LED da porta D
setupADC(); // Configuração do ADC
setupInt(); // Configuração da Interrupção
setupPWM(); // Configuração do PWM
while(1) {
ADCON0bits.GO = 1; // Lê ADC, para recarregar valor no PWM
while (ADCON0bits.NOT_DONE) {
}
}
}
// Gera um sinal PWM na saída com ciclo variando de acordo com a tensão no pino A0
Fim de Código
EXEMPLO - SERIALInicio
Configuração;Envia texto pra
porta serial;Aguarda interrupção
Envia texto para a porta serial com caractere digitado;
não simInterrupção da recepção
serial?
EXEMPLO - SERIAL#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#include <stdlib.h>
#define _XTAL_FREQ 4000000 // Oscilador interno de 4 MHz
#include <xc.h>
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
char caracter;
bit flag_interrupcao = 0;
void interrupt RS232(void) //vetor de interrupção
{
caracter = RCREG; // Lê caractere recebido do registrador
flag_interrupcao = 1; // Habilita variável indicando que houve recepção
RCIF = 0; // Limpa flag de interrupção de recepção
}
SERIALvoid inicializa_RS232(long velocidade,int modo)
{
RCSTA = 0X90; // Habilita porta serial, recepção de
// 8 bits em modo continuo, assíncrono.
int valor;
if (modo == 1) { // modo = 1, modo alta velocidade
TXSTA = 0X24; // modo assíncrono, transmissão 8 bits.
valor =(int)(((_XTAL_FREQ/velocidade)-16)/16); // Cálculo do baud rate
} else { //modo = 0 ,modo baixa velocidade
TXSTA = 0X20; //modo assincrono,trasmissao 8 bits.
valor =(int)(((_XTAL_FREQ/velocidade)-64)/64);
//calculo do valor do gerador de baud rate
}
SPBRG = valor;
RCIE = 1; //habilita interrupção de recepção
TXIE = 0; //deixa interrupção de transmissão desligado
//(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
}
SERIAL
void escreve(char valor)
{
TXIF = 0; // limpa flag que sinaliza envio completo.
TXREG = valor; // Envia caractere à porta serial
while(TXIF ==0); // espera caractere ser enviado
}
void imprime(const char frase[])
{
char indice = 0; // índice da cadeia de caracteres
char tamanho = strlen(frase); // tamanho total da cadeia a ser impressa
while(indice < tamanho ) { // verifica se todos foram impressos
escreve(frase[indice]); // Chama rotina que escreve o caractere
indice++; // incrementa índice
}
}
SERIAL
void main(void)
{
OSCCON = 0b01010000; // Oscilador interno a 4 MHz
TRISB = 0X02; // configura portB B1 (pino RX) como entrada
PORTB = 0; // limpar as portas que estão configuradas como saidas
inicializa_RS232(9600,1); // modo de alta velocidade
GIE = 1; // GIE: Global Interrupt Enable bit
PEIE = 1; // habilita interrupção de periféricos do pic
imprime("Usando a serial MPLAB X XC8 \n\r");
imprime(“Digite algo: \n\r");
while (1) {
if(flag_interrupcao == 1) { //tem dados para ler
imprime(" \n\rCaractere digitado :");
escreve(caracter);
flag_interrupcao = 0;
}
} //loop infinito
}
Fim de Código
EXEMPLO – SERIAL + LCDInicio
Configuração;Envia texto pra porta serial e
LCD;
Aguarda interrupção
Envia texto para a porta serial e LCD com caractere digitado;
não simInterrupção da recepção
serial?
Organiza posição do caractere na segunda linha
do LCD
EXEMPLO – SERIAL + LCD#define _XTAL_FREQ 4000000 // Oscilador interno de 4 MHz
#include <xc.h>
#define RS LATD2 // < Pinos do LCD
#define EN LATD3
#define D4 LATD4
#define D5 LATD5
#define D6 LATD6
#define D7 LATD7 // Pinos do LCD >
#include "lcd.h"
#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#include <stdlib.h>
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
EXEMPLO – SERIAL + LCD
char caracter;
char linha1[16]; // Variável linha1 com 16 caracteres
char linha2[16]; // Variável linha2 com 16 caracteres
bit flag_interrupcao = 0;
void interrupt RS232(void) //vetor de interrupção
{
caracter = RCREG; // Lê caractere recebido do registrador
flag_interrupcao = 1; // Habilita variável indicando que houve recepção
RCIF = 0; // Limpa flag de interrupção de recepção
}
void inicializa_RS232(long velocidade,int modo)
{
RCSTA = 0X90; // Habilita porta serial, recepção de
// 8 bits em modo continuo, assíncrono.
int valor;
if (modo == 1) { // modo = 1, modo alta velocidade
EXEMPLO – SERIAL + LCD
TXSTA = 0X24; // modo assíncrono, transmissão 8 bits.
valor =(int)(((_XTAL_FREQ/velocidade)-16)/16); // Cálculo do baud rate
} else { //modo = 0 ,modo baixa velocidade
TXSTA = 0X20; //modo assincrono,trasmissao 8 bits.
valor =(int)(((_XTAL_FREQ/velocidade)-64)/64);
//calculo do valor do gerador de baud rate
}
SPBRG = valor;
RCIE = 1; //habilita interrupção de recepção
TXIE = 0; //deixa interrupção de transmissão desligado
//(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
}
void escreve(char valor)
{
TXIF = 0; // limpa flag que sinaliza envio completo.
TXREG = valor; // Envia caractere à porta serial
while(TXIF ==0); // espera caractere ser enviado
}
EXEMPLO – SERIAL + LCD
void imprime(const char frase[])
{
char indice = 0; // índice da cadeia de caracteres
char tamanho = strlen(frase); // tamanho total da cadeia a ser impressa
while(indice < tamanho ) { // verifica se todos foram impressos
escreve(frase[indice]); // Chama rotina que escreve o caractere
indice++; // incrementa índice
}
}
void main(void)
{
OSCCON = 0b01010000; // Oscilador interno a 4 MHz
TRISB = 0X02; // configura portB B1 (pino RX) como entrada
PORTB = 0; // limpar as portas que estão configuradas como saidas
inicializa_RS232(9600,1); // modo de alta velocidade
GIE = 1; // GIE: Global Interrupt Enable bit
PEIE = 1; // habilita interrupção de perifericos do pic
EXEMPLO – SERIAL + LCD
TRISD = 0x00; // configura portD como saída
Lcd_Init(); // Inicia o LCD
int posicao = 1; // Variável que guarda posição do caractere no LCD
imprime("Usando a serial MPLAB X XC8 \n\r"); // Envia texto para a serial
imprime("Digite algo: \n\r");
Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1
sprintf(linha1, "Digite algo:"); // Grava texto em linha1
Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD
while (1) {
if(flag_interrupcao == 1) { // Tem dados para ler
imprime(" \n\rCaractere digitado: ");
escreve(caracter);
Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1
sprintf(linha1, "Ultima tecla: %c", caracter); // Grava texto em linha1
Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD
EXEMPLO – SERIAL + LCD
Lcd_Set_Cursor(2,posicao); // Posiciona o cursor na linha 2, ultima posicao
sprintf(linha1, "%c", caracter); // Grava texto em linha2
Lcd_Write_String(linha1); // Escreve texto de linha2 no LCD
if (posicao == 16) {
posicao = 1;
} else {
posicao++;
}
flag_interrupcao = 0;
}
} //loop infinito
}
Fim de Código
EXEMPLO – SERIAL + ADCInicio
Configuração;Envia texto pra
porta serial;
Inicia leitura da tensão no pino AN0
Envia texto para a porta serial com tensão lida;
não simFinalizou a
leitura?
EXEMPLO – SERIAL + ADC#define _XTAL_FREQ 4000000 // Oscilador interno de 4 MHz
#include <xc.h>
#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#include <stdlib.h>
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
char caracter;
bit flag_interrupcao = 0;
char linha[22];
int contador;
float tensao;
void inicializa_RS232(long velocidade,int modo)
{
RCSTA = 0X90; // Habilita porta serial, recepção de
EXEMPLO – SERIAL + ADC
// 8 bits em modo continuo, assíncrono.
int valor;
if (modo == 1) { // modo = 1, modo alta velocidade
TXSTA = 0X24; // modo assíncrono, transmissão 8 bits.
valor =(int)(((_XTAL_FREQ/velocidade)-16)/16); // Cálculo do baud rate
} else { //modo = 0 ,modo baixa velocidade
TXSTA = 0X20; //modo assincrono,trasmissao 8 bits.
valor =(int)(((_XTAL_FREQ/velocidade)-64)/64);
//calculo do valor do gerador de baud rate
}
SPBRG = valor;
RCIE = 1; //habilita interrupção de recepção
TXIE = 0; //deixa interrupção de transmissão desligado
//(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
}
void escreve(char valor)
{
TXIF = 0; // limpa flag que sinaliza envio completo.
EXEMPLO – SERIAL + ADC
TXREG = valor; // Envia caractere à porta serial
while(TXIF ==0); // espera caractere ser enviado
}
void imprime(const char frase[])
{
char indice = 0; // índice da cadeia de caracteres
char tamanho = strlen(frase); // tamanho total da cadeia a ser impressa
while(indice < tamanho ) { // verifica se todos foram impressos
escreve(frase[indice]); // Chama rotina que escreve o caractere
indice++; // incrementa índice
}
}
void setupADC(void) {
TRISA = 0b00000001; // Habilita pino A0 como entrada
ADCON2bits.ADCS = 0b111; // Tempo de aquisição: 4 Tad
ADCON2bits.ACQT = 0b110; // Clock do AD: Fosc/64
EXEMPLO – SERIAL + ADC
ADCON2bits.ADFM = 0b1; // Formato: à direita
ADCON1bits.VCFG = 0b00; // Tensões de referência: Vss e Vdd
ANSEL = 0x00000001; // Seleciona o canal AN0
ADCON0bits.ADON = 1; // Liga o AD
}
void SuperDelay(long counter) { // Função com valor de entrada “counter”
counter = counter / 10; // Divide o valor informado por 10
for (long i = 1; i <= counter; i++) { // E usa o resultado como base
__delay_ms(10); // Para repetir uma contagem de 10 ms
}
}
void main(void)
{
OSCCON = 0b01010000; // Oscilador interno a 4 MHz
EXEMPLO – SERIAL + ADCTRISB = 0X02; // configura portB B1 (pino RX) como entrada
PORTB = 0; // limpar as portas que estão configuradas como saidas
inicializa_RS232(9600,1); // modo de alta velocidade
setupADC(); // Configuração do AD
sprintf(linha, "Tensão lida: 0.000"); // Grava texto em linha1
imprime(linha);
while (1) {
ADCON0bits.GO = 1; // Inicia leitura do ADC
while(ADCON0bits.NOT_DONE) { // Aguarda leitura do ADC
}
contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável
tensao = ((5 * contador) * 0.0009765625); // Calcula tensão real
sprintf(linha, "\b\b\b\b\b%1.3f", tensao); // Grava texto em linha1
imprime(linha);
SuperDelay(1000);
} //loop infinito
}
Fim de Código
PROGRAMAS COM BUGS #1 – ROTAÇÃO DE LEDS
Comportamento esperado:Os LEDs rotacionem no estilo “bate-e-volta”.
Sintoma:Ao iniciar o programa, os LEDscomeçam a rotacionarcorretamente, mas depois de várias rotações, ele volta a rotacionar do primeiro LED.
PROGRAMAS COM BUGS #1 – ROTAÇÃO DE LEDS#define _XTAL_FREQ 1000000 // Oscilador de 1 MHz
#include <xc.h>
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = ON // Watchdog Timer ligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void main(void) {
TRISA = 0b00000000; // Habilita porta A como saída
LATA = 1; // Liga o primeiro pino da porta A
while(1) { // Inicia loop infinito
while(LATA != 0b00000001) {
LATA = (LATA >> 1 | LATA << 7); // Rotacionando com estilo pra esquerda
__delay_ms(100); // Atraso de 100 ms
}
while(LATA != 0b10000000) {
LATA = (LATA << 1 | LATA >> 7); // Rotacionando com estilo pra direita
__delay_ms(100); // Atraso de 100 ms
}
}
}
Fim de Código
PROGRAMAS COM BUGS #2 – ROTAÇÃO DE LEDS
Comportamento esperado:Os LEDs rotacionem no estilo “bate-e-volta”.
Sintoma:Ao iniciar o programa, nada acontece.
PROGRAMAS COM BUGS #2 – ROTAÇÃO DE LEDS#define _XTAL_FREQ 1000000 // Oscilador de 1 MHz
#include <xc.h>
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = ON // Watchdog Timer ligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void main(void) {
TRISA = 0b00000000; // Habilita porta A como saída
LATA = 1; // Liga o primeiro pino da porta A
while(1) { // Inicia loop infinito
while(LATA != 0b00000001) {
LATA = (LATA >> 1 | LATA << 7); // Rotacionando com estilo pra esquerda
__delay_ms(100); // Atraso de 100 ms
}
while(LATA != 0b10000000) {
LATA = (LATA << 1 | LATA >> 7); // Rotacionando com estilo pra direita
__delay_ms(100); // Atraso de 100 ms
}
}
}
Fim de Código
PROGRAMAS COM BUGS #3 – ROTAÇÃO DE LEDS
Comportamento esperado:Os LEDs rotacionem no estilo “bate-e-volta”.
Sintoma:Ao iniciar o programa, nada acontece. A tensão nos pinos de saída dos LEDs não mostram nenhum valor bem definido.
PROGRAMAS COM BUGS #3 – ROTAÇÃO DE LEDS#define _XTAL_FREQ 1000000 // Oscilador de 1 MHz
#include <xc.h>
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void main(void) {
LATA = 1; // Liga o primeiro pino da porta A
while(1) { // Inicia loop infinito
while(LATA != 0b00000001) {
LATA = (LATA >> 1 | LATA << 7); // Rotacionando com estilo pra esquerda
__delay_ms(100); // Atraso de 100 ms
}
while(LATA != 0b10000000) {
LATA = (LATA << 1 | LATA >> 7); // Rotacionando com estilo pra direita
__delay_ms(100); // Atraso de 100 ms
}
}
}
Fim de Código
Comportamento esperado:Piscar um LED na porta D0 a cada 100 ms.
Sintoma:O LED pisca, mas o osciloscópio mostra que ele pisca a cada 25 ms.
PROGRAMAS COM BUGS #4 – PISCAR LED
#define _XTAL_FREQ 1000000 // Oscilador de 1 MHz
#include <xc.h>
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void main(void) {
OSCCON = 0b01010000; // Define frequência do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
while(1) { // Inicia loop infinito
LATDbits.LATD0 = !LATDbits.LATD0; // Inverte sinal do pino D0
__delay_ms(100); // Atraso de 100 ms
}
}
Fim de Código
PROGRAMAS COM BUGS #4 – PISCAR LED
Comportamento esperado:Piscar um LED na porta D0 a cada 100 ms.
Sintoma:O LED fica ligado o tempo todo.
PROGRAMAS COM BUGS #5 – PISCAR LED
#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void main(void) {
OSCCON = 0x01010000; // Define frequência do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
while(1) { // Inicia loop infinito
LATDbits.LATD0 = !LATDbits.LATD0; // Inverte sinal do pino D0
__delay_ms(100); // Atraso de 100 ms
}
}
Fim de Código
PROGRAMAS COM BUGS #5 – PISCAR LED
PROGRAMAS COM BUGS #6 – LCD
Comportamento esperado:Escrever “Hello, world!” e um contador na tela do LCD. A cada contagem, o LED da porta D0 deve piscar.
Sintoma:Ao iniciar o programa, o LCD não mostra nada escrito. Apesar disso, o LED pisca.
PROGRAMAS COM BUGS #6 – LCD#define _XTAL_FREQ 1000000
#include <xc.h>
#define RS LATD2 // < Pinos do LCD ligados na porta D
#define EN LATD3
#define D4 LATD4
#define D5 LATD5
#define D6 LATD6
#define D7 LATD7 // Pinos do LCD ligados na porta D >
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
#include "lcd.h"
#include <stdio.h>
PROGRAMAS COM BUGS #6 – LCDchar linha1[16]; // Variável linha1 com 16 caracteres
char linha2[16]; // Variável linha2 com 16 caracteres
int contador = 0; // Variável contador com valor inicial 0
void main(void) {
Lcd_Init(); // Inicia o LCD, ligado na porta D
TRISD = 0; // Define porta D inteira como saída
sprintf(linha1, "Hello world! "); // Grava texto em linha1
Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1
Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD
while(1) {
sprintf(linha2, "Contador: %i ",contador); // Grava texto em linha2
contador ++; // Incrementa contador
Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1
Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD
LATDbits.LATD0 = !LATDbits.LATD0; // Pisca LED na porta D0
}
}
Fim de Código
Comportamento esperado:O LED deve acender ou apagar a cada pressionar do botão ligado à porta B0 (ou INT0)
Sintoma:Nada acontece ao pressionar o botão.
PROGRAMAS COM BUGS #7 – INTERRUPÇÃO
#define _XTAL_FREQ 1000000
#include <xc.h>
#pragma config FOSC = INTIO67 // Oscilador interno
#pragma config WDTEN = OFF // Watchdog Timer desligado
#pragma config MCLRE = OFF // Master Clear desabilitado
void setupInt(void) {
GIE = 1; // Habilita interrupção global
INT0IE = 1; // Interrupção da INT 0
INT0F = 0; // Flag de interrupção da INT 0
INTEDG0 = 1; // Interrupção por borda crescente.
}
PROGRAMAS COM BUGS #7 – INTERRUPÇÃO
void interrupt interrupcao(void) { // Função de interrupção
if (INT0F) { // Caso a flag da INT0 esteja habilitada
LATAbits.LA0 = !LATAbits.LA0; // Inverte o sinal no pino A0
INT0F = 0; // Desabilita a flag da INT0
}
}
void main(void) {
TRISA = 0x00; // Porta A com todos pinos de saída
TRISB = 0x01; // Somente pino B1 como entrada (INT0)
setupInt(); // Função de inicializar Interrupção
while(1) { // Loop infinito
}
}
Fim de Código
PROGRAMAS COM BUGS #7 – INTERRUPÇÃO
PROGRAMAS COM BUGSChecklist contra a maioria dos bugs:
1. Verificar os bits de configuração:• MCLRE – impede qualquer funcionamento;• FOSC – impede qualquer funcionamento;• WDTEN – causa resets inesperados pouco depois de ligado;• PBADEN – impede leitura digital na porta B
2. Verificar se as portas estão definidas corretamente como entrada ou saída na sequência correta:
• Impede leitura ou saída nas portas e funcionamento de periféricos.
3. Verificar velocidade do oscilador ou cristal (definição da frequência em OSCCON) e se está condizente com a definição de _XTAL_FREQ:
• Causa função __delay_ms gerar atrasos diferentes do esperado;
PROGRAMAS COM BUGS
Checklist contra a maioria dos bugs:
4. Verificar se definições de variáveis ou registradores estão corretas:• Usar 0x10101010 é bem diferente de usar 0b10101010;
5. Ler o datasheet.