Microcontroladores PIC

Documentos relacionados
MICROCONTROLADORES PIC

Interrupções e Timers

Sistemas Digitais e Microcontrolados

AAAA AAAA SEL Aplicação de Microprocessadores I. Aula 5 Temporização e Interrupção. Marcelo Andrade da Costa Vieira

Sistemas Digitais e Microcontrolados

Sistemas Digitais e Microcontrolados

Sistemas Microcontrolados. Período Aula 9. 1 Saulo O. D. Luiz

Sistemas Microcontrolados

ET53C - SISTEMAS DIGITAIS

Funções dos Microcontroladores Microcontroladores e Microprocessadores Especialização em Automação Industrial

1.1 Noções básicas sobre interrupções em Microcontroladores

1.2 Registradores relacionados as Interrupções. 3. TOSE Sentido da transição da borda do sinal aplicado am TMR0

Sistemas Embarcados:

Eder Terceiro. Programação C com o PIC16F628a. Eder Terceiro. 31 de Outubro de 2016

Acetatos de apoio às aulas teóricas

Curso de Microcontroladores PIC 16F84A

Sistemas Microcontrolados

OMicrocontrolador PIC16F877A implementa um conversor

Interrupção Externa. Capítulo 1. Noções básicas sobre interrupções em Microcontroladores PIC

Faculdade de Tecnologia SENAI Pernambuco - Unidade Santo Amaro Curso de Tecnologia em Mecatrônica Industrial

Projeto Instrumentação Eletrônica Conversor A/D para Tensões 3φ

Conversor Analógico Digital do MSP430G2553

Sistemas Microcontrolados. Período Aula Saulo O. D. Luiz

Microprocessadores. Cap. 4 Assembly

Registros do 16F628A. Prof. Luiz Antonio Vargas Pinto Prof. Vargas

Sistemas Embarcados:

Placa de desenvolvimento USB AFSmartBoard utiliza PIC18F4550 da Microchip, microcontrolador com o Flash 32kb, 2048 bytes de memória RAM

Interrupções do Interrupções Gabriel Kovalhuk. UTFPR DAELN - Tecnologia em Mecatrônica Industrial

Jadsonlee da Silva Sá

2a Prova de ELT024 Programação para Sistemas Embarcados Prof. Rodrigo Maximiano Antunes de Almeida

Suporta os microcontroladores: R. Leonardo da Vinci, Campinas/SP CEP F.: (19) Kit de Desenvolvimento ACEPIC 28

Arquitetura PIC - PWM

PMR2415 Microprocessadores em Automação e Robótica. Jun Okamoto Jr.

Microcontroladores: Programação em C

KIT DIDÁTICO PIC-2377

ENG-1450 Microcontroladores e Sistemas Embarcados. Lab02 Apresentação Kit PicGenios Interrupção e Timers

OMicrocontrolador PIC16F877A apresenta dois módulos

Microcontroladores: Programação em C

C:\Users\House\Desktop\fluxo.c 1: /****************************************************************************** 2: * Objetivo: Este projeto visa

Sistemas Digitais e Microcontrolados

INTRODUÇÃO: MICROCONTROLADORES

Laboratório de Microprocessadores e Microcontroladores

BANKSEL ADCON1 clrf ADCON1 bsf ADCON1,ADFM ; seta AD para VCC, GND e entradas analogicas, setando o bit ADFM configura como justificado a direita

PMR5229 Projeto de Sistemas Mecatrônicos com Microprocessadores. Jun Okamoto Jr.

Prof. Amauri Assef. UTFPR Campus Curitiba 1

Sistemas Microcontrolados. Período Aula 6. 1 Saulo O. D. Luiz

Aplicações Avançadas de Microprocessadores. Professor: Marco Shawn Meireles Machado

Sistemas Embarcados:

LABORATÓRIO DE ARQUITETURA DE COMPUTADORES PREPARAÇÃO 03: INTERRUPÇÕES

Microcontroladores. Contadores e Temporizadores. Prof. Guilherme Peron Prof. Heitor S. Lopes Prof. Ronnier Rohrich Prof. Rubão

O Pino P2.7 não está sendo usado e cada Display mostrará valores de 0 a 9.

Período Saulo O. D. Luiz

Revisão da Linguagem C Prof. Evandro L. L. Rodrigues

Laboratório de Microprocessadores e Microcontroladores

Experiência. Montagem Kit Didático. 2. Turma: Nota: 5. MICRO-I Prof. Mauricio. Identificação dos Alunos:

Objetivos MICROCONTROLADORES SOFTWARE PROGRAMAÇÃO (PARTE: 04) Programação em Linguagem C

Projeto para interligação do Teclado Matricial 4X3 o módulo PIC PCI-208 Princípio de Funcionamento:

Usando Display Gráfico com C18 e C30

UTFPR Departamento Acadêmico de Eletrônica Curso Técnico em Eletrônica Microcontroladores 1 - Prof. Cion nov/2010 (atualizado em jul 2015)

Programação ARM. Engenharia de Sistemas Embarcados Prof. Abel Guilhermino

Microcontroladores: Programação em C

Tutoriais PET-Tele. Introdução à Amostragem de Sinais com o kit Arduino (Versão: A2016M06D21)

Microcontrolador 8051

Microcontroladores PROF. ME. HÉLIO ESPERIDIÃO

Plano de Aula. 1 o semestre. Aula número 011 Periféricos Display LCD, Conversor AD e conversor DA (PWM)

Aula 10 Microcontrolador Intel 8051 Parte 1

RTC Real Time Counter e Pinos do JM60

INTRODUÇÃO AO ARDUINO DUE, CANAL DIGITAL, FUNÇÃO DELAY

Cerne. Conhecimento para o Desenvolvimento. Cerne Tecnologia e Treinamento. Apostila de BASIC para PIC16F628A

Prof. Adilson Gonzaga

Introdução ao Microcontrolador PIC

Portas de entrada e saída; Interrupções; Interrupções externas; Temporizadores Contadores; Interface Serial

Microcontrolador 8051:

Plano de Aula. 1 o semestre. Aula número 010 Interrupções Internas Timers. Uso de interrupções internas produzidas pelos timers

Experimento 6 Conversor analógico digital e comunicação serial

Guia da Placa de desenvolvimento PD Mega16 N1

16F628A - The Configuration Word Jon Wilder 25 de agosto de 2011.

Circuito Eletrônico. Entendendo o circuito eletrônico na robótica. domingo, 28 de agosto de 11

Objetivos MICROCONTROLADORES HARDWARE. Aula 03: Periféricos. Prof. Mauricio. MICRO I Prof. Mauricio 1. Arquitetura de um Microcontrolador

Laboratório de Microprocessadores e Microcontroladores

Temporizadores e Contadores (Timer/Counter)

Arquitetura de Computadores. Prof. João Bosco Jr.

Laboratório de Microprocessadores e Microcontroladores

Microcontrolador PIC: Conceitos Básicos

Cerne. Conhecimento para o Desenvolvimento. Cerne Tecnologia e Treinamento

TECLADO MATRICIAL. Universidade Tecnológica Federal do Paraná - UTFPR Sistemas Microcontrolados Monitor da disciplina: Luís Paulo Custódio

SEL0338 Tópicos Especiais em Sistemas Digitais

Interrupções e timers

Laboratório de Microprocessadores e Microcontroladores

PRÁTICAS. Microcontroladores: (LT36D) Prof: DaLuz. Práticas - 2º sem Microcontroladores LT36D - 26/04/ :56 1/16

Métodos Computacionais. Operadores, Expressões Aritméticas e Entrada/Saída de Dados

programáveis por software

Acetatos de apoio às aulas teóricas

Estruturas da linguagem C. 1. Identificadores, tipos primitivos, variáveis e constantes, operadores e expressões.

Sistemas Embutidos Prática. Prof. Marcos Augusto Menezes DCC/ /UFMG

Robótica com Arduino Professor: Paulo Marcos Trentin

Conhecendo o PIC24 e o mikropascal

Sistemas Microcontrolados

Transcrição:

Microcontroladores PIC Prática MSc. Gustavo Souto de Sá e Souza Revisado por José Wilson Nerys

Introdução O principal microcontrolador utilizado nesse estudo é o PIC18F4550, cujas características principais são: Fontes de clock possíveis: Cristal externo (4 modos); Clock externo (2 modos. Até 48 MHz); Oscilador interno (8 frequências diferentes: de 31 khz a 8 MHz) Memórias: 32 K de memória Flash; 2 K de SRAM e 256 bytes de EEPROM 35 pinos de entrada/saída Conversor Analógico/Digital de 10 bits, 13 entradas multiplexadas Obs.: É importante lembrar que as informações contidas aqui podem variar para outras famílias PIC ou até mesmo para outros chips da mesma família.

Introdução O principal microcontrolador utilizado nesse estudo é o PIC18F4550, cujas características principais são: 3 interrupções externas Capacidade de corrente nos pinos de I/O: 25 ma 4 módulos temporizadores (Timer 0 a Timer 3) Até 2 módulos de Captura/Comparação/PWM (CCP) Unidade interna de USB (transceiver) Programação via canal serial com 2 pinos Canal serial universal melhorado (EUSART) Canal I 2 C (vários transdutores usam esse canal para a transferência de dados. Exemplos: giroscópio e barômetro)

PIC18F4550

Linguagem C compilador XC8 Inicialização da variável variavel : Bit ou boolean: bit variavel; Valor inteiro: int variavel; Valor inteiro com sinal (positivo ou negativo): signed int variavel; Caractere: char variavel; String (conjunto de, digamos, 10 caracteres): char variavel[10]; Valor flutuante: float variavel;

Linguagem C compilador XC8 Definição de variável: Decimal: variavel = 100; Binário: variavel = 0b1100100; Hexadecimal: variavel = 0x64; Caractere: variavel = d ;

Linguagem C compilador XC8 Operações: Definição de variável: variavel = 255; Soma: variavel = 15 + b; Subtração: variavel = 15 - b; Multiplicação: variavel = 15 * b; Divisão: variavel = 15 / b; Rotação de N bits para esquerda: variavel = variavel << N; Rotação de N bits para a direita: variavel = variavel >> N;

Linguagem C compilador XC8 Operações: Operação E: variavel = variavel & 55; Operação OU: variavel = variavel 55; Operação NÃO (inverte apenas 1 bit): variavel =!variavel; Incrementar em 1: variavel++; Decrementar em 1: variavel--;

Linguagem C compilador XC8 Condições (retornam 1 se verdadeiro, 0 se falso): Verificar se é igual: (variavel == b); Verificar se é diferente: (variavel!= b); Verificar se é maior: (variavel > b); Verificar se é menor: (variavel < b); Verificar se é maior ou igual: (variavel >= b); Verificar se é menor ou igual: (variavel <= b); Condição E: (variavel <= b && variavel!= 0); Condição OU: (variavel <= b variavel!= 0);

Linguagem C compilador XC8 Definições: Define _constante como 5: #define _constante 5 Define PINO_DO_LED como LATD1: #define PINO_DO_LED LATD1 Inclusões de bibliotecas: Inclui biblioteca do compilador: #include <stdlib.h> Inclui biblioteca da pasta local: #include lcd.h

Linguagem C compilador XC8 Se: if: if (variavel == 10) { // executa se condição for verdadeira else { // executa se condição for falsa

Linguagem C compilador XC8 Se: if: Condição if (variavel == 10) { // executa se condição for verdadeira else { // executa se condição for falsa

Linguagem C compilador XC8 Loops: While: while (variavel!= 0) { // código em loop

Linguagem C compilador XC8 Condição (executa enquanto for 1) Loops: While: while (variavel!= 0) { // código em loop

Linguagem C compilador XC8 Loops: for: for (variavel = 1; variavel < 100; variavel++) { // código em loop

Loops: for: Linguagem C compilador XC8 for (variavel = 1; variavel < 100; variavel++) { // código em loop Valor inicial

Linguagem C compilador XC8 Condição (executa enquanto for 1) Loops: for: for (variavel = 1; variavel < 100; variavel++) { // código em loop

Linguagem C compilador XC8 Loops: for: for (variavel = 1; variavel < 100; variavel++) { // código em loop Incremento

Linguagem C compilador XC8 Loops: break: for (variavel = 1; variavel < 100; variavel++) { // código em loop if (variavel < 0) { break;

Linguagem C compilador XC8 Loops: break: for (variavel = 1; variavel < 100; variavel++) { // código em loop if (variavel < 0) { break; Finaliza e sai do loop aqui

Linguagem C compilador XC8 Funções: Principal: void main (void) { // Código principal do programa vem aqui

Linguagem C compilador XC8 Funções: Interrupção: void interrupt int_func (void) { // Código da interrupção

Linguagem C compilador XC8 Funções: Interrupção de baixa prioridade: void interrupt low_priority int_low_funcao (void) { // Código da interrupção de baixa prioridade

Linguagem C compilador XC8 Funções: Secundárias: void LigaTimer (void) { TMR0ON = 1;

Linguagem C compilador XC8 Funções: Secundárias com valores de entrada e saída: int SomaDez (int valor_de_entrada) { valor_de_entrada = valor_de_entrada + 10; return valor_de_entrada;

Linguagem C compilador XC8 Chamando Funções: LigaTimer(); variavel = SomaDez(variavel);

Linguagem C compilador XC8 Função de atraso por milissegundo: delay_ms(tempo_em_milissegundos);!!! Requer que a velocidade do oscilador seja definido antes, por meio da linha #define _XTAL_FREQ 1000000 (para um oscilador de 1 MHz) Também requer a library xc.h incluída por meio da linha: #include <xc.h> Pode causar erro se o valor de entrada for muito grande, relativo à velocidade do oscilador.

Linguagem C compilador XC8 Comentando o código: TRISA = 0; // A parte comentada vem depois de // duas barras ok++; /* Ou você pode comentar todo um trecho do código usando asterisco e barra */

