Carregar apresentação
A apresentação está carregando. Por favor, espere
1
Microcontroladores PIC
Prática MSc. Gustavo Souto de Sá e Souza
2
Introdução Para fins de avaliação e estudo prático, usaremos os microcontroladores da família PIC18, mais especificamente o PIC18F45K20. É 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.
3
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;
4
Linguagem C – compilador XC8
Definição de variável: Decimal: variavel = 100; Binário: variavel = 0b ; Hexadecimal: variavel = 0x64; Caractere: variavel = “d”;
5
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;
6
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--;
7
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);
8
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”
9
Linguagem C – compilador XC8
Se: if: if (variavel == 10) { // executa se condição for verdadeira } else { // executa se condição for falsa }
10
Linguagem C – compilador XC8
Se: if: if (variavel == 10) { // executa se condição for verdadeira } else { // executa se condição for falsa } Condição
11
Linguagem C – compilador XC8
Loops: While: while (variavel != 0) { // código em loop }
12
Linguagem C – compilador XC8
Loops: While: while (variavel != 0) { // código em loop } Condição (executa enquanto for 1)
13
Linguagem C – compilador XC8
Loops: for: for (variavel = 1; variavel < 100; variavel++) { // código em loop }
14
Linguagem C – compilador XC8
Loops: for: for (variavel = 1; variavel < 100; variavel++) { // código em loop } Valor inicial
15
Linguagem C – compilador XC8
Loops: for: for (variavel = 1; variavel < 100; variavel++) { // código em loop } Condição (executa enquanto for 1)
16
Linguagem C – compilador XC8
Loops: for: for (variavel = 1; variavel < 100; variavel++) { // código em loop } Incremento
17
Linguagem C – compilador XC8
Loops: break: for (variavel = 1; variavel < 100; variavel++) { // código em loop if (variavel < 0) { break; }
18
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
19
Linguagem C – compilador XC8
Funções: Principal: void main (void) { // Código principal do programa vem aqui }
20
Linguagem C – compilador XC8
Funções: Interrupção: void interrupt int_func (void) { // Código da interrupção }
21
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 }
22
Linguagem C – compilador XC8
Funções: Secundárias: void LigaTimer (void) { TMR0ON = 1; }
23
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; }
24
Linguagem C – compilador XC8
Chamando Funções: LigaTimer(); variavel = SomaDez(variavel);
25
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 (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.
26
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++;
27
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
28
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
29
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
30
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
31
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
32
Linguagem C – compilador XC8
Definindo bits de Configuração: #pragma config LVP = OFF; // Desabilita o bit ICSP de fonte de alimentação simples (única)
33
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)
34
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
35
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;
36
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;
37
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;
38
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;
39
Linguagem C – compilador XC8
Registradores essenciais: OSCCON: Byte que define a frequência do oscilador interno do PIC18F45K20: OSCCON=0b ; // Frequência: 16 MHz OSCCON=0b ; // Frequência: 8 MHz OSCCON=0b ; // Frequência: 4 MHz OSCCON=0b ; // Frequência: 1 MHz (padrão)
40
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=0b ; // Frequência: 8 MHz OSCCON=0b ; // Frequência: 4 MHz OSCCON=0b ; // Frequência: 2 MHz OSCCON=0b ; // Frequência: 1 MHz (padrão) OSCCON=0b ; // Frequência: 500 kHz OSCCON=0b ; // Frequência: 250 kHz
41
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
42
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
43
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
44
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
45
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
46
Linguagem C – compilador XC8
Registradores importantes – ADC : ANSEL e ANSELH: bytes que selecionam quais canais analógicos ficam ativos: ANSEL = 0b ; // Habilita ADC nas portas // AN2 e AN4 ANSELH = 0b ; // Habilita ADC nas portas // AN8 até AN12
47
Linguagem C – compilador XC8
Registradores importantes – ADC (PIC18F4550): ADCON0: Registrador de Controle do ADC Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 X CHS3 CHS2 CHS1 CHS0 GO/DONE\ ADON Bits de seleção do Canal Analógico Status da conversão Habilita 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
48
Linguagem C – compilador XC8
Registradores importantes – ADC (PIC18F4550): ADCON1: Registrador de Controle do ADC Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 X VCFG1 VCFG0 PCFG3 PCFG2 PCFG1 PCFG0 Bits de configuração da tensão de referência ADCON1bits.VCFG = 0b00; Tensões de referência: Vss e Vdd
49
Linguagem C – compilador XC8
Registradores importantes – ADC (PIC18F4550): ADCON2: Registrador de Controle do ADC 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 ADCON2bits.ADCS = 0b110 Clock do AD: Fosc/64 ADCON2bits.ACQT = 0b010 Tempo de aquisição: 4 TAD ADCON2bits.ADFM = 0b Formato do resultado: justificado à direita
50
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”
51
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%
52
LEIAM O DATASHEET!
53
EXEMPLO – PISCAR LED Inicio Inverte sinal do pino D0 Configuração
Atrasa 100 ms Configuração
54
EXEMPLO – PISCAR LED Fim de Código
#define _XTAL_FREQ // 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 = 0b ; // Define velocidade do oscilador para 4MHz TRISD = 0b ; // 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
55
EXEMPLO – PISCAR LED – 1 Segundo
Inicio Inverte sinal do pino D0 Atrasa 100 vezes 10 ms Configuração
56
EXEMPLO – PISCAR LED – 1 Segundo
#define _XTAL_FREQ // 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 = 0b ; // Define velocidade do oscilador para 4MHz TRISD = 0b ; // Habilita porta D como saída
57
EXEMPLO – PISCAR LED – 1 Segundo
while(1) { // Inicia loop infinito LATDbits.LATD0 = !LATDbits.LATD0; // Inverte sinal do pino D0 SuperDelay(1000); // Atraso de 1 s } Fim de Código
58
EXEMPLO – ROTACIONAR LED
Inicio LED aceso na borda direita? Rotaciona para a esquerda Configuração sim não LED aceso na borda esquerda? Rotaciona para a direita não sim
59
EXEMPLO – ROTACIONAR LED
#define _XTAL_FREQ // 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 = 0b ; // Habilita porta A como saída LATA = 1; // Liga o primeiro pino da porta A while(1) { // Inicia loop infinito while(LATA != 0b ) { LATA = (LATA >> 1 | LATA << 7); // Rotacionando com estilo pra esquerda __delay_ms(100); // Atraso de 100 ms } while(LATA != 0b ) { LATA = (LATA << 1 | LATA >> 7); // Rotacionando com estilo pra direita Fim de Código
60
EXEMPLO – ROTACIONAR LED - Explicação
Digamos que LATA = 0b LATA >> 1 retorna o seguinte valor: 0b , 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: 0b , 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) = 0b ; Continuemos com LATA = 0b LATA >> 1 retorna o seguinte valor: 0b , 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: 0b , 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) = 0b ;
61
Atualiza LCD com valor de contador
EXEMPLO – LCD Inicio Adiciona 1 em contador Configuração Atualiza LCD com valor de contador
62
EXEMPLO – LCD #define _XTAL_FREQ 1000000 #include <xc.h>
#define RS LATD // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD // 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>
63
EXEMPLO – LCD Fim de Código
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) { 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
64
Atualiza LCD com valor de contador
EXEMPLO – LCD + contador Float Inicio Adiciona 1 em contador Configuração Atualiza LCD com valor de contador
65
EXEMPLO – LCD + contador Float
#define _XTAL_FREQ #include <xc.h> #define RS LATD // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD // 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>
66
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 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 ; // 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
67
EXEMPLO – INTERRUPÇÃO (INT0)
Inicio Aguarda interrupção Configuração Interrupção ativada? Inverte sinal do LED não sim
68
EXEMPLO – INTERRUPÇÃO (INT0)
#define _XTAL_FREQ #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. }
69
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
70
(temporizador configurado para gerar interrupção a cada 50 ms)
EXEMPLO – Temporizador 0 Inicio Configuração (temporizador configurado para gerar interrupção a cada 50 ms) Aguarda interrupção Interrupção ativada? Inverte sinal do LED não sim
71
EXEMPLO – Temporizador 0
#define _XTAL_FREQ // 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é (conta 50 mil vezes) TMR0ON = 1; // Liga o timer
72
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é (conta 50 mil vezes) TMR0IF = 0; // Flag do timer 0 em 0 void main(void) { OSCCON = 0b ; // 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 us, via temporizador 0. Fim de Código
73
(temporizador configurado para gerar interrupção a cada 1s)
EXEMPLO – Temporizador 0 + PRESCALER Inicio Configuração (temporizador configurado para gerar interrupção a cada 1s) Aguarda interrupção Interrupção ativada? Inverte sinal do LED não sim
74
EXEMPLO – Temporizador 0 + PRESCALER
#define _XTAL_FREQ // 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 us = 1 segundo
75
EXEMPLO – Temporizador 0 + PRESCALER
TMR0H = 0x85; // Começa a contar de 34285 TMR0L = 0xED; // até (conta 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é (conta vezes) TMR0IF = 0; // Flag do timer 0 em 0 void main(void) { OSCCON = 0b ; // 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
76
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
77
(temporizador configurado para gerar interrupção a cada 10 ms)
EXEMPLO – Temporizador 2 Inicio Configuração (temporizador configurado para gerar interrupção a cada 10 ms) Aguarda interrupção Interrupção ativada? Inverte sinal do LED não sim
78
EXEMPLO – Temporizador 2
#define _XTAL_FREQ // 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 vezes (~10 ms) por interrupção
79
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 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 = 0b ; // 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
80
EXEMPLO – Conversor ANALÓGICO-DIGITAL
Inicio Configuração Inicia leitura da tensão no pino A0 Finalizou leitura? Grava valor da leitura nos bits da porta C e D não sim
81
EXEMPLO – Conversor ANALÓGICO-DIGITAL
#define _XTAL_FREQ // 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 = 0b ; // Define velocidade do oscilador para 4MHz TRISD = 0b ; // Habilita porta D como saída TRISC = 0b ; // Habilita porta C como saída TRISA = 0x ; // Habilita pino A0 como entrada ADCON2 = 0b ; // ADCON1 = 0b ; // Tensões de referência: Vss e Vdd ANSEL = 0x ; // Seleciona o canal AN0
82
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
83
EXEMPLO – ADC + LCD não sim Inicio Configuração
Inicia 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
84
EXEMPLO – ADC + LCD #define _XTAL_FREQ 4000000 // Oscilador de 4 MHz
#include <xc.h> #define RS LATD // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD // 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
85
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 = 0b ; // 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 = 0x ; // Seleciona o canal AN0 ADCON0bits.ADON = 1; // Liga o AD } void main(void) { OSCCON = 0b ; // Define velocidade do oscilador para 4MHz TRISD = 0b ; // Habilita porta D como saída
86
EXEMPLO – ADC + LCD Fim de Código setupADC();
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) * ); // 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
87
EXEMPLO – ADC + LCD + Dois canais
Inicio Configuração Lê tensão no pino A0 Atualiza LCD com valor lido Atualiza LCD com valor lido Lê tensão no pino A1
88
EXEMPLO – ADC + LCD + Dois canais
#define _XTAL_FREQ // Oscilador de 4 MHz #include <xc.h> #define RS LATD // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD // 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
89
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 = 0b ; // 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 = 0b ; // Habilita canais AN0 e AN1 como AD ADCON0bits.ADON = 1; // Liga o circuito AD } void main(void) { OSCCON = 0b ; // Define velocidade do oscilador para 4MHz
90
EXEMPLO – ADC + LCD + Dois canais
TRISD = 0b ; // 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) * ); // Calcula tensão real ADCON0bits.CHS = 0b0001; // Seleciona canal AN1
91
EXEMPLO – ADC + LCD + Dois canais
} contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável tensao2 = ((5 * contador) * ); // 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
92
EXEMPLO – ADC + LCD + 4 canais
#define _XTAL_FREQ // Oscilador de 4 MHz #include <xc.h> #define RS LATD // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD // 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
93
(chama rotina que lê tensão nos pinos A0 a A4 automaticamente)
EXEMPLO – ADC + LCD + 4 canais Inicio Configuração Atualiza LCD (chama rotina que lê tensão nos pinos A0 a A4 automaticamente)
94
EXEMPLO – ADC + LCD + 4 canais
void setupADC(void) { TRISA = 0b ; // 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 = 0b ; // 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
95
EXEMPLO – ADC + LCD + 4 canais
float tensao = ((5 * contador) * ); // Calcula tensão real return tensao; } void main(void) { OSCCON = 0b ; // Define velocidade do oscilador para 4MHz TRISD = 0b ; // 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
96
EXEMPLO – ADC + LCD + 8 canais + INT
Inicio Configuração (x = 0) Atualiza LCD com as variáveis tensão[0] a tensão[7]; Inicia leitura do pino ANx Atualiza variável tensão[x] com o valor da tensão no pino Ax; Incrementa x não Leitura finalizada? x é maior que 7? não sim sim x = 0
97
EXEMPLO – ADC + LCD + 8 canais + INT
#define _XTAL_FREQ // Oscilador de 4 MHz #include <xc.h> #define RS LATD // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD // 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
98
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 = 0b ; // Habilita pinos A0 a A3 e A5 como entrada TRISE = 0b ; // 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 = 0b ; // Habilita canais AN0 a AN7 como AD ADCON0bits.ADON = 1; // Liga o circuito AD }
99
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 interrupt adc_interrupt(void) { if (ADIF) { int contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável tensao[canal] = ((5 * contador) * ); // 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.GO = 1; // Inicia a conversão ADIF = 0; // Desmarca flag da interrupção ADC
100
EXEMPLO – ADC + LCD + 8 canais + INT
} void main(void) { OSCCON = 0b ; // Define velocidade do oscilador para 4MHz TRISD = 0b ; // 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
101
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
102
EXEMPLO – ADC + LCD + TIMER
Inicio Configuração (configura timer para interromper a cada 10 ms) Atualiza LCD com o valor da variável “tensão” e “contador” sim não Interrupção do conversor AD? Grava tensão do pino AN0 na variável “tensão”; Incrementa “contador”; sim Interrupção do timer? Inicia leitura no conversor AD
103
EXEMPLO – ADC + LCD + TIMER
#define _XTAL_FREQ #define RS LATD // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD // 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
104
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) * ); // 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
105
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 = 0b ; // 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
106
EXEMPLO – ADC + LCD + TIMER
ANSEL = 0b ; // 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 = 0b ; // 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
107
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
108
(configura temporizador e PWM)
EXEMPLO – PWm Inicio Configuração (configura temporizador e PWM) . . . É, não faz nada.
109
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 ( ), portanto 128 = 50%
110
EXEMPLO – PWM Fim de Código TMR2IF = 0; // Limpa flag do TMR2
TMR2ON = 1; // Dispara o timer TRISCbits.RC1 = 0; // "liga" bit de saída } void main(void) { OSCCON = 0b ; // Oscilador interno a 4 MHz setupPWM(); while(1) { // Gera um sinal PWM na saída do pino RC1 Fim de Código
111
EXEMPLO – PWM + ADC sim não Inicio Inicia conversão AD no pino AN0
Configuração Inicia conversão AD no pino AN0 sim não Interrupção do conversor AD? Atualiza valor do “duty cycle” do PWM baseado no valor de tensão lido no pino AN0
112
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
113
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 = 0b ; // 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 = 0b ; // Habilita canal AN0
114
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 ( ) TMR2IF = 0; // Limpa flag do TMR2 TMR2ON = 1; // Dispara o timer
115
EXEMPLO – PWM + ADC Fim de Código
TRISCbits.RC1 = 0; // "liga" bit de saída } void main(void) { OSCCON = 0b ; // 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
116
EXEMPLO - SERIAL não sim Inicio Configuração;
Envia texto pra porta serial; Aguarda interrupção Interrupção da recepção serial? não sim Envia texto para a porta serial com caractere digitado;
117
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 // 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 }
118
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 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)
119
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
120
SERIAL Fim de Código void main(void) {
OSCCON = 0b ; // 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
121
EXEMPLO – SERIAL + LCD não sim Inicio Configuração;
Envia texto pra porta serial e LCD; Aguarda interrupção Organiza posição do caractere na segunda linha do LCD Interrupção da recepção serial? não sim Envia texto para a porta serial e LCD com caractere digitado;
122
EXEMPLO – SERIAL + LCD #define _XTAL_FREQ // Oscilador interno de 4 MHz #include <xc.h> #define RS LATD // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD // 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
123
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
124
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
125
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 = 0b ; // 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
126
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
127
EXEMPLO – SERIAL + LCD Fim de Código
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
128
EXEMPLO – SERIAL + ADC não sim Inicio Configuração;
Envia texto pra porta serial; Inicia leitura da tensão no pino AN0 Finalizou a leitura? não sim Envia texto para a porta serial com tensão lida;
129
EXEMPLO – SERIAL + ADC #define _XTAL_FREQ // 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
130
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.
131
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 = 0b ; // Habilita pino A0 como entrada ADCON2bits.ADCS = 0b111; // Tempo de aquisição: 4 Tad ADCON2bits.ACQT = 0b110; // Clock do AD: Fosc/64
132
EXEMPLO – SERIAL + ADC ADCON2bits.ADFM = 0b1; // Formato: à direita
ADCON1bits.VCFG = 0b00; // Tensões de referência: Vss e Vdd ANSEL = 0x ; // 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 = 0b ; // Oscilador interno a 4 MHz
133
EXEMPLO – SERIAL + ADC Fim de Código
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 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) * ); // Calcula tensão real sprintf(linha, "\b\b\b\b\b%1.3f", tensao); // Grava texto em linha1 SuperDelay(1000); } //loop infinito Fim de Código
134
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.
135
Programas com BUGS #1 – ROTAÇÃO DE LEDS
#define _XTAL_FREQ // 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 = 0b ; // Habilita porta A como saída LATA = 1; // Liga o primeiro pino da porta A while(1) { // Inicia loop infinito while(LATA != 0b ) { LATA = (LATA >> 1 | LATA << 7); // Rotacionando com estilo pra esquerda __delay_ms(100); // Atraso de 100 ms } while(LATA != 0b ) { LATA = (LATA << 1 | LATA >> 7); // Rotacionando com estilo pra direita Fim de Código
136
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.
137
Programas com BUGS #2 – ROTAÇÃO DE LEDS
#define _XTAL_FREQ // 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 = 0b ; // Habilita porta A como saída LATA = 1; // Liga o primeiro pino da porta A while(1) { // Inicia loop infinito while(LATA != 0b ) { LATA = (LATA >> 1 | LATA << 7); // Rotacionando com estilo pra esquerda __delay_ms(100); // Atraso de 100 ms } while(LATA != 0b ) { LATA = (LATA << 1 | LATA >> 7); // Rotacionando com estilo pra direita Fim de Código
138
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.
139
Programas com BUGS #3 – ROTAÇÃO DE LEDS
#define _XTAL_FREQ // 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 != 0b ) { LATA = (LATA >> 1 | LATA << 7); // Rotacionando com estilo pra esquerda __delay_ms(100); // Atraso de 100 ms } while(LATA != 0b ) { LATA = (LATA << 1 | LATA >> 7); // Rotacionando com estilo pra direita Fim de Código
140
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.
141
Programas com BUGS #4 – PISCAR LED
#define _XTAL_FREQ // 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 = 0b ; // Define frequência do oscilador para 4MHz TRISD = 0b ; // 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
142
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.
143
Programas com BUGS #5 – PISCAR LED
#define _XTAL_FREQ // 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 = 0x ; // Define frequência do oscilador para 4MHz TRISD = 0b ; // 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
144
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.
145
Programas com BUGS #6 – LCD
#define _XTAL_FREQ #include <xc.h> #define RS LATD // < Pinos do LCD ligados na porta D #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD // 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>
146
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 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
147
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.
148
Programas com BUGS #7 – InterrupçãO
#define _XTAL_FREQ #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. }
149
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
150
Programas com BUGS Checklist contra a maioria dos bugs:
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 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. 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;
151
Programas com BUGS Checklist contra a maioria dos bugs:
Verificar se definições de variáveis ou registradores estão corretas: Usar 0x é bem diferente de usar 0b ; Ler o datasheet.
Apresentações semelhantes
© 2024 SlidePlayer.com.br Inc.
All rights reserved.