A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Microcontroladores PIC

Apresentações semelhantes


Apresentação em tema: "Microcontroladores PIC"— Transcrição da apresentação:

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.


Carregar ppt "Microcontroladores PIC"

Apresentações semelhantes


Anúncios Google