Linguagem C compilador XC8 sprintf: imprime e manipula strings e caracteres. Requer que a biblioteca stdio.h seja incluída. #include <stdio.h> char linha1[16]; sprintf(linha1, Hello, world! ); // Grava o texto Hello, world! na variável linha1

Linguagem C compilador XC8 char linha1[16]; contador = 15; sprintf(linha1, Contagem: %i, contador); // Grava o texto Contagem: 15 na variável linha1 // %i imprime um número inteiro

Linguagem C compilador XC8 char linha1[16]; contador = 15; sprintf(linha1, Contagem: %3.2i, contador); // Grava o texto Contagem: 15.00 na variável linha1 // %X.Yi imprime um número inteiro com X casas fixas // antes do separador decimal e Y fixas casas depois

Linguagem C compilador XC8 char linha1[16]; temperatura = 37.52; sprintf(linha1, Graus: %2.2f, temperatura); // Grava o texto Graus: 37.52 na variável linha1 // %f imprime um número de ponto flutuante

Linguagem C compilador XC8 char linha1[16]; caractere_u = 0x55; sprintf(linha1, Letra U: %c, caractere_u); // Grava o texto Letra U: U na variável linha1 // %c imprime um caractere correspondente à tabela // ASCII

Linguagem C compilador XC8 Definindo bits de Configuração: O símbolo # precedido da configuração desejada é uma diretiva de programa, que indica ao Compilador a ação a ser tomada antes da execução do código do programa. As 3 principais diretivas utilizadas nos exemplos são: #include - inclui bibliotecas padrões e do usuário #define - define constantes e variáveis antes da execução do programa #pragma config - define configurações em uma área específica da memória flash, fora do código do programa principal

