Escolar Documentos
Profissional Documentos
Cultura Documentos
5 Micro Parte 5 (PIC) Pratica PDF
5 Micro Parte 5 (PIC) Pratica PDF
5 Micro Parte 5 (PIC) Pratica PDF
Prática
Obs.: É importante lembrar que as informações contidas aqui podem variar para outras
famílias PIC ou até mesmo para outros chips da mesma família.
Introdução
O principal microcontrolador utilizado nesse estudo é o PIC18F4550,
cujas características principais são:
3 interrupções externas
Capacidade de corrente nos pinos de I/O: 25 mA
4 módulos temporizadores (Timer 0 a Timer 3)
Até 2 módulos de Captura/Comparação/PWM (CCP)
Unidade interna de USB (transceiver)
Programação via canal serial com 2 pinos
Canal serial universal melhorado (EUSART)
Canal I2C (vários transdutores usam esse canal para a transferência
de dados. Exemplos: giroscópio e barômetro)
PIC18F4550
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: Condição
if:
if (variavel == 10) {
// executa se condição for verdadeira
} else {
// executa se condição for falsa
}
Linguagem C – compilador XC8
Loops:
While:
while (variavel != 0) {
// código em loop
}
Linguagem C – compilador XC8
Loops:
for:
for (variavel = 1; variavel < 100; variavel++)
{
// código em loop
}
Linguagem C – compilador XC8
Valor inicial
Loops:
for:
for (variavel = 1; variavel < 100; variavel++)
{
// código em loop
}
Linguagem C – compilador XC8
Condição (executa enquanto for 1)
Loops:
for:
for (variavel = 1; variavel < 100; variavel++)
{
// código em loop
}
Linguagem C – compilador XC8
Incremento
Loops:
for:
for (variavel = 1; variavel < 100; variavel++)
{
// código em loop
}
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);
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];
char linha1[16];
contador = 15;
char linha1[16];
contador = 15;
sprintf(linha1, “Contagem: %3.2i”, contador);
char linha1[16];
temperatura = 37.52;
char linha1[16];
caractere_U = 0x55;
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
Inicio
void main(void) {
OSCCON = 0b01100000; // Define frequência do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
Fim de Código
EXEMPLO – PISCAR LED (VERSÃO 2)
#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#define Led LATDbits.LATD0
void main(void) {
Fim de Código
EXEMPLO – PISCAR LED – 1 SEGUNDO
Inicio
#include <xc.h>
void main(void) {
OSCCON = 0b01100000; // Define velocidade do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
EXEMPLO – PISCAR LED – 1 SEGUNDO
Fim de Código
EXEMPLO 1 DE ROTAÇÃO DE LEDS
Inicio
Rotaciona 1 passo
Configuração
para a esquerda
não sim
PORTD=0? LATD = 1
#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#pragma config FOSC = HS // Cristal oscilador externo (clock externo)
#pragma config WDT= OFF // Watchdog Timer desligado
#pragma config MCLRE = ON // Define pino 1 como Reset
if (PORTD == 0)
{
LATD = 1;
SuperDelay(500);
}
}
return; Fim de Código
}
EXEMPLO 2 DE ROTAÇÃO DE LEDS
Inicio
Rotaciona 1 passo
Configuração
para a esquerda
não sim
PORTD=0? LATD = 1
#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
void main(void) {
Fim de Código
EXEMPLO 3 – ROTACIONAR LED
Inicio
LED aceso
não na borda sim Rotaciona para a
esquerda direita
?
EXEMPLO – ROTACIONAR 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) {
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ÇÃO
Digamos 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;
Display LCD
EXEMPLO – LCD
Inicio
Configuração Adiciona 1 em
contador
#include <xc.h>
Conexão da Porta D #define RS LATD2 // < Pinos do LCD
no LCD #define EN LATD3
Os pinos D0, D1, D2 #define D4 LATD4
e D3 do LCD são #define D5 LATD5
conectados ao Terra #define D6 LATD6
#define D7 LATD7 // Pinos do LCD >
void main(void) {
TRISD = 0; // Define porta D inteira como saída
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
Adiciona 0.01 em
Configuração
contador
#include <xc.h>
#include "lcd.h"
#include <stdio.h>
EXEMPLO – LCD + CONTADOR FLOAT
char 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
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
Interrupções
Linguagem C – compilador XC8
Registradores importantes - interrupção:
GIE: bit que habilita a interrupção global:
GIE = 1; // Habilita interrupção
Inicio
Aguarda
Configuração
interrupção
não
Interrupção sim
Inverte sinal do LED
ativada?
EXEMPLO – INTERRUPÇÃO (INT0)
#include <xc.h>
void setupInt(void) {
GIE = 1; // Habilita interrupção global
INT0IE = 1; // Habilita Interrupção da INT0
INT0F = 0; // Zera a Flag de interrupção da INT0
INTEDG0 = 1; // Interrupção por borda crescente.
}
Para usar a interrupção INT0 (Pino RB0, da porta B), deve-se desabilitar o conversor AD dessa porta
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
Conversor
Analógico/Digital
(10 bits)
Características do Conversor Analógico Digital (ADC):
10 bits
13 entradas multiplexadas
Registradores importantes:
Registrador Função
ADRESH Byte superior do resultado
ADRESL Byte inferior do resultado
ADCON0 Registrador de controle 0 – escolha de canais, liga/desliga/inicia conversão
ADCON1 Registrador de controle 1 – tensão de referência / configuração dos pinos
de entrada como analógico ou digital
ADCON2 Registrador de controle 2 – configura a fonte de clock e a taxa de
aquisição
Linguagem C – compilador XC8
Registradores importantes – ADC (PIC18F4550):
Inicia leitura da
Configuração
tensão no pino A0
#include <xc.h>
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
Fim de Código
EXEMPLO – ADC + LCD
Inicio
Inicia leitura da
Configuração
tensão no pino A0
#include <xc.h>
#include "lcd.h"
#include <stdio.h>
void setupADC(void) {
TRISA = 0b00000001; // Habilita pino A0 como entrada
ADCON0bits.ADON = 1; // Liga o AD
}
void main(void) {
OSCCON = 0b01100000; // Define velocidade do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
EXEMPLO – ADC + LCD
setupADC();
Fim de Código
EXEMPLO – ADC + LCD + DOIS CANAIS
Inicio
Lê tensão no pino
A1 e guarda
EXEMPLO – ADC + LCD + DOIS CANAIS
#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#include "lcd.h"
#include <stdio.h>
void setupADC(void) {
TRISA = 0b00000011; // Habilita pinos A0 e A1 como entrada
void main(void) {
OSCCON = 0b01100000; // 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
Fim de Código
EXEMPLO – ADC + LCD + 4 CANAIS
Início
Atualiza LCD
(chama rotina que
Configuração lê tensão nos pinos
A0 a A4
automaticamente)
EXEMPLO – ADC + LCD + 4 CANAIS
#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#include "lcd.h"
#include <stdio.h>
void setupADC(void) {
void main(void) {
OSCCON = 0b01100000; // 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
Fim de Código
EXEMPLO – ADC + LCD + 8 CANAIS + INT
Inicio
Atualiza LCD
com as variáveis
Configuração
tensão[0] a tensão[7];
(x = 0)
Inicia leitura do pino
ANx
Atualiza não
variável
Leitura tensão[x] com xé
finalizada o valor da maior
não ? sim tensão no pino que 7?
Ax;
Incrementa x sim
x=0
EXEMPLO – ADC + LCD + 8 CANAIS + INT
#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#include "lcd.h"
#include <stdio.h>
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
}
EXEMPLO – ADC + LCD + 8 CANAIS + INT
void 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 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
Fim de Código
TEMPORIZADORES/
CONTADORES
Timer 0 configurado para 8 bits
(T08BIT = 1) ou 16 bits (T08BIT = 0)
Inicio
Configuração
(temporizador
Aguarda
configurado para
interrupção
gerar interrupção
a cada 50 ms)
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 (operando como temporizador, e não como contador
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
LATDbits.LD0 = !LATDbits.LD0; // Inverte pino D0
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) {
TRISD = 0x00; // Porta D como saída
setupInt(); // Função de habilitar interrupção
setupTmr0(); // Função de configurar timer 0
while(1) { // Loop infinito
}
}
// O código acima inverte o sinal do pino D0 a cada 50000 us, via temporizador 0.
Fim de Código
EXEMPLO – TEMPORIZADOR 0 + PRESCALER
Inicio
Configuração
(temporizador
Aguarda
configurado para
interrupção
gerar interrupção
a cada 1s)
Interrupção
Inverte sinal do LED
ativada? sim
não
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.
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; // Fonte do clock = interna
PSA = 0; // Habilita Prescaler
T0CONbits.T0PS = 0b100; // Multiplicador Prescaler: 32 x 31.250us = 1 s
EXEMPLO – TEMPORIZADOR 0 + PRESCALER PIC16F4550
TMR0H = 0x85; // Começa a contar de 34285
TMR0L = 0xED; // até 65535 (conta 31250 vezes)
TMR0ON = 1; // Liga o timer
}
Fim de Código
Temporizador 2
Em operação normal, o Timer 2 começa a contar de TMR2 = 0 e, a cada ciclo de
contagem, compara os valores de TMR2 e PR2. Quando os dois valores forem iguais, ele
gera um sinal na saída do temporizador, além de zerar o registrador TMR2 e setar a flag
TMR2IF.
EXEMPLO – TEMPORIZADOR 2
Inicio
Configuração
(temporizador
Aguarda
configurado para
interrupção
gerar interrupção
a cada 10 ms)
Interrupção
Inverte sinal do LED
ativada? sim
não
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 = HS // Oscilador Externo
#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 2
TMR2 = 0x00; // Começa a contar de 0
PR2 = 249; // até 249 (conta 250 vezes + recarga automatica)
TMR2ON = 1; // Liga o timer
}
void main(void) {
setupInt(); // Função de habilitar interrupção
setupTmr2(); // Função de configurar timer 0
TRISD = 0x00; // Porta D como saída
while(1) { // Loop infinito
}
} // O código acima inverte o valor do pino D0 a cada 10 ms usando o Timer 2.
Fim de Código
EXEMPLO – ADC + LCD + TIMER
Inicio
Configuração
Atualiza LCD com o
(configura timer
valor da variável
para interromper
“tensão” e “contador”
a cada 10 ms)
não sim
Interrupção Inicia leitura no
do timer? conversor AD
EXEMPLO – ADC + LCD + TIMER
#define _XTAL_FREQ 4000000
#include <xc.h>
#include "lcd.h"
#include <stdio.h>
void setupADC(void) {
TRISA = 0b00000001; // Habilita pino A0 entrada
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
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
MÓDULOS DE CAPTURE/
COMPARE/PWM
(CCP)
Os módulos de Captura, Comparação e
PWM contém:
1 registrador de 16 bits que opera como registrador de captura
Permanecer inalterado
Modo PWM
No modo PWM (Modulação de
Largura de Pulso), o pino CCPx produz
uma saída PWM com resolução de
até 10 bits.
TMR2 é zerado
Inicio
Configuração
(configura
. . . É, não faz nada.
temporizador
e PWM)
EXEMPLO – PWM
#define _XTAL_FREQ 4000000
#include <xc.h>
void setupTmr2() {
TMR2 = 0x00; // Começa a contar de 0
PR2 = 249; // até 250 (conta 250 vezes + recarga automatica)
}
void main(void) {
OSCCON = 0b01100000; // Oscilador interno a 4 MHz
setupPWM();
while(1) {
}
}
Fim de Código
EXEMPLO – PWM + ADC
Inicio
Inicia conversão AD no
Configuração
pino AN0
#include <xc.h>
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
void main(void) {
OSCCON = 0b01100000; // 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
TRANSDUTOR DE TEMPERATURA
+ LCD
LM35 + LCD
Inicio
A tensão de referência
do AD é fundamental
porque a tensão máxima Converte leitura do AD
Acabou a
de saída do LM35 é 1,5 V, em temperatura
não conversão? sim
para uma temperatura Mostra valor no LCD
de 150ºC
LM35 + LCD
#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "lcd.h"
void setupADC(void) {
TRISA = 0b00000001; // Habilita pino A0 como entrada
Com essa configuração, a tensão de referência positiva VREF+ para o AD está no pino AN3. Foi utilizada
uma fonte de 1,5 V nesse pino. Assim, a saída máxima do LM35 resulta na saída máxima do AD
LM35 + LCD
void main(void) {
OSCCON = 0b01100000; // Define velocidade do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
setupADC();
Lcd_Init(); // Inicia o LCD
Bit de seleção da polaridade dos dados Bit que habilita o registrador de baud rate de 16 bits
recebidos BRG16 = 1 gerador de baud rate de 16 bits
Modo assíncrono: habilitado
RXDTP = 1 dado de RX invertido
Modo síncrono: Bit que habilita auto-detecção
RXDTP =1 dado recebido é invertido de baud rate
SERIAL – Baud Rate O valor de “n” na
fórmula de cálculo do
baud rate
corresponde ao par:
SPBRGH:SPBRG
Carregando o valor
desejado nesses
registradores, o PIC
automaticamente
calcula a taxa de
transmissão/recepção
SERIAL – Baud Rate – alguns valores de SPBRGH:SPBRG
para algumas taxas de transmissão/recepção
Modo assíncrono de 8 bits de baixo
baud rate
4. Se quiser usar interrupção da transmissão, fazer TXIE = 1. É necessário também fazer GIE = 1 e PEIE =1
5. Para a transmissão de 9 bits, deve-se fazer TX9=1. O 9º bit deve ser carregado em TX9D
6. Para habilitar a transmissão serial fazer TXEN = 1, que setará também o bit TXIF.
Configuração;
Envia texto pra Aguarda interrupção
porta serial;
#include <xc.h>
char caracter;
bit flag_interrupcao = 0;
SERIAL
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 (BRGH = 1)
TXSTA = 0X24; // modo assíncrono, transmissão 8 bits.
valor =(int)(((_XTAL_FREQ/velocidade)-16)/16); // valor para gerar o baud rate
}
else { //modo = 0 ,modo baixa velocidade (BRGH = 0)
TXSTA = 0X20; //modo assincrono,trasmissao 8 bits.
valor =(int)(((_XTAL_FREQ/velocidade)-64)/64);
//calculo do valor do gerador de baud rate
}
SPBRG = valor; esse registrador, carregado com o “valor” calculado, define o baud rate
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)
}
Fim de Código
EXEMPLO – SERIAL + LCD
Inicio
Configuração;
Organiza posição do
Envia texto pra
Aguarda interrupção caractere na segunda
porta serial e
linha do LCD
LCD;
#include <xc.h>
#include "lcd.h"
#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#include <stdlib.h>
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 main(void)
{
OSCCON = 0b01100000; // 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
while (1) {
if(flag_interrupcao == 1) { // Tem dados para ler
imprime(" \n\rCaractere digitado: ");
escreve(caracter);
if (posicao == 16) {
posicao = 1;
} else {
posicao++;
}
flag_interrupcao = 0;
}
} //loop infinito
Fim de Código
EXEMPLO – SERIAL + ADC
Inicio
Configuração;
Inicia leitura da tensão
Envia texto pra
no pino AN0
porta serial;
#include <xc.h>
#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#include <stdlib.h>
char caracter;
bit flag_interrupcao = 0;
char linha[22];
int contador;
float tensao;
void setupADC(void) {
TRISA = 0b00000001; // Habilita pino A0 como entrada
ADCON0bits.ADON = 1; // Liga o AD
}
void main(void)
{
OSCCON = 0b01010000; // Oscilador interno a 4 MHz
EXEMPLO – SERIAL + ADC
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
setupADC(); // Configuração do AD
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 LEDs
começam a rotacionar
corretamente, 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
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
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
PROGRAMAS COM BUGS #4 – PISCAR LED
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>
void main(void) {
OSCCON = 0b01010000; // Define frequência do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
Fim de Código
PROGRAMAS COM BUGS #5 – 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>
void main(void) {
OSCCON = 0x01010000; // Define frequência do oscilador para 4MHz
TRISD = 0b00000000; // Habilita porta D como saída
Fim de Código
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>
#include "lcd.h"
#include <stdio.h>
PROGRAMAS COM BUGS #6 – LCD
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
void main(void) {
Lcd_Init(); // Inicia o LCD, ligado na porta D
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
PROGRAMAS COM BUGS #7 –
INTERRUPÇÃO
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
#include <xc.h>
void setupInt(void) {
GIE = 1; // Habilita interrupção global
INT0IE = 1; // Habilita Interrupção da INT 0
INT0F = 0; // Limpa Flag de interrupção da INT 0
INTEDG0 = 1; // Interrupção por borda crescente.
}
PROGRAMAS COM BUGS #7 – INTERRUPÇÃO
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
Checklist contra a maioria dos bugs:
5. Ler o datasheet.