Linguagem C compilador XC8 Bits de Configuração essenciais (incluídos com #pragma config): 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 High Speed)

Linguagem C compilador XC8 Bits de Configuração essenciais: WDT: // No PIC18F4550 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 WDT = OFF; // desabilita watchdog timer #pragma config WDTPS = 32768;

Linguagem C compilador XC8 Bits de Configuração essenciais: MCLRE: Master Clear Enable. Habilita ou desabilita o pino de reset no microcontrolador. #pragma config MCLRE = OFF;

Linguagem C compilador XC8 Bits de Configuração não tão essenciais (podem ficar no valor padrão): PWRT: Aguarda um tempo depois de ligar para iniciar o programa. Habilitá-lo evita instabilidade no programa devido a oscilações na alimentação e oscilador: #pragma config PWRT = ON;

Linguagem C compilador XC8 Bits de Configuração não tão essenciais (podem ficar no valor padrão): BOREN: Brown-out reset enable. Habilita o reset automático em caso de baixa tensão de alimentação: #pragma config BOREN = SBORDIS;

Linguagem C compilador XC8 Bits de Configuração essenciais: PBADEN: Habilita ou desabilita o conversor Analógico-Digital na porta B. Caso for utilizar interrupção na porta B ou usá-la como entrada/saída digital, este deve estar desabilitado. Por padrão é habilitado: #pragma config PBADEN = OFF;

Linguagem C compilador XC8 Registradores essenciais: OSCCON: Byte que define a frequência do oscilador interno do PIC18F45K20: OSCCON=0b01110000; OSCCON=0b01100000; OSCCON=0b01010000; OSCCON=0b00110000; // Frequência: 16 MHz // Frequência: 8 MHz // Frequência: 4 MHz // Frequência: 1 MHz (padrão)

Linguagem C compilador XC8 Registradores essenciais: OSCCON: Byte que define a frequência do oscilador interno do PIC18F4550: Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 IDLEN IRCF2 IRCF1 IRCF0 OSTS IOFS SCS1 SCS0 Bits de seleção da frequência OSCCON=0b01110000; OSCCON=0b01100000; OSCCON=0b01010000; OSCCON=0b01000000; OSCCON=0b00110000; OSCCON=0b00100000; // Frequência: 8 MHz // Frequência: 4 MHz // Frequência: 2 MHz // Frequência: 1 MHz (padrão) // Frequência: 500 khz // Frequência: 250 khz

Exemplos Gerais

EXEMPLO PISCAR LED Inicio Configuração Inverte sinal do pino D0 Atrasa 100 ms

EXEMPLO PISCAR LED #define _XTAL_FREQ 4000000 // Oscilador de 4 MHz #include <xc.h> // Biblioteca do compilador xc8 #pragma config FOSC = INTOSC #pragma config WDT = OFF #pragma config MCLRE = OFF void main(void) { OSCCON = 0b01100000; TRISD = 0b00000000; // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado // Define frequência do oscilador para 4MHz // Habilita porta D como saída while(1) { LATDbits.LATD0 =!LATDbits.LATD0; delay_ms(100); // Inicia loop infinito // Inverte sinal do pino D0 // Atraso de 100 ms Fim de Código

EXEMPLO PISCAR LED (VERSÃO 2) #define _XTAL_FREQ 4000000 #define Led LATDbits.LATD0 // Oscilador de 4 MHz #include <xc.h> // Biblioteca do compilador xc8 #pragma config FOSC = HS #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador externo // Watchdog Timer desligado // Master Clear desabilitado void main(void) { TRISD = 0b00000000; while(1) { Led =!Led; delay_ms(100); // Habilita porta D como saída // Inicia loop infinito // Inverte sinal do pino Led // Atraso de 100 ms Fim de Código

EXEMPLO PISCAR LED 1 SEGUNDO Inicio Configuração Inverte sinal do pino D0 Atrasa 100 vezes 10 ms

EXEMPLO PISCAR LED 1 SEGUNDO #define _XTAL_FREQ 4000000 // Oscilador de 4 MHz #include <xc.h> #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador interno // Watchdog Timer desligado // 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 = 0b01100000; TRISD = 0b00000000; // Define velocidade do oscilador para 4MHz // Habilita porta D como saída

EXEMPLO PISCAR LED 1 SEGUNDO while(1) { LATDbits.LATD0 =!LATDbits.LATD0; SuperDelay(1000); // Inicia loop infinito // Inverte sinal do pino D0 // Atraso de 1 s Fim de Código

EXEMPLO 1 DE ROTAÇÃO DE LEDS Inicio Configuração Rotaciona 1 passo para a esquerda não sim PORTD=0? LATD = 1

#define _XTAL_FREQ 4000000 #include <xc.h> #pragma config FOSC = HS #pragma config WDT= OFF #pragma config MCLRE = ON // Oscilador de 4 MHz // Cristal oscilador externo (clock externo) // Watchdog Timer desligado // Define pino 1 como Reset 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) { TRISD = 0; // Habilita porta D como saída LATD = 0b00000001; // Liga o Led do pino 0 da porta D while(1) { LATD = LATD << 1; // Rotacionando para a esquerda SuperDelay(500); if (PORTD == 0) { LATD = 1; SuperDelay(500); return; Fim de Código

EXEMPLO 2 DE ROTAÇÃO DE LEDS Inicio Configuração Rotaciona 1 passo para a esquerda não sim PORTD=0? LATD = 1

#define _XTAL_FREQ 4000000 // Oscilador de 4 MHz #include <xc.h> #pragma config FOSC = HS #pragma config WDT= OFF #pragma config MCLRE = ON // Cristal oscilador externo (clock externo) // Watchdog Timer desligado // Define pino 1 como Reset 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) { TRISD = 0; LATD = 0b00000001; SuperDelay(500); // Habilita porta D como saída // Liga o primeiro pino da porta D

while(1) { while(latd!= 0b10000000) { LATD = LATD << 1; // Rotacionando para a esquerda SuperDelay(500); while(latd!= 1) { LATD = LATD >> 1; // Rotacionando para a direita SuperDelay(500); return; Fim de Código

EXEMPLO 3 ROTACIONAR LED Inicio Configuração Rotaciona para a esquerda sim LED aceso na borda direita? não não LED aceso na borda esquerda? sim Rotaciona para a direita

EXEMPLO ROTACIONAR LED #define _XTAL_FREQ 4000000 #include <xc.h> #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador de 4 MHz // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado void main(void) { TRISA = 0b00000000; // Habilita porta A como saída LATA = 1; // Liga o primeiro pino da porta A while(1) { // Inicia loop infinito while(lata!= 0b00000001) { LATA = (LATA >> 1 LATA << 7); // Rotacionando com estilo pra esquerda delay_ms(100); // Atraso de 100 ms while(lata!= 0b10000000) { LATA = (LATA << 1 LATA >> 7); // Rotacionando com estilo pra direita delay_ms(100); // Atraso de 100 ms Fim de Código

EXEMPLO ROTACIONAR LED - EXPLICAÇÃO Digamos que LATA = 0b00000001 LATA >> 1 retorna o seguinte valor: 0b00000000, pois rotacionou o 1 para a direita e ele caiu fora dos 8 bits. O oitavo bit é preenchido com 0. LATA << 7 retorna o seguinte valor: 0b10000000, pois rotacionou o 1 um total de sete bits para a esquerda e ele ficou no lugar do oitavo bit. Os 7 primeiros bits são preenchidos com 0. Fazendo a operação OU entre ambos, temos (LATA >> 1 LATA << 7) = 0b10000000; Continuemos com LATA = 0b10000000 LATA >> 1 retorna o seguinte valor: 0b01000000, pois rotacionou o 1 para a direita e ele caiu no lugar do sétimo bit. O oitavo bit é preenchido com 0. LATA << 7 retorna o seguinte valor: 0b00000000, pois rotacionou o 1 um total de sete bits para a esquerda e ele saiu do espaço dos bits. Os 7 primeiros bits são preenchidos com 0. Fazendo a operação OU entre ambos, temos (LATA >> 1 LATA << 7) = 0b01000000;

Display LCD

EXEMPLO LCD Inicio Configuração Adiciona 1 em contador Atualiza LCD com valor de contador

EXEMPLO LCD #define _XTAL_FREQ 1000000 Conexão da Porta D no LCD Os pinos D0, D1, D2 e D3 do LCD são conectados ao Terra #include <xc.h> #define RS LATD2 // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD7 // Pinos do LCD > Biblioteca local do LCD #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF #include "lcd.h" #include <stdio.h> // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado

EXEMPLO 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) { TRISD = 0; // Define porta D inteira como saída Lcd_Init(); // Inicia o LCD sprintf(linha1, "Hello world! "); // Grava texto em linha1 Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1 Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD while(1) { sprintf(linha2, "Contador: %i ",contador); // Grava texto em linha2 contador ++; // Incrementa contador Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1 Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD Fim de Código

EXEMPLO LCD + CONTADOR FLOAT Inicio Configuração Adiciona 0.01 em contador Atualiza LCD com valor de contador

EXEMPLO LCD + CONTADOR FLOAT #define _XTAL_FREQ 1000000 #include <xc.h> #define RS LATD2 // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD7 // Pinos do LCD > #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado #include "lcd.h" #include <stdio.h>

EXEMPLO LCD + CONTADOR FLOAT char linha1[16]; // Variável linha1 com 16 caracteres char linha2[16]; // Variável linha2 com 16 caracteres float contador = 0.0; // Variável contador com valor inicial 0.0 void main(void) { TRISD = 0; // Define porta D inteira como saída Lcd_Init(); // Inicia o LCD sprintf(linha1, "Hello world! "); // Grava texto em linha1 Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1 Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD while(1) { sprintf(linha2, "Contador: %3.2f",contador); // Grava texto em linha2 contador = contador + 0.01; // Incrementa contador em 0.01 Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1 Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD Fim de Código

Interrupções

Linguagem C compilador XC8 Registradores importantes - interrupção: GIE: bit que habilita a interrupção global: GIE = 1; // Habilita interrupção PBIE: bit que habilita a interrupção de periféricos (timer2, adc): PEIE = 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 INT1IE = 1; // Habilita interrupção externa 1 INT2IE = 1; // Habilita interrupção externa 2

Linguagem C compilador XC8 Registradores importantes - interrupção: ADIF: bit que habilita a interrupção do conversor AD: ADIF = 1; // Habilita interrupção do ADC TXIE: bit que habilita a interrupção de transmissão da serial: TXIE = 1; // Habilita interrupção do TX da serial RCIE: bit que habilita a interrupção de recepção da serial: RCIE = 1; // Habilita interrupção do RX da serial

Linguagem C compilador XC8 Registradores importantes - interrupção: TMRXIE: bit que habilita a interrupção do timer X (X pode ser 0, 1, 2 ou 3): TMR0IE = 1; TMR1IE = 1; TMR2IE = 1; TMR3IE = 1; // Habilita interrupção do TMR0 // Habilita interrupção do TMR1 // Habilita interrupção do TMR2 // Habilita interrupção do TMR3

Linguagem C compilador XC8 Registradores importantes interrupção (flags): INTXIF: bit que sinaliza a flag da interrupção externa X (X=0, 1, 2): INT0IF = 0; // Limpa a flag do INT0 TMRXIF: bit que sinaliza a flag de interrupção do timer X (X=0, 1, 2, 3): TMR3IF = 0; // Limpa a flag do TMR3 ADIF: bit que sinaliza a flag de interrupção do ADC: ADIF = 0; // Limpa a flag do ADC

EXEMPLO INTERRUPÇÃO (INT0) Inicio Configuração Aguarda interrupção não Interrupção ativada? sim Inverte sinal do LED

EXEMPLO INTERRUPÇÃO (INT0) #define _XTAL_FREQ 1000000 #include <xc.h> #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF #pragma config PBADEN = OFF // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado // Conversor AD da porta B desligado void setupint(void) { GIE = 1; // Habilita interrupção global INT0IE = 1; // Habilita Interrupção da INT0 INT0F = 0; // Zera a Flag de interrupção da INT0 INTEDG0 = 1; // Interrupção por borda crescente. Para usar a interrupção INT0 (Pino RB0, da porta B), deve-se desabilitar o conversor AD dessa porta

EXEMPLO INTERRUPÇÃO (INT0) void interrupt interrupcao(void) { if (INT0F) { LATAbits.LA0 =!LATAbits.LA0; INT0F = 0; void main(void) { TRISA = 0x00; TRISB = 0x01; setupint(); while(1) { // Função de interrupção // Caso a flag da INT0 esteja habilitada // Inverte o sinal no pino A0 // Desabilita a flag da INT0 // Porta A com todos pinos de saída // Somente pino B1 como entrada (INT0) // Função de inicializar Interrupção // Loop infinito // O código acima inverte o sinal no pino A0 a cada pressionar de um botão ligado à INT0 Fim de Código

Conversor Analógico/Digital (10 bits)

Características do Conversor Analógico Digital (ADC): 10 bits 13 entradas multiplexadas Registradores importantes: Registrador ADRESH ADRESL ADCON0 ADCON1 ADCON2 Função Byte superior do resultado Byte inferior do resultado Registrador de controle 0 escolha de canais, liga/desliga/inicia conversão Registrador de controle 1 tensão de referência / configuração dos pinos de entrada como analógico ou digital Registrador de controle 2 configura a fonte de clock e a taxa de aquisição

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 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

Linguagem C compilador XC8 Registradores importantes ADC : ADCON0bits.GO: bit que inicia a conversão analógica: ADCON0bits.GO = 1; // Inicia a conversão AD ADCON0bits.DONE: flag que sinaliza o fim da conversão analógica: while (!ADCON0bits.DONE) { // Aguarda finalização da conversão AD

Linguagem C compilador XC8 Registradores importantes ADC (PIC18F4550): ADCON1: Registrador de Controle do ADC Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 X X VCFG1 VCFG0 PCFG3 PCFG2 PCFG1 PCFG0 Bits de configuração da tensão de referência ADCON1bits.VCFG = 0b00; Tensões de referência: Vss e Vdd

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 T AD ADCON2bits.ADFM = 0b1 Formato do resultado: justificado à direita

Linguagem C compilador XC8 Registradores importantes ADC : ADRESL: byte que guarda os 8 bits menos significativos da conversão AD: ADRESH: byte que guarda os 8 bits mais significativos da conversão AD: valor_convertido = (ADRESH * 0x0100) + ADRESL; // guarda o valor da conversão AD na variável // de 16 bits valor_convertido

EXEMPLO CONVERSOR ANALÓGICO- DIGITAL Inicio Configuração Inicia leitura da tensão no pino A0 não Finalizou leitura? sim Grava valor da leitura nos bits da porta C e D

EXEMPLO CONVERSOR ANALÓGICO- DIGITAL #define _XTAL_FREQ 4000000 // Oscilador de 4 MHz #include <xc.h> #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF void main(void) { OSCCON = 0b01100000; TRISD = 0b00000000; TRISC = 0b00000000; TRISA = 0x00000001; ADCON2 = 0b10010110; ADCON1 = 0b00000000; ADCON0bits.CHS = 0b0000; // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado // Define velocidade do oscilador para 4MHz // Habilita porta D como saída // Habilita porta C como saída // Habilita pino A0 como entrada // Tempo Aquisição: 4TAD; Clock: Fosc/64 // Tensões de referência: Vss e Vdd // Seleciona o canal AN0

EXEMPLO CONVERSOR ANALÓGICO-DIGITAL ADCON0bits.ADON = 1; while(1) { ADCON0bits.GO = 1; while (!ADCON0bits.GODONE) { LATD = ADRESL; LATC = ADRESH; delay_ms(100); // Habilita o conversor AD // Inicia loop infinito // Inicia a conversão // Aguarda fim da conversão // Transfere valor para porta D // Transfere valor para porta C // Atraso de 100 ms Fim de Código

EXEMPLO ADC + LCD Inicio Configuração Inicia leitura da tensão no pino A0 não Finalizou leitura? sim Calcula tensão no pino e exibe valor lido e tensão calculada no LCD

EXEMPLO ADC + LCD #define _XTAL_FREQ 4000000 // Oscilador de 4 MHz #include <xc.h> #define RS LATD2 // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD7 // Pinos do LCD > #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado #include "lcd.h" #include <stdio.h> char linha1[16]; char linha2[16]; // Variável linha1 com 16 caracteres // Variável linha2 com 16 caracteres

EXEMPLO ADC + LCD int contador = 0; // Variável contador com valor inicial 0 float tensao = 0.0; // Variável tensao com valor inicial 0.0 void setupadc(void) { TRISA = 0b00000001; ADCON2bits.ADCS = 0b110; ADCON2bits.ACQT = 0b010; ADCON2bits.ADFM = 0b1; ADCON1bits.VCFG = 0b00; ADCON0bits.CHS = 0b0000; // Habilita pino A0 como entrada // Clock do AD: Fosc/64 // Tempo de aquisição: 4 Tad // Formato: à direita // Tensões de referência: Vss e Vdd // Seleciona o canal AN0 ADCON0bits.ADON = 1; void main(void) { OSCCON = 0b01100000; TRISD = 0b00000000; // Liga o AD // Define velocidade do oscilador para 4MHz // Habilita porta D como saída

setupadc(); EXEMPLO ADC + LCD Lcd_Init(); // Inicia o LCD while(1) { // Inicia loop infinito ADCON0bits.GO = 1; // Inicia a conversão A/D while (!ADCON0bits.GODONE) { // Aguarda fim da conversão contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável tensao = ((5 * contador) * 0.0009765625); // Calcula tensão real sprintf(linha1, "Conversor: %4i ", contador); // Grava texto em linha1 sprintf(linha2, "Tensao: %1.2f ",tensao); // Grava texto em linha2 Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1 Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1 Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD Fim de Código

EXEMPLO ADC + LCD + DOIS CANAIS Inicio Configuração Lê tensão no pino A0 e guarda Atualiza LCD com os valores lidos Lê tensão no pino A1 e guarda

EXEMPLO ADC + LCD + DOIS CANAIS #define _XTAL_FREQ 4000000 // Oscilador de 4 MHz #include <xc.h> #define RS LATD2 // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD7 // Pinos do LCD > #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado #include "lcd.h" #include <stdio.h> char linha1[16]; char linha2[16]; // Variável linha1 com 16 caracteres // Variável linha2 com 16 caracteres

EXEMPLO ADC + LCD + DOIS CANAIS int contador = 0; // Variável contador com valor inicial 0 float tensao1 = 0.0; // Variável tensao com valor inicial 0.0 float tensao2 = 0.0; // Variável tensao com valor inicial 0.0 void setupadc(void) { TRISA = 0b00000011; ADCON2bits.ADCS = 0b110; ADCON2bits.ACQT = 0b010; ADCON2bits.ADFM = 0b1; ADCON1bits.VCFG = 0b00; // Habilita pinos A0 e A1 como entrada // Clock do AD: Fosc/64 // Tempo de aquisição: 4 Tad // Formato: à direita // Tensões de referência: Vss e Vdd ADCON0bits.ADON = 1; // Liga o circuito AD void main(void) { OSCCON = 0b01100000; // Define velocidade do oscilador para 4MHz

EXEMPLO ADC + LCD + DOIS CANAIS TRISD = 0b00000000; setupadc(); Lcd_Init(); // Habilita porta D como saída // Inicia o LCD while(1) { ADCON0bits.CHS = 0b0000; ADCON0bits.GO = 1; while (!ADCON0bits.GODONE) { contador = (ADRESH * 0x100) + ADRESL; tensao1 = ((5 * contador)/1023.0); ADCON0bits.CHS = 0b0001; ADCON0bits.GO = 1; while (!ADCON0bits.GODONE) { contador = (ADRESH * 0x100) + ADRESL; tensao2 = ((5 * contador)/1.023.0); // Inicia loop infinito // Seleciona canal AN0 // Inicia a conversão // Aguarda fim da conversão // Transfere valor para variável // Calcula tensão real // Seleciona canal AN1 // Inicia a conversão // Aguarda fim da conversão // Transfere valor para variável // Calcula tensão real

EXEMPLO ADC + LCD + DOIS CANAIS sprintf(linha1, "Tensao 1: %1.2f ",tensao1); sprintf(linha2, "Tensao 2: %1.2f ",tensao2); // Grava texto em linha1 // Grava texto em linha2 Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1 Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1 Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD Fim de Código

EXEMPLO ADC + LCD + 4 CANAIS Início Configuração Atualiza LCD (chama rotina que lê tensão nos pinos A0 a A4 automaticamente)

EXEMPLO ADC + LCD + 4 CANAIS #define _XTAL_FREQ 4000000 // Oscilador de 4 MHz #include <xc.h> #define RS LATD2 // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD7 // Pinos do LCD > #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado #include "lcd.h" #include <stdio.h> char linha1[16]; char linha2[16]; // Variável linha1 com 16 caracteres // Variável linha2 com 16 caracteres

EXEMPLO ADC + LCD + 4 CANAIS Seleção do clock do AD void setupadc(void) { TRISA = 0b00001111; ADCON2bits.ADCS = 0b110; ADCON2bits.ACQT = 0b110; ADCON2bits.ADFM = 0b1; ADCON1bits.VCFG = 0b00; ADCON0bits.ADON = 1; // Habilita pinos A0 a A3 como entrada // Clock do AD: Fosc/64 // Tempo de aquisição automático: 16 Tad // Formato: à direita // Tensões de referência: Vss e Vdd // Liga o circuito AD float letensao(int canal_adc) { ADCON0bits.CHS = canal_adc; // Seleciona canal ADCON0bits.GO = 1; // Inicia a conversão while (!ADCON0bits.GODONE) { // Aguarda fim da conversão int contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável

EXEMPLO ADC + LCD + 4 CANAIS float tensao = ((5 * contador)/1023.0); return tensao; // Calcula tensão real void main(void) { OSCCON = 0b01100000; // Define velocidade do oscilador para 4MHz TRISD = 0b00000000; // Habilita porta D como saída setupadc(); Lcd_Init(); // Inicia o LCD while(1) { // Inicia loop infinito sprintf(linha1, "T0: %1.1f T1: %1.1f", letensao(0), letensao(1)); //Grava texto em linha1 sprintf(linha2, "T2: %1.1f T3: %1.1f", letensao(2), letensao(3)); //Grava texto em linha2 Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1 Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1 Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD Fim de Código

EXEMPLO ADC + LCD + 8 CANAIS + INT Inicio Configuração (x = 0) Atualiza LCD com as variáveis tensão[0] a tensão[7]; Inicia leitura do pino ANx não Leitura finalizada? sim Atualiza variável tensão[x] com o valor da tensão no pino Ax; Incrementa x não x é maior que 7? sim x = 0

EXEMPLO ADC + LCD + 8 CANAIS + INT #define _XTAL_FREQ 4000000 // Oscilador de 4 MHz #include <xc.h> #define RS LATD2 // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD7 // Pinos do LCD > #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado #include "lcd.h" #include <stdio.h> char linha1[16]; char linha2[16]; // Variável linha1 com 16 caracteres // Variável linha2 com 16 caracteres

EXEMPLO ADC + LCD + 8 CANAIS + INT int canal = 0; float tensao[8]; bit atualizado; void setupadc(void) { TRISA = 0b00101111; TRISE = 0b00000111; // Variável que diz qual canal é lido atualmente // Vetor que guarda a tensão em cada um dos canais // Flag que indica se todos canais já foram lidos // Habilita pinos A0 a A3 e A5 como entrada // Habilita pinos E0 a E2 como entrada // São os pinos relativos a AN0 a AN7 ADCON2bits.ADCS = 0b110; ADCON2bits.ACQT = 0b110; ADCON2bits.ADFM = 0b1; ADCON1bits.VCFG = 0b00; // Clock do AD: Fosc/64 // Tempo de aquisição automático: 16 Tad // Formato: à direita // Tensões de referência: Vss e Vdd ADCON0bits.ADON = 1; // Liga o circuito AD

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)/1023.0); // Calcula tensão real if (canal == 7) { // Verificação para alternar canal = 0; // o canal lido a cada interrupcao ADCON0bits.CHS = canal; // Seleciona canal atualizado = 1; // Marca a flag caso ja leu os 4 canais else { canal++; // Atualiza o canal ADCON0bits.CHS = canal; // Seleciona canal ADCON0bits.GO = 1; ADIF = 0; // Inicia a conversão // Desmarca flag da interrupção ADC

EXEMPLO ADC + LCD + 8 CANAIS + INT void main(void) { OSCCON = 0b01010000; TRISD = 0b00000000; Lcd_Init(); setupadc(); setupinterrupcao(); atualizado = 0; ADCON0bits.CHS = canal; ADCON0bits.GO = 1; // Define velocidade do oscilador para 4MHz // Habilita porta D como saída // Inicia o LCD // Configura o ADC // Configura a interrupção // Marca a flag para atualizar os 8 canais // Seleciona canal // Inicia a conversão while(1) { // Inicia loop infinito sprintf(linha1, "1:%1.0f 2:%1.0f 3:%1.0f 4:%1.0f", tensao[0], tensao[1], tensao[2], tensao[3]); // Grava texto em linha1 sprintf(linha2, "5:%1.0f 6:%1.0f 7:%1.0f 8:%1.0f", tensao[4], tensao[5], tensao[6], tensao[7]); // Grava texto em linha2

EXEMPLO ADC + LCD + 8 CANAIS + INT Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1 Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1 Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD atualizado = 0; // Marca a flag para atualizar os 4 canais ADCON0bits.GO = 1; // Inicia a conversão Fim de Código

TEMPORIZADORES/ CONTADORES

Timer 0 configurado para 8 bits (T08BIT = 1) ou 16 bits (T08BIT = 0) Escolha entre temporizador (T0CS = 0) ou contador (T0CS = 1) No modo Contador, o Timer 0 incrementa seu registrador interno na transição de 0 para 1 no pino RA4 (T0CKI), se T0SE = 0. Se T0SE = 1, o incremento é na transição de 1 para 0

EXEMPLO TEMPORIZADOR 0 Inicio Configuração (temporizador configurado para gerar interrupção a cada 50 ms) Aguarda interrupção não Interrupção ativada? sim Inverte sinal do LED

EXEMPLO TEMPORIZADOR 0 #define _XTAL_FREQ 4000000 // Oscilador a 4 MHz. O número de instruções por // segundo é de 1 milhão. O tempo para executar uma #include <xc.h> // instrução (e do tick do timer) é de 1 us. #pragma config FOSC = HS #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador externo // Watchdog Timer desligado // 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 (operando como temporizador, e não como contador PSA = 1; // Desabilita Prescaler TMR0H = 0x3C; // Começa a contar de 15535 TMR0L = 0xAF; // até 65535 (conta 50 mil vezes) TMR0ON = 1; // Liga o timer

EXEMPLO TEMPORIZADOR 0 void interrupt interrupcao(void) { // Função de interrupção if (TMR0IF) { // Caso a flag do temporizador esteja ativa LATDbits.LD0 =!LATDbits.LD0; // Inverte pino D0 TMR0H = 0x3C; // Começa a contar de 15535 TMR0L = 0xAF; // até 65535 (conta 50 mil vezes) TMR0IF = 0; // Flag do timer 0 em 0 void main(void) { TRISD = 0x00; // Porta D como saída setupint(); // Função de habilitar interrupção setuptmr0(); // Função de configurar timer 0 while(1) { // Loop infinito // O código acima inverte o sinal do pino D0 a cada 50000 us, via temporizador 0. Fim de Código

EXEMPLO TEMPORIZADOR 0 + PRESCALER Inicio Configuração (temporizador configurado para gerar interrupção a cada 1s) Aguarda interrupção não Interrupção ativada? sim Inverte sinal do LED

EXEMPLO TEMPORIZADOR 0 + PRESCALER #define _XTAL_FREQ 4000000 #include <xc.h> #pragma config FOSC = HS #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador a 4 MHz. O número de instruções por // segundo é de 1 milhão. O tempo para executar uma // instrução (e do tick do timer) é de 1 us. // Oscilador externo // Watchdog Timer desligado // 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; // Fonte do clock = interna PSA = 0; // Habilita Prescaler T0CONbits.T0PS = 0b100; // Multiplicador Prescaler: 32 x 31.250us = 1 s

EXEMPLO TEMPORIZADOR 0 + PRESCALER PIC16F4550 TMR0H = 0x85; // Começa a contar de 34285 TMR0L = 0xED; // até 65535 (conta 31250 vezes) TMR0ON = 1; // Liga o timer void interrupt interrupcao(void) { // Função de interrupção if (TMR0IF) { // Caso a flag do temporizador esteja ativa LATDbits.LD0 =!LATDbits.LD0; // Inverte pino D0 TMR0H = 0x85; // Começa a contar de 34285 TMR0L = 0xED; // até 65535 (conta 31250 vezes) TMR0IF = 0; // Flag do timer 0 em 0 void main(void) { setupint(); // Função de habilitar interrupção setuptmr0(); // Função de configurar timer 0 TRISD = 0x00; // Porta D como saída while(1) { // Loop infinito // O código acima inverte o sinal do pino D0 a cada 1 s, via temporizador 0. Fim de Código

Temporizador 2 Em operação normal, o Timer 2 começa a contar de TMR2 = 0 e, a cada ciclo de contagem, compara os valores de TMR2 e PR2. Quando os dois valores forem iguais, ele gera um sinal na saída do temporizador, além de zerar o registrador TMR2 e setar a flag TMR2IF.

EXEMPLO TEMPORIZADOR 2 Inicio Configuração (temporizador configurado para gerar interrupção a cada 10 ms) Aguarda interrupção não Interrupção ativada? sim Inverte sinal do LED

EXEMPLO TEMPORIZADOR 2 #define _XTAL_FREQ 4000000 #include <xc.h> #pragma config FOSC = HS #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador a 4 MHz. O número de instruções por // segundo é de 1 milhão. O tempo para executar uma // instrução (e do tick do timer) é de 1 us. // Oscilador Externo // Watchdog Timer desligado // Master Clear desabilitado void setupint(void) { GIE = 1; // Habilita interrupção global PEIE = 1; // Timer 2 exige interrupção de periféricos habilitada TMR2IE = 1; // interrupção do Timer 2 void setuptmr2() { T2CKPS0 = 1; // Prescaler x 4 T2CKPS1 = 0; // T2OUTPS0 = 0; // Postscaler x 10 T2OUTPS1 = 1; // T2OUTPS2 = 0; // Conta 250 (PR2, abaixo) x 4 (prescaler) x 10 (postscaler) vezes T2OUTPS3 = 1; // totalizando 10000 vezes (~10 ms) por interrupção

EXEMPLO TEMPORIZADOR 2 TMR2 = 0x00; // Começa a contar de 0 PR2 = 249; // até 249 (conta 250 vezes + recarga automatica) TMR2ON = 1; // Liga o timer void interrupt interrupcao(void) { // Função de interrupção if (TMR2IF) { // Caso a flag do temporizador esteja ativa LATAbits.LD0 =!LATAbits.LD0; // Inverte pino D0 TMR2IF = 0; // Flag do timer 2 em 0 void main(void) { setupint(); // Função de habilitar interrupção setuptmr2(); // Função de configurar timer 0 TRISD = 0x00; // Porta D como saída while(1) { // Loop infinito // O código acima inverte o valor do pino D0 a cada 10 ms usando o Timer 2. Fim de Código

EXEMPLO ADC + LCD + TIMER Inicio Configuração (configura timer para interromper a cada 10 ms) Atualiza LCD com o valor da variável tensão e contador não Interrupção do conversor AD? sim Grava tensão do pino AN0 na variável tensão ; Incrementa contador ; não Interrupção do timer? sim Inicia leitura no conversor AD

EXEMPLO ADC + LCD + TIMER #define _XTAL_FREQ 4000000 #define RS LATD2 // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD7 // Pinos do LCD > #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado #include <xc.h> #include "lcd.h" #include <stdio.h> char linha1[16]; // Variável linha1 com 16 caracteres char linha2[16]; // Variável linha2 com 16 caracteres int contador = 0; // Variável contador com valor inicial 0

EXEMPLO ADC + LCD + TIMER float tensao = 0.0; // Variável que guarda a tensão lida no conversor AD long contagem = 10000; // Variável que define quantos us serão contados a cada conversão void interrupt interrupcao() { if (ADIF) { int leitura_adc = (ADRESH * 0x100) + ADRESL; tensao = ((5 * leitura_adc) * 0.0009765625); contador++; ADIF = 0; if (TMR3IF) { // Transfere valor para variável // Calcula tensão real // Incrementa contador // Desmarca flag da interrupção ADC TMR3H = (0xFFFF - contagem) >> 8; // Cálculo do valor inicial do TMR3 TMR3L = ((0xFFFF - contagem) & 0xFF); // Cálculo do valor inicial do TMR3 LATDbits.LD0 =!LATDbits.LD0; // Inverte sinal no pino D0 TMR3IF = 0; // Limpa a Flag da interrupção ADCON0bits.GO = 1; // Inicia conversao AD

EXEMPLO ADC + LCD + TIMER void setuptmr3() { T3CKPS0 = 0; T3CKPS1 = 0; TMR3CS = 0; // Prescaler // Prescaler // Clock origina do clock interno TMR3H = (0xFFFF - contagem) >> 8; TMR3L = ((0xFFFF - contagem) & 0xFF); // Cálculo do valor inicial do TMR3 // Cálculo do valor inicial do TMR3 TMR3ON = 1; // Liga o timer void setupadc(void) { TRISA = 0b00000001; ADCON2bits.ADCS = 0b1111; ADCON2bits.ACQT = 0b110; ADCON2bits.ADFM = 0b1; ADCON1bits.VCFG = 0b00; // Habilita pino A0 entrada // Clock do AD: Fosc/64 // Tempo de aquisição automático: 16 Tad // Formato: à direita // Tensões de referência: Vss e Vdd

EXEMPLO ADC + LCD + TIMER ADCON0bits.CHS = 0b0000; ADCON0bits.ADON = 1; // Seleciona canal AN0 // Liga o circuito AD void setupint(void) { GIE = 1; // Habilita interrupção global PEIE = 1; // Habilita interrupção de periféricos TMR3IE = 1; // Interrupção do timer 3 ADIE = 1; // Habilita interrupção do ADC void main(void) { OSCCON = 0b01010000; TRISA = 1; TRISD = 0; setupadc(); setupint(); // Oscilador interno a 4 MHz // A0 como entrada // Define porta D inteira como saída // Configuração do ADC // Configuração da Interrupção

EXEMPLO ADC + LCD + TIMER setuptmr3(); // Configuração do Timer 3 Lcd_Init(); // Inicia o LCD while(1) { sprintf(linha1, "N: %i", contador); // Grava texto em linha1 Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1 Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD sprintf(linha2, "Tensao: %3.2f", tensao); // Grava texto em linha2 Lcd_Set_Cursor(2,1); // Posiciona o cursor na linha 2, caractere 1 Lcd_Write_String(linha2); // Escreve texto de linha2 no LCD Fim de Código

MÓDULOS DE CAPTURE/ COMPARE/PWM (CCP)

Os módulos de Captura, Comparação e PWM contém: 1 registrador de 16 bits que opera como registrador de captura 1 registrador de 16 bits para comparação ou 1 registrador Mestre/Escravo para o Duty cycle de PWM

Configuração do Módulo CCP: Cada módulo (Captura, Comparação e PWM) está associado a um registrador de controle (genericamente, CCPxCON) e um registrador de dados (CCPRx) O registrador CCPRx é composto por dois registradores de 8 bits: CCPRxL, para o byte inferior e CCPRxH, para o byte superior A Tabela a seguir mostra os temporizadores associados a cada modo

Modo de Captura: No modo de Captura, o par de registradores CCPRxH:CCPRxL captura o valor de 16 bits dos registradores do Timer 1 ou do Timer 3, quando ocorre um evento no pino CCPx correspondente Um evento é definido como uma das seguintes ocorrências: Cada transição decrescente Cada transição crescente Cada 4ª transição crescente Cada 16ª transição crescente

Modo de Comparação: No modo de Comparação, o valor do registrador CCPRx é constantemente comparado com os valores dos pares de registradores do Timer 1 ou do Timer 3 Quando ocorre uma equivalência (igualdade), o pino CCPx pode ser: Levado ao nível lógico alto Levado ao nível lógico baixo Inverter o estado do pino (baixo para alto ou alto para baixo) Permanecer inalterado

Modo PWM No modo PWM (Modulação de Largura de Pulso), o pino CCPx produz uma saída PWM com resolução de até 10 bits. Uma vez que o pino CCP2 é multiplexado com um latch de dados da Porta B ou da Porta C, o bit TRIS apropriado deve ser zerado para fazer o pino CCP2 um pino de saída.

Modo PWM (Período) O Período de PWM é definido através do registrador PR2 O Período de PWM pode ser calculado usando a fórmula: A frequência de PWM é o inverso do período (1/PWM) Quando TMR2 é igual a PR2, os três eventos seguintes ocorrem no próximo ciclo crescente: TMR2 é zerado O pino CCPx é setado (exceto se o duty cycle for 0%) O duty cycle do PWM é transferido de CCPRxL para CCPRxH

Modo PWM (Duty Cycle) O Duty Cycle do PWM é definido escrevendo-se no registrador CCPRxL e nos bits 4 e 5 de CCPxCON. Uma resolução de até 10 bits está disponível O registrador CCPRxL contém dos 8 bits mais significativos e os dois bits (4 e 5 de CCPxCON) são os bits menos significativos O valor de 10 bits é representado por: CCPRxL:CCPxCON<5:4> O Duty Cycle pode ser calculado usando a expressão:

Modo PWM (Passos para a Configuração do PWM) Os seguintes passos devem ser executados quando configurando o módulo CCPx para operação no modo PWM: o Definir o período de PWM escrevendo no registrador PR2 o Definir o duty cycle escrevendo no registrador CCPRxL e nos bits CCPxCON<5:4> o Definir o pino CCPx como saída, através da instrução TRIS o Definir o valor de pré-escala de TMR2, e então habitar o Timer 2, escrevendo em T2CON o Configurar o módulo CCPx para operação no modo PWM

Linguagem C compilador XC8 Registradores importantes PWM: CCPR2L: byte que define o duty cycle do PWM2: CCPR2L = 26; // Define PWM com duty-cycle de 10% CCPR2L = 255; // Define PWM com duty-cycle de 100% CCPR2L = 128; // Define PWM com duty-cycle de 50% CCPR2L = 77; // Define PWM com um duty-cycle de 30%

EXEMPLO PWM Inicio Configuração (configura temporizador e PWM)... É, não faz nada.

EXEMPLO PWM #define _XTAL_FREQ 4000000 #pragma config FOSC = INTIO #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado #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; // Duty cycle % do PWM (0-255), portanto 128 = 50%

EXEMPLO PWM TMR2IF = 0; TMR2ON = 1; TRISCbits.RC1 = 0; // Limpa flag do TMR2 // Dispara o timer // "liga" bit de saída void main(void) { OSCCON = 0b01100000; setuppwm(); // Oscilador interno a 4 MHz while(1) { // Gera um sinal PWM na saída do pino RC1 Fim de Código

EXEMPLO PWM + ADC Inicio Configuração Inicia conversão AD no pino AN0 não Interrupção do conversor AD? sim Atualiza valor do duty cycle do PWM baseado no valor de tensão lido no pino AN0

EXEMPLO PWM + ADC #define _XTAL_FREQ 4000000 #pragma config FOSC = HS #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador externo High Speed // Watchdog Timer desligado // Master Clear desabilitado #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; // rotacional 2 posições à direita (divide por 4) CCPR2L = contagem; // para ajustar aos aos 8 bits do PWM ADIF = 0; // Desmarca flag da interrupção ADC if (TMR2IF) { // Caso a flag do temporizador esteja ativa, TMR2IF = 0; // desmarca a mesma

EXEMPLO PWM + ADC void setuptmr2() { TMR2 = 0x00; // Começa a contar de 0 PR2 = 249; // até 250 (conta 250 vezes + recarga automatica) void setupadc(void) { TRISA = 0b00000001; ADCON2bits.ADCS = 0b110; ADCON2bits.ACQT = 0b010; ADCON2bits.ADFM = 0b1; ADCON1bits.VCFG = 0b00; // Habilita pino A0entrada // Clock do AD: Fosc/64 // Tempo de aquisição: 4 Tad // Formato: à direita // Tensões de referência: Vss e Vdd ADCON0bits.CHS = 0b0000; ADCON0bits.ADON = 1; // Seleciona o canal AN0 // Liga o AD

EXEMPLO PWM + ADC void setupint(void) { GIE = 1; // Habilita interrupção global PEIE = 1; // Habilita interrupção de periféricos TMR2IE = 1; // Interrupção do timer 2 ADIE = 1; // Habilita interrupção do ADC void setuppwm (void) { TRISCbits.RC1 = 1; // "desliga" bit de saída setuptmr2(); // Configura timer 2 CCP2CONbits.CCP2M = 0b1100; // Modo PWM ativo CCPR2L = 128; // Configura % do PWM (0-255) TMR2IF = 0; // Limpa flag do TMR2 TMR2ON = 1; // Dispara o timer

EXEMPLO PWM + ADC TRISCbits.RC1 = 0; // "liga" bit de saída void main(void) { OSCCON = 0b01100000; TRISD = 0; LATD = 1; setupadc(); setupint(); setuppwm(); // Oscilador interno a 4 MHz // Define porta D inteira como saída // Acende o primeiro LED da porta D // Configuração do ADC // Configuração da Interrupção // Configuração do PWM while(1) { ADCON0bits.GO = 1; // Lê ADC, para recarregar valor no PWM while (ADCON0bits.NOT_DONE) { // Gera um sinal PWM na saída com ciclo variando de acordo com a tensão no pino A0 Fim de Código

TRANSDUTOR DE TEMPERATURA + LCD

LM35 + LCD Inicio Configuração do ADC e do LCD Leitura do LM35 Inicia conversão AD no pino AN0 A tensão de referência do AD é fundamental porque a tensão máxima de saída do LM35 é 1,5 V, para uma temperatura de 150ºC não Acabou a conversão? sim Converte leitura do AD em temperatura Mostra valor no LCD

LM35 + LCD #define _XTAL_FREQ 4000000 // Oscilador de 4 MHz #define RS LATD2 // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD7 // Pinos do LCD > #include <xc.h> #include <stdio.h> #include <stdlib.h> #include "lcd.h" #pragma config FOSC = HS #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador externo // Watchdog Timer desligado // Master Clear desabilitado

LM35 + LCD char linha1[16]; char linha2[16]; long contador; float temperatura; void setupadc(void) { TRISA = 0b00000001; ADCON2bits.ADCS = 0b110; ADCON2bits.ACQT = 0b010; ADCON2bits.ADFM = 0b1; ADCON1bits.VCFG = 0b01; // Variável linha1 com 16 caracteres // Variável linha2 com 16 caracteres // Habilita pino A0 como entrada // Clock do AD: Fosc/64 // Tempo de aquisição: 4 Tad // Formato: à direita // Tensões de referência: Vss e Pino AN3 // ADCON0 = 0; // Seleciona o canal AN0 ADCON0bits.CHS = 0b0001; // Seleciona o canal AN1 ADCON0bits.ADON = 1; // Liga o AD Com essa configuração, a tensão de referência positiva VREF+ para o AD está no pino AN3. Foi utilizada uma fonte de 1,5 V nesse pino. Assim, a saída máxima do LM35 resulta na saída máxima do AD

LM35 + LCD void main(void) { OSCCON = 0b01100000; TRISD = 0b00000000; setupadc(); Lcd_Init(); // Define velocidade do oscilador para 4MHz // Habilita porta D como saída // 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 temperatura = ((1.5 * 100 * contador)/1023.0); // Calcula temperatura return; sprintf(linha1, "Leitura AD: %4i ", contador); // Grava texto em linha1 sprintf(linha2, "Temperat.: %3.1f ",temperatura); // 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 LM35: 10mV/ºC leitura do AD é convertida para tensão e dividida por 0,01 (multiplicada por 100)

COMUNICAÇÃO SERIAL

SERIAL EUSART O módulo de comunicação serial EUSART (Enhanced Universal Synchronous Asynchronous Receiver Transmitter) do PIC18F4550 é um dos dois módulos de comunicação serial. Ele pode ser configurado para operar nos seguintes modos: Asynchronous full duplex com Auto reativação, com sinal de parada Calibração automática da taxa baud rate Transmissão de caracteres de parada de 12 bits Synchronous Master (half duplex) com polaridade de clock selecionável Synchronous Slave (half duplex) com polaridade de clock selecionável

SERIAL EUSART Os pinos do módulo EUSART são multiplexados com a Porta C. Para configurar os pinos RC6/TX/CK e RC7/RX/DT/SDO como uma EUSART, é necessário: Fazer SPEN = 1 (bit 7 do registrador RCSTA) Definir os bits 6 e 7 da Porta C como entrada: TRISCbits.RC6 = 1 e TRISCbits.RC7 = 1 Obs.: O controle do módulo EUSART fará a reconfiguração de entrada para saída desses pinos, sempre que necessário. A operação do módulo EUSART é controlada através de 3 registradores TXSTA Transmit Status and Control RCSTA Receive Status and Control BAUDCON Controle de Baud Rate

SERIAL EUSART Bit de seleção da fonte de clock No modo síncrono: 1 Master (clock interno) 0 Slave (clock externo) No modo assíncrono: irrelevante TX9 = 1 transmissão de 9 bits TX9 = 0 transmissão de 8 bits TXEN = 1 habilita transmissão TXEN = 0 desabilita transmissão SYNC = 1 modo síncrono SYNC = 0 modo assíncrono Modo síncrono: bit irrelevante Modo assíncrono: SENDB = 1 envia bit de parada SENDB = 0 transmissão completada Modo síncrono: não utilizado Modo assíncrono: BRGH = 1 baud rate alto BRGH = 0 baud rate baixo Bit de status do registrador de deslocamento TRMT = 1 TSR vazio TRMT = 0 TSR cheio Dado transmitido no 9º bit. Pode ser endereço, dado ou paridade

SERIAL EUSART Habilita porta serial SPEN = 1 configura os pinos RX/DT e TX/CK como porta serial SPEN = 0 desabilita porta serial RX9 = 1 recepção de 9 bits RX9 = 0 recepção de 8 bits Modo assíncrono irrelevante Modo síncrono: SREN =1 habilita recepção simples SREN = 0 desabilita recepção simples Habilita recepção contínua Modo assíncrono: CREN = 1 habilita Modo síncrono: CREN = 1 habilita modo contínuo, até CREN = 0 Habilita detecção de endereço Modo 9 bits assíncrono: Habilita detecção de endereço e interrupção Modo 8 bits assíncrono: Irrevante Bit de erro de ultrapassagem Bit de erro de quadro (framing) Dado recebido no 9º bit. Pode ser endereço, dado ou paridade

SERIAL EUSART Bit de status de rolagem na aquisição automática de baud rate RCIDL = 1 operação de recepção está ociosa Bit de seleção da polidade dos dados transmitidos e do clock Modo assíncrono: TXCKP = 1 dado de TX invertido Modo síncrono: TXCKP = 1 clock invertido Bit que habilita a função Wakeup Modo assíncrono: WUE = 1 EUSART continuará a leitura do pino RX Bit de seleção da polaridade dos dados recebidos Modo assíncrono: RXDTP = 1 dado de RX invertido Modo síncrono: RXDTP =1 dado recebido é invertido Bit que habilita o registrador de baud rate de 16 bits BRG16 = 1 gerador de baud rate de 16 bits habilitado Bit que habilita auto-detecção de baud rate

SERIAL Baud Rate O valor de n na fórmula de cálculo do baud rate corresponde ao par: SPBRGH:SPBRG Carregando o valor desejado nesses registradores, o PIC automaticamente calcula a taxa de transmissão/recepção

SERIAL Baud Rate alguns valores de SPBRGH:SPBRG para algumas taxas de transmissão/recepção Modo assíncrono de 8 bits de baixo baud rate Modo assíncrono de 8 bits de alto baud rate O valor de n a ser carregado em SPBRG é 6, para gerar baud rate de 9600 bps (valor efetivo é 8.929 bps) O valor de n a ser carregado em SPBRG é 25, para gerar baud rate de 9600 bps (valor efetivo é 9.615 bps)

SERIAL Passos para a transmissão serial assíncrona 1. Defina o valor de SPBRGH:SPBRG (chamado de n na fórmula usada). A fórmula a ser usada depende dos valores de BRGH e BRG16. : BRG16 BRGH Cálculo de n = SPBRGH:SPBRG 0 0 n = F OSC/(Baud_rate desejada) 64 0 1 n = F OSC/(Baud_rate desejada) 16 2. Habilite a comunicação serial assíncrona fazendo SYNC = 0 e SPEN = 1. 3. Se se deseja inverter o sinal do pino TX, faz-se TXCKP = 1 4. Se quiser usar interrupção da transmissão, fazer TXIE = 1. É necessário também fazer GIE = 1 e PEIE =1 5. Para a transmissão de 9 bits, deve-se fazer TX9=1. O 9º bit deve ser carregado em TX9D 6. Para habilitar a transmissão serial fazer TXEN = 1, que setará também o bit TXIF. 7. A transmissão de dados começa automaticamente quando o dado a ser transmitido é carregado em TXREG. 1 1

SERIAL Passos para a recepção serial assíncrona 1. Defina o valor de SPBRGH:SPBRG (chamado de n na fórmula usada). A fórmula a ser usada depende dos valores de BRGH e BRG16. : BRG16 BRGH Cálculo de n = SPBRGH:SPBRG 0 0 n = F OSC/(Baud_rate desejada) 64 0 1 n = F OSC/(Baud_rate desejada) 16 1 1 2. Habilite a comunicação serial assíncrona fazendo SYNC = 0 e SPEN = 1. 3. Se se deseja inverter o sinal do pino RX, faz-se RXDTP = 1 4. Se quiser usar interrupção da recepção, fazer RCIE = 1. É necessário também fazer GIE = 1 e PEIE =1 5. Para a recepção de 9 bits, deve-se fazer RX9=1. O 9º bit é recebido através do registrador RCSTA 6. Para habilitar a recepção serial fazer CREN = 1. 7. A flag RCIF será automaticamente setada quando a recepção estiver completa. Assim, se a interrupção estiver habilitada (RCIE =1), desviará para a função de tratamento da interrupção. 8. O byte recebido via serial é carregado no registrado RCREG

EXEMPLO - SERIAL Inicio Configuração; Envia texto pra porta serial; Aguarda interrupção não Interrupção da recepção serial? sim Envia texto para a porta serial com caractere digitado;

#include <stdio.h> #include <string.h> #include <stdlib.h> #define _XTAL_FREQ 4000000 #include <xc.h> EXEMPLO - SERIAL //para usar funçoes de string deve se adicionar este header // Oscilador interno de 4 MHz #pragma config FOSC = HS #pragma config WDT = OFF #pragma config MCLRE = OFF // Oscilador externo // Watchdog Timer desligado // Master Clear desabilitado char caracter; bit flag_interrupcao = 0; void interrupt RS232(void) { caracter = RCREG; flag_interrupcao = 1; RCIF = 0; //vetor de interrupção // Lê caractere recebido do registrador // Habilita variável indicando que houve recepção // Limpa flag de interrupção de recepção

SERIAL RCSTA: SPEN RX9 SREN CREN ADDEN FERR OERR RX9D 1 0 0 1 0 0 0 0 void inicializa_rs232(long velocidade,int modo) { RCSTA = 0X90; // Habilita porta serial, recepção de 8 bits em modo continuo, assíncrono. int valor; if (modo == 1) { // modo = 1, modo alta velocidade (BRGH = 1) TXSTA = 0X24; // modo assíncrono, transmissão 8 bits. valor =(int)(((_xtal_freq/velocidade)-16)/16); // valor para gerar o baud rate else { //modo = 0,modo baixa velocidade (BRGH = 0) TXSTA = 0X20; //modo assincrono,trasmissao 8 bits. valor =(int)(((_xtal_freq/velocidade)-64)/64); //calculo do valor do gerador de baud rate SPBRG = valor; esse registrador, carregado com o valor calculado, define o baud rate RCIE = 1; //habilita interrupção de recepção TXIE = 0; //deixa interrupção de transmissão desligado //(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo) TXSTA: CSRC TX9 TXEN SYNC SENDB BRGH TRMT TX9D 0 0 1 0 0 1 0 0

SERIAL void escreve(char valor) { TXIF = 0; TXREG = valor; while(txif ==0); // limpa flag que sinaliza envio completo. // Envia caractere desejado à porta serial // espera caractere ser enviado void imprime(const char frase[]) { char indice = 0; char tamanho = strlen(frase); while(indice < tamanho ) { escreve(frase[indice]); indice++; // índice da cadeia de caracteres // tamanho total da cadeia a ser impressa // verifica se todos foram impressos // Chama rotina que escreve o caractere // incrementa índice

SERIAL void main(void) { OSCCON = 0b01100000; // Oscilador interno a 4 MHz TRISB = 0X02; // configura portb B1 (pino RX) como entrada PORTB = 0; // limpar as portas que estão configuradas como saidas inicializa_rs232(9600,1); // modo de alta velocidade GIE = 1; // GIE: Global Interrupt Enable bit PEIE = 1; // habilita interrupção de periféricos do pic imprime("usando a serial MPLAB X XC8 \n\r"); imprime( Digite algo: \n\r"); while (1) { if(flag_interrupcao == 1) { //tem dados para ler imprime(" \n\rcaractere digitado :"); escreve(caracter); flag_interrupcao = 0; //loop infinito Fim de Código

EXEMPLO SERIAL + LCD Inicio Configuração; Envia texto pra porta serial e LCD; Aguarda interrupção Organiza posição do caractere na segunda linha do LCD não Interrupção da recepção serial? sim Envia texto para a porta serial e LCD com caractere digitado;

EXEMPLO SERIAL + LCD #define _XTAL_FREQ 4000000 #include <xc.h> #define RS LATD2 // < Pinos do LCD #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD7 // Pinos do LCD > // Oscilador interno de 4 MHz #include "lcd.h" #include <stdio.h> #include <string.h> #include <stdlib.h> //para usar funçoes de string deve se adicionar este header #pragma config FOSC = INTIO #pragma config WDTEN = OFF #pragma config MCLRE = OFF // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado

EXEMPLO SERIAL + LCD char caracter; char linha1[16]; char linha2[16]; bit flag_interrupcao = 0; void interrupt RS232(void) { caracter = RCREG; flag_interrupcao = 1; RCIF = 0; // Variável linha1 com 16 caracteres // Variável linha2 com 16 caracteres //vetor de interrupção // Lê caractere recebido do registrador // Habilita variável indicando que houve recepção // Limpa flag de interrupção de recepção void inicializa_rs232(long velocidade,int modo) { RCSTA = 0X90; int valor; if (modo == 1) { // Habilita porta serial, recepção de // 8 bits em modo continuo, assíncrono. // modo = 1, modo alta velocidade

EXEMPLO SERIAL + LCD TXSTA = 0X24; // modo assíncrono, transmissão 8 bits. valor =(int)(((_xtal_freq/velocidade)-16)/16); // Cálculo do baud rate else { //modo = 0,modo baixa velocidade TXSTA = 0X20; //modo assincrono,trasmissao 8 bits. valor =(int)(((_xtal_freq/velocidade)-64)/64); //calculo do valor do gerador de baud rate SPBRG = valor; RCIE = 1; //habilita interrupção de recepção TXIE = 0; //deixa interrupção de transmissão desligado //(pois corre-se o risco de ter uma interrupção escrita e leitura ao mesmo tempo) void escreve(char valor) { TXIF = 0; TXREG = valor; while(txif ==0); // limpa flag que sinaliza envio completo. // Envia caractere à porta serial // espera caractere ser enviado

EXEMPLO SERIAL + LCD void imprime(const char frase[]) { char indice = 0; char tamanho = strlen(frase); while(indice < tamanho ) { escreve(frase[indice]); indice++; // índice da cadeia de caracteres // tamanho total da cadeia a ser impressa // verifica se todos foram impressos // Chama rotina que escreve o caractere // incrementa índice void main(void) { OSCCON = 0b01100000; // Oscilador interno a 4 MHz TRISB = 0X02; // configura portb B1 (pino RX) como entrada PORTB = 0; // limpar as portas que estão configuradas como saidas inicializa_rs232(9600,1); // modo de alta velocidade GIE = 1; // GIE: Global Interrupt Enable bit PEIE = 1; // habilita interrupção de perifericos do pic

EXEMPLO SERIAL + LCD TRISD = 0x00; Lcd_Init(); int posicao = 1; // configura portd como saída // Inicia o LCD // Variável que guarda posição do caractere no LCD imprime("usando a serial MPLAB X XC8 \n\r"); imprime("digite algo: \n\r"); // Envia texto para a serial 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) { imprime(" \n\rcaractere digitado: "); escreve(caracter); // Tem dados para ler Lcd_Set_Cursor(1,1); // Posiciona o cursor na linha 1, caractere 1 sprintf(linha1, "Ultima tecla: %c", caracter); // Grava texto em linha1 Lcd_Write_String(linha1); // Escreve texto de linha1 no LCD

EXEMPLO SERIAL + LCD Lcd_Set_Cursor(2,posicao); // Posiciona o cursor na linha 2, ultima posicao sprintf(linha1, "%c", caracter); // Grava texto em linha2 Lcd_Write_String(linha1); // Escreve texto de linha2 no LCD if (posicao == 16) { posicao = 1; else { posicao++; flag_interrupcao = 0; //loop infinito Fim de Código

EXEMPLO SERIAL + ADC Inicio Configuração; Envia texto pra porta serial; Inicia leitura da tensão no pino AN0 não Finalizou a leitura? sim Envia texto para a porta serial com tensão lida;

EXEMPLO SERIAL + ADC #define _XTAL_FREQ 4000000 #include <xc.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #pragma config FOSC = INTIO #pragma config WDTEN = OFF #pragma config MCLRE = OFF // Oscilador interno de 4 MHz //para usar funçoes de string deve se adicionar este header // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado char caracter; bit flag_interrupcao = 0; char linha[22]; int contador; float tensao; void inicializa_rs232(long velocidade,int modo) { RCSTA = 0X90; // Habilita porta serial, recepção de

EXEMPLO SERIAL + ADC // 8 bits em modo continuo, assíncrono. int valor; if (modo == 1) { // modo = 1, modo alta velocidade TXSTA = 0X24; // modo assíncrono, transmissão 8 bits. valor =(int)(((_xtal_freq/velocidade)-16)/16); // Cálculo do baud rate else { //modo = 0,modo baixa velocidade TXSTA = 0X20; //modo assincrono,trasmissao 8 bits. valor =(int)(((_xtal_freq/velocidade)-64)/64); //calculo do valor do gerador de baud rate SPBRG = valor; RCIE = 1; //habilita interrupção de recepção TXIE = 0; //deixa interrupção de transmissão desligado //(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo) void escreve(char valor) { TXIF = 0; // limpa flag que sinaliza envio completo.

EXEMPLO SERIAL + ADC TXREG = valor; while(txif ==0); // Envia caractere à porta serial // espera caractere ser enviado void imprime(const char frase[]) { char indice = 0; char tamanho = strlen(frase); while(indice < tamanho ) { escreve(frase[indice]); indice++; // índice da cadeia de caracteres // tamanho total da cadeia a ser impressa // verifica se todos foram impressos // Chama rotina que escreve o caractere // incrementa índice void setupadc(void) { TRISA = 0b00000001; ADCON2bits.ADCS = 0b111; ADCON2bits.ACQT = 0b110; // Habilita pino A0 como entrada // Tempo de aquisição: 4 Tad // Clock do AD: Fosc/64

EXEMPLO SERIAL + ADC ADCON2bits.ADFM = 0b1; ADCON1bits.VCFG = 0b00; ANSEL = 0x00000001; ADCON0bits.ADON = 1; // Formato: à direita // Tensões de referência: Vss e Vdd // Seleciona o canal AN0 // Liga o AD void SuperDelay(long counter) { // Função com valor de entrada counter counter = counter / 10; // Divide o valor informado por 10 for (long i = 1; i <= counter; i++) { // E usa o resultado como base delay_ms(10); // Para repetir uma contagem de 10 ms void main(void) { OSCCON = 0b01010000; // Oscilador interno a 4 MHz

EXEMPLO SERIAL + ADC TRISB = 0X02; // configura portb B1 (pino RX) como entrada PORTB = 0; // limpar as portas que estão configuradas como saidas inicializa_rs232(9600,1); // modo de alta velocidade setupadc(); // Configuração do AD sprintf(linha, "Tensão lida: 0.000"); imprime(linha); // Grava texto em linha1 while (1) { ADCON0bits.GO = 1; // Inicia leitura do ADC while(adcon0bits.not_done) { // Aguarda leitura do ADC contador = (ADRESH * 0x100) + ADRESL; // Transfere valor para variável tensao = ((5 * contador) * 0.0009765625); // Calcula tensão real sprintf(linha, "\b\b\b\b\b%1.3f", tensao); // Grava texto em linha1 imprime(linha); SuperDelay(1000); //loop infinito Fim de Código

PROGRAMAS COM BUGS #1 ROTAÇÃO DE LEDS Comportamento esperado: Os LEDs rotacionem no estilo bate-e-volta. Sintoma: Ao iniciar o programa, os LEDs começam a rotacionar corretamente, mas depois de várias rotações, ele volta a rotacionar do primeiro LED.

PROGRAMAS COM BUGS #1 ROTAÇÃO DE LEDS #define _XTAL_FREQ 1000000 #include <xc.h> #pragma config FOSC = INTIO67 #pragma config WDTEN = ON #pragma config MCLRE = OFF // Oscilador de 1 MHz // Oscilador interno // Watchdog Timer ligado // Master Clear desabilitado void main(void) { TRISA = 0b00000000; // Habilita porta A como saída LATA = 1; // Liga o primeiro pino da porta A while(1) { // Inicia loop infinito while(lata!= 0b00000001) { LATA = (LATA >> 1 LATA << 7); // Rotacionando com estilo pra esquerda delay_ms(100); // Atraso de 100 ms while(lata!= 0b10000000) { LATA = (LATA << 1 LATA >> 7); // Rotacionando com estilo pra direita delay_ms(100); // Atraso de 100 ms Fim de Código

PROGRAMAS COM BUGS #2 ROTAÇÃO DE LEDS Comportamento esperado: Os LEDs rotacionem no estilo bate-e-volta. Sintoma: Ao iniciar o programa, nada acontece.

PROGRAMAS COM BUGS #2 ROTAÇÃO DE LEDS #define _XTAL_FREQ 1000000 #include <xc.h> #pragma config FOSC = INTIO67 #pragma config WDTEN = ON #pragma config MCLRE = OFF // Oscilador de 1 MHz // Oscilador interno // Watchdog Timer ligado // Master Clear desabilitado void main(void) { TRISA = 0b00000000; // Habilita porta A como saída LATA = 1; // Liga o primeiro pino da porta A while(1) { // Inicia loop infinito while(lata!= 0b00000001) { LATA = (LATA >> 1 LATA << 7); // Rotacionando com estilo pra esquerda delay_ms(100); // Atraso de 100 ms while(lata!= 0b10000000) { LATA = (LATA << 1 LATA >> 7); // Rotacionando com estilo pra direita delay_ms(100); // Atraso de 100 ms Fim de Código

PROGRAMAS COM BUGS #3 ROTAÇÃO DE LEDS Comportamento esperado: Os LEDs rotacionem no estilo bate-e-volta. Sintoma: Ao iniciar o programa, nada acontece. A tensão nos pinos de saída dos LEDs não mostram nenhum valor bem definido.

PROGRAMAS COM BUGS #3 ROTAÇÃO DE LEDS #define _XTAL_FREQ 1000000 #include <xc.h> #pragma config FOSC = INTIO67 #pragma config WDTEN = OFF #pragma config MCLRE = OFF // Oscilador de 1 MHz // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado void main(void) { LATA = 1; // Liga o primeiro pino da porta A while(1) { // Inicia loop infinito while(lata!= 0b00000001) { LATA = (LATA >> 1 LATA << 7); // Rotacionando com estilo pra esquerda delay_ms(100); // Atraso de 100 ms while(lata!= 0b10000000) { LATA = (LATA << 1 LATA >> 7); // Rotacionando com estilo pra direita delay_ms(100); // Atraso de 100 ms Fim de Código

PROGRAMAS COM BUGS #4 PISCAR LED Comportamento esperado: Piscar um LED na porta D0 a cada 100 ms. Sintoma: O LED pisca, mas o osciloscópio mostra que ele pisca a cada 25 ms.

PROGRAMAS COM BUGS #4 PISCAR LED #define _XTAL_FREQ 1000000 // Oscilador de 1 MHz #include <xc.h> #pragma config FOSC = INTIO #pragma config WDTEN = OFF #pragma config MCLRE = OFF void main(void) { OSCCON = 0b01010000; TRISD = 0b00000000; // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado // Define frequência do oscilador para 4MHz // Habilita porta D como saída while(1) { LATDbits.LATD0 =!LATDbits.LATD0; delay_ms(100); // Inicia loop infinito // Inverte sinal do pino D0 // Atraso de 100 ms Fim de Código

PROGRAMAS COM BUGS #5 PISCAR LED Comportamento esperado: Piscar um LED na porta D0 a cada 100 ms. Sintoma: O LED fica ligado o tempo todo.

PROGRAMAS COM BUGS #5 PISCAR LED #define _XTAL_FREQ 4000000 // Oscilador de 4 MHz #include <xc.h> #pragma config FOSC = INTIO67 #pragma config WDTEN = OFF #pragma config MCLRE = OFF void main(void) { OSCCON = 0x01010000; TRISD = 0b00000000; // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado // Define frequência do oscilador para 4MHz // Habilita porta D como saída while(1) { LATDbits.LATD0 =!LATDbits.LATD0; delay_ms(100); // Inicia loop infinito // Inverte sinal do pino D0 // Atraso de 100 ms Fim de Código

PROGRAMAS COM BUGS #6 LCD Comportamento esperado: Escrever Hello, world! e um contador na tela do LCD. A cada contagem, o LED da porta D0 deve piscar. Sintoma: Ao iniciar o programa, o LCD não mostra nada escrito. Apesar disso, o LED pisca.

PROGRAMAS COM BUGS #6 LCD #define _XTAL_FREQ 1000000 #include <xc.h> #define RS LATD2 // < Pinos do LCD ligados na porta D #define EN LATD3 #define D4 LATD4 #define D5 LATD5 #define D6 LATD6 #define D7 LATD7 // Pinos do LCD ligados na porta D > #pragma config FOSC = INTIO67 #pragma config WDTEN = OFF #pragma config MCLRE = OFF // Oscilador interno // Watchdog Timer desligado // Master Clear desabilitado #include "lcd.h" #include <stdio.h>

PROGRAMAS COM BUGS #6 LCD char linha1[16]; // Variável linha1 com 16 caracteres char linha2[16]; // Variável linha2 com 16 caracteres int contador = 0; // Variável contador com valor inicial 0 void main(void) { Lcd_Init(); // Inicia o LCD, ligado na porta D 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

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.