296
Família High End PIC 18 e MPLAB C18 Curso Módulo 4 Rinaldo Câmara Gonçalves Grupo Mosaico www.mosaico-eng.com.br Revisão 1

Apostila Mosaico Pic MÓDULO4

Embed Size (px)

Citation preview

Page 1: Apostila Mosaico Pic MÓDULO4

Família High End

PIC 18 e MPLAB C18

Curso Módulo 4

Rinaldo Câmara Gonçalves

Grupo Mosaico www.mosaico-eng.com.br

Revisão 1

Page 2: Apostila Mosaico Pic MÓDULO4
Page 3: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 1

Índice

SUMÁRIO

CAPÍTULO 1 - INTRODUÇÃO......................................................................................................................... 7 NOSSO OBJETIVO............................................................................................................................................. 7 PRÉ – REQUISITOS ........................................................................................................................................... 7 DIDÁTICA DO LIVRO .......................................................................................................................................... 7

CAPÍTULO 2 - INSTALANDO O COMPILADOR MPLAB C18 ...................................................................... 8 INSTALAÇÃO DO COMPILADOR C18.................................................................................................................... 8 INTRODUÇÃO AO MPLAB................................................................................................................................ 10 CRIANDO UM PROJETO ................................................................................................................................... 10 HABILITANDO O GRAVADOR ............................................................................................................................. 16

CAPÍTULO 3 - ARQUITETURA DA LINHA HIGH END................................................................................ 17 O PIC 18FXXXX – HARDWARE ..................................................................................................................... 17 ARQUITETURA INTERNA DO PIC 18F4520 ....................................................................................................... 18 CONFIGURAÇÕES DO OSCILADOR.................................................................................................................... 19

Opções de Oscilador................................................................................................................................ 19 Fonte de Clock e Chaveamento do Oscilador ......................................................................................... 19 Oscilador Primário.................................................................................................................................... 19 Oscilador Secundário ............................................................................................................................... 19 Bloco Oscilador Interno ............................................................................................................................ 20 Registrador de Controle do Oscilador ...................................................................................................... 20 Oscilador a Cristal e Ressonador Cerâmico ............................................................................................ 20 Operação com oscilador externo ............................................................................................................. 21 Operação com oscilador do tipo RC externo ........................................................................................... 21 Multiplicador de Freqüência PLL.............................................................................................................. 21 Configuração do Tipo de Oscilador a Cristal ou Ressonador.................................................................. 22 Configuração do Tipo de Oscilador manualmente................................................................................... 22 Configuração do Oscilador por linha de Comando .................................................................................. 23

GERENCIAMENTO DE ENERGIA ........................................................................................................................ 24 Selecionando o modo power Managed.................................................................................................... 24 As fontes de clock .................................................................................................................................... 25 Seleção do modo Power managed .......................................................................................................... 25

RUN MODE .................................................................................................................................................... 25 Modo PRI_RUN........................................................................................................................................ 25 Modo SEC_RUN ...................................................................................................................................... 25 Modo RC_RUN......................................................................................................................................... 25 Modo Sleep .............................................................................................................................................. 25

MODO IDLE .................................................................................................................................................... 26 MODOS DE RESET .......................................................................................................................................... 26

Registrador RCON ................................................................................................................................... 26 MEMÓRIA....................................................................................................................................................... 28

Memória de Programa - EEPROM Flash................................................................................................. 28 CAPÍTULO 4 - CAPITULO 4 – OPERAÇÃO COM A MEMÓRIA RAM........................................................ 29

CRIANDO VARIÁVEIS....................................................................................................................................... 29 Mapa da Memória RAM ........................................................................................................................... 29

BANCOS DA MEMÓRIA RAM........................................................................................................................... 30 TIPOS DE VARIÁVEIS....................................................................................................................................... 30

Tipos e formato das Variáveis.................................................................................................................. 30 Criando Variáveis e Inicializando ............................................................................................................. 31 Classificação do tipo de variável .............................................................................................................. 32 Variável Global e Local ............................................................................................................................ 33 Constantes ............................................................................................................................................... 34

CLASSES DE ARMAZENAMENTO ....................................................................................................................... 35 Overlay ..................................................................................................................................................... 35 Auto .......................................................................................................................................................... 35 Static......................................................................................................................................................... 35 Extern ....................................................................................................................................................... 36

Page 4: Apostila Mosaico Pic MÓDULO4

2

Register .................................................................................................................................................... 36 Typedef..................................................................................................................................................... 36

QUALIFICADOR DE ARMAZENAMENTO............................................................................................................... 36 const ......................................................................................................................................................... 36 volatile ...................................................................................................................................................... 36

QUALIFICADORES NEAR E FAR ......................................................................................................................... 36 near/far – Memória de Dados................................................................................................................... 37 near/far – Memória de Programa ............................................................................................................. 37

CAPÍTULO 5 - OPERAÇÕES LÓGICAS E ARITMÉTICAS ......................................................................... 38 HARDWARE DE MULTIPLICAÇÃO DE 8X8........................................................................................................... 38 OPERADORES ................................................................................................................................................ 38 OPERADORES ARITMÉTICOS ........................................................................................................................... 38

Atribuição.................................................................................................................................................. 38 Soma ........................................................................................................................................................ 39 Multiplicação............................................................................................................................................. 39 Divisão...................................................................................................................................................... 39 Resto da Divisão ...................................................................................................................................... 39 Incremento e Decremento........................................................................................................................ 40 Pré-incremento ......................................................................................................................................... 40 Pós-incremento ........................................................................................................................................ 40 Pré-decremento........................................................................................................................................ 40 Pós-decremento ....................................................................................................................................... 41

OPERADORES RELACIONAIS ........................................................................................................................... 41 OPERADORES LÓGICOS.................................................................................................................................. 42

Operador Lógico Booleano ...................................................................................................................... 42 Operador Lógico bit a bit .......................................................................................................................... 42

EXPRESSÕES ................................................................................................................................................. 42 Abreviando Expressões ........................................................................................................................... 42 Operador virgula “,” .................................................................................................................................. 43 Precedência dos operadores ................................................................................................................... 43 Modelador (Cast)..................................................................................................................................... 44 Comando .................................................................................................................................................. 44

CAPÍTULO 6 - COMANDOS DA LINGUAGEM C......................................................................................... 45 COMANDOS.................................................................................................................................................... 45 CONTROLE DO FLUXO DE PROCESSAMENTO.................................................................................................... 45

Comando IF – simplificado....................................................................................................................... 45 Comando IF – ELSE Simplificado............................................................................................................ 46 Comando IF e IF – ELSE Composto........................................................................................................ 46 Comando SWITCH................................................................................................................................... 50

COMANDOS PARA CONTROLE DE REPETIÇÃO (LOOP) ....................................................................................... 53 Comando WHILE...................................................................................................................................... 53 Comando Do While .................................................................................................................................. 54 Comando For............................................................................................................................................ 55 Cláusulas para controle dos comandos de laço ...................................................................................... 56 Comando goto .......................................................................................................................................... 57

CAPÍTULO 7 - FUNÇÕES ............................................................................................................................. 59 FUNÇÕES....................................................................................................................................................... 59

Criando uma Função................................................................................................................................ 60 Retorno de Função................................................................................................................................... 60 Parâmetros de uma Função..................................................................................................................... 60 Passagem por valor.................................................................................................................................. 61 Passagem por referência ......................................................................................................................... 61 Trabalhando com tipo void em Funções .................................................................................................. 61 Chamada de função externa .................................................................................................................... 62 Recursividade........................................................................................................................................... 63

CAPÍTULO 8 - MANIPULAÇÃO DOS PINOS DE I/O ................................................................................... 64 CONFIGURANDO OS PINOS DE I/O.................................................................................................................... 64 DESCRIÇÃO DOS PINOS .................................................................................................................................. 65

Pinos de alimentação, Oscilador e Master Clear ..................................................................................... 66 ESTUDO DO PORTA ...................................................................................................................................... 68

Page 5: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 3

Descrição dos pinos de I/O do PORTA.................................................................................................... 68 Registradores para configuração do PORTA........................................................................................... 68

ESTUDO DO PORTB ...................................................................................................................................... 69 Descrição dos pinos de I/O do PORTB.................................................................................................... 69 Registradores para configuração do PORTB........................................................................................... 70

ESTUDO DO PORTC ...................................................................................................................................... 71 Descrição dos pinos de I/O do PORTC ................................................................................................... 71 Registradores para configuração do PORTC .......................................................................................... 71

ESTUDO DO PORTD ...................................................................................................................................... 72 Descrição dos pinos de I/O do PORTD ................................................................................................... 72 Registradores para configuração do PORTD .......................................................................................... 72

ESTUDO DO PORTE ...................................................................................................................................... 73 Descrição dos pinos de I/O do PORTE.................................................................................................... 73 Registradores para configuração do PORTE........................................................................................... 73

ACESSO AOS SFR’S DE CONFIGURAÇÃO DOS PINOS DE I/O .............................................................................. 73 Função para manipulação do PORTB ..................................................................................................... 74 Descrição das Funções do PORTB ......................................................................................................... 74

CAPÍTULO 9 - TRATAMENTO DE INTERRUPÇÃO .................................................................................... 77 O que é Interrupção? ............................................................................................................................... 77 Hardware da Lógica de Interrupção......................................................................................................... 78 Habilitando uma Interrupção .................................................................................................................... 78 Definindo o vetor de interrupção .............................................................................................................. 78 Tratando uma interrupção ........................................................................................................................ 79

CAPÍTULO 10 - ESTUDO DOS TIMERS....................................................................................................... 80 TIMER 0 ......................................................................................................................................................... 80

A modalidade de 16 Bits .......................................................................................................................... 80 O Prescaler............................................................................................................................................... 80 Interrupção do Timer0 .............................................................................................................................. 80 Diagrama do Timer 0 no modo 8 Bit ........................................................................................................ 80 Diagrama do Timer 0 no modo 16 Bit ...................................................................................................... 80 O registrador T0CON ............................................................................................................................... 81 Registradores para configuração do TIMER0.......................................................................................... 81 T0CON: Registrador de Controle ............................................................................................................. 81 Funções para manipulação do Timer 0.................................................................................................... 82

TIMER 1 ......................................................................................................................................................... 82 Diagrama do Timer 1................................................................................................................................ 82 Modo de 16 bits para Leitura ou Escrita .................................................................................................. 82 Diagrama do Timer 1 modo de escrita e leitura de 16 Bit........................................................................ 83 Oscilador do Timer1 ................................................................................................................................. 83 Usando o TIMER1 como uma fonte de clock........................................................................................... 83 Timer1 em Low Power ............................................................................................................................. 84 Interrupção do Timer1 .............................................................................................................................. 84 Reset do Timer1....................................................................................................................................... 84 Registradores para configuração do TIMER1.......................................................................................... 84 T1CON: Registrador de Controle ............................................................................................................. 84 Funções para manipulação do Timer 1.................................................................................................... 85

TIMER 2 ......................................................................................................................................................... 85 Diagrama do Timer 2................................................................................................................................ 85 Operação do Timer2 ................................................................................................................................ 85 Interrupção do Timer2 .............................................................................................................................. 86 Timer como Base de Tempo .................................................................................................................... 86 Registradores para configuração do TIMER2.......................................................................................... 86 T2CON: Registrador de Controle ............................................................................................................. 86

TIMER 3 ......................................................................................................................................................... 87 Diagrama do Timer 3................................................................................................................................ 87 Modo de 16 bits para Leitura ou Escrita .................................................................................................. 87 Diagrama do Timer 3 modo de escrita e leitura de 16 Bit........................................................................ 88 Oscilador do Timer3 ................................................................................................................................. 88 Interrupção do Timer3 .............................................................................................................................. 88 Reset do Timer3....................................................................................................................................... 88 Registradores para configuração do TIMER3.......................................................................................... 89 T1CON: Registrador de Controle ............................................................................................................. 89

Page 6: Apostila Mosaico Pic MÓDULO4

4

Funções para manipulação do Timer 3.................................................................................................... 89 CAPÍTULO 11 - MÓDULO CCP .................................................................................................................... 90

INTRODUÇÃO.................................................................................................................................................. 90 TEORIA E RECURSOS DO PIC .......................................................................................................................... 90

Modo Capture........................................................................................................................................... 90 Modo Compare......................................................................................................................................... 92 Modo PWM............................................................................................................................................... 93

CAPÍTULO 12 - MÓDULO CONVERSOR AD .............................................................................................. 97 TEORIA .......................................................................................................................................................... 97 RECURSOS DO PIC ........................................................................................................................................ 98

CAPÍTULO 13 - MÓDULO MSSP................................................................................................................ 104 INTRODUÇÃO................................................................................................................................................ 104 TEORIA E RECURSOS DO PIC PARA SPI......................................................................................................... 104 TEORIA PARA I2C.......................................................................................................................................... 109

Condição de Start................................................................................................................................... 110 Condição de Stop................................................................................................................................... 110 Condição de Re-Start ............................................................................................................................. 111 Condição de Acknowledge (ACK) .......................................................................................................... 111 Transmissão de endereço...................................................................................................................... 111 Transmissão de dados ........................................................................................................................... 111 Pausas.................................................................................................................................................... 112 Diagramas de tempo .............................................................................................................................. 112

RECURSOS DO PIC PARA I2C........................................................................................................................ 115 Modo Slave............................................................................................................................................. 115 Modo Master........................................................................................................................................... 120

CAPÍTULO 14 - MÓDULO USART.............................................................................................................. 125 INTRODUÇÃO................................................................................................................................................ 125 TEORIA ........................................................................................................................................................ 125

Modo Assíncrono.................................................................................................................................... 125 Modo síncrono........................................................................................................................................ 126

RECURSOS DO PIC ...................................................................................................................................... 127 Modo Assíncrono.................................................................................................................................... 130 Modo Síncrono ....................................................................................................................................... 131

CAPÍTULO 15 - VARIÁVEIS ORGANIZADAS............................................................................................ 133 INTRODUÇÃO................................................................................................................................................ 133 MATRIZ ........................................................................................................................................................ 133

Criando um Vetor ................................................................................................................................... 133 Criando um vetor na memória RAM....................................................................................................... 133 Iniciando um Vetor.................................................................................................................................. 133 Criando um vetor na memória de programa .......................................................................................... 133 Leitura e Escrita de um vetor ................................................................................................................. 134 Criando uma matriz multidimensional .................................................................................................... 135 Strings .................................................................................................................................................... 136

ESTRUTURA DE DADOS ................................................................................................................................. 136 Criando uma struct de variáveis............................................................................................................. 136 Acessando elementos de uma estrutura................................................................................................ 137 Escrevendo nos elementos de uma estrutura........................................................................................ 138 Leitura de um elemento de estrutura ..................................................................................................... 138 Operação entre estruturas ..................................................................................................................... 138 Inicialização de uma estrutura................................................................................................................ 139 Matrizes de estruturas............................................................................................................................ 139 Estrutura de Bits ..................................................................................................................................... 139

UNIÕES........................................................................................................................................................ 141 Acessando os elementos de uma union ................................................................................................ 141 Escrevendo em um elemento de uma union.......................................................................................... 142 Leitura de um elemento de uma union................................................................................................... 142

VARIÁVEIS ENUMERADAS.............................................................................................................................. 142 Operações com variáveis enumeradas.................................................................................................. 143

PONTEIROS.................................................................................................................................................. 143

Page 7: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 5

Definindo um ponteiro ............................................................................................................................ 143 Carregando um endereço no ponteiro ................................................................................................... 143 Operações com ponteiros ...................................................................................................................... 144

CAPÍTULO 16 - MCMASTER – DESENVOLVIMENTO DE SISTEMAS COM MICROCONTROLADORES PIC................................................................................................................................................................. 146

INTRODUÇÃO................................................................................................................................................ 146 VISÃO MACRO DO SISTEMA........................................................................................................................... 146 MÓDULOS PADRÃO....................................................................................................................................... 147

Microcontrolador..................................................................................................................................... 147 LCD alfanumérico................................................................................................................................... 147 Displays de leds com 7 segmentos........................................................................................................ 147 Leds........................................................................................................................................................ 148 Teclado matricial .................................................................................................................................... 148 Buzzer .................................................................................................................................................... 149 Memória E2PROM externa .................................................................................................................... 149 Relógio de tempo real (RTC) ................................................................................................................. 149 Comunicação serial RS-232................................................................................................................... 149 Conversão analógica / digital (A/D)........................................................................................................ 150

PERIFÉRICOS ADICIONAIS ............................................................................................................................. 152 Placa de experiências EXP01................................................................................................................ 152

GRAVADOR .................................................................................................................................................. 152 CAPÍTULO 17 - EXPERIÊNCIAS ................................................................................................................ 153

EXPERIÊNCIA 1 - LEITURA DE UMA TECLA E ACIONAMENTO DE UM LED............................................................. 153 OBJETIVO ................................................................................................................................................ 153 DESCRIÇÃO ............................................................................................................................................. 153 ESQUEMA ELÉTRICO ................................................................................................................................ 154 FLUXOGRAMA........................................................................................................................................... 155 CÓDIGO ................................................................................................................................................... 156 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 158

EXPERIÊNCIA 2 – PISCA - PISCA ................................................................................................................... 159 OBJETIVO ................................................................................................................................................ 159 DESCRIÇÃO ............................................................................................................................................. 159 ESQUEMA ELÉTRICO ................................................................................................................................ 160 FLUXOGRAMA........................................................................................................................................... 161 CÓDIGO ................................................................................................................................................... 163 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 166

EXPERIÊNCIA 3 - DIMMER ............................................................................................................................. 167 OBJETIVO ................................................................................................................................................ 167 DESCRIÇÃO ............................................................................................................................................. 167 ESQUEMA ELÉTRICO ................................................................................................................................ 168 FLUXOGRAMA........................................................................................................................................... 169 CÓDIGO ................................................................................................................................................... 172 DICAS E COMENTÁRIOS ............................................................................................................................ 176 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 176

EXPERIÊNCIA 4 – BOTÕES, LEDS E BUZZER .................................................................................................. 177 OBJETIVO ................................................................................................................................................ 177 DESCRIÇÃO ............................................................................................................................................. 177 ESQUEMA ELÉTRICO ................................................................................................................................ 178 FLUXOGRAMA........................................................................................................................................... 179 CÓDIGO ................................................................................................................................................... 183 DICAS E COMENTÁRIOS ............................................................................................................................ 188 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 188

EXPERIÊNCIA 5 – VARREDURA DE DISPLAYS E UTILIZAÇÃO DO TIMER 1 ......................................................... 189 OBJETIVO ................................................................................................................................................ 189 DESCRIÇÃO ............................................................................................................................................. 189 ESQUEMA ELÉTRICO ................................................................................................................................ 191 FLUXOGRAMA........................................................................................................................................... 192 CÓDIGO ................................................................................................................................................... 197 DICAS E COMENTÁRIOS ............................................................................................................................ 204 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 204

EXPERIÊNCIA 6 – DISPLAY DE CRISTAL LÍQUIDO LCD ..................................................................................... 205 OBJETIVO ................................................................................................................................................ 205

Page 8: Apostila Mosaico Pic MÓDULO4

6

DESCRIÇÃO ............................................................................................................................................. 205 ESQUEMA ELÉTRICO ................................................................................................................................ 206 FLUXOGRAMA........................................................................................................................................... 207 CÓDIGO ................................................................................................................................................... 212 DICAS E COMENTÁRIOS ............................................................................................................................ 219 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 219

EXPERIÊNCIA 7 – CONVERSOR A/D .............................................................................................................. 220 OBJETIVO ................................................................................................................................................ 220 DESCRIÇÃO ............................................................................................................................................. 220 ESQUEMA ELÉTRICO ................................................................................................................................ 221 FLUXOGRAMA........................................................................................................................................... 222 CÓDIGO ................................................................................................................................................... 225 DICAS E COMENTÁRIOS ............................................................................................................................ 229 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 229

EXPERIÊNCIA 8 – MODULO PWM.................................................................................................................. 230 OBJETIVO ................................................................................................................................................ 230 DESCRIÇÃO ............................................................................................................................................. 230 ESQUEMA ELÉTRICO ................................................................................................................................ 232 FLUXOGRAMA........................................................................................................................................... 233 CÓDIGO ................................................................................................................................................... 236 DICAS E COMENTÁRIOS ............................................................................................................................ 243 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 243

EXPERIÊNCIA 9 – MASTER I2C ...................................................................................................................... 244 OBJETIVO ................................................................................................................................................ 244 DESCRIÇÃO ............................................................................................................................................. 244 ESQUEMA ELÉTRICO ................................................................................................................................ 246 FLUXOGRAMA........................................................................................................................................... 247 CÓDIGO ................................................................................................................................................... 252 DICAS E COMENTÁRIOS ............................................................................................................................ 259 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 259

EXPERIÊNCIA 10 – COMUNICAÇÃO SERIAL RS232 VIA USART ...................................................................... 260 OBJETIVO ................................................................................................................................................ 260 DESCRIÇÃO ............................................................................................................................................. 260 ESQUEMA ELÉTRICO ................................................................................................................................ 261 FLUXOGRAMA........................................................................................................................................... 262 CÓDIGO ................................................................................................................................................... 264 DICAS E COMENTÁRIOS ............................................................................................................................ 269 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 269

EXPERIÊNCIA 11 – TECLADO MATRICIAL 4X4 ................................................................................................ 270 OBJETIVO ................................................................................................................................................ 270 DESCRIÇÃO ............................................................................................................................................. 270 ESQUEMA ELÉTRICO ................................................................................................................................ 271 FLUXOGRAMA........................................................................................................................................... 272 CÓDIGO ................................................................................................................................................... 276 DICAS E COMENTÁRIOS ............................................................................................................................ 282 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 282

EXPERIÊNCIA 12 – RELÓGIO DE TEMPO REAL (RTC)...................................................................................... 283 OBJETIVO ................................................................................................................................................ 283 DESCRIÇÃO ............................................................................................................................................. 283 ESQUEMA ELÉTRICO ................................................................................................................................ 284 FLUXOGRAMA........................................................................................................................................... 285 CÓDIGO ................................................................................................................................................... 289 DICAS E COMENTÁRIOS ............................................................................................................................ 294 EXERCÍCIOS PROPOSTOS ......................................................................................................................... 294

Page 9: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 7

Capítulo 1 - Introdução

Nosso Objetivo

Esta obra tem como finalidade introduzir o leitor no mundo da linha High End da Microchip, num novo conceito de hardware e método de programação.

Para este treinamento adotamos a linguagem C por ser de alto nível, e pensando na velocidade de desenvolvimento de novos projetos com este conceito. Hoje quando pensamos em ganhar tempo em desenvolvimento de sistemas microcontrolados é difícil não pensar na linguagem C.

No estudo do hardware você conhecerá as melhorias nos periféricos já conhecidos da família 16 e muito mais.

Para completar os nossos estudos vamos aprender a programar em linguagem C usando o compilador MPLAB C18 da Microchip.

A Microchip disponibiliza uma versão demo válida por 60 dias, renovável, o que facilita o acesso e o aprendizado do leitor.

A escolha de um curso abordando a linguagem C se dá devido à arquitetura dos PIC 18, desenvolvidos para contemplar está linguagem de programação.

Pré – requisitos

Como todo treinamento, este também necessita de alguns pré-requisitos, que são, conhecer a linha 16 da Microchip, hardware e software (as 35 instruções), e ter noções de linguagem C ou Pascal. Além de um conhecimento mínimo de Eletrônica.

Didática do Livro

Visando facilitar a vida do leitor à ordem dos capítulos, estão de forma cronológica até o capítulo 8, deste ponto em diante os assuntos são independentes ficando a cargo do leitor a escolha do capítulo desejado.

Padrões textuais Para facilitar o entendimento deste material, alguns padrões textuais foram adotados: Itálico Termo adotado em língua estrangeira que ainda não foi popularmente adotado no Brasil. Negrito Nome do registrador, bit ou pino; Registrador<bit> Nome do registrador e nome do(s) bit(s) interno(s);

Page 10: Apostila Mosaico Pic MÓDULO4

8

Capítulo 2 - Instalando o compilador MPLAB C18

Instalação do compilador C18

A família 18 é linha de alta performance de microcontroladores da Microchip. Sua arquitetura foi especialmente desenvolvida para programação em alto nível.

Neste nosso estudo de microcontroladores da família 18, utilizaremos o compilador C18 da Microchip para programação em linguagem C que nos permitirá utilizar as instruções avançadas desta família.

Escolhemos este compilador por ter sido desenvolvido pela Microchip e por possuir uma versão demo válida por 60 dias, o que permitirá que hobistas, técnicos e engenheiros tenham um acesso facilitado para estudo do microcontrolador e da programação em linguagem C.

Vejamos agora, como instalar o compilador C18 passo a passo.

• Primeiro Passo

Você pode fazer o download do compilador C18 diretamente do site da Microchip no endereço www.microchip.com\download\c18 .

Após ter feito o download execute o programa, MPLAB-c18-v2.30.01-demo-win32.exe. O arquivo estará na pasta selecionado por você para salvar o download.

Figura 2.1 – Pasta contendo o arquivo de instalação.

• Segundo Passo

Pressione o botão NEXT, para prosseguirmos com a instalação.

Figura 2.2 – Tela inicial de instalação.

Page 11: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 9

• Terceiro Passo

Neste passo você pode escolher o nome do diretório que será instalado o compilador C18 ou manter o nome sugerido mcc18.

Figura 2.3 – Tela de escolha do diretório onde vai ser instalado o MPLAB C18.

• Quarto Passo

Fim da instalação dos arquivos no diretório mcc18.

Figura 2.4 – Tela do andamento de instalação do MPLAB C18.

• Quinto Passo

Pressione a tecla Finish para concluir a instalação.

Figura 2.5 – Tela de conclusão da instalação do MPLAB C18.

Page 12: Apostila Mosaico Pic MÓDULO4

10

• Sexto Passo

Após a instalação será necessário reiniciar o seu computador para concluir a instalação, pressione a tecla OK.

Figura 2.6 – Tela onde o programa de instalação pede ao usuário reiniciar o computador.

Introdução ao MPLAB

Criando um Projeto

Após a instalação do compilador C, iremos criar um projeto no MPLAB e selecionaremos o compilador C18 para compilar nossos programas.

Clique na opção Project e depois em Project Wizard.

Figura 2.7 – Menu Project.

Esta é a tela de boas vindas. Pressione o botão Avançar, para continuarmos o processo.

Figura 2.8 – Tela inicial do Assistente de Criação do Projeto.

Page 13: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 11

Nesta tela você deve selecionar o modelo de PIC da família 18 que você deseja utilizar. Observe que no canto superior esquerdo de cada tela temos a indicação do passo em que estamos para

criação de um projeto. Este é o passo um.

Figura 2.9 – Tela de seleção do microcontrolador.

No passo dois você irá selecionar, o compilador, pressione a seta da opção Active Toolsuite e selecione a opção Microchip C18 Toolsuite. Em alguns casos no campo Toolsuite Contents, um dos caminhos pode estar corrompido, quando isto ocorrer veremos um X vermelho antes do nome da ferramenta.

Para resolver este problema selecione a opção com o X vermelho e pressione o botão Browse, vá até o diretório em que o arquivo está instalado e selecione o mesmo, pronto isto irá resolver o problema.

Pressione a tecla Avançar e vá para o passo seguinte.

Figura 2.10 – Tela seleção da ferramenta de trabalho.

No passo três iremos dar um nome para o nosso projeto e selecionar o diretório para o nosso projeto. Dependendo da versão do MPLAB o nível da subpasta pode ser um problema, não podemos ultrapassar

62 caracteres. Portanto quanto mais próximo da raiz a sua pasta estiver melhor. Veja o exemplo abaixo.

Page 14: Apostila Mosaico Pic MÓDULO4

12

Figura 2.11 – Tela de Criação do Projeto.

No passo quatro, vamos selecionar o(s) arquivo(s) que devem ser compilados no nosso projeto. Você deve selecionar os arquivos e pressionar o botão ADD>>, depois pressione o botão Avançar para

irmos ao próximo passo.

Figura 2.12 – Tela de seleção dos arquivos a serem usados no projeto.

Page 15: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 13

Na última tela, podemos ver o modelo de microcontrolador, o compilador selecionado e o diretório de nosso projeto. Para finalizar pressione o botão Concluir.

Figura 2.13 – Tela de conclusão do Assistente de Criação do Projeto.

Agora o nosso trabalho está quase concluído, como estamos criando um projeto para trabalhar com o compilador C18, devemos incluir em nosso projeto um arquivo de linker, que passará informações importantes ao compilador sobre a área de memória que podemos utilizar.

Para cada microcontrolador existem dois arquivos de linker um deles é para utilizarmos o ICD2 da Microchip para gravar ou depurar e o outro para ser utilizado para qualquer outro tipo de gravador.

Alguns modelos de microcontrolador possuem um terceiro arquivo de linker para que possamos utilizar as instruções de modo expandido, essas instruções economizam código na programação em Linguagem C.

Figura 2.14 – Tela com o projeto aberto.

Page 16: Apostila Mosaico Pic MÓDULO4

14

Observe que o arquivo de Linker está no diretório mcc18, este é o diretório criado na instalação do compilador C18.

Figura 2.15 – Tela de inclusão dos arquivos de linker.

Para concluir a criação do projeto vamos novamente selecionar a opção Project e depois Build Options Project. Neste passo vamos indicar o caminho dos arquivos de linker e do projeto.

Figura 2.16 – Configurando o Build Options.

Page 17: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 15

Nesta janela você irá pressionar o botão Browse, e selecione o caminho de cada diretório.

Figura 2.17 – Selecionando os diretórios.

Agora vamos definir o tipo padrão de variáveis que serão criadas por nós em nossos desenvolvimentos.

Veja que definimos o padrão STATIC.

Figura 2.18 – Definindo o tipo padrão de variáveis.

Depois de todas estas configurações já podemos compilar nosso programa e ver os resultados.

Page 18: Apostila Mosaico Pic MÓDULO4

16

Figura 2.19 – Compilando o programa.

Habilitando o gravador

Para que possamos gravar o nosso código compilado devemos agora habilitar o gravador de nossa preferência.

Você pode utilizar: Opção 1 para PICSTART Plus, McFlash e McPlus, estes são gravadores de PIC. Opção 2 para MPLAB ICD2, estes pode ser usado como gravador e ou depurador. Opção 3 para MPLAB PM3, este é um gravador para produção. Opção 4 para PRO MATE II, este é um gravador para produção. Opção 5 para Pickit 1, estes é um kit de treinamento da Microchip.

Figura 2.20 – Habilitando o gravador.

Page 19: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 17

Capítulo 3 - Arquitetura da Linha High End

O PIC 18FXXXX – Hardware

Para o nosso estudo da família 18, escolhemos o modelo PIC 18F4520 por ser uma versão atualizada do

modelo PIC 18F452 e por ser compatível pino a pino com o PIC 16F877A, modelo da família 16. Desta forma nossos projetos baseados neste modelo poderão ser facilmente migrados para a família 18. A partir de agora veremos como a família High End da Microchip poderá nos ajudar em

desenvolvimentos mais complexos e que exigem uma capacidade de memória maior. Vamos estudar a sua arquitetura, os seus periféricos e a programação em linguagem C com o

compilador MPLAB C18. A linha High End teve a sua arquitetura e o set de instruções otimizado para programação em linguagem

C, por este motivo escolhemos o compilador MPLAB C18, como linguagem de programação para nossos estudos.

Como filosofia da Microchip ela manteve a compatibilidade entre as outras famílias para que possamos migrar facilmente, das famílias 16 e 17 para a família 18.

Uma das evoluções desta família se encontra no acesso a memória de programa, que agora é feita de forma linear não existindo a necessidade de seleção de página.

Quando falamos em seleção de página lembramos que a memória RAM possui seleção de banco, continuamos com a seleção de banco, mas a grande sacada da Microchip foi de aumentar a capacidade desta memória, agora os bancos são de 256 bytes. Para você ter uma dimensão do que estamos falando, um PIC16F877A possui 367bytes divididos em 4 bancos.

Outra vantagem é o ACESS BANK, ele possibilita livre acesso aos 128 bytes de registradores de função especial, (SFR, banco 15) e 128 bytes de registrador de uso geral, (GPR, banco 0).

Vamos ver agora o que um microcontrolador de alta performance pode nos oferecer. Como todo modelo de microcontrolador este também foi lançado aos pares veja a tabela abaixo.

DISPOSITIVO FLASH (BYTES)

INSTRUÇÕES DE UMA WORD RAM (BYTES) DATA EEPROM

(BYTES) NÚMERO DE

PINOS PIC18F2420 16K 8192 768 256 28 PIC18F2520 32K 16384 1536 256 28 PIC18F4420 16K 8192 768 256 40 PIC18F4520 32K 16384 1536 256 40

Estes microcontroladores são apenas uma amostra da linha 18 da Microchip, existem outros modelos

com interface CAN, USB 2.0 e modelos específicos para controle de motor e uso geral. Com um line card da Microchip é possível escolher o modelo adequado ao seu projeto. E os recursos não param por ai veja mais: • Capacidade de processamento de 10MIPS. • Fonte de clock interna de 32KHz e 8MHz do tipo RC. • PLL interno para multiplicar a freqüência de clock. • Prioridade no tratamento de interrupção é possível escolher entre alta ou baixa prioridade. • Hardware de multiplicação 8X8 bits executado em 1 ciclo de máquina. • Alta capacidade de corrente nos pinos de I/O, 25mA por pino. • Três fontes de interrupção externa. • Uma interrupção de mudança de estado, quatro fontes. • Timer 0 de 8 ou 16 bits configurável. • Timer 1 e 3 de 16 bits. • Timer 2 e 4 de 8 bits. • Módulo CCP. • Módulo MSSP (SPI e I2C). • Enhanced USART. • Módulo PSP. • ADC de 10bits. • PLVD. • BOR. • WDT.

Page 20: Apostila Mosaico Pic MÓDULO4

18

Arquitetura interna do PIC 18F4520

Figura 3.1 – Arquitetura do PIC 18F4520

Page 21: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 19

Configurações do Oscilador

Uma das inovações deste microcontrolador está nas opções de oscilador, temos a possibilidade de utilizar um oscilador interno de 31KHz e 8MHz.

O tipo de Oscilador é definido através dos configuration bits no momento de gravar o microcontrolador, através do registrador 1H, podemos escolher uma das 10 opções de oscilador como pode ser visto abaixo:

Tabela 3.1 - Opções de Oscilador.

1 LP Low Power Cristal 2 XT Cristal/Ressonador 3 HS High-Speed Cristal/Ressonador 4 HSPLL High-Speed Cristal/Ressonador com o PLL habilitado 5 RC Oscilador externo com Resistor e Capacitor, RA6 é saída de clock, Fosc\4. 6 RCIO Oscilador externo com Resistor e Capacitor, RA6 pino de I/O. 7 INTIO1 Oscilador RC interno, RA6 saída de clock Fosc\4 e RA7 pino de I/O. 8 INTIO2 Oscilador RC interno, RA6 e RA7 pino de I/O. 9 EC RA7 é uma entrada de clock externa e RA6 saída de clock Fosc\4 10 ECIO RA7 é uma entrada de clock externa e RA6 pino de I/O

Fonte de Clock e Chaveamento do Oscilador O sistema de clock permite utilizar o oscilador interno de 31kHz ou 8MHz, ou o Timer1 ou um cristal ou

ressonador para geração de clock do microcontrolador. Este sistema possui essencialmente três fontes de clock, que são: Oscilador Primário, Oscilador

Secundário, Bloco de Oscilador Interno.

LP, XT, HS, RC, EC

HSPLL, INTOSC/PLL

Controle deClock

4 x PLL

111

011

000

101

010

100

001

110

CONFIG1H<Fosc3>CONFIG1H<Fosc2>CONFIG1H<Fosc1>CONFIG1H<Fosc0>

OSCON<SCS1>OSCON<SCS0>

POS

TSCALE

R

1

0

8MHz4MHz2MHz1MHz

500kHz250kHz125kHz

31,25kHz

OSCTUNE<INTSRC>

INTRC31kHz

INTRC8MHz

BlocoOscilador

Interno 8MHzINTRC

31kHz(INTRC)

OSCON<IRCF0>OSCON<IRCF1>OSCON<IRCF2>

PARA OS PERIFÉRICOS

WDT, PWRT, FSCM etwo Speed Startup

OSCTUNE<PLLEN>FONTE DE CLOCK PARA

OUTROS MÓDULOS

T1OSC

OSCILADOR INTERNO

SLEEP

T1OSCENHABILITA OSCILADOR

OSC2

OSC1

T1OSI

T1OSO

IDLEN

CPU

Figura 3.2 – Fonte de Clock.

Oscilador Primário O oscilador primário e formado pelo oscilador externo Que pode ser um cristal ou ressonador (LP, XT,

HS e HSPLL), pelo oscilador interno do tipo RC ou pelo sistema de clock externo (EC).

Oscilador Secundário O módulo secundário é formado pelo Timer1.

Page 22: Apostila Mosaico Pic MÓDULO4

20

Bloco Oscilador Interno A terceira fonte de clock faz parte do power managed mode, sistema para baixo consumo. Este sistema

pode ser utilizado na falha do oscilador primário, garantindo a continuidade de funcionamento do sistema. Sendo possível trabalhar com 31KHz ou 8MHz. Trabalhando em 8MHz podemos utilizar o postscale e

selecionar freqüências mais baixas, diminuindo desta forma o consumo do microcontrolador.

Registrador de Controle do Oscilador O registrador OSCCON é responsável pela seleção das fontes de clock do sistema, primário, secundário

e bloco oscilador interno. Através dos bits <SCS1:SCS0> podemos selecionar a fonte de clock. Com os bits <IRCF2:IRCF0>,

selecionamos o postscale do oscilador interno RC, que pode ser ajustado de 31.25kHz a 8MHz, desde que o RC esteja configurado para 8MHz.

Os bits <OSTS:IOFS> e T1CON <T1RUN>, indicam qual é a fonte de clock do microcontrolador. O bit IDLEN determina se o microcontrolador está no modo sleep ou no modo IDLE.

OSCCON: Controle do oscilador

Oscilador a Cristal e Ressonador Cerâmico No modo oscilador temos as opções: LP, XT, HS e HSPLL, o cristal ou ressonador são conectados nos

pinos OSC1 e OSC2. A interligação do cristal pode ser vista na figura 3.3.

Page 23: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 21

SLEEP

OSC2

OSC1

C2

C1

18FXXXXSistema Oscilador

Figura 3.3 – Esquema de ligação do cirstal ou ressonador.

Operação com oscilador externo Quando trabalhamos com oscilador externo nos modos EC e ECIO podemos conectar um circuito

externo de oscilador no pino OSC1. No modo EC teremos no pino OSC2 a freqüência de clock dividida por quatro, este sinal pode ser

utilizado por outros circuitos externos. O esquema de ligação pode ser visto na figura 3.4a. No modo ECIO o pino OSC2 pode ser utilizado como pino de I/O nós teremos o pino RA6 disponível.

Veja na figura 3.4b o esquema de ligação.

RA6

OSC1/CLKIN

18FXXXXSistema de Oscilador Externo

para outros dispositivos

Pino de I/O

Entrada doClock Externo

OSC2/CLKOUT

OSC1/CLKIN

18FXXXXSistema de Oscilador Externo

para outros dispositivos

Fosc/4

Entrada doClock Externo

Figura 3.4a Figura 3.4b

Operação com oscilador do tipo RC externo Este é o modo de menor custo, o circuito oscilador é formado apenas por um resistor e um capacitor. Um cuidado com este modo é que a freqüência pode variar de acordo com a temperatura e a variação

na tensão de alimentação, já que o sistema depende da carga e descarga de um capacitor. Este modo possui duas formas de configuração, OSC2/RA6 como saída de clock (Fosc/4) ou como pino

de I/O. Na figura 3.5a temos o modo RCIO e na figura 3.5b temos o modo RC.

OSC2/CLOCKOUT

OSC1/CLKIN

18FXXXXSistema de Oscilador Externo

Fosc/4

Rext

Cext

VDD

RA6

OSC1/CLKIN

18FXXXXSistema de Oscilador Externo

Pino de I/O

Rext

Cext

VDD

Figura 3.5a. Figura 3.5b

Multiplicador de Freqüência PLL Um dos recursos adicionais é o circuito de PLL que nos permite multiplicar a freqüência do oscilador

interno em 4 vezes, utilizando um cristal externo de menor valor. Desta forma poderemos trabalhar com um cristal de menor valor, o que diminui o problema com EMI, já

que iremos multiplicar a freqüência de clock internamente. Para que possamos habilitar o PLL devemos, selecionar o modo HSPLL, o que quer dizer que teremos

que trabalhar com um cristal cuja freqüência seja maior do que 4MHz. No modo oscilador interno deveremos selecionar o RC para 8MHz a fim de podermos utilizar o PLL com o circuito RC interno.

Page 24: Apostila Mosaico Pic MÓDULO4

22

A seleção e habilitação do PLL podem ser feitas através dos fuses e do registrador OSCTUNE, veja o registrador e para maiores detalhes, veja o apêndice A. OSCTUNE: Registrador de ajuste do oscilador

Configuração do Tipo de Oscilador a Cristal ou Ressonador Para que possamos configurar um dos tipos de oscilador citados podemos, ou inserir uma linha de

comando em nosso programa ou realizar a configuração manualmente.

Configuração do Tipo de Oscilador manualmente Para selecionar o tipo de oscilador, devemos selecionar o microcontrolador desejado, ele pode ser

definido na etapa de criação do projeto ou como veremos na figura 3.6a e 3.6b. Na barra de ferramenta vamos selecionar a opção Configure Select Device.

Figura 3.6a – Seleção do microcontrolador.

Na janela que foi aberta vamos selecionar o microcontrolador desejado, para que possamos seguir para

a próxima etapa, configurar o tipo de oscilador.

Page 25: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 23

Figura 3.6b – Seleção do microcontrolador.

Após a seleção do microcontrolador vamos até a opção Configure Configuration Bits, nesta janela veremos as possibilidades de configuração de oscilador.

Figura 3.7 – Menu Configure, Configuration Bits.

Nesta janela podemos selecionar qualquer uma das opções de oscilador desejado.

Figura 3.8 – Seleção do tipo de oscilador.

Configuração do Oscilador por linha de Comando Em nosso código vamos incluir uma linha de comando que fará a configuração dos fuses do

microcontrolador. Esta linha de comando de configuração deve vir logo após a linha de include do arquivo de header do microcontrolador escolhido.

O comando #pragma config, é utilizado para que possamos entrar com a palavra de configuração dos fuses, que é gravada na memória de programa.

As demais palavras de configuração do oscilador podem ser vistas na tabela 3.2, a seguir temos um exemplo de palavra de configuração dos fuses.

Exemplo: #pragma config OSC = HSPLL No arquivo de include do microcontrolador escolhido temos as opções de configuração do oscilador,

veja as opções:

Page 26: Apostila Mosaico Pic MÓDULO4

24

Tabela 3.2 – Palavras de configuração para os tipos de osciladores

Palavra de Configuração Tipo de Oscilador Faixa de Freqüência _OSC_LP_1H LP 0 a 200kHz _OSC_XT_1H XT 200kHz a 4MHz _OSC_HS_1H HS 4MHz a 25MHz

_OSC_RC_1H RC externo/RA6 clock out(Fosc/4) 0 a 16MHz

_OSC_RCIO6_1H RC externo/RA6 I/O 0 a 16MHz _OSC_EC_1H Clock Externo 0 a 25MHz

_OSC_ECIO6_1H Clock Externo/RA6 I/O 0 a 25MHz _OSC_HSPLL_1H HS multiplicado pelo PLL Até 10MHz

_OSC_INTIO67_1H RC Interno/ RA6 e RA7 I/O 31kHz a 8MHz

_OSC_INTIO7_1H RC Interno/RA6 clock out (Fosc/4) 31kHz a 8MHz

_FCMEN_OFF_1H Disabled Desabilita verificação de falha no oscilador principal

_FCMEN_ON_1H Enable Habilita verificação de falha no oscilador principal

_IESO_OFF_1H Disabled Desabilita a comutação entre oscilador interno e externo

_IESO_ON_1H Enable Habilita a comutação entre oscilador interno e externo

Gerenciamento de Energia

Visando melhorar a inicialização dos microcontroladores a Microchip, desenvolveu para a família 18, três categorias de gerenciamento de energia, são elas:

• Run modes • Idle modes • Sleep modes

Estas modalidades fornecem uma variedade de opções para diminuição do consumo de energia, para as

aplicações onde os recursos podem ser limitados (sistemas alimentados por pilhas e baterias). O modo Run e o modo Idle podem usar um dos três blocos interno de geradores de clock (primário,

secundário ou bloco oscilador interno); a modalidade Sleep obviamente não fonte de clock. As modalidades de power managed podem incluir diversas possibilidades de salvar do dispositivo e

mate-lo funcionando. Uma delas é a característica de chavear a fonte de clock, oferecida em outros dispositivos PIC18, permitindo que o controlador use o oscilador Timer1 no lugar do oscilador primário.

É incluída também a modalidade Sleep, comum nos microcontroladores da Microchip, onde o oscilador interno é desligado interrompendo todas as fontes de clock do dispositivo.

Selecionando o modo Power Managed Para selecionar o modo de gerenciamento de energia é necessário tomar duas decisões: • Se processador central está recebendo sinal de clock ou não. • E qual fonte de clock será selecionada.

O processador central controla o bit de OSCCON<IDLEN> que controla o clock da CPU, quando os bits

OSCCON<SCS1:SCS0> selecionam a fonte de clock. Os módulos individuais, os bits de controle, as fontes de clock e os módulos afetados são vistos na

tabela abaixo.

Page 27: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 25

Tabela 3.3 – Modo de gerenciamento e módulos afetados

As fontes de clock Os bits OSCCON<SCS1:SCS0> permitem a seleção de uma de três fontes de clock, são: • Fonte de clock primário, definido pelos bit de configuração CONFIG1H<FOSC3:FOSC0> • Fonte de clock secundário (oscilador do Timer1) • Bloco oscilador interno (para modo RC)

Seleção do modo Power Managed Para selecionar um dos modos devemos configurar o registrador OSCCON. Os bits <SCS1:SCS0> selecionam a fonte de clock e qual o modo de trabalho Run ou Idle. Mudar estes bits causa uma comutação imediata para a nova fonte de clock, supondo que está

funcionando.

Run Mode

No modo Run, o sinal de clock é fornecido ao microcontrolador e para os periféricos.

Modo PRI_RUN O modo PRI_RUN é o modo normal de trabalho do microcontrolador. Este também é o modo padrão de inicialização do microcontrolador. Neste modo o bit OSCCON<OSTS> é colocado em um, já o bit OSCCON<IOFS> pode ser colocado em

um se o bloco oscilador interno for a fonte de clock primária.

Modo SEC_RUN O modo SEC_RUN é o modo compatível com a característica de chaveamento do sinal de clock

oferecida em outros dispositivos PIC18. Nesta modalidade, o processador central e os periféricos recebem o sinal de clock do Timer1.

Isto dá ao usuário a opção de um consumo de potência mais baixa ou ainda usar uma fonte de clock de maior precisão.

O modo SEC_RUN é configurado pelos bits <SCS1:SCS0>. O oscilador do Timer1 já deve estar funcionar antes de entrar no modo SEC_RUN.

Modo RC_RUN No modo RC_RUN, o processador central e os periféricos recebem o sinal de clock do bloco do oscilador

interno, usando o multiplex do INTOSC. Neste modo, o sinal de clock primário é desligado. Ao usar o bloco oscilador interno (INTRC), este modo permite um menor consumo de energia.

Modo Sleep Quando o dispositivo entra no modo Sleep o bit IDLEN é zerado. Entrar no modo sleep, desliga o oscilador interrompendo o processamento. Se o WDT for selecionado, a

fonte de INTRC continuará operando. Se o oscilador Timer1 for permitido, também continuara funcionando. Quando um evento acordar o microcontrolador do modo sleep (por interrupção, por reset ou por WDT), o

dispositivo iniciará o processamento até que a fonte de clock selecionada esteja funcionando

Page 28: Apostila Mosaico Pic MÓDULO4

26

Modo Idle

O modo Idle permite que somete os periféricos trabalhem, quando uma instrução Sleep é executada. Selecionar o modo Idle permite que os usuários controlem mais o consumo de energia. Se o bit de

IDLEN estiver em um, quando uma instrução Sleep for executada, os periféricos continuam a operar através da fonte de clock selecionada pelos bits <SCS1:SCS0>.

Como o microcontrolador não está operando, as únicas maneiras de sair do modo sleep será pelo WDT ou por reset.

Quando o processador central começa a executar o código, recomeça com a mesma fonte de clock do modo Idle.

Modos de Reset

Os dispositivos PIC18F2420/2520/4420/4520 possuem vários tipos de reset: a) Power on Reset (POR) b) MCLR reset durante operação normal c) MCLR reset durante o power managed modo d) Watchdog Timer (WDT) reset durante a execução e) Reset por Brown-out f) Instrução de Reset g) Reset por estouro de pilha (Stack Full) h) Reset por Stack Underflow

Observe o diagrama de bloco simplificado do circuito de reset.

Figura 3.9 - Circuito de reset.

Page 29: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 27

Registrador RCON Os eventos que podem gerar reset no microcontrolador podem ser observados no registrador RCON. Os cinco bits menos significativos indicam que um evento específico de reset ocorreu. Na maioria dos casos, estes bits podem somente mudar de estado pelo evento e devem ser ajustados

pela aplicação após o evento. O registrador RCON também tem o bit de controle para ajustar a prioridade da interrupção (IPEN) e o

controle por software do BOR (SBOREN). RCON: Eventos de reset

Page 30: Apostila Mosaico Pic MÓDULO4

28

Memória

Este microcontrolador possui três tipos de memória são elas: • Memória de Programa • Memória de Dados • Memória EEPROM

Como este dispositivo utiliza arquitetura Harvard, a memória de dados e a memória de programa utilizam

barramentos separados, isto permite o acesso as duas memórias ao mesmo tempo. A memória de dados EEPROM é práticamente um periférico, como tal é necessário configura-lo para

termos acesso a escrita ou leitura.

Memória de Programa - EEPROM Flash Os microcontroladores da família PIC18 da memória de programa executam um contador de programa

de 21 bits, que seja capaz de dirigir a um espaço de memória do programa 2Mbyte. Alcançar uma posição entre o limite superior da memória fisicamente executada e o endereço 2Mbyte retornará 0 (uma instrução de NOP). Os PIC18F2420 e os PIC18F4420 cada um têm 16 kbytes de memória flash e podem armazenar até 8.192 instruções single-word. Os PIC18F2520 e os PIC18F4520 cada um têm 32 kbytes da memória flash e podem armazenar até 16.384 instruções single-word. Os dispositivos PIC18 têm dois vetores de interrupção.

O endereço de vetor de reset está no endereço 0000h e os endereços dos vetores de interrupção são em 0008h e em 0018h. O mapa de memória do programa para os dispositivos PIC18F2420/2520/ 4420/4520 é mostrado em figura abaixo.

Figura 3.10 - Mapa de memória de programa.

Page 31: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 29

Capítulo 4 - Capitulo 4 – Operação com 0a memória RAM

Criando Variáveis

Neste capitulo estudaremos a forma como o MPLAB C18, manipula a memória RAM, como criar variáveis e quais os tipos existentes.

Mapa da Memória RAM

Figura 4.1 – Mapa de memória de dados.

Page 32: Apostila Mosaico Pic MÓDULO4

30

Bancos da Memória RAM

Figura 4.1 – Registradores especiais.

Tipos de Variáveis

Até agora estudamos o hardware do microcontrolador, como devemos selecionar bancos da memória RAM, a área de SFR e GPR.

Agora vamos estudar o compilador C18 e aprender como utilizar a memória RAM, como reservar espaço para nossos registradores, como utilizar a área de acess bank, como inicializar nossas variáveis e como classificar estas variáveis.

Vamos ao que interessa, estudaremos primeiro como criar variáveis e como inicializa-las.

Tipos e formato das Variáveis Para criar uma variável devemos primeiro ver quais os tipos disponíveis no compilador C utilizado. O compilador da Microchip segue o padrão ANSI, desta forma podemos classificar as variáveis em dois

tipos: inteiros e ponto flutuante. As variáveis do tipo inteiro podem ter de 8bits a 32bits. Desta forma podemos utilizar uma variável de tamanho adequado a nossa operação, o que permitira o

uso econômico da memória. Facilitando a criação de expressões matemáticas e lógicas, já que podemos escolher o tamanho da

variável. Observe na tabela que uma variável sinalizada divide o range de uma variável ao meio.

Page 33: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 31

Já as variáveis do tipo ponto flutuante nos permite realizar operações com valores fracionários, o que é muito útil para realizarmos operações matemáticas com valores reais.

Variáveis do Tipo inteiro Vejamos quais são os tipos de variáveis do tipo inteiro que podemos criar.

Tabela 4.1 – Tipo de dados e tamanho

Tipo Tamanho Mínimo Máximo char(1,2) 8 bits -128 127

int 16 bits -32768 32767 short 16 bits -32768 32767 long 32 bits -2147483648 2147483647

Nota

1: Por padrão todos os tipos de variáveis são do tipo sinalizado. 2: Para que o tipo unsigned char, seja padrão devemos incluir na linha de comando a opção -k.

Variável do Tipo Ponto Flutuante O MPLAB C18, permite criar variáveis de 32 bits do tipo float (ponto flutuante). A Microchip criou um formato especifico para variáveis float, que foi adotado até a versão 2.30.01 do

MPLAB C18. Com a nova versão do compilador, o MPLAB C18 Student Edition – V 2.40, foi adotado o formara

simples da IEEE754. A biblioteca da versão estudante possui duas funções para conversão do formato float de Microchip ↔

IEEE754. Na tabela abaixo podemos ver o range deste tipo de variável.

Tabela 4.2 – Outros tipos de dados e tamanho

Tipo Tamanho Expoente mínimo Expoente máximo Valor mínimo normalizado

Valor máximo normalizado

float 32 bits -126 128 1,17549435e-30 6,80564693e+46

double 32 bits -126 128 1,17549435e-30 6,80564693e+46

Criando Variáveis e Inicializando Nossa primeira pergunta pode ser: Como defino a seleção de bancos da memória RAM? Vejamos

estamos utilizando uma linguagem de alto nível, portanto está não é uma preocupação do programador, o compilador fará a seleção de banco quando necessário.

Mesmo a seleção de banco sendo de responsabilidade do compilador, existe a possibilidade de definirmos o banco em que a variável será criada, estudaremos esta forma mais tarde.

Para criar uma variável devemos informar o seu tipo e o seu nome. Também é possível criar mais de uma variável do mesmo tipo, basta separar por virgula as variáveis

criadas. A forma de criar uma variável serve tanto para variável do tipo inteiro quanto para variável do tipo ponto

flutuante.

Sintaxe: Tipo nome; ou Tipo var_1, var_2, ... , var_n;

Page 34: Apostila Mosaico Pic MÓDULO4

32

Exemplo: a) char contador; b) int tempo1, auxiliar1, auxiliar2;

Para facilitar a nossa programação, podemos criar a variável e inicializar ao mesmo tempo. Sintaxe: Tipo nome = valor; ou Tipo var_1 = valor_1, var_2 = valor_2, ... , var_n = valor_n; Exemplo: a) char contador = 10; b) int tempo1 = 0, auxiliar_1 = -20, auxiliar_2 = 10454;

Nomes de Variáveis • Você pode dar qualquer nome para as suas variáveis. Mas devemos seguir algumas regras: • O nome de uma variável de ser iniciada por letra, os demais caracteres pode ser: letras, números e o

sublinhado (_). • Não podemos utilizar palavras reservadas do compilador C e nem utilizar nome dada a funções e ou

rotinas. • Utilizar no máximo 32 caracteres, da para escrever nome e sobre nome da variável. • O compilador C é “case sensitive”, quer dizer que ele diferencia letra maiúscula de minúscula. • Utilize letra minúscula para variável e maiúscula para constante, está é uma boa prática de

programação.

Classificação do tipo de variável As variáveis do tipo inteiro ainda podem ser classificadas como sinalizadas (signed) e não sinalizadas

(unsigned). Quando criamos uma variável devemos informar a sua classificação. Por padrão toda variável criada é

do tipo sinalizada. Veja uma variável signed char pode assumir valores de -128 a 127. Para representar o valor negativo utilizamos o bit 7 como bit de sinal, Quando o bit 7 for 1 o valor

armazenado na variável é negativo, com o bit 7 igual a zero o valor é positivo. Na tabela abaixo temos o número 0 armazenado na variável teste do tipo unsigned char. unsigned char teste =0;

Variável teste 7 6 5 4 3 2 1 0 0 0 0 0 0 0 0 0

Em uma variável não sinalizada utilizamos todos os bits para representar o valor armazenado na

variável, já em uma variável sinalizado utilizamos somente os 7 bits menos significativos. Agora observe o número -128 armazenados na variável teste2 do tipo signed char. signed char teste2 = -128;

Variável teste2 7 6 5 4 3 2 1 0 1 0 0 0 0 0 0 0

Page 35: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 33

Tabela 4.3 – Tipos de dados e tamalho.

Tipo Tamanho Mínimo Máximo char 8 bits -128 127

signed char 8 bits -128 127 unsigned char 8 bits 0 255

int 16 bits -32768 32767 unsigned int 16 bits 0 65535

short 16 bits -32768 32767 unsigned short 16 bits 0 65535

short long 24 bits -8388608 8388607 unsigned short long 24 bits 0 16777215

long 32 bits -2147483648 2147483647 unsigned long 32 bits 0 4294967295

Um outro tipo de variável que aparece em nossa tabela é a short long, que quer dizer “longo curto”, a

variável do tipo long é de 32bits, portanto para o C18, uma variável short long é de 24bits.

Variável Global e Local

Quando criamos uma variável, esta pode ser Global ou Local, isto depende do local onde está variável foi criado.

Variável Global Uma variável é Global quando a mesma é criada fora de qualquer tipo de função. E qual a vantagem

dela ser global? A vantagem está em podermos utilizar está variável em qualquer local de nosso programa e dentro de

qualquer função do programa. Mas a principal vantagem é que este tipo de variável não perde o último valor armazenado. No exemplo a seguir podemos ver uma variável global.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. unsigned char CONTADOR = 0; unsigned char TEMPO = 10; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Protótipo da função de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void delay10TCYx(unsigned char tempo_x); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) for (CONTADOR = TEMPO;CONTADOR!=0; CONTADOR--) delay10TCYx(TEMPO);

Page 36: Apostila Mosaico Pic MÓDULO4

34

Variável Local Para que uma variável seja definida como local ela deve ser criada dentro do bloco de programa de uma

função. Esta função pode ser a principal, de usuário ou uma função especifica do MPLAB C18. A característica marcante desta variável é que ela perde o seu dado ao final da execução da função

onde ela foi criada. Outra característica da variável local é que ela só é “vista” pela função onde ela foi criada. Isso nos permite criar variáveis locais em funções diferentes com o mesmo nome. Prática que eu não

utilizo em meus programas para evitar confusões durante a analise de um código. Fazendo o uso de variáveis locais podemos economizar memória RAM, além de permitir a portabilidade

de uma função. Isso quer dizer que você pode criar as suas funções e passar valores para essa função que serão

armazenados em uma variável local. A seguir seja um exemplo de como criar uma variável local.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Protótipo da função de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void delay10TCYx(unsigned char tempo_x); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () unsigned char CONTADOR = 0, TEMPO = 10; // variáveis local /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) for (CONTADOR = TEMPO;CONTADOR!=0; CONTADOR--) delay10TCYx(TEMPO);

Constantes As constantes podem ser numéricas e de caractere, estas por sua vez não podem ser alteradas, em

tempo de processamento.

Constantes Numéricas As constantes numéricas são usadas para representar números inteiros, constantes hexadecimais,

binárias e octais. Uma constante hexadecimal é precedida por 0X ou 0x. Já uma constante octal é precedida por um zero. Um número binário é precedido por 0B ou 0b. Veja na tabela como podemos representar uma constante em sua respectiva base.

Tabela 4.4 – Representação de constantes numéricas

Tipo de constante Representação Inteiro (decimal) 35

Hexadecimal 0x23 Octal 043

Binário 0b00100011

Page 37: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 35

Constantes de Caractere Em sistemas computadorizados, os caracteres são representados por valores numéricos, o sistema de

representação foi padronizado pelo uso do código ASCII(American Standard Code for Information Interchange).

Uma constante de caractere é representada por apostrofo, ‘A’, que equivale ao número 0x41. Um conjunto de caractere é chamado de string, uma string é representada por um conjunto de

caracteres entre aspas, veja o exemplo: “Grupo Mosaico” Esta string é formada por um conjunto de constantes e finalizada pelo caractere nulo, ‘\0’, representado

por suas constante teremos: 0x47, 0x72, 0x75, 0x70, 0x6F, 0x20, 0x4D, 0x6F, 0x73, 0x61, 0x69, 0x63, 0x6F, 0x00.

Na tabela ASCII existe um conjunto de caracteres que não permitem a sua impressão, são chamados de seqüência de escape ou código de barra invertida.

No apêndice C poderemos ver a tabela ASCII, mais o conjunto de caracteres de escape.

Classes de armazenamento

Os compiladores C do padrão ANSI possuem cinco classes de armazenamento, o MPLAB C18 suporta estas classes de armazenamento, são elas: auto, extern, register, static e typedef.

Overlay O compilador MPLAB C18 introduz uma classe do armazenamento chamado overlay. Esta classe de

armazenamento aplica-se somente quando o compilador esta operando no modo não extendido, (non-extended). Sua finalidade é economia de memória RAM.

Ela pode ser aplicada a variáveis locais, mas não aos parâmetros formais de uma função, a tipo de função ou a variáveis globais.

A classe de armazenamento overlay alocará os símbolos associados em uma função-específica, e serão do tipo static overlay. Esta variável será alocada e inicializada a cada entrada da função.

Veja o exemplo: void f (void)

overlay int x = 5; x++;

A variável x será inicializada com cinco a cada entrada da função, embora seu armazenamento seja

alocado estaticamente. Caso a variável não seja inicializada, o valor da mesma será indefinido. Se o linker do MPLINK detectar uma função recursiva que contenha uma variável local de classe de

armazenamento overlay, o compilador irá gerar uma mensagem de erro.

Auto Uma variável auto tem o seu endereço da memória RAM definido quando o bloco de programa onde ela

foi criada é executado. Ao final da execução do bloco de programa onde a variável foi criada, o espaço reservado da memória RAM é liberado para que outra variável auto a utilize. Usado para criar variáveis locais.

Este tipo de classe será utilizado quando desejarmos economizar memória RAM, pois a uma grande chance de variáveis da classe auto, ocuparem o mesmo endereço de memória em momentos distintos, evitando a sobre carga.

Quando uma variável de classe auto não é inicializada, ela pode assumir qualquer valor. Sintaxe: auto tipo variável;

Static Uma variável do de classe de armazenamento static, tem a sua posição na memória RAM definida em

tempo de compilação, ou seja, está variável utilizará sempre o mesmo endereço. Será usado para definir uma variável como global.

Page 38: Apostila Mosaico Pic MÓDULO4

36

Como uma variável static possui sempre o mesmo endereço, a quantidade de RAM usada para este tipo de classe depende do tipo da variável e da quantidade de variáveis criadas.

Uma variável static deve ser inicializada, isto ocorre em tempo de compilação, caso não o seja, a variável será iniciada com zero.

Este tipo de classe é válido somente com o MPLAB C18 no modo não estendido. Sintaxe: static tipo variável;

Extern Esta classe de armazenamento define que a variável utilizada encontra-se em outro programa, ou seja, é

uma variável externa. Podemos utilizar esta classe de armazenamento para unir diversos módulos de programas, sejam eles grandes e ou complexos, através do MpLink do MPLAB C18. Desta forma é possível utilizar em uma rotina ou função do seu programa principal uma variável de um dos módulos externos de programa.

Sintaxe: extern tipo variável;

Register No padrão ANSI este tipo de classe utiliza registradores da CPU para armazenar dados e acessa-los de

forma mais rápida. Nos microcontroladores os dados já são armazenados em registradores. Sintaxe: register tipo variável;

Typedef Sua finalidade é de redefinir o tipo de dado, o que este comando faz é criar um novo tipo de dado em

função de um tipo já existente. Sintaxe: typedef tipo novo_tipo;

Qualificador de armazenamento

O compilador MPLAB C18 pode trabalhar com os qualificadores de armazenamento do padrão ANSI são eles, const e volatile, também chamados de modificadores de acesso.

Const Modifica o acesso a uma variável, tratando a como uma constante. A diferença fica na forma de armazenamento, uma const fica armazenada na memória de programa,

“não podendo” ser modificada. A finalidade deste qualificador é proteger a variável contra modificações do seu conteúdo. Volatile Este qualificador informa ao compilador que a variável qualificada como volatile, pode ter o seu conteúdo

alterado sem prévio aviso. Imagine que o sistema micro – controlado desenvolvido por você possui um sistema operacional, que

este sistema possui um RTC, as variáveis de atualização do relógio podem ser qualificadas como volatile. Enquanto o seu sistema executa o programa do usuário, o sistema operacional pode atualizar as

variáveis do relógio sem causar nenhum tipo de problema ao sistema, ou seja, são variáveis que podem ser acessadas pelo sistema operacional e pelo programa do usuário.

Qualificadores near e far

Além dos qualificadores const e volatile, o compilador MPLAB C18 introduz dois novos qualificadores de armazenamento far, near, que qualificam o uso da rom e ram.

A condição padrão quando um qualificador não é definido são far e ram.

Page 39: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 37

Tabela 4.4 – Posição do objeto baseado nos qualificadores de armazenamento.

Qualificador ROM (memória de programa) RAM (memória de dados) far Em qualquer lugar na memória de programa Em qualquer lugar na memória RAM

near Na memória de programa até o endereço 64K Na área de ACESS BANK

near/far – Memória de Dados O qualificador far é usado para deixar explicito que a variável está em uma área de RAM onde existe a

necessidade de seleção de banco para acessa-la. Já o qualificador near deixa claro que a variável faz parte da área de acess bank da memória RAM.

near/far – Memória de Programa O qualificador far é usado para denotar que uma variável situada na memória do programa pode ser

encontrada em qualquer lugar na memória do programa, através de um ponteiro, que pode alcançar até e ou além de 64k de espaço de memória do programa.

O qualificador near é usado para denotar que uma variável alocada na memória de programa pode ser acessada por um ponteiro, com capacidade de endereçamento de 64k.

Qualificadores ram e rom Os qualificadores ram e rom se fazem necessários devido à divisão interna do barramento de dados, nos

microcontroladores da Microchip temos um barramento para a memória RAM e outro para a memória ROM. Visto que para acessar a variável podemos fazer uso de ponteiros, devemos utilizar os qualificadores

rom e ram, para definir o tipo de ponteiro que será utilizado. O tamanho de um ponteiro depende do tipo de ponteiro declarado. Observe que ao escrever uma variável na ROM, o compilador usa uma instrução de TBLWT.

Tabela 4.5 – Uso dos qualificadores ROM

Tipo de Ponteiro Exemplo Tamanho Ponteiro para memória RAM char *ponteiro; 16 bits Near – memória de programa rom near char *ponteiro 16 bits Far – memória de programa rom far char *ponteiro 24 bits

Page 40: Apostila Mosaico Pic MÓDULO4

38

Capítulo 5 - Operações Lógicas e Aritméticas

Hardware de multiplicação de 8X8

Os microcontroladores da família 18 possuem um hardware interno para operação de multiplicação de 8 X 8 bits, com resultado de 16 bits.

A operação é realizada em apenas um ciclo de máquina, ela não afeta nenhum flag da ULA. O resultado da multiplicação é armazenado em dois registradores de função especial PRODH e PRODL. O MPLAB C18 por suas vez faz uso deste hardware para implementar as rotinas aritméticas de

multiplicação, desta forma ele economiza, memória de programa e memória RAM.

Figura 5.1 – Multiplicador 8 x 8

Operadores

Os operadores são utilizados para realização de operações lógicas ou aritméticas. Com eles poderemos montar expressões, com variáveis inteiras e do tipo float.

O MPLAB C18 irá utilizar os recursos da ULA e do hardware de multiplicação para otimização do código. Porém devemos sempre tomar cuidado com o tamanho em bits, do resultado de uma operação, e ter

certeza que o tipo de variável escolhido pode receber este resultado. Vejamos os operadores disponíveis para nossas operações.

Operadores Aritméticos

Estudaremos agora os operadores aritméticos, estes nos permitirão criar expressões matemáticas simples e complexas, com variáveis inteiras e fracionárias.

Teremos uma versatilidade ainda maior, quando utilizarmos estes operadores com as funções aritméticas do MPLAB C18.

Atribuição O operador de atribuição é utilizado para passar um valor a uma variável. O símbolo utilizado é o sinal de igual “=”. Exemplo: int A, B; A = 10; // A variável foi carregada com a constante 10. B = 20; // A variável foi carregada com a constante 20.

Page 41: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 39

Soma O operador “soma” tem como símbolo o sinal de mais “+” e obviamente a operação realizada é de

somar. Exemplo: unsigned char X = 15, Y = 34, A; A = X + Y; // “A” será igual a soma de “X” e “Y” “A” será igual a 49.

Subtração Nas operações de subtração utilizaremos o sinal de menos “-“, entre as variáveis ou expressões. Exemplo: unsigned char X = 55, Y = 14, A; A = X - Y; // “A” será igual a “X” menos “Y” “A” será igual a 41.

Multiplicação Para representar a operação de multiplicação utilizaremos o símbolo “*”. Exemplo: unsigned int X = 15, Y = 34, A; X = X * Y; // “A” será a “X” vezes “Y” “X” será igual a 510.

Divisão A divisão entre variáveis e expressões é realizada utilizando como símbolo a barra invertida “/”. Quando

esta operação é realizada por variáveis inteiras, teremos como resposta somente o Quociente, para resgatar o resto da divisão devemos utilizar operador “%”.

Exemplo: unsigned char X = 5, Y = 2, A; A = X / Y; // “A” será igual a “X” dividido por “Y” “A“ será igual a 2.

Se utilizarmos uma variável do tipo float resultado da divisão será: unsigned float X = 5, Y = 2, A; A = X / Y; // “A” será igual a “X” dividido por “Y” “A“ será igual a 2,5.

A operação realizada utilizou no total 12 bytes, cada variável float é formada por 4 bytes.

Resto da Divisão Quando realizamos uma operação com variáveis do tipo inteiro, o resultado da divisão não retorna o

resto. Para retornar o resto de uma divisão utilizaremos o símbolo de porcentagem “%”. Veja como podemos realizar a operação e economizar memória RAM. Exemplo:

unsigned char X = 5, Y = 2, A, B; A = X / Y; // “A” será igual a “X” dividido por “Y” “A“ será igual a 2. B = X % Y; // “B” será igual ao resto da divisão de “X” por “Y” “B“ será igual a 1.

Page 42: Apostila Mosaico Pic MÓDULO4

40

Podemos escrever esta operação da seguinte forma:

B = ((X % Y)*10) / Y; Teremos como resposta “B” igual a 5. Os parênteses definem a ordem da execução das operações.

Incremento e Decremento Quando queremos adicionar ou subtrair uma unidade de uma variável, em linguagem C podemos utilizar

um recurso bem interessante que são os operadores de incremento e decremento. Estes operadores são classificados de duas maneiras pré e pós. Vejamos como funciona.

Pré-incremento Uma variável pode ser pré-incrementada, ou seja, antes de você realizar qualquer tipo de operação, sua

variável será acrescida de uma unidade. Exemplo: unsigned char X = 10, Y = 20, Z = 30; ++X; // “X” será igual a 11. Z = X + ++Y;

Antes da soma de X com Y, a variável Y será incrementada(pré-incremento). O resultado final será:

X = 11, Y = 21 e Z = 32.

Pós-incremento Uma variável pode ser pós-incrementada, ou seja, após a realização de uma operação, a variável será

acrescida de uma unidade. Exemplo:

unsigned char X = 10, Y = 20, Z = 30; X++; // “X” será igual a 11. Z = X + Y++;

Após a soma de X com Y, a variável Y será incrementada (pós-incremento). No momento da soma teremos:

X = 11, Y = 20 e Z = 31.

O resultado final será:

X = 11, Y = 21 e Z = 31.

Pré-decremento Uma variável pode ser pré-decrementada, ou seja, antes de você realizar qualquer tipo de operação, a

variável será subtraída de uma unidade. Exemplo

unsigned char X = 10, Y = 20, Z = 30; --X; // “X” será igual a 9. Z = X + --Y;

Antes da soma de X com Y, a variável Y será decrementada (pré-decremento). O resultado final será:

X = 9, Y = 19 e Z = 28.

Page 43: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 41

Pós-decremento Uma variável pode ser pós-decrementada, ou seja, após a realização de uma operação, a variável será

subtraída de uma unidade. Exemplo:

unsigned char X = 10, Y = 20, Z = 30; X--; // “X” será igual a 9. Z = X + Y--;

Após a soma de X com Y, a variável Y será incrementada(pós-incremento). No momento da soma teremos: X = 11, Y = 20 e Z = 31.

O resultado final será: X = 11, Y = 21 e Z = 31.

Operadores Relacionais

Os operadores relacionais referem-se as relações de comparação que podem ser usadas entre variáveis e expressões.

Uma operação relacional retorna como resposta, verdadeiro ou falso. Qualquer resultado de uma operação relacional será “zero” para falso e “um” para verdadeiro. Na

linguagem C podemos assumir que todo resultado diferente de zero é verdadeiro e todo resultado igual a zero é falso.

Iremos utilizar estes operadores com os comando de controle de Fluxo e controle Laço, para auxiliar na tomada de decisão. Por eles retornarem verdadeiro ou falso como resposta.

Para representar os operadores relacionais são utilizados os símbolos de comparação, são eles:

Operador Descrição == Comparação != Diferente de > Maior que < Menor que

>= Maior ou igual a <= Menor ou igual a

Exemplo: unsigned char contador; void main (void) contador = 1; // carrega contador com 1 TRISB = 0; //configura PORTB como saída while (contador <= 15) // O contador é menor ou igual a 15? // Sim, PORTB = contador; // carrega o PORTB com o valor da variável contador contador++; // incrementa o contador. // Não, fim do laço volta para inicio da função void main

Page 44: Apostila Mosaico Pic MÓDULO4

42

Operadores Lógicos

Os operadores lógicos nos permitirão elaborar expressões de lógica bit a bit e expressões booleanas. Utilizando os operadores lógicos e os operadores relacionais, poderemos implementar expressões

lógicas de tomada de decisão complexas.

Operador Lógico Booleano Os operadores booleanos são utilizados para relacionarmos variáveis expressões ou até mesmo

entradas e saídas digitais. Este tipo de operador também retorna como resultado, verdadeiro ou falso. São três os operadores relacionais: Operador E “&&”, Operador OU “||” e Operador Negação “!“.

Operador Descrição && Operador “E” relacional (AND) || Operador “OU” relacional (OR) ! Operador Negação

Operador Lógico bit a bit Os operadores bit a bit são utilizados para realizar operações lógicas entre variáveis, eles operam

somente com variáveis do tipo inteiro.

Operador Descrição & Operador E | Operador OU ^ Operador OU EXCLUSIVO

<< Operador de rotação à esquerda >> Operador de rotação à direita ~ Complemento de um número

Expressões

Uma expressão em C, representa a associação de variáveis, chamadas de funções e constantes, agrupadas por meio de operadores e separados por parênteses, da mesma forma como estamos acostumados na matemática.

Estas expressões serão avaliadas e nos retornarão valores que dependem do tipo de operador utilizado, poderemos ter como resposta um valor qualquer ou retornarão verdadeiro ou falso.

Abreviando Expressões A linguagem C nos permite simplificar algumas expressões lógicas e aritméticas. Esta simplificação não

quer dizer que facilitará o entendimento de um programa, e sim que deveremos ter um cuidado maior ainda. Portanto para que não tenhamos surpresas desagradáveis sem que montar uma expressão faça o uso

dos parênteses, a ordem de execução da expressão ficará clara e dessa forma facilitará o entendimento.

Figura 5.1 – Tabela de expressões simplificadas

Formato original Formato equivalente A=A+B; A+=B; A=A-B; A-=B; A=A*B; A*=B;

A=A/B; A/=B; A=A%B; A%=B; A=A>>B; A>>=B; A=A<<B; A<<=B; A=A&B; A&=B; A=A|B; A|=B;

A=A^B; A^=B;

Page 45: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 43

Operador virgula “,” Este tipo de operador permite agrupar um conjunto de expressões que serão executadas

seqüencialmente. Veja o exemplo: x=(y=2,y+3); No exemplo acima teremos como retorno o valor calculado da última expressão, ou seja, a expressão

mais à direita. Portanto no nosso exemplo teremos como resposta x = 5. Observe, y será igualado ao valor 2, depois será somado a constante 3 com o valor de y, desta forma

teremos como resposta x = 5. Não existe um limite quanto ao encadeamento de expressões, devemos sempre tomar cuidado para que

a expressão fique mais clara possível, a fim de facilitar, as modificações futuras que se fizerem necessárias. O exemplo a seguir mostra um outro uso para o operador “virgula”, dentro de um for: int main() int x, y;

for(x=0 , y=0 ; x+y < 100 ; ++x , y++) PORTB = x + y;

/* No laço for, temos duas variáveis de controle, x e y. As duas variáveis foram inicializadas com zero a cada execução do laço estas variáveis são incrementadas e a soma das duas variáveis, será atribuída ao PORTB */

Precedência dos operadores Esta é a tabela de precedência dos operadores da linguagem C. Entende-se por precedência como

sendo a ordem como a expressão será executada, seguinte do operador de maior precedência até o operador de menor precedência. Como já foi dito, para que não tenhas problemas na montagem de expressões procure sempre separa – las, utilizando os parênteses que possuem maior precedência.

Operador Precedência ( ) [ ] → Maior

! ~ ++ -- . -(unário) (cast) *(unário) &(unário) sizeof * / % + -

<< >> <<= >>=

== != & ^ |

&& || ?

= += -= *= /= , Menor

Page 46: Apostila Mosaico Pic MÓDULO4

44

Modelador (Cast) A finalidade do modelador é mudar o tipo de variável, de uma expressão temporariamente. Desta forma

o resultado da expressão virá formatado para o tipo de variável do modelador. Sintaxe: (tipo) expressão; Veja o exemplo: Sem o uso do modelador:

char X = 5, Y = 2; float Z; Z = X / Y;

Veja as variáveis X e Y são do tipo char, portanto de 8 bits, desta forma não é possível, que a operação

retorne um valor fracionário. Deste jeito teremos a variável Z igual a 2. Aplicando o modelador, teremos em Z outro resultado, veja:

char X = 5, Y = 2; float Z; Z = (float) X / Y;

Aplicando o modelador, as variáveis X e Y, tiveram o seu tipo alterado para float, sendo assim o

resultado da operação será Z igual a 2,5. Observe que durante a execução da operação tivemos um aumento no consumo de posições de

memória RAM. Somente ao final da execução as posições de RAM adicionais foram liberadas.

Comando Um comando é qualquer expressão válida finalizada por ponto e virgula “;”. Exemplo: A = 10; A = A + 76; Podemos ter um comando composto ou bloco de comando como também é chamado, é formado por

comandos simples que se encontram entre chaves . Utilizaremos os comandos associados aos comandos de controle de fluxo e comando de lanço da

linguagem C. Exemplo: a) // aqui você colocará os comandos simples. b) while (exp) // comando de laço. // aqui você colocará os comandos simples.

Page 47: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 45

Capítulo 6 - Comandos da Linguagem C

Comandos

Os comandos determinam o fluxo de processamento ou controle de laço (execução de uma rotina repetidamente), estes comandos podem ser utilizados varias vezes em um programa.

Isso depende do tipo de comando utilizado. Um comando pode ser a execução de uma operação lógica ou aritmética ou a chamada de uma função.

Podemos executar outros comandos de controle da linguagem C dentro

Controle do Fluxo de Processamento

Freqüentemente em um programa precisamos tomar decisões, que afetarão o fluxo do processamento. Essas decisões determinam se iremos executar um determinado comando ou não.

Podemos até escolher entre executar um comando ou um bloco de comando. Para controlar o fluxo de processamento temos dois comandos, o comando if e o comando switch. Vejamos como eles se comportam.

Comando If – simplificado Este comando verifica se o resultado de uma expressão é verdadeiro ou falso. O comando if significa

“se”. Se o resultado de uma expressão for verdadeiro ele executa um comando ou um bloco de comando, em um bloco de comando, os comando a serem executados estarão entre chaves.

A exp é verdadeira? NÃOSIM

Executa o Comando

Fluxo deProcessamento

Fluxo deProcessamento

Segue o fluxo de Processamentoe não executa o comando.

Figura 6.1 – Fluxograma do comando if

Sintaxe: a) Executa apenas um comando, se a expressão for verdadeira.

if(expressão) comando; // Se a expressão for verdadeira, execute o comando. // Se não segue o fluxo do programa sem executar o comando. b) Executa mais de um comando, se a expressão for verdadeira.

if(expressão) // A expressão é verdadeira? // Sim, executa o bloco de comando.

// Bloco de comandos // Não, salta o bloco de comando e segue o

// fluxo do programa.

Page 48: Apostila Mosaico Pic MÓDULO4

46

Comando If – else simplificado Quando desejamos mais de uma alternativa de comando a ser executado, utilizamos o comando if-else.

Ele permite executar um comando ou bloco de comando se a expressão for verdadeira ou falsa. Caso a expressão seja verdadeira ele executa um comando ou se a expressão for falsa, executa outro

comando.

A exp é verdadeira? NÃOSIM

Executa o Comando A

Fluxo deProcessamento

Fluxo deProcessamento

Quando o resultado da expressãofor falso, será executado estebloco do comando IF

Executa o Comando B

Quando o resultado da expressãofor verdadeiro, será executadoeste bloco do comando IF

Figura 6.2 – Fluxograma do comando if-else

Sintaxe: a) Executa apenas um comando, se a expressão for verdadeira.

if(expressão) comando_A; // Se a expressão for verdadeira, execute o comando_A. else comando_B; // Se não for verdadeira, executa o comando_B. b) Executa mais de um comando, se a expressão for verdadeira.

if(expressão) // A expressão é verdadeira? // Sim, executa o bloco de comando. // Bloco de comandos // Não, salta o bloco de comando e segue o

// fluxo do programa.

else // Sim, executa o bloco de comando. // Bloco de comandos // Não, salta o bloco de comando e segue o

// fluxo do programa.

Comando If e if – else Composto O comando a ser executado pode ser uma expressão matemática, uma expressão lógica, pode ser a

execução de uma função ou pode ser executado outro comando if que também terá um comando a ser executado.

Podemos utilizar os outros comando que serão aprendidos no bloco de comando, aumentando assim as possibilidades de controle do programa.

Podemos fazer associações de comandos if para uma lógica mais complexa. Veja outros exemplos de escrita do comando if. Observação: Entre chaves podemos ter quantos comandos desejarmos e o compilador permitir.

Page 49: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 47

Exemplos: A)

A exp_1 éverdadeira?

NÃOSIM

Fluxo deProcessamento

Fluxo deProcessamento

Segue o fluxo de Processamentoe não executa o comando.

A exp_2 éverdadeira?

NÃOSIM

Executa o Comando ouBloco de Comando

Quando o resultado da expressãofor verdadeiro, será executadoeste bloco do comando IF

Quando o resultado desta segundaexpressão for verdadeiro, seráexecutado este bloco do comando IF

Bloco de Comando doPrimeiro IF

Figura 6.3 – Fluxograma do comando if-else composto

Sintaxe: if(exp_1) // A expressão 1 é verdadeira? // Sim, verifica a expressão 2. if(exp_2) comando; // A expressão 2 é verdadeira? // Sim, executa o comando. // Não, expressão 1 ou expressão 2 são falsas

Page 50: Apostila Mosaico Pic MÓDULO4

48

B)

A exp_1 éverdadeira?

NÃO

SIM

Fluxo de Processamento

Fluxo deProcessamento

A exp_2 éverdadeira?

NÃO

SIM

Executa o Comando ouBloco de Comando

Quando o resultado da exp_1 for verdadeiro, será executado este bloco de comando

Quando o resultado desta exp_2 for verdadeiro, será executado este bloco de comando

Executa o Comando_B

Executa o Comando_A

Para que o comando_B seja executado, basta que a exp_1 seja verdadeira.

Segue o fluxo de processamentoe não executa o comando.

Figura 6.4 – Fluxograma do comando if-else composto

Sintaxe: if(exp_1) // A expressão 1 é verdadeira?

// Sim, executa o Comando_A e verifica a Comando_A; // a expressão 2. if(exp_2) comando; // A exp 2 é verdadeira? Sim, executa o comando

// e depois o Comando_B Comando_B; // Não, então executa somente o

// Comando_B // Não, a expressão 1 é falsa

Page 51: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 49

C)

A exp_1 éverdadeira?

NÃOSIM

Fluxo deProcessamento

Fluxo deProcessamento

A exp_2 éverdadeira?

NÃO

SIM

Executa o Comando ouBloco de Comando

Se a exp_1 for verdadeira,executa este bloco de comando

Se a exp_2 for verdadeira, seráexecutado este bloco de comando

Executa o Comando_B

A exp_3 éverdadeira?

Executa o Comando ouBloco de Comando

Executa o Comando_D

Se a exp_3 for verdadeiro, seráexecutado este bloco de comando

Executa o Comando_A Executa o Comando_C

Se a exp_1 for verdadeira,executa este bloco de comando

Para que o comando_B sejaexecutado, basta que a exp_1seja verdadeira.

Para que o comando_B sejaexecutado, basta que a exp_1seja verdadeira.

Figura 6.5 – Fluxograma do comando if-else composto

Sintaxe: if(exp_1) // A expressão 1 é verdadeira?

// Sim, executa o Comando_A e verifica a Comando_A; // a expressão 2. if(exp_2) comando; // A exp 2 é verdadeira? Sim, executa o comando

// e depois o Comando_B Comando_B; // Não, então executa somente o

// Comando_B // Não, a expressão 1 é falsa else

// Sim, executa o Comando_C e verifica a Comando_C; // a expressão 2. if(exp_3) comando; // A exp 2 é verdadeira? Sim, executa o comando

// e depois o Comando_D Comando_D; // Não, então executa somente o

// Comando_D // FIM

Page 52: Apostila Mosaico Pic MÓDULO4

50

Comando Switch Em alguns casos encontraremos a necessidade de testar uma variável muitas vezes, a fim de tomar uma

decisão em funções do seu valor. Uma solução para este problema é utilizar o comando if aninhado, em contra partida o seu código ficará

maior e pouco elegante. Então como resolveremos este problema? A solução é utilizarmos o comando switch, este realizará o teste de forma eficiente e mais rápido e

tornará o programa mais legível. Como ele funciona então? Este comando avalia o valor de uma variável e salta para um label, conhecido

como case e executa o bloco de comando, este é finalizado pelo comando break. Cada case é acompanhado de uma constante ou expressão de constante, nunca uma variável, esta

constante define qual case será executado. Em uma avaliação do comando switch, pode acontecer de nenhum case, ter uma constante que

corresponda ao valor da variável comparada, neste caso será executado o bloco de comando do label default.

A sintaxe do comando switch ficará desta forma:

A variável é igual acontante_1?

NÃO

SIM

Fluxo deProcessamento

Segue o fluxo doProcessamento

A variável é igual acontante_2?

NÃO

Executa o Comando ouBloco de Comando

Executa o comando oubloco de comando

A variável é igual acontante_n?

Executa o Comando ouBloco de Comando

NÃO

SIM

SIM

Executa o Comando ouBloco de Comando

Bloco da condiçãodefault

Figura 6.6 – Fluxograma do comando switch

Page 53: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 51

Sintaxe: switch(variavel) // Verifica se a variável é igual a constante de um

// dos “cases”

case constante_1: // bloco de comando break; // Fim de execução do SWITCH case constante_2: // bloco de comando break; // Fim de execução do SWITCH case constante_n: // bloco de comando break; // Fim de execução do SWITCH default: // bloco de comando

Podemos ter o comando switch sem a cláusula default, veja a sintaxe do comando.

A variável é igual acontante_1?

NÃO

SIM

Fluxo deProcessamento

Segue o fluxo doProcessamento

A variável é igual acontante_2?

NÃO

Executa o Comando ouBloco de Comando

Executa o comando oubloco de comando

A variável é igual acontante_n?

Executa o Comando ouBloco de Comando

NÃO

SIM

SIM

Figura 6.7 – Fluxograma do comando switch

Page 54: Apostila Mosaico Pic MÓDULO4

52

Sintaxe: switch(variavel) // Verifica se a variável é igual a constante de um

// dos “cases”

case constante_1: // bloco de comando break; // Fim de execução do SWITCH case constante_2: // bloco de comando break; // Fim de execução do SWITCH case constante_n: // bloco de comando break; // Fim de execução do SWITCH

No bloco de comandos você pode utilizar qualquer comando de controle de fluxo ou de faço. Portanto

você pode fazer um switch dentro de um bloco de comando de um case, isto aumenta as possibilidades e a complexidade dos nossos programas.

Veja mais um exemplo de construções do comando switch. Exemplos: A) Pode existir uma situação que desejamos executar mais de um case. Veja como pode ser resolvido

este problema.

A variável é igual a1?

NÃO

SIM

Fluxo deProcessamento

Segue o fluxo doProcessamento

A variável é igual a2?

NÃO

Executa o Comando ouBloco de Comando

Executa o comando oubloco de comando

A variável é igual a3?

Executa o Comando ouBloco de Comando

NÃO

SIM

SIM

No final deste Bloco de Comandonão existe a cláusula Break

Figura 6.8 – Fluxograma do comando SWITCH

Page 55: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 53

Sintaxe: switch(variavel) // Verifica se a variável é igual a constante de um

// dos “cases”

case 1: // bloco de comando // Ao final da execução desse bloco // o case 2 é imediatamente executado case 2: // bloco de comando break; // Fim de execução do SWITCH case 3: // bloco de comando break; // Fim de execução do SWITCH

Observe que no exemplo anterior não existe a cláusula break no final do bloco de comando do case 1,

desta forma ao final da execução deste bloco o case 2 será executado. Desta forma se a variável for igual a 1 o case 1 e case 2 serão executados. Para a variável igual a 2,

somente o case 2 será executado e para a variável igual a 3, somente o case 3 será executado.

Comandos para Controle de Repetição (Loop)

Em um programa escrito em C, podemos ter a necessidade de ter dentro da função principal um laço infinito, que chamaremos de rotina principal.

Muitas vezes desejamos executar uma certa rotina mais de uma vez, ou para gerar um atraso (delay), ou para que uma tarefa seja concluída. O que estamos querendo fazer é o que chamamos de loop, um laço de repetição.

Um loop é formado por um comando ou um conjunto de comando que será executado de forma seqüencial, tantas vezes quanto se fizer necessário.

Um loop pode ter a sua execução de forma finita ou infinita. Para finalizar a execução do laço, o comando de laço deve realizar um teste, que retornará como

resultado, verdadeiro ou falso. Este teste avalia se o conteúdo de uma variável ou o resultado de uma expressão é verdadeiro, se sim o

laço continua sendo executado, caso seja falso a execução do laço é finalizada. Todo laço pode ter sua execução infinita, basta que a expressão retorne sempre verdadeiro.

A seguir veremos os comandos de laço disponíveis para elaboração de nossos programas.

Comando While O comando while quer dizer “Enquanto for verdadeiro, Faça”. Este comando primeiro avalia uma expressão ou variável, como verdadeiro ou falso. O bloco de comando somente será executado se o resultado da avaliação for verdadeiro. A finalidade da avaliação da expressão ou variável é determinar a quantidade de vezes que o bloco de

comando será executado. A sintaxe para o comando while pode ser vista a seguir bem como o seu fluxograma.

Page 56: Apostila Mosaico Pic MÓDULO4

54

A exp é verdadeira?NÃO

SIM

Fluxo deProcessamento

Segue o fluxo doProcessamento

Executa o Comando ouBloco de Comando

Retorno do Laço

Fim da execução do Laço WHILE

Figura 6.9 – Fluxograma do comando while

Sintaxe: while(variavel ou expressão) // O resultado da avaliação é verdadeira? // Sim, executa o bloco de comando // comando ou bloco de comando // Se a avaliação for verdadeira volta para

// nova avaliação. Se não, fim da execução

Podemos ter um laço infinito inserindo no corpo de avaliação do comando a constante 1. Qualquer número diferente de zero é verdadeiro, portanto o laço nunca será finalizado. A sintaxe ficará assim:

while(1) // comando ou bloco de comando

Comando Do-while O comando do-while que dizer “faça enquanto for verdadeiro”. Assim como o comando while, este comando também avalia uma expressão ou variável para poder

executar o bloco de comando do laço. Porém executa-se primeiro o bloco de comando, depois o teste de validação do laço. Portanto quando

desejamos executar o bloco de comando de um laço pelo menos uma única vez, iremos utilizar este comando.

Com um resultado verdadeiro o bloco de comando é executado novamente, com um resultado falso o laço é finalizado.

Observe no fluxograma a seqüência de execução do comando.

Page 57: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 55

A exp é verdadeira?

NÃO

SIM

Fluxo deProcessamento

Segue o fluxo doProcessamento

Retorno do Laço

Fim da execuçãodo Laço WHILE

Executa o Comando ouBloco de Comando

Primeiro executa o bloco de comando,depois testa a expressão

Figura 6.10 – Fluxograma do comando do-while

Sintaxe: do // Executa o bloco de comando

// comando ou bloco de comando while(variável ou expressão); // A avaliação é verdadeira? // Sim, volta para executar o bloco de comando. // Não, fim de execução do laço.

Comando For O comando for, em execução é semelhando ao comando while. O laço for somente será executado se o teste da variável de controle retornar verdadeiro. Quanto o laço for é executado pela primeira vez, a variável de controle é inicializada e em seguida

testada, se for verdadeiro executa o bloco de comando, e retorna para testar a variável novamente. Se for falso finaliza a execução do comando for. Sendo assim para que o bloco de comando seja executado pelo menos uma vez, a avaliação da variável

deve ser verdadeira. Veja o fluxograma deste comando e a sintaxe a seguir.

Page 58: Apostila Mosaico Pic MÓDULO4

56

A variável éverdadeira?

NÃO

SIM

Fluxo deProcessamento

Segue o fluxo deProcessamento

Retorno do Laço

Fim da execução doLaço For

(Comando do Laço For)Inicializa a variável

Primeiro inicializa a variável depoisexecuta o bloco de comando.

Executa o comando oubloco de comando

(Comando do Laço For)Incrementa a variável

Figura 6.11 – Fluxograma do comando FOR

Sintaxe:

for(inicialização; condição; incremento) comando; ou for(inicialização; condição; incremento) // bloco de comando;

Parâmetros do comando For - Inicialização: É um comando de atribuição para inicilalizar uma variável de controle do laço. - Condição: É um comando para testar a variável de controle do laço, ela define quanto o laço será finalizado. - Incremento: Define como a variável de controle do laço será alterada, este campo pode conter uma expressão para definir a forma de atualização desta variável.

Cláusulas para controle dos comandos de laço Quando estamos em um loop finito ou infinito, podemos ter a necessidade de interromper a execução do

mesmo ou executar apenas uma parte do bloco de comando. Conseguiremos este controle utilizando as cláusulas break e continue.

Cláusula Continue A função desta cláusula é forçar a verificação da condição, que permite que o bloco de comando, do laço

de repetição seja executado. Com isso você pode executar apenas uma parte do bloco de comando. Podemos realizar um teste

condicional, para executar a cláusula continue, desta forma poderemos controlar o que será executado no bloco de comando.

Page 59: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 57

Veja um exemplo de aplicação da clausula continue: contador = 100; while (contador) contador--; // decrementa o contador : : // executa os seus comandos : if (!botão_1) continue; // Entrada igual a zero?

// Sim, volta para testar a variável contador : // Não, executa os seus comandos :

Cláusula Break A função desta cláusula é forçar o fim da execução do comando de laço, ele tem prioridade sobre a

verificação da condição, que permite que o bloco de comando do laço de repetição seja executado. Desta forma um laço infinito pode ter a sua execução cancelada, ou um laço que deve ser executado n

vezes pode ser finalizado antes de atingir a quantidade de vezes definida. Para cancelar a execução do laço basta executar a clausula break, portanto para executar está clausula,

podemos realizar um teste condicional, que permitirá a execução ou não da clausula. Veja um exemplo de aplicação da clausula break.

while (contador > 10) contador++; : : // executa os seus comandos : if (!botão_1) break; // Entrada igual a zero?

// Sim, fim da execução do laço. : // Não, executa os comandos : // e volta para testar a variável

Comando Goto O comando goto é utilizado para provocar um salto incondicional. Neste caso utilizamos o comando para

desviar para rotinas dentro de uma função que pode ser a função principal (main) ou uma função criada pelo programador.

Procure não utilizar este comando ele pode dificultar o compilador à otimização do código de preferência trabalhe com funções.

A operação deste comando é saltar para um local especifico. Este local é identificado através de um rótulo (label).

O nome dado ao rótulo, geralmente é o nome da rotina que vamos escrever, este nome para o compilador C, corresponde ao endereço da memória de programa onde está localizada a nossa rotina.

Sintaxe: nome_da_rotina: // rotina goto nome_do_rotina; Exemplo: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Variáveis Globais int unidade = 9; int dezena = 9;

Page 60: Apostila Mosaico Pic MÓDULO4

58

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de incremento do Timer * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void incrementa_timer() unidade ++; if (unidade == 10) unidade = 0; dezena ++; if (dezena == 10) dezena = 0; centena ++; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ loop: void main() while(1) // Laço infinito. if (!PORTBBits.RB0)// A entrada está em zero? goto trata_bt // desvia para a rotina trata_bt. trata_up: incrementa_timer(); // incrementa o timer. goto loop;

Page 61: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 59

Capítulo 7 - Funções

Funções

Antes de falarmos em função vamos definir o que é uma rotina. Podemos definir rotina como sendo um programa curto ou longo que realiza uma determinada tarefa. Por exemplo: while(counter <= 15)

PORTB = converte[contador]; contador++; Definido o que é rotina, vamos falar sobre sub–rotina, uma sub–rotina é um programa que realiza uma

tarefa especifica, e podemos solicitar a execução desta tarefa muitas vezes no decorrer do programa. Quando solicitamos a execução de uma sub–rotina desejamos que no final da execução da mesma, ela

retorne para a rotina que solicitou a execução. Observe que a linha de retorno é a linha imediatamente após a chamada da sub–rotina. Exemplo:

Figura 7.1 – Rotina e sub-rotina.

A linguagem C é conhecida por ser uma linguagem de programação estruturada, esta qualidade vem da possibilidade de criarmos ou trabalharmos com funções já prontas.

Elas nos permitem separar os programas em blocos, desta forma o programa ficará muito mais legível, de fácil compreensão e permitirá o reaproveitamento das rotinas ou até de um programa inteiro, da vem o conceito de biblioteca.

A função tem um comportamento semelhante às sub–rotinas, ao final da execução da mesma, ela retorna ao local que solicitou a execução da função, sempre na linha seguinte a chamada.

As funções podem ser do compilador, são funções com uma tarefa pré–determinada, podemos ter funções especificas para o microcontrolador e funções de usuário, que darão ao programador imensas possibilidades de programação.

Enfim uma função é um conjunto de comandos agrupados para cumprir uma tarefa especifica, e recebem um nome para referência–las.

Uma função pode ser chamada varias vezes em um programa, o seu código só é escrito uma única vez na memória de programa, somente serão acrescidos o comando de chamada da função.

Page 62: Apostila Mosaico Pic MÓDULO4

60

Criando uma Função Uma função é definida pelo tipo, nome, parâmetro e corpo da função. O tipo da função determina o tipo de dado a ser retornado, o nome é usado para chamar a função,

(invocar a sua execução) e o campo parâmetros permitirá passarmos valores para a função, podemos não ter nenhum parâmetro, como podemos ter um ou mais de um parâmetro, quando isto acontecer devemos separa-los por virgula.

Sintaxe: tipo nome_função (parametros) // Bloco de comandos, é o corpo da função

Retorno de Função Uma função pode ser finalizada de duas maneiras, pelo fim da execução dos comandos do corpo da

função, ao final será encontrada a chave que fecha o corpo da função, ou pela execução do comando return, quando ele é executado a execução da função é finalizada e provoca o retorno a linha seguinte a chamada da função.

Uma função só pode retornar um único valor, portanto o comando return, retornará somente um valor do mesmo tipo da função.

A sintaxe deste comando pode ser escrita da seguinte forma: return; return expressão; return (expressão); Exemplo: unsigned char a, b; // variáveis globais unsigned char soma () return a+b; // retorna o resultado da soma de a e b void main ()

a = 16; // carrega a variável a com 16 b = 23; // carrega a variável b com 23 a = soma(); // carrega em “a” o resultado da soma

Neste exemplo a função principal (main), chama a função soma, está por sua vez retorna o resultado de

a + b, o valor de retorno e armazenado na própria variável “a”.

Parâmetros de uma Função Os parâmetros de uma função podem ser variáveis inteiras, de ponto flutuante, matrizes, estruturas,

uniões e nulo, podemos ter uma função como parâmetro de uma função. Na declaração dos parâmetros devemos informar o tipo de cada variável.

As variáveis criadas no corpo de parâmetro, só existem enquanto a função está sendo executada. Ao final da execução as posições de memória destas variáveis são liberadas. Estas posições de

memória podem ser usadas por outras variáveis locais, ou por variáveis de parâmetro de função. Sintaxe: a) Apenas um parâmetro. tipo nome_função (tipo parametro) // Bloco de comandos, é o corpo da função

Page 63: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 61

b) Mais de um parâmetro. tipo nome_função (tipo parâmetro1, tipo parâmetro2, tipo parâmetroN) // Bloco de comandos, é o corpo da função

Passagem por valor Quando criamos uma variável no corpo de parâmetro da função estamos querendo armazenar um valor

passado a função, desta forma temos uma passagem por valor. O valor passado a função pode ser uma constante ou o conteúdo de uma outra variável, que pode ser

global ou local. A variável criada no corpo da função é uma variável local, logo o seu conteúdo será perdido ao final da

execução da função. Exemplo: unsigned char soma(unsigned char A, unsigned char B)

return A+B; unsigned char C; void main(void)

C = soma(25, 15); No exemplo a função principal (main) chama uma função chamada soma, que tem como finalidade

somar dois números, que são carregas nas variáveis A e B, o dado 25 é carregado em A e o dado 15 é carregado em B, a função soma retorna o resultado da soma e armazena na variável C.

Passagem por referência Podemos passar os parâmetros por referência, quando realizamos este tipo de passagem a variável

criada no corpo de parâmetro da função é um ponteiro. A passagem por referência se justifica, quando desejamos que a função retorne mais de um valor. Os parâmetros recebem o endereço da variável que devem ser lidas. Sintaxe: tipo nome_função (tipo *parâmetro1, tipo *parâmetro2, tipo *parâmetroN) // Bloco de comandos, é o corpo da função

Trabalhando com tipo void em Funções Um de nossos estudos até agora foram os tipos de variáveis, estudamos que um uma delas era o tipo

void, este é um tipo nulo de variável. As funções também podem ser do tipo void, e ou os parâmetros da função, neste vejamos o irá

acontecer : • Função do tipo void: Como ela é de um tipo nulo, ela não retornará valor. Temos como exemplo a função principal, ela é o ponto de origem, é o inicio de nosso programa portanto não há local de retorno. Por este motivo ela é do tipo void. • Corpo de parâmetro do tipo void: Quando o corpo de parâmetro de uma função está preenchido com o tipo void, quer dizer que está função não recebe valor de forma alguma. Dentro do seu corpo de comandos ela pode tranqüilamente manipular variáveis globais e locais.

Page 64: Apostila Mosaico Pic MÓDULO4

62

Prototipagem de Função Nos exemplos anteriores você pode observar que as funções são criadas antes da função principal. O

motivo para isso é que o compilador C, realiza a codificação do programa linha por linha. Caso exista algum erro no programa ou o compilador não saiba da existência da função, (na seqüência

de programação a chamada da função veio primeiro que a criação da própria função), a compilação será finalizada na linha do erro.

Por este motivo não podemos escrever um programa onde a chamada da função vem primeiro do que a própria função.

Observe no exemplo que a função soma é escrita antes da função principal. Exemplo: unsigned char soma(unsigned char A, unsigned char B)

return A+B; unsigned char C; void main(void)

C = soma(25, 15); Mas existe uma outra forma de evitar o erro de compilação, mesmo porque temos que nos preocupar

com situações mais importante do que a ordem de definição de funções. Vamos resolver esta situação com um protótipo da função que será criada posteriormente, podendo ser

localizada depois da função principal. O protótipo da função nada mais é do que a definição do seu tipo, nome e parâmetros, sem o seu corpo. Um protótipo ficaria assim: tipo nome (parâmetro); Veja o exemplo da função de soma com o protótipo da função. Exemplo: unsigned char soma(unsigned char A, unsigned char B); // protótipo da função unsigned char C; void main(void)

C = soma(25, 15); unsigned char soma(unsigned char A, unsigned char B)

return A+B; No exemplo anterior utilizamos o protótipo da função desta forma posso criar a minha função antes ou

depois da função que a chama.

Chamada de função externa Uma prática bem interessante é a reutilização de funções criadas por nós em outros programas. Para que possamos realizar está tarefa com sucesso, nossas funções preferêncialmente devem utilizar

variáveis locais, isto facilita a migração e utilizar a diretiva include para carregar a função externa no nosso programa.

Exemplo: #include <funcao_soma.c> unsigned char C; void main(void)

C = soma(25, 15);

Page 65: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 63

A diretiva include carregará a rotina funcao_soma.c no programa principal. Desta forma poderemos criar bibliotecas para facilitar a nossa vida. Não é necessário incluir o header do microcontrolador usado nem a configuração dos fuses.

unsigned char soma(unsigned char A, unsigned char B)

return A+B;

Recursividade A recursividade é a capacidade da função chamar a si mesma, para ser executada uma tarefa. O calculo do fatorial e um exemplo perfeito para demonstrar a recursividade. O fatorial de um número é definido por: n! = n * (n - 1)! Uma função recursiva deve ter uma condição de término, para que não entremos em um laço infinito. A função do fatorial tem como condição de término, n igual a zero. Quando n for igual a zero a função é

finalizada. Veja o exemplo: unsigned char fatorial (int n); void main (void) int n; TRISB = 0; PORTB = 0; while(1) // rotina principal if (n < 0)break; PORTB = fatorial (5); // carrega no PORTB o fatorial de 5 unsigned char fatorial (int n) return ((n==0)? 1: n * fatorial (n-1));

Page 66: Apostila Mosaico Pic MÓDULO4

64

Capítulo 8 - Manipulação dos Pinos de I/O

O PIC 18F4520 possui 5 ports e 36 pinos de I/O, são 3 pinos em comparação ao o modelo 16F877A. Você além de estar trabalhando com um modelo mais sofisticado você pode contar com mais pinos de I/O.

Alguns destes pinos de I/O são compartilhados com periféricos e o oscilador. Devemos ter atenção com os pinos que possuem mais de uma função, para não termos nenhum conflito

entre periférico e pinos de I/O. Outro ponto a ser observado é a característica elétrica do pino de I/O, eles podem ser do tipo TTL ou

Schmitt Trigger (ST). Um pino TTL considera nível lógico um, uma tensão entre 25% de VDD até VDD, e nível lógico zero uma

tensão entre 0V e 20% de VDD. A região entre 20% e 25% de VDD é considerada região indeterminada. O que pode acontecer com um pino de I/O, quando a tensão injetada no pino encontra – se na região

indeterminada? Neste caso o pino permanece com o estado lógico anterior. Se a condição anterior do pino era nível

lógico um, então o pino permanecerá em um, se o mesmo estava com nível lógico zero, ele permanecerá em zero, até que a tensão no pino seja suficiente para mudar o estado lógico do pino.

Em um pino ST consideramos nível lógico zero uma tensão entre 0V e 20% de VDD e o nível lógico um, uma tensão a partir de 80% de VDD.

0 0,5

1,0(0,2VDD)

1,25(0,25VDD)

5,0

10

VDD

NívelLógico

Região Indeterminada

0 0,5

1,0(0,2VDD)

4,0(0,8VDD)

5,0

10

VDD

Região Indeterminada

NívelLógico

Pino TTL Pino Schmitt Trigger

Figura 8.1 – Gráfico Nível Lógico x Tensão

Configurando os pinos de I/O

Todos os PORT’s podem ter os seus pinos de I/O configurados como entrada ou saída digital. Para esta operação devemos configurar o registrador TRIS, do port desejado. Cada bit do registrador TRISX corresponde a um pino de I/O. Para configurar um pino como entrada

devemos colocar o bit correspondente em nível lógico 1 e para configura – lo como saída devemos colocar o bit correspondente em zero.

TRISx Controle de direção do Pino de I/O.

TRISx7 TRISx6 TRISx5 TRISx4 TRISx3 TRISx2 TRISx1 TRISx0 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1

Exemplo de configuração: a) Vamos configurar os pinos do PORTB, RB0, RB1, RB3, RB7 como saída.

TRISB7 TRISB6 TRISB5 TRISB4 TRISB3 TRISB2 TRISB1 TRISB0

0 1 1 1 0 1 0 0

TRISB = 0b01110100;

Page 67: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 65

Devemos ainda observar a existência de periféricos compartilhando os pinos de I/O, e configurar o

registrador correspondente, para ligar ou desligar o periférico conforme o seu projeto.

Descrição dos Pinos

Na tabela abaixo, temos a descrição dos pinos do PIC18F4520 e o diagrama dos tipos de encapsulamento deste microcontrolador.

Figura 8.2 – PIC 18F4520 – Encapsulamento PDIP

Figura 8.3 – PIC 18F4520 – Encapsulamento TQFP

Page 68: Apostila Mosaico Pic MÓDULO4

66

Figura 8.4 – PIC 18F4520 – Encapsulamento QFN

Pinos de alimentação, Oscilador e Master Clear Podemos observar que os pinos de I/O RE3, RA6 e RA7 compartilhados com o pino de RESET e com os

pinos do Oscilador do PIC.

NÚMERO DO PINO NOME DO PINO DIP PLCC TQFP TIPO DE

PINO TIPO DE BUFFER DESCRIÇÃO

_____ MCLR/VPP

MCLR VPP

RE3

1

2

18

I

P

ST

ST

Este é o pino de reset, ele é ativo em zero. VPP é o pino de entrada para tensão de programação do dispositivo. Entrada Digital.

OSC1/CLKI OSC1

CLKI

RA7

13 14 30

ST

CMOS

TTL

Entrada para cristal oscilador ou entrada para clock externo Entrada de clock externo, circuito RC. Pino de I/O de uso geral.

OSC2/CLKO/ RA6

OSC2

CLKO

RA6

13 14 30

--

--

TTL

Saída de clock, este pino terá um sinal com a mesma freqüência do cristal. Quando usado como saída teremos ¼ da freqüência de clock. Pino de I/O de uso geral.

VSS 12, 31

6, 30, 31 6, 29 P __ Referência negativa para pinos de

I/O e sistema Lógico.

VDD 11, 32

7, 8, 28, 29 7, 28 P __ Referência positiva para pinos de

I/O e sistema Lógico.

NC __ 13 12, 13, 33, 34

__ __ Não conectar.

Page 69: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 67

Legenda da tabela:

TTL Entrada compatível com nível TTL

ST Entrada compatível com nível Schmitt Trigger

I Entrada CMOS Entrada/Saída compatível com CMOS

O Saída P Power

A configuração destas funções é feita através da janela de configuration bits no MPLAB ou através da

diretiva “#pragma config” a ser inserida em seu código, podemos configurar o tipo de oscilador e a configuração do RE3.

Habilitação do MCLR: MCLRE = OFF DISABLED – RA3 PINO DE I/O MCLRE = ON ENABLE – RA3 PINO DE RESET

Exemplo: #pragma config OSC = HS #pragma config MCLRE = ON

Page 70: Apostila Mosaico Pic MÓDULO4

68

Estudo do PORTA

O PORTA possui 8 pinos que podemos utilizar como entrada digital/analógica ou saída digital. Alguns destes pinos são compartilhados com os periféricos do microcontrolador são eles, comparador

analógico, conversor de analógico para digital, entrada de clock externa para o timer 0 e os pinos do cristal. Curiosamente o pino RA4 não é dreno aberto como na maioria dos microcontroladores da Microchip,

logo não é necessário o uso do resistor de pull – up, normalmente utilizado, quando o mesmo é configurado como saída.

Descrição dos pinos de I/O do PORTA NÚMERO DO PINO NOME DO PINO DIP PLCC TQFP

TIPO DE PINO

TIPO DE BUFFER DESCRIÇÃO

RA0/AN0 RA0 AN0

2 3 19

I/O I

TTL

A

I/O bi-direcional do PORTA. I/O digital. Entrada Analógica canal 0.

RA1/AN1 RA1 AN1

3 4 20

I/O I

TTL

A

I/O bi-direcional do PORTA. I/O digital. Entrada Analógica canal 1.

RA2/AN2/ VREF- RA2 AN2

VREF-

4 5 21

I/O I I

TTL A A

I/O bi-direcional do PORTA. I/O digital. Entrada Analógica canal 2. Tensão de referência, patamar inferior.

RA3/AN3/ VREF+

RA3 AN3

VREF+

5 6 22

I/O I I

TTL

A A

I/O bi-direcional do PORTA. I/O digital. Entrada Analógica canal 3. Tensão de referência, patamar superior.

RA4/T0CKI RA4

T0CKI 6 7 23

I/O I

ST/OD

ST

I/O bi-direcional do PORTA. I/O digital de dreno aberto. Entrada de clock externo do TMR0.

RA5/AN4/SS/LVDIN RA5 AN4 SS

LVDIN

7 8 24

I/O

TTL A

ST A

I/O Digital. Entrada Analógica canal 4. Seleção de escravo no modo SPI. Entrada de Low Voltage Detect.

OSC2/CLKO/ RA6

OSC2

CLKO

RA6

13 14 30

--

--

TTL

Saída de clock, este pino terá um sinal com a mesma freqüência do cristal. Quando usado como saída teremos ¼ da freqüência de clock. Pino de I/O de uso geral.

OSC1/CLKI OSC1

CLKI RA7

13 14 30

ST

CMOS TTL

Entrada para cristal oscilador ou entrada para clock externo. Entrada de clock externo, circuito RC. Pino de I/O de uso geral.

Registradores para configuração do PORTA NOME BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0 PORTA RA7 RA6 RA5 RA4 RA3 RA2 RA1 RA0 LATA LATA7 LATA6 LATA5 LATA4 LATA3 LATA2 LATA1 LATA0 TRISA TRISA7 TRISA6 TRISA5 TRISA4 TRISA3 TRISA2 TRISA1 TRISA0 ADCON1 --- --- VCFG1 VCFG0 PCFG3 PCFG2 PCFG1 PCFG0 CMCON C2OUT C1OUT C2INV C1INV CIS CM2 CM1 CM0 CVRCON CVREN CVROE CVRR CVRSS CVR3 CVR2 CVR1 CVR0

Page 71: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 69

Estudo do PORTB

Assim como PORTA, o PORTB possui 8 pinos que podemos utilizar como entrada ou saída digital. Os pinos de RB0 a RB4 podem ser configurados como entrada analógica.

O PORTB pode ainda contar com 8 resistores de pull – up interno que são habilitados pelo registrador INTCON2</RBPU>, quando ocorre um power–up o bit </RBPU> é iniciado com nível lógico um, ou seja, pull – up’s desabilitados. Quando o pino de I/O é configurado como saída, o pull – up é desligado.

Outro recurso do PORTB é a interrupção de mudança de estado nos pinos RB4 até RB7, esta interrupção é habilitada pelo registrador INTCON<RBIE>. Na rotina de tratamento desta interrupção devemos primeiro atualizar o PORTB (Ler ou Escrever), não utilize a instrução MOVFF para está finalidade, para depois limpar o flag de indicação de interrupção INTCON<RBIF>.

No PORTB, temos três fontes para gerar a interrupção externa, que são através dos pinos RB0, RB1 e RB2, podemos escolher a borda que gera a interrupção através do registrador INTCON2<INTEDG0:INTEDG1:INTEDG2>, a habilitação da interrupção é feita pelo registrador INTCON<INT0IE> pelo registrador INTCON3<INT1IE:INT2IE>.

Um último recurso do PORTB é o pino RB3 que pode ser utilizado como saída de PWM do módulo CCP2, através do configuration bits (CCP2MX = 0).

Descrição dos pinos de I/O do PORTB

NÚMERO DO PINO NOME DO PINO DIP PLCC TQFP TIPO DE

PINO TIPO DE BUFFER DESCRIÇÃO

RB0/INT0 RB0

INT0

33 36 8

I/0

I

TTL

ST

I/O bi-direcional do PORTB. I/O Digital. Entrada de int. Externa 0.

RB1/INT1 RB1

INT1

34 37 9

I/0

I

TTL

ST

I/O bi-direcional do PORTB. I/O Digital. Entrada de int. Externa 1.

RB2/INT2 RB2

INT2

35 38 10

I/0

I

TTL

ST

I/O bi-direcional do PORTB. I/O Digital. Entrada de int. Externa 2.

RB3/CCP2 RB3

CCP2 36 39 11

I/O I/O

TTL ST

I/O bi-direcional do PORTB I/O digital. Capture2 ent.,Compare2 saída, PWM2 saída.

RB4

37 41 14

I/O TTL I/O bi-direcional do PORTB I/O digital. Entrada de interrupção de mudança de estado.

RB5/PGM RB5 PGM 38 42 15

I/O I

TTL ST

I/O bi-direcional do PORTB I/O digital. Entrada de habilitação de Low Voltage ICSP. Entrada de interrupção de mudança de estado.

RB6/PGC RB6 PGC 39 43 16

I/O I

TTL ST

I/O bi-direcional do PORTB I/O digital. Entrada de clock para ICSP e In-Circuit Debugger. Entrada de interrupção de mudança de estado.

RB7/PGD RB7 PGD 37 41 14

I/O I/O

TTL ST

I/O bi-direcional do PORTB I/O digital. Entrada de dados para ICSP e In-Circuit Debugger. Entrada de interrupção de mudança de estado.

Page 72: Apostila Mosaico Pic MÓDULO4

70

Registradores para configuração do PORTB NOME BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0 PORTB RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 LATB LATB7 LATB6 LATB5 LATB4 LATB3 LATB2 LATB1 LATB0 TRISB TRISB7 TRISB6 TRISB5 TRISB4 TRISB3 TRISB2 TRISB1 TRISB0

INTCON GIE/GIEH PEIE/GIEL TMR0IE INT0IE RBIE TMR0IF INT0IF RBIF INTCON2 /RBPU INTEDG0 INTEDG1 INTEDG2 --- TMR0IP --- RBIP INTCON3 INT2IP INT1IP --- INT2IE INT1IE --- INT2IF INT1IF ADCON1 --- --- VCFG1 VCFG0 PCFG3 PCFG2 PCFG1 PCFG0

Algumas das opções de configuração do PORTB são feitas através da janela de configuration bits no

MPLAB ou através da diretiva #pragma config a ser inserida em seu código. PORTB A/D Habilitação: PBADEN = OFF PORTB<4:0> PINOS DIGITAIS PBADEN = ON PORTB<4:0> PINOS ANALÓGICOS

Exemplo: #pragma config PBADEN = OFF

Page 73: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 71

Estudo do PORTC

O PORTC possui 8 pinos que podemos utilizar como entrada ou saída digital. Alguns destes pinos são compartilhados com os módulos MSSP (SPI e I2C), EUSART, CCP e ECCP. O pino RC1 é usado como saída de PWM que também é compartilhado pelo pino RB3.

Descrição dos pinos de I/O do PORTC

NÚMERO DO PINO NOME DO PINO DIP PLCC TQFP TIPO DE

PINO TIPO DE BUFFER DESCRIÇÃO

RC0/T1OSO/T1CKI RC0 T1OSO T1CKI

15 16 32

I/0 O I

ST -- ST

I/O bi-direcional do PORTC I/O Digital TIMER 1 saída do Oscilador (cristal externo) TIMER1 ou TIMER3 clock externo

RC1/T1OSI/CCP2 RC1 T1OSI CCP2

16 18 35

I/0 I

ST CMOS ST

I/O bi-direcional do PORTC I/O Digital TIMER 1 entrada do oscilador (cristal externo) Capture2 entrada, Compare2 saída, PWM2 saída.

RC2/CCP1 RC2 CCP1 17 19 36

I/0 I

TTL ST

I/O bi-direcional do PORTC I/O Digital Capture2 entrada, Compare2 saída, PWM2 saída.

RC3/SCK/SCL RC3 SCK SCL

18 20 37

I/O I/O I/O

ST ST ST

I/O bi-direcional do PORTC I/O digital Entrada/Saída de Clock da comunicação serial síncrona SPI Entrada/Saída de Clock da comunicação serial síncrona I2C

RC4/SDI/SDA RC4 SDI DAS

23 25 42

I/O I I/O

ST ST ST

I/O bi-direcional do PORTC I/O digital Entrada de Dados da comunicação SPI Entrada/Saída de Dados da comunicação I2C

RC5/SDO RC5 SDO 24 26 43

I/O O

ST --

I/O bi-direcional do PORTC I/O digital Saída de Dados da comunicação SPI

RC6/TX/CK RC6 TX CK

25 27 44

I/O O I/O

ST -- ST

I/O bi-direcional do PORTC I/O digital Pino de Transmissão de Dados da USART, modo Assíncrono. Pino de Clock da USART, modo Síncrono.

RC7/RX/DT RC7 RX DT

26 29 1

I/O I I/O

ST ST ST

I/O bi-direcional do PORTC I/O digital Pino de Recepção da USART, modo Assíncrono. Entrada/Saída de dados da USART, modo Síncrono.

Registradores para configuração do PORTC NOME BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0 PORTC RC7 RC6 RC5 RC4 RC3 RC2 RC1 RC0 LATC LATC7 LATC6 LATC5 LATC4 LATC3 LATC2 LATC1 LATC0 TRISC TRISC7 TRISC6 TRISC5 TRISC4 TRISC3 TRISC2 TRISC1 TRISC0

O pino RC1 é usado como saída de PWM que também que compartilhado pelo pino RB3. Esta opção de troca do pino de PWM do módulo CCP2 é realizada através da janela de configuration bits

no MPLAB ou através da diretiva #pragma config a ser inserida em seu código.

Page 74: Apostila Mosaico Pic MÓDULO4

72

CCP2 Mux: CCP2MX = PORTBE CCP2 LIGADO AO PINO RB3 CCP2MX = PORTC CCP2 LIGADO AO PINO RC1

Exemplo: #pragma config CCP2MX = PORTBE

Estudo do PORTD

O PORTD pode ser configurado como entrada ou saída digital. Os pinos RD5, RD6 e RD7 são usados para as funções P1B, P1C e P1D respectivamente, do módulo

ECCP. Este PORT, também pode ser usado como barramento de dados do módulo PSP, porta paralela do tipo escravo.

Descrição dos pinos de I/O do PORTD

NÚMERO DO PINO NOME DO PINO DIP PLCC TQFP TIPO DE

PINO TIPO DE BUFFER DESCRIÇÃO

O PORTD é um port de I/O bidirecional ou Porta Paralela do tipo Escravo, neste modo os pinos são TTL.

RD0/PSP0 19 21 38 I/0 ST TTL

I/O Digital. Pino de Dados da Porta Paralela (PSP mode).

RD1/PSP1 20 22 39 I/0 ST TTL

I/O Digital. Pino de Dados da Porta Paralela (PSP mode).

RD2/PSP2 21 23 40 I/0 ST TTL

I/O Digital. Pino de Dados da Porta Paralela (PSP mode).

RD3/PSP3 22 24 41 I/0 ST TTL

I/O Digital. Pino de Dados da Porta Paralela (PSP mode).

RD4/PSP4 27 30 2 I/0 ST TTL

I/O Digital. Pino de Dados da Porta Paralela (PSP mode).

RD5/PSP5 28 31 3 I/0 ST TTL

I/O Digital. Pino de Dados da Porta Paralela (PSP mode).

RD6/PSP6 29 32 4 I/0 ST TTL

I/O Digital Pino de Dados da Porta Paralela (PSP mode)

RD7/PSP7 30 33 5 I/0 ST TTL

I/O Digital Pino de Dados da Porta Paralela (PSP mode)

Registradores para configuração do PORTD NOME BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0 PORTD RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 LATD LATD7 LATD6 LATD5 LATD4 LATD3 LATD2 LATD1 LATD0 TRISD TRISD7 TRISD6 TRISD5 TRISD4 TRISD3 TRISD2 TRISD1 TRISD0 TRISE IBF OBF IBOV PSPMODE --- TRISE2 TRISE1 TRISE0

CCP1CON P1M1 P1M0 DC1B1 DC1B0 CCP1M3 CCP1M2 CCP1M1 CCP1M0

Page 75: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 73

Estudo do PORTE

O PORTE possui apenas 4 pinos, podemos utilizar como entrada digital/analógica ou saída digital. Os pinos RE0, RE1, RE2 são usados como pinos de controle para a porta paralela, PSP, eles possuem

as seguintes funções respectivamente: /RD – Habilitação de Leitura, /WR – Habilitação de Escrita, /CS – Habilita operação da porta paralela.

O pino RE3 pode ser configurado como pino de reset como já foi visto anteriormente.

Descrição dos pinos de I/O do PORTE

NÚMERO DO PINO NOME DO PINO DIP PLCC TQFP TIPO DE

PINO TIPO DE BUFFER DESCRIÇÃO

Os pinos de I/O do PORTE são bidirecionais.

RE0/RD/AN5 RE0 RD

AN5

81 92 25

I/O

ST TTL

A

I/O Digital. Controle para Leitura da Porta Paralela(PSP mode). Entrada Analógica, canal 5.

RE1/WR/AN6 RE1 WR

AN6

9 10 26

I/O ST TTL

A

I/O Digital. Controle de Escrita da Porta Paralela(PSP mode). Entrada Analógica, canal 6.

RE2/CS/AN7 RE2 CS

AN7

10 11 27

I/O ST TTL

A

I/O Digital. Controle para Seleção de Chip da Porta Paralela(PSP mode). Entrada Analógica, canal 7.

______ MCLR/RE3

1

2

18

I

ST

Entrada Digital.

Registradores para configuração do PORTE NOME BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0 PORTA RA7 RA6 RA5 RA4 RA3 RA2 RA1 RA0 LATA LATA7 LATA6 LATA5 LATA4 LATA3 LATA2 LATA1 LATA0 TRISA TRISA7 TRISA6 TRISA5 TRISA4 TRISA3 TRISA2 TRISA1 TRISA0 ADCON1 --- --- VCFG1 VCFG0 PCFG3 PCFG2 PCFG1 PCFG0 CVRCON CVREN CVROE CVRR CVRSS CVR3 CVR2 CVR1 CVR0

Acesso aos SFR’s de configuração dos pinos de I/O

O compilador MPLAB C18 nos dá acesso direto aos registradores de função especial. Para configurar os PORT’s basta escrever o nome do registrador de função especial (SFR) e igualar ao valor desejado. Veja no arquivo de header como foram declarados os registradores.

Também é possível acessar facilmente os bits dos SFR’s, veja os exemplos abaixo. Exemplo: a) Vamos configurar todos os pinos do PORTA como saída. PORTA = 0x00; // Limpa os circuitos de saída do PORTA LATA = 0x00; // Desabilita o LATCH do PORTA ADCON1 = 0x07; // Desliga a função analógica do PORTA CMCON = 0x07; // Deliga os comparadores analógicos TRISA = 0b00000000; // Configura os pinos de I/O como saída b) Configurando os pinos RA0, RA4 e RA5 como saída. PORTA = 0x00; LATA = 0x00; ADCON1 = 0x07; CMCON = 0x07; TRISA = 0b11001110;

Page 76: Apostila Mosaico Pic MÓDULO4

74

c) Vamos configurar todos os pinos do PORTB como saída. PORTB = 0x00; // Limpa os circuitos de saída do PORTB LATB = 0x00; // Desabilita o LATCH do PORTB ADCON1 = 0x0F; // Desliga a função analógica do PORTB TRISB = 0b00000000; // Configura os pinos de I/O como saída d) Manipulando individualmente os pinos RA0 e RB4. LATA = 0x00, LATB = 0x00; ADCON1 = 0x0F, CMCON = 0x07; TRISA = 0b11111110; TRISB = 0b11101111; PORTbits.RA0 = 0; PORTbits.RB4 = 1;

Funções para manipulação do PORTB ClosePORTB Desabilita a interrupção e pull-up do PortB CloseRBxINT Desabilita interrupção do PORTB pin x DisablePullups Desabilita os pull-ups do PORTB EnablePullups Habilita os pull-ups do PORTB OpenPORTB Configura as interrupções e os pull-ups do PORTB OpenRBxINT Habilita a interrupção do PORTB pin x

Descrição das Funções do PORTB

ClosePORTB Função: Desabilita a interrupção de mudança de estado e os resistores de pull – up interno do PORTB. Include: portb.h Protótipo da Função: void ClosePORTB( void ); Nome do arquivo: pbclose.c CloseRB0INT CloseRB1INT CloseRB2INT Função: Desabilita a interrupção externa, de um pino especifico do PORTB. Include: portb.h Protótipo da Função: void CloseRB0INT( void );

void CloseRB1INT( void ); void CloseRB2INT( void );

Nome do arquivo: rb0close.c, rb1close.c, rb2close.c DisablePullups Função: Desabilita os resistores de pull – up do PORTB. Include: portb.h Protótipo da Função: void DisablePullups( void ); Nome do arquivo: pulldis.c

Page 77: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 75

EnablePullups Função: Habilita os resistores de pull – up do PORTB. Include: portb.h Protótipo da Função: void EnablePullups( void ); Nome do arquivo: pullen.c OpenPORTB Função: Configura a interrupção de mudança de estado e os resistores de pull – up do PORTB. Include: portb.h Protótipo da Função: void OpenPORTB( unsigned char config); Argumento da Função: config, Interrupt-on-change: PORTB_CHANGE_INT_ON Habilita a interrupção PORTB_CHANGE_INT_OFF Desabilita a interrupção Enable Pullups: PORTB_PULLUPS_ON Resistores de pull – up habilitados PORTB_PULLUPS_OFF Resistores de pull – up desabilitados Os parâmetros da função são constantes binárias que irão definir através de uma operação lógica E (&), a configuração do PORTB. O valor corresponde as opções de configuração estão no arquivo portb.h Nome do arquivo: pbopen.c Exemplo de código: OpenPORTB(PORTB_CHANGE_INT_ON & PORTB_PULLUPS_ON);

Page 78: Apostila Mosaico Pic MÓDULO4

76

OpenRB0INT, OpenRB1INT, OpenRB2INT Função: Habilita as interrupções especificas do PORTB. Include: portb.h Protótipo da Função: void OpenRB0INT( unsigned char config );

void OpenRB1INT( unsigned char config ); void OpenRB2INT( unsigned char config );

Argumento da Função: config, Interrupt-on-change: PORTB_CHANGE_INT_ON Habilita a interrupção PORTB_CHANGE_INT_OFF Desabilita a interrupção Enable Pullups: PORTB_PULLUPS_ON Resistores de pull – up habilitados PORTB_PULLUPS_OFF Resistores de pull – up desabilitados Interrupt-on-edge: RISING_EDGE_INT Interrupt on rising edge FALLING_EDGE_INT Interrupt on falling edge Nome do arquivo: rb0open.c rb1open.c rb2open.c Exemplo de Código OpenRB0INT(PORTB_CHANGE_INT_ON & PORTB_CHANGE_INT_ON & RISING_EDGE_INT & PORTB_PULLUPS_ON);

Page 79: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 77

Capítulo 9 - Tratamento de Interrupção

O que é Interrupção? Antes de falarmos em como habilitar e tratar uma interrupção vamos primeiro defini-la. Interrupção é o ato de para a execução da tarefa principal, para executar uma tarefa que julgamos

secundária e ao final desta tarefa retornar para a tarefa principal. Quando trabalhamos com microcontroladores, temos a possibilidade de coloca-los para realizar uma

tarefa principal e somente quando a tarefa secundária solicitar a atenção da CPU, é que o microcontrolador irá executar a rotina escrita para esta tarefa.

Ao final da execução da tarefa secundária a CPU volta a executar a rotina da tarefa principal. Os microcontroladores da família 18 possuem dois vetores de interrupção, estes vetores são endereços

de memória de programa, eles indicam o inicio da rotina de tratamento de interrupção. A família 18 possui dois vetores para tratamento de interrupção, um para interrupção de alta prioridade

que corresponde ao endereço 0x008, e outro para interrupção de baixa prioridade que está localizado no vetor 0x0018.

Veja como temos dois vetores, além de termos que habilitar individualmente a interrupção desejada, temos também que definir a sua prioridade.

Para esta finalidade temos registradores específicos e funções para configurar estes registradores. Os registradores responsáveis são: RCON, INTCON, INTCON2, INTCON3, PIR1, PIR2, PIE1, PIE2,

IPR1 e IPR2. Os registradores IPR1 e IPR2, definem a prioridade da interrupção, alta ou baixa. Toda interrupção possui um bit (flag), para sinalizar que a interrupção aconteceu, nos devemos limpar

este bit, ao final da execução da função de tratamento de interrupção, estes flags se encontram nos registradores citados acima. O MPLAB C18 não realiza está operação automaticamente, como ocorre no compilador da CCS.

Um dos cuidados quando estamos trabalhando com interrupção é na hora de salvar o contexto (WREG, BSR e STATUS), na interrupção de alta prioridade ele é salvo automaticamente no SHADOW, e restaurado ao sair da interrupção.

Já em uma interrupção de baixa prioridade devemos salvar o contexto na pilha criada na memória RAM e restaurar ao sair da mesma.

Uma interrupção de alta prioridade pode interromper uma de baixa prioridade, no caso contrario a de alta prioridade não é interrompida.

O tratamento de interrupção possibilita ao programador gerenciar melhor o tempo de processamento do microcontrolador, desta forma o microcontrolador pode executar a função principal enquanto os periféricos estão trabalhando em paralelo. Somente quando for necessário ou a tarefa de um periférico estiver finalizada, a função principal será interrompida.

Page 80: Apostila Mosaico Pic MÓDULO4

78

Hardware da Lógica de Interrupção

Figura 9.1 – Lógica de tratamento das interrupções

Habilitando uma Interrupção O MPLAB C18 possui funções especificas para habilitar o tratamento de interrupção. Elas devem ser habilitadas na função principal ou em uma função de usuário. Estas funções serão vistas quando estudarmos os periféricos.

Definindo o vetor de interrupção Para criar uma função de tratamento de interrupção, utilizaremos a diretiva pragma code, que tem como

finalidade, informar o endereço da memória de programa onde o código será gravado e informar o nome do vetor de alta e baixa prioridade.

Exemplo: #pragma code VETOR_INT_HIGH=0x0008 // Vetor de alta prioridade. void atVETOR_INT_HIGH (void) // nome da função _asm goto INT_HIGH // Salta para a função de tratamento de alta _endasm #pragma code #pragma code VETOR_INT_LOW=0x18 // Vetor de baixa prioridade void atVETOR_INT_LOW (void) // nome da função _asm goto INT_LOW // Salta para a função de tratamento de baixa _endasm #pragma code

Page 81: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 79

Tratando uma interrupção Depois que definimos o vetor de interrupção, podemos escrever a função de tratamento em qualquer

posição da memória de programa. Podemos incluir na função outra diretiva pragma, pragma interrupt, para salvar o valor dos registradores

que desejarmos, além daqueles já sitados. Não podemos esquecer de limpar o flag de interrupção na função de tratamento da mesma. Sintaxe: #pragma interrupt INT_HIGH save = Reg1, Reg2 #pragma interrupt INT_LOW save = RegA, RegB Vejamos como ficará a função: Exemplo:

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Tratamento da interrupção de alta prioridade * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * #pragma code INT_HIGH=0x100 //Posiciona o código (ORG) #pragma interrupt INT_HIGH save=PRODL,PRODH void INT_HIGH(void) TRATA_INT_HIGH(); //TRATA INT DE ALTA PRIORIDADE #pragma code void TRATA_INT_HIGH(void) if (PIR1bits.TMR1IF) TRATA_TIMER1() //Int. de Timer1 void TRATA_TIMER1(void) WriteTimer1(ReadTimer1()+0xfc49); // Inicia timer1 para contar 1000 pulsos PIR1bits.TMR1IF = 0; // Limpa flag da int

Page 82: Apostila Mosaico Pic MÓDULO4

80

Capítulo 10 - Estudo dos Timers

Timer 0

O Timer 0 é um contador / temporizador que pode operar com 8 ou 16 bits, na linha 16 o timer 0 possui 8 bits.

Outra vantagem em relação a linha 16 é o prescaler dedicado, que pode ser ajustado a qualquer momento.

Podemos selecionar a origem do sinal de clock do Timer 0, através do bit T0CS. Para o TMR0 ser incrementado pelo ciclo de máquina, devemos colocar o bit T0CS em 0. Quando

ocorrer uma operação de escrita o no timer ele ficará parado por dois ciclos de máquina. Para clock externo (vindo do pino RA4) colocaremos o bit T0CS em 1, agora podemos escolher o borda

que irá incrementar o timer, com o bit T0SE em 0, selecionamos a borda de subida, com o bit T0SE em 1, selecionamos a borda de descida.

Este timer possui dois registradores responsáveis pela contagem / temporização, TMR0L e TMR0H, podemos ler ou escrever nestes registradores a qualquer momento.

A modalidade de 16 Bits O registrador TMR0H não é o byte mais significativo do Timer0, na modalidade 16-bit, ele é um buffer

intermediaria. A parte alta do Timer 0 não está disponível para leitura ou escrita. A atualização do TMR0H ocorre toda vez que realizamos uma leitura do registrador TMR0L. Isto fornece a habilidade de ler todos os 16 bits do Timer0 de uma única vez, evitando erro de leitura

caso o timer esteja ligado. Da mesma forma podemos carregar os 16 bits do Timer0 de uma única vez, basta para isso carregar o

valor desejado no TMR0H de depois carregar o registrador TMR0L, neste momento os dois bytes são transferidos ao Timer.

O Prescaler O prescaler é um contador de 8 bits que trabalha como um divisor de freqüência para o módulo Timer0. Não temos acesso ao prescaler ele não pode ser diretamente lido ou escrito, o seu valor é ajustado

pelos bits PSA e <T0PS2:T0PS0> do registrador T0CON. Colocando o bit PSA em 0, atribuiremos o prescaler ao módulo Timer0. Quando isto ocorre podemos

selecionar o divisor de freqüência na faixa de 1:2 a 1:256, por exemplo selecionando 1:4 o Timer0 precisara receber quatro pulsos de clock para incrementar uma unidade.

Quando realizamos uma operação de escrita no módulo Timer0, o prescaler é zerado, porém o ajuste dos bits <T0PS2:T0PS0> não são afetados.

A atribuição do prescaler ao Timer0 está inteiramente sob o controle do software e pode ser mudada "on-the-fly", ou seja, durante a execução de programa.

Interrupção do Timer0 A interrupção é gerada pelo “estouro” do timer, ou seja quando ele chegar na sua capacidade máxima de

contagem, para o modo 8 bits o valor máximo será de 255 (0XFF) e no modo 16 bits o valor máximo será de 65535 (0XFFFF), e voltar para zero, será gerado uma interrupção.

O tratamento da interrupção é habilitado pelo bit INTCON<TMR0IE>, não podemos esquecer de definir a prioridade no tratamento da interrupção, quando ocorre um estouro no Timer0 o bit INTCON<TMR0IF>, e colocado em nível lógico um, na rotina de tratamento de interrupção devemos coloca-lo em zero antes de sair da rotina de tratamento de interrupção.

Diagrama do Timer 0 no modo 8 Bit

Figura 10.1 – Timer 0 modo 8 bit

Page 83: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 81

Diagrama do Timer 0 no modo 16 Bit

Figura 10.2 – Timer 0 modo 16 bit

Após um reset o TIMER 0 é configurado para 8 bits e o prescaler ajustado para o valor máximo.

O registrador T0CON Este registrador é responsável por configurar o TIMER0, definir o valor do prescaler, a origem do sinal de

clock, a borda de incremento, operação em 8 ou 16 bit’s e finalmente ligar ou desligar o timer. Através do MPLAB C18 temos funções especificas para configuração deste registrador, mas lembre-se

que podemos configurar o TIMER 0 através deste registrador, para isso basta escrever o nome do registrador e igualar ao valor desejado.

Registradores para configuração do TIMER0 NOME BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0

INTCON GIE/GIEH PEIE/GIEL TMR0IE INT0IE RBIE TMR0IF INT0IF RBIF T0CON TMR0ON T08BIT T0CS T0SE PSA T0PS2 T0PS1 T0PS0 TRISA TRISA7 TRISA6 TRISA5 TRISA4 TRISA3 TRISA2 TRISA1 TRISA0 TMR0L Registrador do Timer 0, Low byte TMR0H Registrador do Timer 0, High byte

T0CON: Registrador de Controle

Page 84: Apostila Mosaico Pic MÓDULO4

82

Funções para manipulação do Timer 0 CloseTimer0 Desabilta o Timer0 OpenTimer0 Configura o Timer0 WriteTimer0 Escreve no Timer0 ReadTimer0 Lê o valor do Timer0

Timer 1

O Timer1 é um contador/temporizador de 16 bits que possui as seguintes características: Podemos selecionar através do software a forma de trabalho do timer, temporizador ou um contador de

16-bits. Ele possui dois registradores para está operação que podem ser lidos ou escritos, TMR1H e TMR1L.

A origem da fonte de clock pode ser selecionada como interna ou externa. Este timer gera Interrupção na transição de 0XFFFF -> 0X0000, pode ser zerado por uma das

configurações do módulo CCP. Uma opção nova é a utilização do Timer1, como gerador de clock para o microcontrolador, está opção é

sinalizada pelo bit T1RUN. Com o seu próprio oscilador low-power, podems utiliza-lo como um RTC (Relógio de Tempo Real). Este

oscilador independe do fonte de clock do microcontrolador. O Timer1 é controlado através do registrador T1CON. Neste registrador encontraremos o bit T1OSCEN, responsável em habilitar o oscilador interno do timer.

Outro bit importante é o TMR1ON este bit pode habilitar ou desabilitar o sinal de clock do Timer1,interrompendo a contagem ou a temporização, este bit não zera o timer .

Diagrama do Timer 1

Figura 10.3 – Timer 1

Modo de 16 bits para Leitura ou Escrita O Timer1 pode ser configurado para operação de Leitura ou Escri ta em 16 bi ts. Quando

co locamos o b i t RD16 em um o registrador TMR1H é mapeado como um buffer, para acesso indireto da parte alta do Timer1.

Uma operação de leitura do registrador TMR1L, carrega o registrador TMR1H com a parte alta do timer. Desta forma realizamos uma leitura de 16 bits.

Page 85: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 83

Para uma operação de escrita de 16 bits devemos carregar o registrador TMR1H como o valor desejado e depois carregar o registrador TMR1L. Logo após a carga do TMR1L, o timer recebe os 16 bits ao mesmo tempo. Veja a parte alta do timer só acessada indiretamente neste modo.

O prescaler do Timer1 é zerado logo após a operação de escrito do registrador TMR1L.

Diagrama do Timer 1 modo de escrita e leitura de 16 Bit

Figura 10.4 – Timer 1 modo de escrite e leitura de 16 bit

Quando o bit T1CON<T1OSCEN>, é colocado em zero o circuito inversor e o resistor de feedback são desligados para eliminar o consumo de energia.

Oscilador do Timer1 Os pinos T1OSI, entrada, e T1OSO, saída, são utilizados para ligarmos um cristal ou ressonador para

gerar sinal de clock para o Timer1. Este oscilador externo é habilitador pelo bit T1OSCEN, Este circuito oscilador é de baixa potencia (LP),

logo poderemos utilizar cristais de 32kHz a 200kHz.

Figura 10.5 – Oscilador do Timer 1

Usando o TIMER1 como uma fonte de clock O Timer1 pode ser usado como uma fonte de clock para o dispositivo. Esta possibilidade é configurada

através dos bits, OSCCON<SCS1:SCS0>, podemos configurar a modalidade SEC_RUN, o microcontrolador e os periféricos são recebem o sinal de clock do Timer1. Caso o bit OSCCON<IDLEN> seja zerado e a instrução de Sleep seja executada, o dispositivo entra no modo SEC_IDLE. Sempre que o oscilador Timer1 está sendo usado como fonte de clock o bit T1RUN, é ajustada para sinalização do mesmo.

Isto pode ser usado para determinar a modalidade de clock usada pelo microcontrolador. Pode também indicar a fonte do pulso de disparo que está sendo usada atualmente pelo monitor à prova

de falhas do pulso de disparo.

Page 86: Apostila Mosaico Pic MÓDULO4

84

Timer1 em Low Power O oscilador do Timer1 pode se configurado para operar em dois níveis distintos de consumo de potência

baseados na configuração de dispositivo. Quando o bit de configuração, CONFIG3H<LPT1OSC>, é colocado em um, o Timer1 opera em low power.

Quando CONFIG3H<LPT1OSC>, é colocado em zero, o Timer1 opera em um nível de um consumo mais elevado.

Com o Timer1 operando em low power, ele tende a ser mais sensível à interferência, os ambientes de ruído elevados podem causar alguma instabilidade do oscilador. A opção low power, conseqüentemente, é melhor para as aplicações de baixo nível de ruído e o baixo consumo é uma consideração importante do projeto.

Interrupção do Timer1 A interrupção é gerada pelo estouro do Timer, quando o mesmo chegou ao seu valor máximo 0XFFFF e

volta para 0X0000, isto é provocado pelo incremento do par de registradores do TMR1<TMR1H:TMR1L>. O evento é sinalizado pelo bit PIR1<TMR1IF>. Este deve ser zerado por software. Esta interrupção

somente será tratada se o bit, PIE1<TMR1IE>, estiver em nível lógico um.

Reset do Timer1 Uma das possibilidade de configuração do módulo CCP, configura o modo capture para gerar um reset

no Timer1. Isto só será possível caso o Timer1 esteja configurado para trabalhar no modo síncrono. Este evento não

gera interrupção de Timer1, apenas zera o Timer. O timer será zerado quando o valor dos registradores CCPRH e CCPRL, forem exatamente iguais ao

valor dos registradores do Timer1.

Registradores para configuração do TIMER1 NOME BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0

INTCON GIE/GIEH PEIE/GIEL TMR0IE INT0IE RBIE TMR0IF INT0IF RBIF T1CON RD16 T1RUN T1CSSPIF T1CKPS0 T1OSCEN /T1SYNC TMR1CS TMR1ON

PIR1 PSPIF ADIF RCIF TXIF SSPIF CCPIF TMR2IF TMR1IF PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE IPR1 PSPIP ADIP RCIP TXIP SSPIP CCP1IP TMR2IP TMR1IP

TMR1L Registrador do Timer 1, Low byte TMR1H Registrador do Timer 1, High byte

T1CON: Registrador de Controle

Page 87: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 85

Funções para manipulação do Timer 1 CloseTimer1 Desabilta o Timer1 OpenTimer1 Configura o Timer1 WriteTimer1 Escreve no Timer1 ReadTimer1 Lê o valor do Timer1

Timer 2

O Timer2 é um módulo temporizador que utiliza o clock da máquina, ele não permite incremento por clock externo.

Ele possui dois registradores de 8 bit, TMR2 temporizador e PR2 periodo, ambos permitem escreta e leitura.

O seu Prescaler é programável por software (1:1, 1:4 e 1:16) e o Postscaler que também é programável por software (1:1 a 1:16), permite contar quantas vezes o timer foi zerado.

Sua Interrupção ocorre quando o TMR2 é igual ao PR2. Este timer é configurado pelo registrador T2CON, que habilita ou desabilita o timer e configura o

prescaler e o postscaler. O Timer2 pode ser desabilitado zerando o bit, TMR2ON<T2CON>, para minimizar o consumo de

energia.

Diagrama do Timer 2

Figura 10.5 – Diagrama do Timer 2

Operação do Timer2

Na operação normal, o TMR2 é incrementado de 00h até o valor ajustado no PR2 a cada pulso de clock

(FOSC/4). Um contador de 4 bits, prescaler, ligado a entrada de clock, nos permite dividir a freqüência de clock por 1, 4, 16. Este precaler é configurado pelos bits, T2CON<T2CKPS1:T2CKPS0>.

Page 88: Apostila Mosaico Pic MÓDULO4

86

O valor do TMR2 é comparado ao registrador PR2, a cada pulso de clock. Quando os dois valores forem iguais, o comparador gera um pulso na saída do temporizador. Este sinal

também zera o valor do TMR2. O registrador TMR2 é zerado em toda operação de reset do dispositivo e quando o registrador PR2

inicializar em FFh. Os contadores do prescaler e do postscaler são zerados nos seguintes eventos: • Uma operação de escrita no registrador TMR2; • Uma operação de escrita no registrador de T2CON; • Algum tipo de reset do dispositivo.

O TMR2 não é zerado quando o registrador T2CON é escrito.

Interrupção do Timer2 O Timer2 também pode gerar interrupção. Sua interrupção ocorre quando o TMR2 é igual ao PR2. Ela

depende também do valor ajustado o Postscaler, este conta a quantidade de vezes que o TMR2 atingiu o mesmo valor do PR2, quando a quantidade de vezes é igual ao valor ajustado no Postscale é então gerado uma interrupção. Uma das escalas do postscale (de 1:1 a 1:16) pode ser selecionada com os bits de controle do postscaler, T2CON<T2OUTPS3:T2OUTPS0>.

Esta ocorrência é sinalizada pelo bit PIR1<TMR2IF>. A interrupção será tratada se o bit PIE1<TMR2IE>, estiver com nível lógico um.

Timer como Base de Tempo A Saída do Timer2 está disponível aos módulos de CCP, onde é usada como uma base do tempo para

operações do PWM. O Timer2 pode opcionalmente ser usado como fonte de clock ao modulo SPI do módulo de MSSP.

Registradores para configuração do TIMER2 NOME BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0

INTCON GIE/GIEH PEIE/GIEL TMR0IE INT0IE RBIE TMR0IF INT0IF RBIF T2CON --- T2OUTPS3 T2OUTPS2 T2OUTPS1 T2OUTPS0 TMR2ON T2CKPS1 T2CKPS0

PIR1 PSPIF ADIF RCIF TXIF SSPIF CCPIF TMR2IF TMR1IF PIE1 PSPIE ADIE REIE TXIE SSPIE CCP1IE TMR2IE TMR1IE IPR1 PSPIP ADIP RCIP TXIP SSPIP CCP1IP TMR2IP TMR1IP TMR2 Registrador do Timer 2 PR2 Registrador de período do Timer2

T2CON: Registrador de Controle

Page 89: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 87

Funções para manipulação do Timer 2

CloseTimer2 Desabilta o Timer2 OpenTimer2 Configura o Timer2 WriteTimer2 Escreve no Timer2 ReadTimer2 Lê o valor do Timer2

Timer 3

O Timer3 é um contador/temporizador de 16 bits que possui as seguintes características: Podemos selecionar através do software a forma de trabalho do timer, temporizador ou um contador de

16-bits. Ele possui dois registradores para está operação que podem ser lidos ou escritos, TMR3H e TMR3L.

A origem da fonte de clock pode ser selecionada como interna ou externa. Este timer gera Interrupção na transição de 0XFFFF -> 0X0000, pode ser zerado por uma das

configurações do módulo CCP. Com o seu próprio oscilador low power, podemos utiliza-lo como um RTC (Relógio de Tempo Real). Este

oscilador independe do fonte de clock do microcontrolador. O Timer3 é controlado através do registrador T3CON. No registrador T1CON encontramos o bit T1OSCEN, responsável em habilitar o oscilador interno do Timer3.

Outro bit importante é o TMR3ON este bit pode habilitar ou desabilitar o sinal de clock do Timer1,interrompendo a contagem ou a temporização, este bit não zera o timer .

Diagrama do Timer 3

Figura 10.6 – Diagrama do Timer 3

Modo de 16 bits para Leitura ou Escrita O Timer3 pode ser configurado para operação de Leitura ou Escrita em 16 bits. Quando colocamos o bit

RD16 em um o registrador TMR3H é mapeado como um buffer, para acesso indireto da parte alta do Timer1. Uma operação de leitura do registrador TMR3L, carrega o registrador TMR3H com a parte alta do timer.

Desta forma realizamos uma leitura de 16 bits. Para uma operação de escrita de 16 bits devemos carregar o registrador TMR3H como o valor desejado e

depois carregar o registrador TMR3L. Logo após a carga do TMR3L, o timer recebe os 16 bits ao mesmo tempo. Veja a parte alta do timer só acessada indiretamente neste modo.

O prescaler do Timer3 é zerado logo após a operação de escrito do registrador TMR3L.

Page 90: Apostila Mosaico Pic MÓDULO4

88

Diagrama do Timer 3 modo de escrita e leitura de 16 Bit

Figura 10.7 – Diagrama do Timer 3 modo 16 bits

Quando o bit T1CON<T1OSCEN>, é colocado em zero o circuito inversor e o resistor de feedback são desligados para eliminar o consumo de energia.

Oscilador do Timer3 Os pinos T1OSI, entrada, e T1OSO, saída, são utilizados para ligarmos um cristal ou ressonador para

gerar sinal de clock para o Timer1. Este oscilador externo é habilitador pelo bit T1OSCEN, Este circuito oscilador é de baixa potencia (LP),

logo poderemos utilizar cristais de 32kHz a 200kHz.

Figura 10.8 – Oscilador do Timer 3

Interrupção do Timer3 A interrupção é gerada pelo estouro do Timer, quando o mesmo chegou ao seu valor máximo 0XFFFF e

volta para 0X0000, isto é provocado pelo incremento do par de registradores do TMR3 (TMR3H e TMR3L). O evento é sinalizado pelo bit PIR2<TMR3IF>. Este deve ser zerado por software. Esta interrupção

somente será tratada se o bit, PIE2<TMR3IE>, estiver em nível lógico um.

Reset do Timer3 Uma das possibilidade de configuração do módulo CCP, configura o modo capture para gerar um reset

no Timer1. Isto só será possível caso o Timer1 esteja configurado para trabalhar no modo síncrono. Este evento não

gera interrupção de Timer1, apenas zera o Timer. O timer será zerado quando o valor dos registradores CCPR2H e CCPR2L, forem exatamente iguais ao

valor dos registradores do Timer1.

Page 91: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 89

Registradores para configuração do TIMER3 NOME BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0

INTCON GIE/GIEH PEIE/GIEL TMR0IE INT0IE RBIE TMR0IF INT0IF RBIF PIR2 OSCFIF CMIF --- EEIF BCLIF HLVDIF TMR3IF CCP2IF PIE2 OSCFIE CMIE --- EEIE BCLIE HLVDIE TMR3IE CCP2IE IPR2 OSCFIF CMIP --- EEIP BCLIP HLVDIP TMR3IP CCP2IP

TMR3L Registrador do Timer 3, Low byte TMR3H Registrador do Timer 3, High byte T1CON RD16 T1RUN T1CSSPIF T1CKPS0 T1OSCEN /T1SYNC TMR1CS TMR1ON T3CON RD16 T3CCP2 T3CKPS1 T3CKPS0 T3CCP1 /T3SYNC TMR3CS TMR3ON

T3CON: Registrador de Controle

Funções para manipulação do Timer 3 CloseTimer3 Desabilta o Timer3 WriteTimer3 Escreve no Timer3 ReadTimer3 Lê o valor do Timer3 OpenTimer3 Configura o Timer3

Page 92: Apostila Mosaico Pic MÓDULO4

90

Capítulo 11 - Módulo CCP

Introdução

Vamos estudar agora os módulos denominados CCPs, cujo nome é originado dos três tipos de recursos oferecidos por eles: Capture, Compare e PWM. Cada um desses recursos é empregado para uma finalidade diferente, que será conhecida a partir de agora.

Teoria e recursos do PIC

O PIC 18F4520 possui dois módulos de CCP, denominados CCP1 e CCP2. Esses módulos são práticamente idênticos e, existe uma diferença no PWM do módulo CCP1, ele é dedicado para controle de motor,os demais módulos serão explicados ao mesmo tempo, sendo feito os comentários necessários quando houver algum tipo de diferença. Para facilitar o entendimento, cada um dos recursos (Capture, Compare e PWM) será descrito separadamente.

Para começar, entretanto, é bom esclarecermos a nomenclatura padrão que será utilizada para descrevermos características comuns aos dois módulos existentes:

Padrão CCP1 CCP2 Descrição

CCPxCON CCP1CON CCP2CON Registrador de configuração

CCPRxH CCPR1H CCPR2H Parte alta do valor de controle

CCPRxL CCPR1L CCPR2L Parte baixa do valor de controle

CCPx CCP1 (RC2)

CCP2 (RC1) Pino relacionado

Outro dado interessante que devemos informar neste momento é quanto ao uso dos dois módulos

conjuntamente. Como eles utilizam recursos compartilhados para suas bases de tempo (Timer 1 e Timer 2), podem existir algumas limitações ou conflitos, conforme a combinação de recursos desejada:

Modo Base de tempo Capture Timer 1/Timer 3 Compare Timer 1/Timer 3

PWM Timer 2

Recursos Desejados Observações

Capture Capture Sem conflitos, entretanto, ambos utilizarão a mesma base de tempo TMR1 e, por isso, serão sincronizados.

Capture Compare Caso o Compare esteja configurado para zerar o Timer 1, isso poderá acarretar em um conflito com o outro modo.

Compare Compare Caso o Compare esteja configurado para zerar o Timer 1, isso poderá acarretar em um conflito com o outro modo.

PWM PWM Ambos os PWM terão a mesma freqüência e serão sincronizados, devido ao uso da mesma base de tempo. Os Duty Cycles possuem controles independentes.

PWM Capture Ambos os modos são completamente independentes. PWM Compare Ambos os modos são completamente independentes.

Modo Capture Este módulo tem como objetivo a contagem de tempo entre dois eventos ocorridos em um dos pinos

CCPx. Para isso será utilizado como base de tempo o Timer 1 e no momento do evento seu valor será capturado (dai o nome Capture). Como o Timer 1 / Timer 3 são de 16 bits, a captura será feita em dois registradores: CCPRxH e CCPRxL.

Page 93: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 91

Com esse recurso é possível então criarmos um periodímetro, contando o tempo gasto, por exemplo, entre duas bordas de subida da onda ligada ao pino CCPx. É importante observarmos, entretanto, que a captura do valor de Timer 1 não reseta este timer, e por isso, para definirmos o tempo real entre duas leituras será necessário uma conta de subtração entre a última leitura e a anterior. Esta conta deverá ser implementada pelo software.

Vejamos, então, como configurar o Capture para que possamos utilizá-lo corretamente. O modo Capture opera com os pinos como entrada, mas essa configuração não é feita automati-

camente. Por isso, antes de mais nada configure, através do TRISC, o pino CCPx como entrada. Caso este esteja configurado como saída, operações de escrita neste pino podem ser consideradas como mudança de borda, ativando a captura.

Quanto ao Timer 1 / Timer 3 , que será usado como base de tempo para este modo, ele não pode estar configurado para operação assíncrona, isto é, confirme a condição T1CON</T1SYNC>=0 e T3CON</T3SYNC>=0.

O Capture possui também quatro diferentes configurações (fora o desligamento), que podem ser escolhidas através de CCPxCON<CCPxM3:CCPxM0>:

CCPxM3: CCPxM0 Descrição

0000 CCPx desligado

0100 Capture ligado para borda de descida Prescale de 1:1

0101 Capture ligado para borda de subida Prescale de 1:1

0110 Capture ligado para borda de subida Prescale de 1:4

0111 Capture ligado para borda de subida Prescale de 1:16

Obs. As demais opções de configuração dizem respeito aos outros modos (Compare/PWM).

As diferenças básicas entre essas configurações dizem respeito à borda que gerará o evento e ao

prescale adotado. Esse prescale é um contador interno (não acessível) de bordas. Por exemplo: caso seja escolhida a opção 0111, a captura do TMR1/TMR3 acontecerá a cada 16 bordas de subida. A finalidade desse prescale é o aumento da precisão do sistema. Quando optamos em trabalhar com prescaler de 1:1, a erro máximo em um período é de um ciclo de máquina (TCY). Quando aumentamos o prescale, esse erro diminui proporcionalmente, e teremos para 1:16 um erro máximo de TCY/16.

Toda vez que o evento de Capture acontecer, o flag CCPxIF será ativado, e caso essa interrupção esteja ligada, ela irá acontecer. Esta é uma maneira fácil de implementarmos a conta de subtração dos tempos absolutos para chegarmos ao período correto. Não se esqueça de que, quando uma nova captura acontece, ela será gravada em CCPRxH e CCPRxL, sobrescrevendo os valores anteriores.

Para alterar entre as opções de configuração do modo, alguns cuidados devem ser tomados. Como o prescale é um contador interno que não pode ser zerado manualmente, a alteração de configuração poderá gerar uma interrupção. Uma maneira de evitarmos isso seria o desligamento da interrupção (CCPxIE) antes dessa operação. Uma outra maneira, mais prática, é desligarmos o modo Capture (limpando o registrador CCPxCON). Isso irá resetar o modo, limpando também o contador de prescale. Depois, basta escolhermos a nova configuração, carregando CCPxCON com o valor desejado.

Quanto ao funcionamento do Capture em modo SLEEP, a história é um pouco confusa, pois nessa situação ou o Timer 1 não está funcionando ou está em modo assíncrono. Por isso, a interrupção de CCP pode até acontecer, acordando o PIC, mas os registradores CCPRxH e CCPRxL não serão atualizados.

Page 94: Apostila Mosaico Pic MÓDULO4

92

Resumo dos registradores associados ao Capture

Endereço Nome Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 0Bh ... INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF OCh PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF 8Ch PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE ODh PIR2 - - - EEIF BCLIF - - CCP2IF 8Dh PIE2 - - - EEIE BCLIE - - CCP2IE 17h CCP1CON - - DC1B1 DC1B0 CCP1M3 CCP1M2 CCP1M1 CCP1M0 16h CCPR1H Captura de TMR1H (Parte alta) 15h CCPR1L Captura de TMR1L (Parte baixa) 1Dh CCP2CON - - DC2B1 DC2B0 CCP2M3 CCP2M2 CCP2M1 CCP2M0 1Ch CCPR2H Captura de TMR1H (Parte alta) 1Bh CCPR2L Captura de TMR1L (Parte baixa) 87h TRISC Configuração do PORTC com Entrada(1) ou Saída(0)

Modo Compare Enquanto no modo Capture o valor de Timer 1 / Timer 3 era capturado e armazenado, aqui ele será

constantemente comparado (olha a origem do nome novamente) com os valores dos registradores CCPRxH e CCPRxL. Sempre que essa comparação de 16 bits resultar numa igualdade, o flag CCPxIF será ativado e a interrupção poderá acontecer, caso a mesma esteja devidamente ligada. Além disso, se desejado, podemos alterar automaticamente o estado do pino CCPx.

Aqui também vale a observação quanto ao funcionamento do Timer 1 / Timer 3, que deve obrigatoriamente estar ajustado em modo síncrono (T1CON</T1SYNC>=0). Não esqueça também de configurar o pino CCPx como saída, através do TRISC.

A ativação do Compare e as opções para mudança no pino podem ser configuradas em CCPxCON<CCPxM3:CCPxM0>:

CCPxM3: CCPxM0 Descrição

0000 CCPx desligado

1000 Inicia com o pino em 0 (baixo) e altera para 1 (alto) quando a comparação for bem-sucedida.

1001 Inicia com o pino em 1 (alto) e altera para 0 (baixo) quando a comparação for bem-sucedida.

1010 Não altera o pino. 1011 Não altera o pino, mas reseta TMR1/TMR3

Obs: As demais opções de configuração dizem respeitos aos outros modos (Compare/PWM).

Em todas as opções, o flag da interrupção sempre será ativado. A última opção (1011) é chamada no Data Sheet do PIC de Special Event Trigger, e apesar dela não

alterar o estado do pino CCPx, uma outra alteração muito importante acontece. Os registradores do Timer 1 ou Timer 3 são zerados. Com isso podemos utilizar o Timer 1 de forma similar ao Timer 2 com o registrador de limite PR2. A vantagem aqui é que estamos trabalhando com 16 bits, e não mais com 8. Este é o único caso de diferença entre CCP1 e CCP2, pois CCP2 além de resetar o TMR1/ TMR3, irá também iniciar uma conversão analógica (ADCON0<GO/DONE>) se o conversor estiver ligado. Atenção ao escolher essa configuração quando os dois modos CCP1 e CCP2 estiverem em uso, pois tanto o Compare quanto o Capture utilizam o Timer 1 como base de tempo.

No modo SLEEP, ou Timer 1/ Timer 3, está em modo assíncrono ou está paralisado. Em nenhum dos dois casos o Compare poderá funcionar. Por isso, este modo não opera durante o SLEEP. Só não se esqueça de que a saída CCPx é um pino como outro qualquer e, por isso, o nível de tensão da mesma será garantido mesmo em SLEEP.

Page 95: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 93

Resumo dos registradores associados ao Compare

Endereço Nome Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 0Bh ... INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF OCh PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF 8Ch PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE ODh PIR2 - - - EEIF BCLIF - - CCP2IF 8Dh PIE2 - - - EEIE BCLIE - - CCP2IE 17h CCP1CON - - DC1B1 DC1B0 CCP1M3 CCP1M2 CCP1M1 CCP1M0 16h CCPR1H Comparação com TMR1H (Parte alta) 15h CCPR1L Comparação com TMR1L (Parte baixa) 1Dh CCP2CON - - DC2B1 DC2B0 CCP2M3 CCP2M2 CCP2M1 CCP2M0 1Ch CCPR2H Comparação com TMR1H (Parte alta) 1Bh CCPR2L Comparação com TMR1L (Parte baixa) 87h TRISC Configuração do PORTC com Entrada(1) ou Saída(0)

Modo PWM O Modo PWM é provavelmente o recurso mais poderoso dos módulos CCPs, pois com ele podemos

obter uma tensão analógica a partir de um sinal digital. Na verdade, esta saída é meramente digital, isto é, somente pode assumir os estados 0 e 1. Porém, pelo conceito aplicado ao PWM, podemos transfor-má-la em uma tensão variável. Obviamente isso exigirá um hardware complementar (filtros) depois da saída do PIC, mas isso é uma outra história. Por enquanto, vamos entender melhor o que é um PWM.

O nome PWM tem sua origem no inglês Pulse Width Modulation que em Português pode ser considerado como Modulação por Largura de Pulso. Mas o que exatamente significa isso? Trata-se de uma onda com freqüência constante (período fixo) e largura de pulso (duty cycle) variável.

Na figura seguinte temos a representação de duas formas de onda tipo PWM, cada uma delas com uma largura de pulso diferente:

Esse tipo de sinal é particularmente importante, já que a partir dele é possível implementar um conversor

digital analógico com um único pino do microcontrolador, uma vez que controlando a largura do pulso é possível obter uma tensão analógica variável.

Vejamos a teoria. Genericamente, a tensão média de uma forma de onda é dada por:

( )dttVT1V

T

0dc ∫=

Onde T é o período da forma de onda e V(t) é a função da tensão no tempo. Para o caso do PWM temos que:

( )⎩⎨⎧

≤<→≤≤→

=Ttt0

tt0VtV

p

ppulso

Onde: pt é a duração do pulso em nível lógico 1

pulsoV é a tensão de pulso do sinal PWM.

Então,

Page 96: Apostila Mosaico Pic MÓDULO4

94

⎟⎟

⎜⎜

⎛+= ∫∫

T

t

t

0pulsodc

p

p

0dtdtVT1V

pulsop

dc VTt

V =

A razão entre a largura de pulso e o período da forma de onda recebe o nome de duty cycle, ou em Português, ciclo ativo. O pulso da onda PWM apresenta tensão fixa, porém o valor médio da tensão desta forma de onda varia em função do duty cycle. A tensão média (Vdc) é diretamente proporcional ao duty cycle e como este varia entre 0 (quando tp = 0) e 1 (quando tp = T) temos que a tensão média de onda pode variar entre 0 e Vpulso. No nosso caso a variação será de VSS a VDD, ou seja, de 0 a 5V.

Assim, para obtermos um conversor digital analógico a partir do pino CCPx, basta implementar um sinal tipo PWM e adicionar à saída um filtro que passa baixa freqüência de corte menor que a própria freqüência do PWM.

Cálculo da freqüência de corte do filtro (fc):

RC21Fc π

=

Adotar:

10f

F PWMc ≤

Quando não é necessário obter uma tensão média continua, a implementação do filtro é descartada,

como nos casos da placa proposta. Tanto o resistor de aquecimento quanto o ventilador trabalham com PWMs sem filtro, pois a função desses componentes faz com que eles atuem como filtros, desde que a freqüência do PWM não seja muito baixa.

Assim sendo, a teoria continua válida, o que significa que podemos, através do PWM, regular a taxa de aquecimento do resistor e a velocidade do ventilador, variando a tensão média aplicada a eles.

Vamos aprender agora um pouco mais sobre o funcionamento dos PWMs dentro do 18F4520. Esse PIC possui dois canais de PWMs (CCP1 e CCP2), cada um com resolução máxima de dez bits.

Isso significa que nosso duty cycle poderá ser regulado de 0 a 100% com uma resolução máxima de 1024 pontos. No entanto, dependendo da configuração adotada, essa resolução não será atingida.

Vamos estudar como os tempos do PWM (pulso e período) são controlados internamente para podermos enterder melhor esse problema.

O período do PWM (T) é controlado diretamente pelo Timer 2, através do registrador PR2. Como já foi visto no primeiro capítulo, sempre que TMR2 = PR2, o timer é zerado. Neste momento, um novo período do PWM é iniciado. Desta forma, podemos definir o período e a freqüência do PWM pelas seguintes fórmulas:

T = [(PR2) + 1] x 4 x TOSC x (Prescale do TMR2) PWMFreq = 1 / T Tudo bem quanto ao período, mas como definimos o duty cycle? Na realidade, no PIC não definimos o

valor do duty cycle e sim o tempo do pulso em nível alto. Desta forma, o tempo do pulso pode ser calculado por:

tp = CCPRxL:CCPxCON<CCPxX:CCPxY> x TOSC x (Prescale do TMR2) Repare que a largura do pulso é ajustada em dois registradores: CCPRxL, que armazena os 8 bits mais

significativos, e CCPxCON, que armazena os dois bits menos significativos. Assim, temos os 10 bits que controlam o duty cycle do PWM alocados da seguinte maneira:

Para ficarmos de acordo com a teoria, calcularemos efetivamente o duty cycle dividindo o tempo do

pulso em nível alto pelo período total do PWM.

TMR2)do(PrescaleT41][(PR2)TMR2)do(PrescaleTxB0DCxB1:CCPxCON:CCPRxL

Tt

OSC

OSCp

×××+××><

=

41][(PR2)b0dcDCxB1:CCPxCON:CCPRxL

Ttp

×+>×<

=

Page 97: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 95

Verifica-se então que apesar do período e o do tempo de pulso dependerem do cristal (Tosc) e do ajuste do prescale do Timer 2, o duty cycle depende única e exclusivamente dos valores ajustados nos registradores PR2, CCPRxL e CCPxCON (bits 5 e 4).

Veja que o registrador PR2 (8 bits) que controla o período do PWM é multiplicado por quatro para poder igualar-se aos 10 bits que controlam o duty cycle. É justamente esse o problema da resolução máxima atingida. Se o registrador PR2 for ajustado com um valor menor que 8 bits, ou seja, menor do que 255, serão necessários menos do que 10 bits para atingir um PWM com 100% de duty cycle. Portanto, o número de pontos para ajuste do duty cycle é quatro vezes maior do que o valor ajustado em (PR2+1). Em termos de bits, podemos dizer que a resolução do duty cycle é 2 bits maior do que o número de bits que formam o valor ajustado em PR2. Repare também que, caso PR2 seja ajustado com 255, nunca será atingido um duty cycle de 100%, pois o período atinigirá o valor máximo de 1024 ([PR2+1]x4), enquanto o tempo do pulso em nível alto (<DCxB9:DCxB0>) será no máximo 1023.

É fácil notar também que a resolução para o ajuste do período depende do prescale do Timer 2, assim:

Prescale Tempo do menor passo (resolução)

1 TOSC 4 4 TOSC ou TCY

16 16 TOSC ou 4 TCY

Porém, de qualquer forma, a menor resolução para o tempo do pulso (duty cycle) será sempre quatro vezes menor que a do período.

Note também que o postscale do Timer 2 não é utilizado para a construção dos tempos envolvidos no PWM.

Uma forma de calcular a quantidade máxima de bits que define a quantidade máxima de passos do nosso PWM é:

log(2)FFlog

PWM PWM

OSC

Resolução

⎟⎟⎠

⎞⎜⎜⎝

=

Vamos a um exemplo prático. Calculemos os valores para um PWM de 78,125 kHz, como um PIC rodando a 20 MHz e ajuste do

prescale do Timer2 em 1:1.

1 / 78,125kHz = [(PR2) + 1) x 4 x (1 / 20 MHz) x 1

12,8µs = [(PR2) + 1] x 4 x 50ns x 1

PR2 = 63 Partimos agora para a conta da resolução:

1 / 78,125kHz = 2PWM Resolução x (1 / 20 MHz) x 1

12,8µs = 2PWM Resolução x 50 ns x 1

2PWM Resolução = 256

PWM Resolução x log (2) = log(256)

PWM Resolução = 8 (bits)

Quanto à operação prática do PWM, já ficou claro que antes de mais nada é necessário definirmos a

freqüência de trabalho, com base na freqüência de funcionamento do PIC e na resolução desejada. Com isso calculamos o valor para ser colocado em PR2.

Depois devemos configurar o pino CCPx para ser utilizado como saída. Essa configuração não é automática e deve ser feita através do TRISC. Em seguida, devemos calcular a largura de pulso desejada. O resultado deve ser armazenado em dois registradores, sendo os 8 bits mais significativos em CCPRxL e os outros dois bits restantes em CCPxCON<DCxB1:DCxB0>.

Para o PWM, o registrador CCPRxH é do tipo somente leitura e ele é utilizado pelo sistema para armazenar uma cópia do CCPRxL. Essa cópia é utilizada para possibilitar que a largura de pulso seja alterada durante o funcionamento do PWM. Assim sendo, a nova largura será adotada automaticamente no próximo período do PWM. Os dois bits adicionais também são armazenados internamente pelo sistema.

Page 98: Apostila Mosaico Pic MÓDULO4

96

Quando TMR2 = PR2, as seguintes ações irão acontecer: • TMR2 = 0, iniciando o próximo período;

• O pino CCPx é colocado em 1 (alto), a menos que a largura do pulso esteja definida para 0 (zero); • O valor do registrador CCPRxL é copiado para CCPRxH, atualizando a largura de pulso. O sistema passa, então, a monitorar o término do pulso, quando TMR2 = CCPRxH. Essa compa-ração

irá considerar ainda os 2 bits menos significativos. Neste momento, a saída CCPx será colocada em 0 (baixo), até que um novo período comece. Caso o tamanho do pulso seja especificado como sendo maior que o período total, a saída CCPx nunca será colocada em 0 (baixo), mas o sistema funcionará normalmente, como ajustado para 100% do PWM.

Para que, finalmente, a saída comece a operar, é necessário ainda ajustar o prescale do Timer 2 e ligá-lo, através do registrador T2CON. Por último, ligue também o módulo de PWM, através dos bits CCPxCON<CCPxM3:CCPxM0>:

CCPxM3:CCPxM0 Descrição 0000 CCPx desligado. 11XX Ativa a saída PWM.

Os PWMs não funcionam em modo SLEEP nem geram interrupções; porém, não se esqueça de que a

interrupção de Timer2 pode continuar acontecendo.

Resumo dos registradores associados ao PWM

Endereço Nome Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 17h CCP1CON - - DC1B1 DC1B0 CCP1M3 CCP1M2 CCP1M1 CCP1M016h CCPR1H Cópia de CCPR1L (somente leitura) 15h CCPR1L Largura do pulso, bits de 9 a 2 (Parte baixa) 1Dh CCP2CON - - DC2B1 DC2B0 CCP2M3 CCP2M2 CCP2M1 CCP2M01Ch CCPR2H Cópia de CCPR2L (somente leitura) 1Bh CCPR2L Largura do pulso, bits de 9 a 2 (Parte baixa) 87h TRISC Configuração do PORTC com Entrada(1) ou Saída(0)

Page 99: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 97

Capítulo 12 - Módulo Conversor AD

Teoria

Para começarmos a entender melhor a teoria da conversão dos sinais analógicos em dados digitais, nada melhor que partirmos para um exemplo prático: os sensores de temperatura normalmente fornecem uma informação analógica (como, por exemplo, uma tensão) proporcional à temperatura e, portanto, para que esta possa ser analisada pelo microcontrolador, necessitamos de um conversor analógico digital (CAD ou simplesmente A/D).

O menor passo, ou resolução, de um CAD é dado diretamente pelo seu número de bits e pode ser expresso por:

nref

2Vresolução =

Em que: refV é uma tensão de referência e n é o número de bits do conversor. Cada um dos n bits que compõem a informação digital representa uma parcela do valor da tensão

analógica a ser convertida, de forma que a soma de todas as contribuições de cada um dos n bits forma a tensão de entrada do conversor A/D. Assim, a parcela de tensão proporcional ao bit m do conversor A/D é dada por:

refn

1)(mm

entrada V22bV

=

Em que: mb é o valor do bit m, ou seja, 0 ou 1. Veja, que apenas os bits em 1 representam algum valor em termos de tensão analógica, uma vez que os bits em zero não contribuem para formar a tensão de entrada. Quanto maior a quantidade de bits, maior a resolução e a precisão do conversor. O PIC 18F4520 possui um conversor interno de 10 bits, mas existem outros modelos com 8 ou 12 bits. Vamos supor que o CAD para o nosso exemplo da temperatura seja de quatro bits, a tensão de referência seja de 5V e o valor da conversão em binário seja 1101. A tensão de entrada, então, é:

( ) ( ) 4,0625V52

1x20x21x21x2V 4

0123

entrada =+++

=

Este valor de tensão é equivalente a uma dada temperatura, e por isso o valor convertido (1101) é equivalente à mesma temperatura. Obviamente, para o exemplo da temperatura, assim como para a maioria dos demais casos práticos, não será necessária somente a conversão. Teremos também que nos preocupar com uma equação ou tabela para a adequação dos valores convertidos para a unidade desejada. Muitas vezes essa equação ou tabela será a responsável também pela linearização. Assim sendo, temos então duas conversões a serem feitas: a primeira de sinal analógico para valor digital, e a segunda de valor digital para a unidade realmente desejada, como por exemplo °C.

Page 100: Apostila Mosaico Pic MÓDULO4

98

Existem diversas maneiras de implementarmos um conversor analógico/digital. Porém, como este livro trata do microcontrolador PIC18F4520 faremos um estudo aprofundado do sistema de conversão adotado pelo mesmo, que é denominado conversor de aproximação sucessiva.

Nesse tipo de conversor, a conversão é realizada do bit mais significativo para o menos significativo. Uma vez que o bit mais significativo (Msb) representa metade da tensão de referência, conhecer o estado deste bit (0 ou 1) já significa saber se a tensão de entrada é maior ou menor que a metade da referência. Conhecido o bit mais significativo, passa-se ao próximo bit, que representa a metade da metade da tensão de referência, ou seja, ¼ da tensão de referência. A conversão segue assim até o bit menos significativo (Lsb).

Vamos supor um CAD de quatro bits com tensão de referência de 5V:

Bit Tensão 4 (Msb) 2,5000 V 3 1,2500 V 2 0,6250 V 1 (Lsb) 0,3125 V

Suponha que a tensão de entrada seja de 3,3V. Neste caso, o procedimento de conversão seria assim:

Testa-se o bit mais significativo, ou seja, a tensão de entrada é maior do que 2,5V? Sim, portanto, este bit vale 1. Testa-se o próximo bit, ou seja, a tensão de entrada é maior do que 3,75V (2,5V + 1,25V)? Não,

portanto, este bit é 0. Testa-se o próximo bit, ou seja, a tensão de entrada é maior do que 3,125V (2,5V + 0,625V)? Sim,

portanto, este bit é 1. Finalmente testa-se o bit menos significativo, ou seja, a tensão de entrada é maior do que 3,4375V

(2,5V + 0,625V + 0,3125V)? Não, portanto, este bit é 0 e o valor final da conversão em binário é 1010. Essa forma de conversão é muito rápida, pois veja que para um conversor de n bits são necessárias n

interações, independente do valor a ser convertido. Em termos de hardware (diagrama de blocos), esse tipo de conversor pode ser representado por:

Recursos do PIC

Vamos agora estudar os modos de operação do conversor interno do PIC 18F4520, conhecendo seus recursos e os registradores de configuração e trabalho.

A primeira coisa que precisamos saber são as características desse conversor: • Conversor interno de 10 bits, dando um total de 1024 pontos;

• Até oito canais de conversão, com diversas configurações entre analógicos e digitais;

• Quatro tipos de referência: VDD (interna), VSS (interna), VREF+ (externa) e VREF- (externa);

• Freqüência de conversão baseada no clock da máquina ou em RC dedicado, possibilitando o funcionamento em modo SLEEP;

• Três ajustes de freqüência (divisores) para o clock de máquina;

• Dois tipos de justificação para o resultado da conversão: direita e esquerda;

• Um interrupção para término da conversão. Bem, agora que já sabemos o resumo dos recursos analógicos do nosso PIC, aprenderemos a utilizá-

los.

Page 101: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 99

O primeiro conceito que deve ser entendido é que apesar do microcontrolador possuir diversos canais analógicos, internamente só existe um sistema de conversão. Por isso, somente um canal pode ser utilizado de cada vez. Vamos começar, então, aprendendo como configurar os canais corretamente.

Inicialmente devemos definir, conforme as necessidades do nosso projeto, qual a quantidade de canais analógicos que serão necessários. Como este PIC possui até oito canais analógicos, podemos utilizar todos ou só parte deles, deixando os demais pinos configurados como I/Os digitais. O problema é que, infelizmente, não é possível configurar individualmente cada canal, conforme nosso desejo. Existem valores padrões de configuração que devem ser respeitados.

Para configurarmos os canais analógicos precisamos alterar o valor dos bits existentes em ADCON1<PCFG3:PCFG0>:

PCFG3: PCFG0

AN11RB7

AN10 RB6

AN9 RB5

AN8RB4

AN7RE2

AN6RE1

AN5RE0

AN4RA5

AN3 RA3

AN2 RA2

AN1 RA1

AN0 RA0

0000 A A A A A A A A A A A A 0001 A A A A A A A A A A A A 0010 A A A A A A A A A A A A 0011 A A A A A A A A A A A A 0100 D A A A A A A A A A A A 0101 D D A A A A A A A A A A 0110 D D D A A A A A A A A A 0111 D D D D A A A A A A A A 1000 D D D D D A A A A A A A 1001 D D D D D D A A A A A A 1010 D D D D D D D A A A A A 1011 D D D D D D D D A A A A 1100 D D D D D D D D D A A A 1101 D D D D D D D D D D A A 1110 D D D D D D D D D D D A 1111 D D D D D D D D D D D D

Pinos configurados como analógicos: A=Analógico / D=Digital.

Além da configuração dos pinos analógicos, conforme tabela apresentada, não pode ser esquecido de

configurar corretamente os registradores TRISA e TRISE, de forma que os canais utilizados estejam ajustados para entrada (TRIS = 1). Caso um canal analógico esteja como saída, o sistema de conversão continuará funcionando, mas os valores convertidos serão equivalentes aos níveis alto (1 = VDD) e baixo (0 = VSS).

Outro ponto importante a ser observado nesta tabela diz respeito às tensões de referência. A conversão sempre será feita comparando-se a tensão no pino em relação as tensões de referência VREF+ e VREF-. Desta forma, quando a tensão de entrada for igual à tensão VREF+, a conversão resultará no valor máximo (1024) e quando a tensão de entrada for igual à VREF-, então o resultado da conversão será zero (0). Como já foi dito anteriormente, podemos ter quatro tipos de referências, sendo duas internas (VSS e VDD) , e duas externas, ligadas aos pinos RA2 (VREF-) e RA3 (VREF+).

Para configurarmos os canais analógicos AN2 e AN3, como entrada de tensão de referência precisamos alterar o valor dos bits existentes em ADCON1<VCFG1:VCFG0>:

VCFG1:VCFG0 VREF+ VREF-

0 0 VDD VSS 0 1 AN3 VSS 1 0 VDD AN2 1 1 AN3 AN2

Nossa entrada analógica poderá operar, por exemplo, com uma tensão variável de 0 a 5V. Para isso

podemos utilizar as referências internas como VREF+ = VDD(5V) e VREF- = VSS(0V). Em uma outra aplicação, nosso sensor pode variar de 1 a 4V. Para que não percamos resolução do A/D, podemos trabalhar com tensões de referência externas: VREF+ (RA3) = 4V e VREF- (RA2) = 1V. O importante é respeitarmos os limites elétricos impostos a essas referências:

Page 102: Apostila Mosaico Pic MÓDULO4

100

Referência Mínimo (V) Máximo (V)VREF+ VDD − 2,5 VDD + 0,3 VREF- VSS − 0,3 VREF+ −2,0

(VREF+ − VREF- ) 2,0 VDD + 0,3 O próximo ponto a ser aprendido diz respeito à velocidade e, conseqüentemente, aos tempos, de

amostragem para a conversão A/D. Vamos começar entendendo como o sistema de conversão funciona internamente.

Para evitarmos problemas de ruído e variações da entrada analógica durante o processo de conversão (não podemos esquecer que nada é absolutamente instantâneo), o PIC utiliza internamente um processo denominado Sample and Hold (S/H). Esse nome poderia ser traduzido como amostra e congela. Mas como isso é feito? Muito simples. Internamente o PIC possui um capacitor (120pF) que é ligado ao canal analógico em uso. Sendo assim, ele fica carregado com a tensão existente no canal (amostra). Quando o processo de conversão é iniciado, este capacitor é desligado, automaticamente, do canal analógico, mantendo a tensão sobre o capacitor constante (congela). Por isso, durante todo o processo de conversão, a tensão utilizada é a existente no capacitor e não mais a do canal analógico. Mesmo que a tensão externa no canal varie, a conversão não será afetada.

Agora que já sabemos como o sistema funciona no âmbito do hardware, vamos conhecer quais são os tempos a serem respeitados de forma a não gerarmos erros durante a conversão. Para ilustrar o processo, mostraremos um gráfico resumido dos tempos de conversão:

Conforme o gráfico mostrado, podemos agora analisar cada um dos tempos envolvidos no sistema de

conversão:

Código Nome A Adequação do capacitor

B Desligamento do capacitor

C Conversão

D Religamento do capacitor

E Nova adequação do capacitor

Adequação do capacitor Internamente o capacitor nunca fica desligado, exceto durante a conversão. Ele sempre encontra-se

ligado ao sistema de entradas analógicas. Mas imaginemos que no momento o canal ativo esteja ligado ao GND. Desta forma o capacitor estará totalmente descarregado. No momento seguinte desejamos medir uma outra entrada analógica (outro canal) e por isso o sistema será chaveado internamente (veremos como isso é possível mais à frente). Caso o outro canal esteja com uma tensão de 5V, o capacitor interno terá que ser completamente carregado antes que possamos começar a efetuar a conversão. Obviamente essa carga não será instantânea. Para evitar problemas, sugerimos que o tempo padrão deixado para garantir a carga do capacitor seja de pelo menos 40 µs. Obviamente, este é um tempo que garante a pior condição. Na verdade, o tempo de adequação pode ser bem menor que isso, chegando no mínimo a 10 µs. Essa variação depende basicamente da diferença de tensão entre a entrada e o capacitor, da temperatura e da impedância de entrada. Essa impedância deve ser de no mínimo 50Ω e no máximo 10 kΩ. Quanto menor a impedância, menor também o tempo de adequação. Para o cálculo exato desse tempo, consulte o data sheet do PIC.

Page 103: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 101

Desligamento do capacitor Depois de iniciada a conversão, o capacitor será desligado internamente. Isso é feito em

aproximadamente 100ns, sendo um valor práticamente desprezível.

Conversão O tempo de conversão já não é tão desprezível assim. Para entendermos o tempo de conversão,

precisaremos entender melhor a freqüência de trabalho do A/D. Para que o sistema de conversão funcione corretamente, um clock deve ser aplicado a ele. Cada período deste clock será chamado de TAD e é equivalente ao tempo de conversão de 1 bit. Como nosso conversor é de 10 bits, o tempo total da conversão será de 11 TAD + 2 TAD. Os dois períodos adicionais são para a adequação e o início da conversão. O valor de TAD dependerá da freqüência empregada, e para isso o sistema possui um RC interno ou divisores para o oscilador da própria máquina, mas veremos isso mais adiante. Assim sendo, o tempo de conversão é 13 TAD.

Religamento do capacitor Ao final da conversão, o valor dos registradores ADRESH e ADRESL de resultado serão atualizados, o

flag da interrupção será marcado é o capacitor será religado. O tempo mínimo recomendado para que tudo isso aconteça é de 2 TAD.

Nova adequação do capacitor Durante o tempo da conversão, o valor da tensão no capacitor interno não foi alterado; porém, ao

término da conversão ele será religado à entrada analógica, que pode ter sofrido uma variação brusca (como no exemplo), seja por imposição do próprio sistema, seja por uma troca de canal. Por isso, entre uma conversão e outra é necessário uma nova adequação da carga do capacitor. Recomendamos novamente um tempo de 40µs. As observações do item "Adequação do capacitor" também são válidas aqui para a diminuição deste tempo. O hardware de sample and hold requer 1,4us para atualizar o capacitor.

Este microcontrolador nos permite ajustar o tempo de aquisição por hardware, caso você queira escolher um tempo de aquisição maior basta configurar os bits ADCON0<ACQT2:ACQT0>, em 000.

Pode ajustar o tempo de aquisição utilize os bits ADCON0<ACQT2:ACQT0>:

ACQT2 ACQT1 ACQT0 Tempo de aquisição

0 0 0 0 TAD(1) 0 0 1 2 TAD 0 1 0 4 TAD 0 1 1 6 TAD 1 0 0 8 TAD 1 0 1 12 TAD 1 1 0 16 TAD 1 1 1 20 TAD

Nota: 1 – Tempo a ser definido por software Agora que já entendemos um pouco mais as características e conceitos do A/D, vejamos como

realmente devemos proceder para operar com ele. Depois de ter configurado quais serão os canais utilizados (ADCON1 e TRIS), teremos que configurar

também a freqüência de trabalho. Para isso devemos ajustar 2 bits em ADCON0<ADCS2:ADCS0>:

ADCS1 ADCS1 ADCS0 Freqüência 0 0 0 FOSC / 2 0 0 1 FOSC / 8 0 1 0 FOSC / 32 0 1 1 RC Interno 1 0 0 FOSC / 4 1 0 1 FOSC / 16 1 1 0 FOSC / 64 1 1 1 RC Interno

Page 104: Apostila Mosaico Pic MÓDULO4

102

Para os três primeiros ajustes, o freqüência de trabalho do A/D será a freqüência do oscilador externo do PIC (FOSC) dividida por uma das opções (2, 4, 8, 16, 32 ou 64). Desta forma, obteremos o valor de TAD. Por exemplo, para um cristal externo de 4MHz e uma opção de FOSC / 8 teremos:

TAD = 8 / 4.000.000

TAD = 0,000002s ou 2µs

Neste caso, nosso TAD é de 2µs. O importante na escolha do cristal e da opção de divisão da freqüência é respeitar os valores mínimos de TAD aceitos pelo PIC. No caso do PIC 18F4520 (Standard) este valor deve ser maior que 0,7µs. Valores muito altos para o TAD também não são muito aconselháveis, e por isso recomendamos que não seja ultrapassado o limite de 25µs.

Continuando com o exemplo dado, chequemos então a freqüência máxima de amostragem para a comutação entre canais:

Desconsiderando-se o tempo de desligamento (desprezível), teríamos um tempo total para a conver-são

de 68µs (40 + 24 + 4). Sendo assim, nossa freqüência de amostragem máxima seria de 14,7 kHz. A última opção de escolha para o clock do A/D refere-se a um RC interno dedicado para essa finalidade.

Neste caso o valor nominal para TAD é de 1µs. Esta opção pode ser utilizada para que o sistema de conversão continue funcionando mesmo em modo SLEEP. Na verdade, este RC pode ser usado a qualquer momento, mas é recomendado que para sistemas que operem com freqüências superiores a 4 MHz este oscilador seja usado somente no modo SLEEP.

A última configuração necessária quanto às características de funcionamento do A/D diz respeito à forma como o resultado será armazenado nos registradores específicos. Como a conversão gera um resultado de 10 bits, serão necessários dois registradores para armazenar este valor. Para isso existem os registradores ADRESH e ADRESL, equivalentes à parte alta e à parte baixa do resultado. Acontece que a soma desses dois registradores resultam em 16 bits. Por isso, o resultado pode ser armazenado neles justificando pela esquerda ou direita. O bit de configuração ADCON1<ADFM> ajusta esta orientação:

ADFM Freqüência

1 Justificado pela direita. Utiliza todos os bits de ADRESL<7:0> e somente 2 bits de ADRESH<1:0> 0 Justificado pela esquerda. Utiliza todos os bits de ADRESH<7:0> e somente 2 bits de ADRESL<7:6>

Essa justificação é válida quando queremos, por exemplo, trabalhar com somente 8 bits do conver-sor.

Neste caso, podemos justificar pela esquerda e acessarmos somente a parte mais significativa através de ADRESH. Com isso estaremos criando um filtro, onde jogamos fora os 2 bits menos signifi-cativos, que se encontram em ADRESL.

Agora que os ajustes da configuração já foram feitos, podemos finalmente efetuar uma conversão. Comecemos ligando o sistema de conversão. Isso é feito através de ADCON0<ADON>:

ADON Estado do A/D 0 Sistema desligado 1 Sistema ligado

O sistema pode ser mantido desligado sempre que não estiver sendo utilizado para redução do

consumo. A próxima ação é a escolha do canal a ser utilizado, entre os oito disponíveis. Essa escolha será feita

através de ADCON0<CHS3:CHS0>:

Page 105: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 103

CHS3:CHS0 Canal Selecionado CHS3: CHS0 Canal Selecionado 0000 Canal 0 1000 Canal 8 0001 Canal 1 1001 Canal 9 0010 Canal 2 1010 Canal 10 0011 Canal 3 1011 Canal 11 0100 Canal 4 1100 Canal 12 0101 Canal 5 1101 Não implementado 0110 Canal 6 1110 Não implementado 0111 Canal 7 1111 Não implementado

O último passo é iniciar a conversão por meio do bit ADCON0<GO/DONE>:

GO/DONE Estado do A/D 1 Inicia a conversão

0 Indica que a conversão términou. Caso seja forçado manualmente, cancela a conversão atual.

Depois de iniciada a conversão, todo o processo será executado. O capacitor interno é desconectado. A

conversão é efetuada (12 TAD) e logo em seguida (no próximo ciclo de máquina), os registradores ADRESH e ADRESL são atualizados. Neste momento, o bit ADCON0<GO/DONE> volta automaticamente para 0 (zero) e poder ser monitorado pelo programa para checar o término da conversão. Além disso, o flag da interrupção PIR1<ADIF> também é ativado. Caso a conversão seja abortada manualmente através de ADCON0<GO/DONE>=0, os registradores ADRESH e ADRESL não serão alterados.

Para fazer uso da interrupção de A/D, não se esqueça de efetuar os seguintes ajustes antes de iniciar a conversão:

• Limpar o flag PIR1<ADIF>=0;

• Ligar a interrupção de A/D em PIE1<ADIE>=1;

• Ligar as interrupções de periféricos em INTCON<PEIE>=1;

• Ligar a chave geral das interrupções em INTCON<GIE>=1;

Resumo dos registradores associados ao A/D Endereço Nome Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0

0Bh INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF Och PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF 8Ch PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE 1Eh ADRESH Resultado da conversão (Parte alta) 9Eh ADRESL Resultado da conversão (Parte baixa) 1Fh ACON0 ADCS1 ADCS0 CHS2 CHS1 CHS0 GO/DONE - ADON 9Fh ADCON1 ADFM - - - PCFG3 PCFG2 PCFG1 PCFG0 85h TRISA - - Configuração do PORTA como Entrada(1) ou Saída(0)

89h TRISE IBF OBF IBOVPSP

MODE - Configuração do PORTE como

Entrada(1) ou Saída(0)

Page 106: Apostila Mosaico Pic MÓDULO4

104

Capítulo 13 - Módulo MSSP

Introdução

Neste capítulo começaremos o estudo de um assunto muito procurado pelos profissionais atuais: a comunicação serial. Dissemos que estaremos começando o estudo porque o PIC possui tantos recursos voltados a ele que utilizaremos dois capítulos para completá-lo. Nesta primeira parte, estudaremos dois tipos distintos de comunicação serial, denominados SPI e I2C. Esses protocolos poderão ser utilizados para a comunicação do PIC com outros microcontroladores, com memórias externas, drives de LCD, conversores, sensores e uma infinidade de outros periféricos.

Os dois protocolos mencionados (SPI e I2C) fazem parte de um sistema comum do PIC denominado MSSP (Master Synchronous Serial Port). Como esse sistema é comum, ele compartilha os mesmos recursos (pinos, hardware internos e registradores) entre os dois casos. Por isso só podemos utilizar um sistema de cada vez. Eles serão estudados separadamente.

Comecemos, então, conhecendo as diferenças e semelhanças básicas entre eles:

SPI I2C

Foi criado pela Motorola e seu nome significa: Serial Peripherall Interface

Foi criado pela Philips e seu nome significa: Inter-Integrade Circuit

Opera em modo Master e Slave Opera em modo Master e Slave Comunicação síncrona (com Clock) Comunicação síncrona (com Clock) A comunicação é feita por três vias: Clock (SCK) Data In (SDI) Data Out (SDO)

A comunicação é feita por duas vias: Clock (SCL) Data In/Out (SDA)

Não endereçável Endereçável (7 ou 10 bits) 8 bits de dados 8 bits de dados

Teoria e recursos do PIC para SPI

Antes de mais nada precisamos saber alguns conceitos básicos sobre a comunicação serial síncrona. Como o próprio nome diz, essa comunicação exige uma via de sincronismo entre os dois componentes envolvidos (receptor e transmissor) para que haja a marcação do momento exato da transmissão/recepção de cada bit. Isso é feito através do clock, que nada mais é que uma onda quadrada para sincronizar o sistema. Acontece que só pode existir um clock, e por isso não podemos deixar ambos os lados da comunicação responsáveis por ele. Para resolver esse problema foi criado o conceito de Master e Slave. O componente denominado Master (Mestre) será responsável pelo controle da comunicação, gerando o clock de sincronismo. Do outro lado, o componente será denominado Slave (Escravo) e ficará sempre aguardando o clock enviado pelo mestre.

Como a SPI não permite o endereçamento, a comunicação só pode ser feita entre dois pontos, sendo um deles o Master e o outro o Slave.

Como podemos observar na tabela comparativa apresentada anteriormente, neste modo de comunicação a ligação entre os componentes deve ser feita através de três vias:

Clock: Trata-se da via de clock, que pode ser uma entrada (Slave) ou saída (Master). O SPI aceita os

quatro tipos de clocks diferentes especificados para o padrão SPI. A descrição e a configuração desses tipos será vista posteriormente. No PIC 18F4520 é chamado de SCK e está localizado no pino 18 (RC3);

Data In: Trata-se da entrada de dados, ou seja, a via de recepção. No PIC 18F4520 é chamada de SDI e está localizada no pino 23 (RC4);

Data Out: Trata-se da saída de dados, ou seja, a via de transmissão. No PIC 18F4520 é chamada de SDO e está localizada no pino 24 (RC5);

O próximo diagrama mostra a ligação entre dois componentes, que podem, por exemplo ser dois PICs:

Page 107: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 105

O PIC do lado esquerdo é o Master e, por isso, é responsável pela geração do clock. Seu pino SCK deve

ser configurado como saída. Já do lado direito o PIC é definido como Slave, ficando o pino de clock configurado como entrada.

Através do diagrama podemos também começar a entender melhor o funcionamento interno do SPI. Esse protocolo de comunicação trabalha com um registrador interno (não acessível) denominado SSPSR. Esse registrador é do tipo rotativo (Shift Register). A cada ciclo do clock, um bit é lido da porta SDI é escrito nesse registrador, entrando pelo bit menos significativo e rotacionando todos os bits para a esquerda. Ao mesmo tempo, o bit mais significativo é enviado para a porta SDO. Por isso, enquanto estamos recebendo um byte estamos também transmitindo outro. O registrador SSPBUF é o responsável pelo valor a ser transmitido e também pelo byte recebido.

A comunicação funciona então da seguinte maneira: 1. Quem manda na comunicação é o Master. Por isso, um valor qualquer é escrito no registrador

SSPBUF deste PIC. 2. O valor então é movido para o registrador SSPSR. 3. Em seguida oito pulsos são gerados na saída de clock SCK (cada pulso transmite 1 bit). 4. Ao término dos oito pulsos o valor que estava no SSPSRMaster é trocado com o valor que estava

SSPSRSlave. 5. Tanto de um lado quanto do outro o valor de SSPSR é então movido novamente para o registrador

SSPBUF. 6. Também de ambos os lados flags são ativados para informar ao sistema o fim da comunicação. Os

dados podem então ser acessados novamente em SSPBUF. Bem simples não é mesmo? Desta forma, a comunicação é feita sempre em sentido duplo, ao mesmo

tempo. Desta forma, três tipos diferentes de situações podem acontecer: • Master envia dado válido / Slave envia dado não-válido: Neste caso o Master está enviando

algum dado para o Slave; porém não interessa a informação que é enviada pelo Slave neste mesmo momento. É muito comum quando o Master está fazendo uma pergunta ao Slave, que terá de ser processada antes da resposta ser transmitida de volta. Neste caso, o dado recebido pelo Master ao final da transmissão deve ser descartado.

• Master envia dado não válido / Slave envia dado válido: Este caso é complementar ao anterior. Depois que o Master efetuou uma pergunta e o Slave a processou, uma resposta deverá ser retornada. Acontece que como é o Master quem manda no clock, ele precisará disparar uma nova transmissão para poder receber o dado do Slave.

• Master envia dado válido / Slave envia dado válido: Pode ser o caso mais raro, mas é usado para

aumento da velocidade. Por exemplo: o Master faz uma pergunta e ao mesmo tempo recebe a resposta da pergunta anterior.

Obviamente, apesar do sistema de comunicação ser de transmissão e recepção ao mesmo tempo, nem

sempre isso é necessário. Caso a comunicação seja em um só sentido, a via de transmissão do Slave (SDO) pode ser desativada configurando-se esse pino como entrada, a recepção do Master (SDI) sem uso.

Page 108: Apostila Mosaico Pic MÓDULO4

106

Existe também um outro pino denominado /SS (RA5) que pode ser usado do lado Slave. Na maioria dos casos, este pino é opcional e serve como um sinal de Chip Select. Sua função é muito simples, quando este pino está em nível baixo (0), o sistema de comunicação funciona normalmente, com o pino SDO funcionando como saída de dados a cada pulso do clock. No entanto, se este pino for colocado em nível alto (1), o sistema de comunicação é desligado e o pino SDO fica flutuante. Com este recurso podemos montar uma rede de comunicação com um Master e vários Slaves, desde que o Master controle individualmente os pinos /SS de cada um dos Slaves. Este controle terá de ser implementado manualmente no software e deve garantir que somente um Slave está ativado de cada vez, evitando conflitos nas saídas SDO.

Quando configurado para Master, o pino /SS opera como um I/O normal (RA5).

Vejamos agora como configurar corretamente o sistema para efetuar uma transmissão. A primeira coisa a ser feita diz respeito à configuração correta dos pinos, como entradas ou saídas:

Pino Configuração SDI Este pino é configurado automaticamente pelo sistema como entrada. SDO Este pino deve ser configurado manualmente como saída através do TRISC.

SCK Este pino deve ser configurado como saída no Master e entrada do Slave, através do TRISC.

/SS Quando habilitado no Slave, deve ser configurado manualmente como entrada.

Depois devemos configurar a comunicação como sendo Slave ou Master. Existe mais de uma opção

para cada tipo, devendo ser configuradas em SSPCON<SSPM3:SSPM0>:

SSPM3: SSPM0

Descrição

0000 SPI Master, com clock = FOSC / 4 0001 SPI Master, com clock = FOSC / 16 0010 SPI Master, com clock = FOSC / 64 0011 SPI Master, com clock = TMR2 / 2 0100 SPI Slave, com /SS habilitado 0101 SPI Slave, com /SS desabilitado.

Obs: As demais opções de configurações dizem respeitos aos outros modos (I2C).

As quatro primeiras opções dizem respeito à escolha do modo Master, cada uma com uma freqüência diferente para o clock. Nas três primeiras, o clock é uma divisão (4, 16 ou 64) da freqüência do oscilador do próprio PIC. Com isso, podemos deduzir que na freqüência máxima de 20 MHz nossa taxa de transmissão é de 5,0Mbps. Na outra opção, o clock é gerado com base na metade do TMR2. Assim, a base de tempo será PR2 / 2. O postscale não é usado para este caso.

As duas últimas opções devem ser escolhidas quando estamos configurando um PIC em modo Slave. Neste caso devemos escolher entre trabalhar ou não com o pino /SS. Mais para a frente será comentado um caso em que a ativação deste pino é obrigatória.

Outra configuração ajusta a condição de recebimento. Assim, o sistema pode efetuar a leitura da porta SDI em dois pontos distintos, conforme o valor imposto em SSPSTAT<SMP>:

Page 109: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 107

SMP Descrição

0 A recepção é feita na borda do meio do período. Pode ser usada tanto no Master quanto no Slave.

1 A recepção é feita na borda do final do período. Só pode ser usada no Master.

O próximo passo diz respeito à escolha da forma de onda do clock. O padrão SPI disponibiliza quatro

opções que podem ser ajustadas em dois bits distinto, SSPCON<CKP> e SSPSTAT<CKE>:

CKP Descrição 0 Clock normalmente em nível baixo (0) 1 Clock normalmente em nível alto (1)

CKE Descrição

0 Pulso do clock no começo do período 1 Pulso do clock no final do período

Graficamente fica muito mais fácil percebermos as diferenças entre os quatro modos resultantes da

combinação desses 2 bits:

Para o Master não existe limitação quanto ao uso de qualquer um dos quatro tipos. Para o Slave, a

questão é um pouco mais complicada. Como os pinos de clock estão diretamente ligados, então o valor padrão da via (nível alto ou baixo) deve

ser o mesmo. Desta forma o valor de CKP para o Slave deve ser obrigatoriamente o mesmo adotado para o Master.

O outro problema está em relação à transmissão/recepção do dado pelo Slave. Para o Master, o primeiro bit (o mais significativo) é colocado em SDO logo depois do começo do período, permanecendo lá até o final do mesmo. Desta forma, podemos considerar que o bit é transmitido no meio do período. Como ele sabe o momento exato de início do período, fica fácil também controlar a leitura da entrada SDI (no começo ou no fim). Para o Slave entretanto, um problema acontece quando CKE=1, pois não há como ele saber o início do período uma vez que não existe nenhuma borda neste ponto. Por esse motivo, para utilizarmos o Slave com CKE=1, obrigatoriamente teremos que habilitar o pino /SS. Quando o pino de /SS for colocado em nível baixo, o primeiro bit é colocado em SDO (até este momento ele estava flutuante) e o sistema fica aguardando o clock para dar continuidade na transmissão. Quanto à recepção, como o Slave só pode operar com leitura no meio do período (SMP=0), a entrada SDI será lida logo na primeira borda do clock.

Para ligar a comunicação SPI, basta ativar o sistema SSP através do bit SSPCON<SSPEN>:

SSPEN Descrição 0 Desabilita a comunicação.

1 Habilita a comunicação. Neste momento, os pinos SCK, SDO, SDI e em alguns casos o /SS, deixam de operar como I/Os convencionais.

Page 110: Apostila Mosaico Pic MÓDULO4

108

Por último, basta escrever o dado que se deseja transmitir no registrador SSPBUF. Se isso for feito no

Master, a transmissão será iniciada imediatamente após a escrita. Para o Slave, o sistema ficará aguardando o clock. No término dos oito pulsos do clock, o dado terá sido enviado do Master para o Slave e vice-versa, como já explicado. Os registradores SSPBUF serão, então, atualizados e o flag SSPSTAT<BF> indicará que o buffer está cheio:

BF Descrição 0 Recebimento em operação. SSPBUF está vazio.1 Recebimento terminado. SSPBUF carregado.

Esse bit é limpo automaticamente toda vez que o registrador SSPBUF é lido, indicando que o programa

já processou a informação recebida. Neste mesmo momento o bit da interrupção PIR1<SSPIF> é ativado. A interrupção só acontecerá no

caso das suas chaves estarem ligadas. Caso seja escrito outro valor em SSPBUF antes do término da transmissão/recepção, ele será ignorado,

não afetando a operação. Entretanto, um bit será setado informando uma colisão de informações. Este bit é denominado SSPCON<WCOL> e deve ser limpo manualmente pelo programa. Por outro lado, caso o Slave receba um novo valor antes do SSPBUF ser lido (BF=1), este novo valor será perdido e o flag de overflow será ativado (SSPCON<SSPOV>=1). Este bit também deve ser limpo manualmente. Para o Master este flag não possui função.

Quanto ao modo SLEEP, o resultado é diferente quando aplicado ao Master ou ao Slave. No caso do Master, a comunicação será completamente interrompida, pois não é possível a geração do clock sem o oscilador estar funcionando. Por outro lado, para o Slave, a comunicação continuará funcionando e o PIC poderá acordar caso a interrupção de SSP esteja ligada.

Resumo dos registradores associados a SPI

Endereço Nome Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 0Bh ... INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF OCh PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF 8Ch PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE 94h SSPSTAT SMP CKE D/A P S R/W UA BF 14h SSPCON WCOL SSPOV SSPEN CKP SSPM3 SSPM2 SSPM1 SSPM0 13h SSPBUF Buffer de transmissão / recepção

Page 111: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 109

Teoria para I2C

O padrão de comunicação I2C possui características bem diferentes do SPI. Isso o torna muito mais poderoso, mas, em contrapartida, muito mais complexo também. Vejamos, então, suas principais características:

• Este protocolo continua com o conceito de Master/Slave, entretanto ele permite o endereçamento de

diversos pontos da rede por meio das próprias vias de comunicação. Com isso podemos ter um Master com diversos Slaves sem necessitarmos de pinos de controle adicionais. Na verdade, é possível também a estruturação de uma rede com diversos Mestres;

• A comunicação é feita somente em duas vias: Clock e Data. Como também se trata de uma comunicação síncrona, a via de clock continua sendo indispensável. Quanto aos dados, eles transitam em uma única via, tanto para a transmissão quanto para a recepção;

• Tanto o Master quanto o Slave podem transmitir e receber dados, mas o controle é sempre do Máster;

• Para evitar conflitos na via de dados (SDA), os pinos são chaveados como entrada ou saída (impõe somente o nível baixo, forçando o GND), conforme a necessidade imposta pelo protocolo. Por esse fato, um resistor de pull-up é necessário, sendo recomendado valores de 10kΩ a 1kΩ. Os valores mais baixos (até 1kΩ) podem ser necessários para velocidades muito elevadas ou uma rede com muitos periféricos;

• O clock (SCL) continua sendo totalmente controlado pelo Mestre. Acontece que, nesse protocolo, pelo compartilhamento de uma única via de dados e pela possibilidade de mais de um Mestre, o clock necessário para a resposta do Escravo deve ser dado no momento correto, evitando conflitos no processamento da informação. Para que isso seja possível, a via de clock também é alterada como entrada e saída (impõe somente o nível baixo, forçando o GND) durante a transmissão, ficando em determinados momentos em um estado flutuante. Por isso, é necessário que esta linha possua um resistor de pull-up para evitar esse estado flutuante e não gerar problemas no protocolo. Este resistor deve ser de 10kΩ a 1kΩ, adotando-se os valores mais baixo quando a velocidade de transferência é maior. O detalhamento deste funcionamento será visto mais à frente;

• Fica claro, então, que o valor padrão tanto para SCL quanto para SDA é o nível alto(1), com esses pinos em alta impedância (entradas). Aproveitamos para comentar também que os bits são lidos sempre da borda de descida do SCL;

• Além desse protocolo permitir a especificação do endereço, existem dois modos diferentes para que isso seja feito: 7 bits ou 10 bits. No primeiro caso é possível acessar até 128 endereços diferentes. Para o segundo caso, este número eleva-se para 1024 endereços.

Com essas explicações básicas, podemos concluir que na comunicação existem quatro situações

distintas do protocolo que teremos de conhecer: • Transmissão do Master / Recepção do Slave, com endereço de 7 bits;

• Recepção do Master / Transmissão do Slave, com endereço de 7 bits;

• Transmissão do Master / Recepção do Slave, com endereço de 10 bits;

• Recepção do Master / Transmissão do Slave, com endereço de 10 bits.

Nas próximas páginas serão mostradas quatro cartas de tempo completas, para cada uma das situações apresentadas. Antes, porém, vamos conhecer alguns outros pontos importantes deste protocolo que aparecerão nos diagramas mencionados.

Page 112: Apostila Mosaico Pic MÓDULO4

110

Condição de Start Trata-se de uma condição especial entre as vias SDA e SCL para informar à rede que uma transmissão

irá começar. Essa condição é controlada pelo Mestre e todos os Escravos podem ficar prontos, esperando um dado ser transmitido. Em rede de Múltiplos Mestres, essa condição serve também para informar aos demais Mestres que a linha está ocupada.

Essa condição é atingida respeitando-se o seguinte diagrama: em que TBRG é o tempo equivalente a um pulso de clock.

Condição de Stop Outro estado especial dos pinos SDA e SCL, com efeito contrário à condição de Start, pois informa a

toda a rede que a transmissão términou, ficando a mesma disponível. Uma condição de Start obriga uma posterior condição de Stop, para que o sistema não fique travado.

Page 113: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 111

Condição de Re-Start É uma condição muito semelhante a de Start, mas que pode ser executada antes do Stop. Isso será

necessário, por exemplo, para a implementação da comunicação com endereço de 10 bits ou nos casos em que precisamos enviar novamente o primeiro byte antes de finalizarmos a comunicação através de um Stop.

Condição de Acknowledge (ACK) Na verdade, isso é uma resposta dada pelo Mestre ou pelo Escravo, no lugar do 9º bit, informando se o

dado foi corretamente recebido ou não. Um acknowledge alto (1) representa um erro, enquanto um acknowledge baixo (0) representa OK. No final de uma transmissão de dados do Escravo para o Mestre, isto é, após o último byte, o Mestre deve sempre responder ACK=1.

Transmissão de endereço Independentemente da informação a ser transmitida (endereço de 7 bits, endereço de 10 bits ou dados

de 8 bits), a comunicação sempre é feita em pacotes de 8 bits e mais um retorno de acknowledge. Desta forma, para cada informação transmitida são necessários nove pulsos no clock. O último bit do primeiro byte não faz parte da informação, pois é utilizado como um flag de marcação para escrita (W-Write) ou leitura (R-Read). Quando o Mestre deseja enviar dados ao escravo, esse bit recebe o valor 0 (zero). Quando ele deseja receber um valor do Escravo, ele começa perguntando com este bit em 1 (um). É por isso que o endereço só comporta 7 bits: são exatamente os sete que sobraram nesse mesmo byte.

Para o endereçamento de 10 bits, será necessária a transmissão inicial de 2 bytes só para o endereço. No primeiro byte, o bit menos significativo continua válido como R/W. Dos outros 7 bits, entretanto, somente dois serão considerados como a parte alta do endereço. Trata-se dos bits 2 e 1. Os bits de 7 a 3 devem ser escritos com o valor 11110. Após a transmissão do primeiro byte, SDA é transformado em entrada para checar o acknowledge ao ser dado o 9º pulso do clock. Se a resposta for afirmativa termos ACK=0.

Para a geração de um pulso no clock, o nível baixo é conseguido impondo-se o aterramento do pino SCL (como se ele fosse uma saída). Em seguida, para o nível alto, desliga-se o aterramento e o nível é conseguido pelo pull-up da linha. Durante todo o tempo do pulso, o pino SCL deve ser monitorado pelo Mestre e, caso ele desça, é porque algum Escravo está pedindo uma pausa no processo. O tempo do clock é, então, paralisado e o Mestre só volta a responder quando a linha de SCL estiver liberada.

Quando o clock estimer liberado, o Mestre irá iniciar a transmissão do segundo byte de endereço. Neste segundo byte estão os 8 bits menos significativos que faltam para completar o endereço de 10 bits. Ao término, um novo ACK será aguardado e conferido.

Transmissão de dados Depois do término da transferência da parte relacionada ao endereço, um dos dois lados (Mestre ou

Escravo) deverá transmitir um ou mais bytes de dados. Caso seja o Escravo que esteja transmitindo para o Mestre, para finalizar a comunicação o Mestre deve responder um ACK=1 ao término do último byte recebido, para só depois enviar uma condição de Stop. Isso se faz necessário para que o Escravo seja informado de que o Mestre não mais deseja receber nenhum dado, evitando conflitos quando a condição de Stop for gerada. Nesta condição o Escravo deve ter sua comunicação paralisada e resetada, ficando no aguardo de uma nova condição de Start. Com isso o protocolo fica mais robusto, evitando erros na contagem do número de bytes enviados.

Page 114: Apostila Mosaico Pic MÓDULO4

112

Pausas Sempre que algum módulo Slave (ou até outro Master) necessitar de uma pausa na comunicação, por

exemplo para processar a informação recebida, ela será conseguida mantendo-se a linha de clock em nível baixo, isto é, em zero.

Diagramas de tempo Os diagramas apresentados nas páginas seguintes demonstram graficamente o protocolo I2C para os

quatro casos possíveis já comentados: 1 Transmissão do Master / Recepção do Slave, com endereço de 7 bits; 2 Recepção do Master / Transmissão do Slave, com endereço de 7 bits; 3 Transmissão do Master / Recepção do Slave, com endereço de 10 bits; 4 Recepção do Master / Transmissão do Slave, com endereço de 10 bits. Em cada um deles são mostradas as informações que trafegam pelas vias de Dados e de Clock. Além disso,

acima e abaixo dos desenhos das formas de onda existem também barras que representam qual dos dois lados está controlando a via. São duas barras para cada pino (SDA e SCL), uma representando o lado do Master e a outra o lado do Slave. Quando a barra está cinza significa que o pino está configurado como entrada e quando a barra está branca é porque o pino está impondo o nível 0 (baixo). Desta forma fica mais fácil visualizarmos o sentido de tráfego da informação:

1 Master para Slave; 2 Slave para Master.

Observando essas barras para o pino de clock (SCL) podemos ver claramente quando o Slave força

pausas na comunicação, impondo o nível baixo (zero) nesta via.

Page 115: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 113

Page 116: Apostila Mosaico Pic MÓDULO4

114

Page 117: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 115

Recursos do PIC para I2C

Agora que as formas gerais do protocolo já estão explicadas, vamos ver como ativar e utilizar esse recurso no PIC 18F4520.

Antes de mais nada, vamos explicar melhor como o PIC controla os pinos SCL e SDA. Como já foi dito na teoria do I2C, para que o protocolo funcione corretamente, evitando conflitos na linha, cada um dos módulos ligados à rede deve somente impor nível baixo (0), sendo o nível alto imposto pelos resistores de pull-up. O hardware interno do PIC respeita essas condições. Para isso, entretanto, é necessário que ambos os pinos (SCL e SDA) sejam configurados inicialmente como entrada através do TRISC, para que os mesmos fiquem em alta impedância, possibilitando que o controle da I2C possa forçar o nível baixo quando necessário. A imposição do GND na linha é feita por intermédio de um transistor interno do tipo N. Este fato possibilita a checagem de colisão de dados na linha SDA, que será explicada posteriormente.

Caso um desses pinos, por exemplo o SCL, seja configurado como saída em nível alto, o sistema poderá continuar funcionando, pois quando a I2C não estiver impondo zero, a própria porta imporá 1. Isso não gerará problemas internos para o PIC, mas poderá gerar problemas de conflito na linha, caso seja utilizado mais de um Master ou caso algum Slave solicite uma pausa através da linha de clock.

Para facilitar o entendimento, dividiremos essas explicações em duas partes: uma dedicada ao Slave e outra ao Master.

Modo Slave Inicie sempre configurando os pinos SCL e SDA como entrada por meio do TRISC. Para configurarmos um PIC para trabalhar em modo Slave, devemos ajustar os bits de

SSPCON<SSPM3:SSPM0>:

SSPM3: SSPM0

Descrição

0110 I2C Slave, endereço de 7 bits. 0111 I2C Slave, endereço de 10 bits.

Obs: As demais opções de configuração dizem respeitos aos outros modos (SPI e I2C Master).

Depois é necessário também ajustar o bit SSPSTAT<SMP> que, neste caso, serve para habilitar um

sistema interno de tratamento das bordas quando operando em freqüência de 400kHz:

SMP Descrição 0 Tratamento desabilitado.

1 Tratamento habilitado, quando usando 400kHz.

O bit SSPSTAT<CKE> serve para configurar o tipo de Smith Trigger utilizado nos pinos SCL e SDA:

CKE Descrição

0 Entradas conforme especificações I2C.

1 Entradas conforme especificações SMBUS.

Por último é necessário ainda habilitar o sistema de comunicação através do bit SSPCON<SSPEN>:

SSPEN Descrição 0 Desabilita a comunicação.

1 Habilita a comunicação. Neste momento os pinos SCL e DAS deixam de operar como I/Os convencionais.

Feito isso, vejamos quais tarefas serão feitas automaticamente e quais deverão ser implementadas pelo

programa. Trataremos separadamente os possíveis casos de transferência de informações.

Page 118: Apostila Mosaico Pic MÓDULO4

116

Recepção para endereçamento de 7 bits

1. Tanto SCL quanto SDA estão em sua configuração padrão, isto é, como entradas. A linha receberá então uma condição de Start.

2. A condição de Start é reconhecida e o bit SSPSTAT<S> é setado; porém nenhuma interrupção acontece.

3. O sistema aguardará, então, um byte com os 7-bits de endereço e mais o bit R/W=0, com oito pulsos de clock. Teremos SSPSTAT<R/W>=0. Como o byte recebido é equivalente a um endereço, então SSPSTAT<D/A>=0.

4. Neste momento, o endereço recebido é comparado automaticamente com o registrador SSPADD. Caso não seja o mesmo, a comunicação do lado Slave é resetada (ACK=1) e o mesmo ficará aguardando um novo Start. Caso o endereço seja idêntico, o bit SSPSTAT<BF> é setado, informando que um valor foi transferido para o buffer (SSPBUF), o pino SDA é transformado automaticamente em saída com nível baixo (ACK=0) e fica aguardando o 9o pulso de clock. Logo depois SDA é liberado, tornando-se novamente entrada. Neste momento também o flag PIR1<SSPIF> é setado e a interrupção pode acontecer (se as chaves estiverem corretamente ligadas). É importante que a interrupção aconteça para que seja feita uma leitura do SSPBUF, forçando novamente BF=0.

5. O sistema aguardará então um byte de dado, com oito novos pulsos de clock. Como agora o byte recebido é equivalente a um dado, então SSPSTAT<D/A>=1. Neste momento, também teremos BF=1 e o dado será colocado em SSPBUF.

6. Mais uma vez o pino SDA impõe um nível baixo para responder ACK=0 no 9º pulso do clock. SDA volta em seguida à condição de entrada.

7. Uma nova interrupção acontece (SSPIF=1) para que o dado recebido possa ser tratado.

8. Novos bytes de dados podem continuar sendo recebidos até que uma condição de Stop seja imposta na linha. Neste momento, a condição será reconhecida, setando o bit SSPSTAT<P> e finalizando a comunicação. A interrupção não é gerada.

9. Caso seja recebido uma condição de Re-Start (entre um Start e um Stop), o Slave ficará esperando um novo byte de endereço, com o R/W, e não mais um byte de dados.

Devido ao buffer duplo de recepção, isto é, o dado entra em SSPSR e depois é colocada em SSPBUF, a

informação recebida, pode então ser lida mesmo durante o recebimento do próximo byte. Depois que lemos SSPBUF, o flag BF é limpo automaticamente. Entretanto, caso o SSPBUF não seja lido antes da nova recepção terminar, o dado mais novo será perdido (SSPBUF não é atualizado) e o bit SSPCON<SSPOV> será setado, indicando um overlflow. SSPOV deve ser limpo manualmente pelo programa. Dependendo das condições de BF e SSPOV, a resposta automática do acknowledge pode ser negativa (ACK=1).

BF SSPOV

Atualiza SSPBUF ACK Interrupção SSPIF=1

0 0 Sim 0 (Ok) Sim 1 0 Não 1 (Erro) Sim 1 1 Não 1 (Erro) Sim

0 (Nota) 1 (Nota) Sim 1 (Erro) Sim Nota: Esta condição representa um erro de programação, pois o SSPBUF foi limpo e o bit de SSPOV não.

Transmissão para endereçamento de 7-bits

1. Tanto SCL quanto SDA estão em sua configuração padrão, isto é, como entradas. A linha receberá, então, uma condição de Start;

2. A condição de Start é reconhecida e o bit SSPSTAT<S> é setado; porém nenhuma interrupção acontece;

3. O sistema aguardará então um byte com os 7-bits de endereço e mais o bit R/W=1, com oito pulsos de clock. Teremos SSPSTAT<R/W>=1. Como o byte recebido é equivalente a um endereço, então SSPSTAT<D/A>=0;

Page 119: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 117

4. O endereço recebido é comparado automaticamente com o registrador SSPADD. Caso não seja o mesmo, a comunicação do lado Slave é resetada (ACK=1) e o mesmo ficará aguardando um novo Start. Caso o endereço seja idêntico, o pino SDA é transformado automaticamente em saída com nível baixo (ACK=0) e o sistema aguarda o 9º pulso de clock. Logo depois SDA é transformado novamente em entrada;

5. O sistema automaticamente altera SSPCON<CKP>=0, desabilitando o clock (pausa). Isso é feito impondo-se nível baixo (0) em SCL (saída);

6. O flag PIR1<SSPIF> é, então, setado e a interrupção pode acontecer (se as chaves estiverem corretamente ligadas). É importante que a interrupção aconteça para que seja escrito o valor a ser transmitido em SSPBUF, o que irá fazer com que BF=1;

7. Depois do buffer atualizado, para que a comunicação proceda, basta impor CKP=1. Neste momento, SCL será novamente liberado (entrada);

8. O clock será liberado e o byte existente em SSPBUF será enviado nos próximos oito pulsos. Ao término teremos BF=0;

9. Mais uma vez o pino SDA fica aguardando um ACK no 9º pulso do clock. Caso seja recebido um ACK=1 é porque a comunicação será encerrada, sendo aguardada, então, uma condição de Stop. Neste momento a condição será reconhecida, setando-se o bit SSPSTAT<P> e finalizando-se a comunicação. A interrupção não é gerada. Caso ACK=0, o sistema volta ao item 5 para que um novo byte de dado seja transmitido;

10. Durante a transferência de dados não pode acontecer uma situação de Re-Start. Para reiniciar completamente o sistema é necessário terminar a transferência com um ACK=1 por parte do Master, seguido de um Stop. Só então uma nova condição de Start poderá ser gerada;

Caso tente-se escrever um valor em SSPBUF enquanto uma transmissão está em progresso (BF=1) o valor

de SSPBUF não será atualizado e o bit SSPCON<WCOL> será setado, indicando uma colisão na escrita. Este bit deve ser limpo manualmente pelo programador.

Recepção para endereçamento de 10 bits

1. Tanto SCL quanto SDA estão em sua configuração padrão, isto é, como entradas. A linha receberá, então, uma condição de Start;

2. A condição de Start é reconhecida e o bit SSPSTAT<S> é setado; porém nenhuma interrupção acontece;

3. O sistema aguardará então um byte com os 2-bits de endereço (A9:A8) e mais o bit R/W=0, com oito pulsos de clock. Teremos, então, SSPSTAT<R/W>=0. Como o byte recebido é equivalente a um endereço, teremos também SSPSTAT<D/A>=0;

4. Neste momento o endereço recebido é comparado automaticamente com o registrador SSPADD. Caso não seja o mesmo, a comunicação do lado Slave é resetada (ACK=1) e o mesmo ficará aguardando um novo Start. Caso esta parte do endereço esteja correta, o bit SSPSTAT<BF> é setado, informando que um valor foi transferido para o buffer (SSPBUF) e teremos SSPSTAT<UA>=1, indicando que o endereço deve ser atualizado. O pino SDA é transformado automaticamente em saída com nível baixo (ACK=0) e fica aguardando o 9º pulso de clock. Logo depois, SDA é transformado novamente em entrada. Neste momento, o flag PIR1<SSPIF> é setado e a interrupção pode acontecer (se as chaves estiverem corretamente ligadas). É importante que a interrupção aconteça para que seja feita uma leitura do SSPBUF, forçando novamente BF=0. O registrador SSPADD deve, então, ser atualizado com a parte baixa do endereço (A7:A0), o que forçará automaticamente UA=0. Depois do ACK e até o momento em que o SSPADD é atualizado, o Slave trava a comunicação (pausa) impondo um nível baixo (0) em SCL. Este controle é totalmente automático;

5. Será aguardado, então, um byte com a segunda parte do endereço (A7:A0), para os próximos oito pulsos do clock. Como o byte recebido ainda é equivalente a um endereço, continuamos com SSPSTAT<D/A>=0;

6. Todo o processo descrito para o item 4 será então repetido. No final, o sistema entra em nova pausa até que SSPADD seja novamente atualizado com a parte alta do endereço (A9:A8);

Page 120: Apostila Mosaico Pic MÓDULO4

118

7. O sistema aguardará então um byte de dado, com mais oito pulsos de clock. Como o byte recebido é equivalente a um dado, então SSPSTAT<D/A>=1. Neste momento também teremos BF=1 e o dado será colocado em SSPBUF;

8. O pino SDA é transformado automaticamente em saída com nível baixo (ACK=0) e o sistema aguarda o 9º pulso do clock. Logo depois SDA é transformado novamente em entrada;

9. Uma nova interrupção acontece (SSPIF=1) para que o dado recebido possa ser tratado;

10. Novos bytes de dados podem continuar sendo recebidos até que uma condição de Stop seja imposta na linha. Neste momento, a condição será reconhecida, setando-se o bit SSPSTAT<P> e finalizando-se a comunicação. A interrupção não é gerada;

11. Caso seja recebido uma condição de Re-Start (entre um Start e um Stop), o Slave ficará esperando um novo byte de endereço, com o bit de R/W e não mais um byte de dados;

Os comentários feitos a respeito do buffer e dos flags BF e SSPOV para a comunicação de 7-bits também são válidos aqui.

Transmissão para endereçamento de 10 bits

1. Tanto SCL quanto SDA estão em sua configuração padrão, isto é, como entradas. A linha receberá, então, uma condição de Start;

2. A condição de Start é reconhecida e o bit SSPSTAT<S> é setado; porém nenhuma interrupção acontece;

3. O sistema aguardará então um byte com os 2 bits de endereço (A9:A8) e mais o bit R/W=0, com oito pulsos de clock. Teremos, então, SSPSTAT<R/W>=0. Como o byte recebido é equivalente a um endereço, teremos também SSPSTAT<D/A>=0;

4. Neste momento, o endereço recebido é comparado automaticamente com o registrador SSPADD. Caso não seja o mesmo, a comunicação do lado Slave é resetada (ACK=1) e ficará aguardando um novo Start. Caso esta parte do endereço esteja correta, o bit SSPSTAT<BF> é setado, informando que um valor foi transferido para o buffer (SSPBUF) e teremos SSPSTAT<UA>=1, indicando que o endereço deve ser atualizado. O pino SDA é transformado automaticamente em saída com nível baixo (ACK=0) enquanto aguarda o 9º pulso do clock. Logo depois SDA é transformado novamente em entrada. Neste momento, o flag PIR1<SSPIF> é setado e a interrupção pode acontecer (se as chaves estiverem corretamente ligadas). É importante que a interrupção aconteça para que seja feita uma leitura do SSPBUF, forçando novamente BF=0. O registrador SSPADD deve, então, ser atualizado com a parte baixa do endereço (A7:A0), o que forçará automaticamente UA=0. Depois do ACK e até o momento em que o SSPADD é atualizado, o Slave trava a comunicação (pausa) impondo um nível baixo (0) em SCL. Esse controle é totalmente automático;

5. Será aguardado então um byte com a segunda parte do endereço (A7:A0) nos próximos oito pulsos do clock. Como o byte recebido ainda é equivalente a um endereço, continuamos com SSPSTAT<D/A>=0;

6. Todo o processo descrito para o item 4 será repetido. No final o sistema entra em pausa até que SSPADD seja novamente atualizado com a parte alta do endereço (A9:A8);

7. A linha fornecerá, então, uma condição de Re-Start, informando que o próximo byte é novamente uma informação de controle;

8. Será aguardado, então, outro byte com a parte alta do endereço e com R/W=1, para os próximos oito pulsos do clock. Como o byte recebido ainda é equivalente a um endereço, continuamos com SSPSTAT<D/A>=0. O valor recebido será colocado em SSPBUF e BF=1;

9. O pino SDA é transformado automaticamente em saída com nível baixo (ACK=0), enquanto o sistema aguarda o 9º pulso do clock. Logo depois, SDA é transformado novamente em entrada.

10. O sistema automaticamente altera SSPCON<CKP>=0, desabilitando o clock (pausa). Isso é feito transformando SCL em saída com nível baixo (0);

11. O flag PIR1<SSPIF> é, então, setado e a interrupção pode acontecer (se as chave estiverem corretamente ligadas). É importante que a interrupção aconteça para que SSPBUF seja lido, forçando BF=0 novamente. Depois devemos escrever o valor a ser transmitido em SSPBUF, o que irá fazer com que BF=1;

Page 121: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 119

12. Depois do buffer atualizado, para que a comunicação proceda, basta impor CKP=1. Neste momento, SCL será novamente liberado;

13. O clock será liberado e o byte existente em SSPBUF será enviado nos próximos oito pulsos. Ao término teremos BF=0;

14. Mais uma vez o pino SDA fica aguardando um ACK no 9º pulso do clock. Caso seja recebido um ACK=1 é porque a comunicação será encerrada, sendo aguardada então uma condição de Stop. Neste momento, a condição será reconhecida, setando-se o bit SSPSTAT<P> e finalizando-se a comunicação. A interrupção não é gerada. Caso ACK=0, o sistema volta ao item 5 para que um novo byte de dado seja transmitido;

15. Durante a transferência de dados não pode acontecer uma nova situação de Re-Start. Para reiniciar completamente o sistema é necessário terminar a transferência com um ACK=1 por parte do Master, seguido de um Stop. Só então uma nova condição de Start poderá ser gerada.

A condição de colisão (WCOL) descrita na comunicação de 7-bits também é valida para a de 10-bits.

Tratamento da interrupção SSP Como só existe uma interrupção de porta serial (SSP) e diversas condições, os bits adicionais desta porta

devem ser checados para sabermos exatamente que atitude deve ser tomada. Veja algumas condições:

BF UA D/A SSPOV Situação

1 X X X

Sempre que a interrupção acontecer BF=1, é porque alguma informação foi colocada em SSPBUF. Para o caso da transmissão, este flag pode ser checado para sabermos se o processo já términou, evitando uma colisão (WCOL).

1 X 0 X Foi recebido um endereço. Como o endereço é checado automaticamente, a interrupção deve somente ler SSPBUF para limpar BF.

1 1 0 X Somente quando configurada comunicação em 10 bits. A interrupção deverá atualizar o endereço, primeiro com o valor baixo e da segunda vez com o valor alto.

1 0 0 X Esta situação só acontece para 7 bits ou quando recebido o segundo byte de controle para a transmissão quando operando em 10 bits, onde também teremos R/W=1.

1 X X 1 Significa que a última informação recebida foi perdida, pois o SSPBUF não havia sido limpo.

Endereçamento global O Slave possui ainda um último recurso, que podemos chamar de endereço global. Isso significa que o

endereço 0 (zero) poderá ser aceito automaticamente por todos os PICs. Desta forma, cada unidade da rede possui um endereço específico (SSPADD) e um endereço global (Zero).

Para habilitar o uso de endereço global em um módulo Slave, basta ativar o bit SSPCON2<GCEN>:

GCEN Descrição 0 Endereço global (Zero) desabilitado. 1 Endereço global (Zero) habilitado.

Quando o endereço global é inserido na rede, todos os módulos Slave irão receber a informação e todos aqueles com GCEN deverão responder com um ACK. Isso nos lembra um comentário muito importante. Quando ACK=0, o Slave coloca SDA como saída em nível baixo. Porém, quando ACK=1, SDA continua como entrada e o nível alto é imposto pelo resistor de pull-up. Isso possibilita que diversos módulos respondam ACKs diferentes, tendo sempre a preferência o erro, ou seja, ACK=0.

Com a habilitação do endereço global a interrupção será gerada e o tratamento ou não das informações será uma escolha do programador.

Page 122: Apostila Mosaico Pic MÓDULO4

120

Resumo dos registradores associados a I2C Slave

Endereço Nome Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 0Bh ... INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF OCh PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF 8Ch PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE 94h SSPSTAT SMP CKE D/A P S R/W UA BF 14h SSPCON WCOL SSPOV SSPEN CKP SSPM3 SSPM2 SSPM1 SSPM0 91h SSPCON2 GCEN ACKSTAT ACKDT ACKEN RCEN PEN RSEN SEN 13h SSPBUF Buffer de transmissão / recepção 93h SSPADD Endereço (parte alta ou parte baixa)

Modo Master

O Master não diferencia automaticamente o tipo de comunicação em 7 ou 10-bits, ele somente transmite e recebe informações de 8-bits. Por isso, toda a lógica da comunicação deve ser feita por intermédio do programa. Internamente, o PIC possui controle de hardware para os seguintes eventos:

• Gerar/Monitorar condição de Start;

• Gerar/Monitorar condição de Stop;

• Gerar/Monitorar condição de Re-Start;

• Gerar/Monitorar condição de Pausa;

• Gerar/Monitorar Acknowledge;

• Gerar/Monitorar o clock;

• Transmitir informação de 8-bits;

• Receber informação de 8-bits. Inicie sempre configurando os pinos SCL como saída e SDA como entrada através do TRISC. Para configurarmos um PIC para trabalhar em modo Master, devemos ajustar os bits de

SSPCON<SSPM3:SSPM0>:

SSPM3: SSPM0

Descrição

1000 I2C Master, controle por hardware com Clock = FOSC / (4 x (SSPADD+1))

1001 Reservado 1010 Reservado 1011 Reservado 1100 Reservado 1101 Reservado 1110 Reservado 1111 Reservado

Obs: As demais opções de configuração dizem respeitos aos outros modos (SPI e I2C Slave).

Depois, é necessário também ajustar o bit SSPSTAT<SMP> que, neste caso, serve para habilitar um

sistema interno de tratamento das bordas, quando operando em freqüência de 400kHz:

SMP Descrição 0 Tratamento desabilitado 1 Tratamento habilitado, quando usando 400kHz

O bit SSPSTAT<CKE> serve para configurar o tipo de Smith Trigger utilizado nos pinos SCL e SDA:

CKE Descrição 0 Entradas conforme especificações I2C 1 Entradas conforme especificações SMBUS

A freqüência do clock deve ser configurada através do registrador SSPADD, respeitando-se a seguinte

fórmula:

Page 123: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 121

14

.FreqF

SSPADD

OSC

−⎟⎟⎠

⎞⎜⎜⎝

=

As freqüências padronizadas para o protocolo I2C são as de 100kHz e 400kHz. Com o PIC, entretanto, é

possível configurar outras freqüências. O fato é que todos os periféricos da rede devem estar aptos a responder na freqüência escolhida. Por isso, o recomendável é verificar a freqüência mais alta suportada pelos periféricos e escolher o valor mais próximo possível dos padronizados.

Por último, é necessário ainda habilitar o sistema de comunicação através do bit SSPCON<SSPEN>:

SSPEN Descrição 0 Desabilita a comunicação.

1 Habilita a comunicação. Neste momento os pinos SCL e SDA deixam de operar como I/Os convencionais.

Feito isso, vejamos que tarefas serão feitas automaticamente e quais deverão ser implementadas pelo

programa. Trataremos separadamente os possíveis casos de transferência de informações.

Transmissão para endereçamento de 7 bits

1. Tanto SCL quanto SDA estão em sua configuração padrão, isto é, como entradas;

2. Deve ser imposta uma condição de Start na linha. Para isso, basta ativar o bit SSPCON2<SEN>. A condição de Start será, então, gerada automaticamente;

3. Ao término do Start, o flag da interrupção será ativado (SSPIF=1) e SEN=0. Deve-se, então, escrever em SSPBUF o endereço do periférico com o qual desejamos nos comunicar. O endereço deve ser escrito nos bits de 7 a 1. O bit 0 deve ser considerado como o valor R/W=0;

4. Automaticamente, logo após a escrita no registrador SSPBUF, teremos SSPSTAT<BF>=1, SSPSTAT<R/W>=1 e o byte será transmitido através de oito pulsos gerados em SCL. No término da transmissão teremos novamente BF=0;

5. O pino SDA aguarda um ACK (deve ser 0) no 9º pulso do clock. O valor recebido é armazenado no bit SSPCON2<ACKSTAT>. O valor de ACK não é checado automaticamente;

6. Neste momento, R/W=0 e SSPIF=1, podendo gerar uma nova interrupção;

7. O dado a ser transmitido é, então, colocado em SSPBUF. Teremos BF=1 e R/W=1;

8. Mais uma vez teremos a transmissão do byte através de oito pulsos em SCL, a partir do momento em que nenhum periférico esteja solicitando uma pausa. No término BF=0;

9. Novamente o pino SDA aguarda um ACK (deve ser 0) no 9o pulso do clock. O valor recebido é armazenado no bit SSPCON2<ACKSTAT>. O valor de ACK não é checado automaticamente;

10. Neste momento R/W=0 e SSPIF=1, podendo gerar outra interrupção;

11. Se um novo byte deve ser transmitido, o processo é reiniciado no item 7. Para interromper a transmissão, uma condição de Stop deve ser gerada. Isso é conseguido por intermédio do bit SSPCON2<PEN>=1;

12. No final da condição de Stop teremos automaticamente PEN=0 e SSPIF=1.

Recepção para endereçamento de 7 bits

1. Tanto SCL quanto SDA estão em sua configuração padrão, isto é, como entradas;

2. Deve ser imposta uma condição de Start na linha. Para isso, basta ativar o bit SSPCON2<SEN>. A condição de Start será, então, gerada automaticamente;

3. Ao término do Start, o flag da interrupção será ativado (SSPIF=1) e SEN=0. Deve-se, então, escrever em SSPBUF o endereço do periférico com o qual desejamos nos comunicar. O endereço deve ser escrito nos bits de 7 a 1. O bit 0 deve ser considerado como o valor R/W=1;

Page 124: Apostila Mosaico Pic MÓDULO4

122

4. Automaticamente, logo após a escrita no registrador SSPBUF, teremos SSPSTAT<BF>=1, SSPSTAT<R/W>=1 e o byte será transmitido através de oito pulsos gerados em SCL. No término da transmissão teremos novamente BF=0;

5. O pino SDA aguarda um ACK (deve ser 0) no 9º pulso do clock. O valor recebido é armazenado no bit SSPCON2<ACKSTAT>. O valor de ACK não é checado automaticamente;

6. Neste momento, R/W=0 e SSPIF=1, podendo gerar uma nova interrupção;

7. O Master deve, então, ser colocado em modo de recepção, ajustando-se SSPCON2<RCEN>=1;

8. Assim que a linha de clock não estiver em pausa, será aguardado um byte de dados, para os próximos oito pulsos do clock. Como o byte recebido é equivalente a um dado, teremos SSPSTAT<D/A>=1. O valor recebido será colocado em SSPBUF e BF=1;

9. Neste momento, RCEN=0 (automaticamente) desligando-se o modo de recepção. Também teremos SSPIF=1, gerando uma nova interrupção;

10. Se um novo byte deve ser recebido, então o Master deverá responder ACK=0. Caso seja o último byte desejado, então ACK=1. Para responder o ACK, o valor desejado deve ser colocado no bit SSPCON2<ACKDT>. Liga-se a geração do sinal de ACK através de SSPCON2<ACKEN>=1;

11. Ao término do ACK teremos ACKEN=0 e SSPIF=1, gerando-se outra interrupção. Caso tenha sido respondido ACK=0, então o processo deve retornar ao item 5 para que um novo byte seja recebido. Se ACK=1, o processo deve ser finalizado através de uma condição de Stop que será gerada com SSPCON2<PEN>;

12. No final da condição de Stop teremos automaticamente PEN=0 e SSPIF=1.

Existem duas situações que podem gerar uma transmissão: • O Master efetua uma pergunta e deseja uma resposta: Neste caso, primeiramente será feita uma

recepção pelo Slave (pergunta) e depois uma transmissão (resposta). Entre a pergunta e a resposta pode ser gerada uma condição de Re-Start, não sendo necessário liberar a linha (Stop). Um exemplo disso são as memórias E2PROM externas. Primeiro devemos informar qual endereço desejamos acessar para que depois ela responda o valor contido no endereço em questão.

• O Master só deseja uma resposta: Em casos de Slaves mais "burros" é provável que somente com seu endereço já seja possível responder corretamente. Por exemplo, para um módulo de teclado, basta que ele transmita o número da tecla pressionada, não precisando processar perguntas diferentes.

Transmissão para endereçamento de 10 bits

1. Tanto SCL quanto SDA estão em sua configuração padrão, isto é, como entradas;

2. Deve ser imposta uma condição de Start na linha. Para isso, basta ativar o bit SSPCON2<SEN>. A condição de Start será, então, gerada automaticamente;

3. Ao término do Start, o flag da interrupção será ativado (SSPIF=1) e SEN=0. Deve-se, então, escrever em SSPBUF a parte alta do endereço do periférico com o qual desejamos nos comunicar. Os 2 bits do endereço (A9:A8) devem ser escritos nos bits de 2 e 1. O bit 0 deve ser considerado como o valor R/W=0. Os demais bits (7:3) devem conter os valores 11110;

4. Automaticamente, logo após a escrita no registrador SSPBUF, teremos SSPSTAT<BF>=1, SSPSTAT<R/W>=1 e o byte será transmitido através de oito pulsos gerados em SCL. No término da transmissão teremos novamente BF=0;

5. O pino SDA aguarda um ACK (deve ser 0) no 9º pulso do clock. O valor recebido é armazenado no bit SSPCON2<ACKSTAT>. O valor de ACK não é checado automaticamente;

6. Neste momento, R/W=0 e SSPIF=1, podendo gerar uma nova interrupção;

7. A segunda parte do endereço (A7:A0) é, então, escrita em SSPBUF;

8. Automaticamente, logo após a escrita no registrador SSPBUF, teremos SSPSTAT<BF>=1, SSPSTAT<R/W>=1 e o byte será transmitido através de oito pulsos gerados em SCL. No término da transmissão teremos novamente BF=0;

9. O pino SDA aguarda um ACK (deve ser 0) no 9º pulso do clock. O valor recebido é armazenado no bit SSPCON2<ACKSTAT>. O valor de ACK não é checado automaticamente.

Page 125: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 123

10. Neste momento, R/W=0 e SSPIF=1, podendo gerar uma nova interrupção;

11. O dado a ser transmitido é, então, colocado em SSPBUF. Teremos BF=1 e R/W=1;

12. Mais uma vez teremos a transmissão do byte através de oito pulsos em SCL, a partir do momento em que nenhum periférico esteja solicitando uma pausa. No término BF=0;

13. Novamente o pino SDA aguarda um ACK (deve ser 0) no 9º pulso do clock. O valor recebido é armazenado no bit SSPCON2<ACKSTAT>. O valor de ACK não é checado automaticamente;

14. Neste momento, R/W=0 e SSPIF=1, podendo gerar outra interrupção;

15. Se um novo byte deve ser transmitido, o processo é reiniciado no item 11. Para interromper a transmissão, uma condição de Stop deve ser gerada. Isso é conseguido por intermédio do bit SSPCON2<PEN>=1;

16. No final da condição de Stop teremos automaticamente PEN=0 e SSPIF=1.

Recepção para endereçamento de 10 bits

1. Tanto SCL quanto SDA estão em sua configuração padrão, isto é, como entradas;

2. Deve ser imposta uma condição de Start na linha. Para isso, basta ativar o bit SSPCON2<SEN>. A condição de Start será, então, gerada automaticamente;

3. Ao término do Start, o flag da interrupção será ativado (SSPIF=1) e SEN=0. Deve-se, então, escrever em SSPBUF a parte alta do endereço do periférico com o qual desejamos nos comunicar. Os 2 bits do endereço (A9:A8) devem ser escritos nos bits de 2 e 1. O bit 0 deve ser considerado como o valor R/W=0. Os demais bits (7:3) devem conter os valores 11110;

4. Automaticamente, logo após a escrita no registrador SSPBUF, teremos SSPSTAT<BF>=1, SSPSTAT<R/W>=1 e o byte será transmitido através de oito pulsos gerados em SCL. No término da transmissão teremos novamente BF=0;

5. O pino SDA aguarda um ACK (deve ser 0) no 9º pulso do clock. O valor recebido é armazenado no bit SSPCON2<ACKSTAT>. O valor de ACK não é checado automaticamente;

6. Neste momento, R/W=0 e SSPIF=1, podendo gerar uma nova interrupção;

7. A segunda parte do endereço (A7:A0) é, então, escrita em SSPBUF;

8. Automaticamente, logo após a escrita no registrador SSPBUF, teremos SSPSTAT<BF>=1, SSPSTAT<R/W>=1 e o byte será transmitido através de oito pulsos gerados em SCL. No término da transmissão teremos novamente BF=0;

9. O pino SDA aguarda um ACK (deve ser 0) no 9º pulso do clock. O valor recebido é armazenado no bit SSPCON2<ACKSTAT>. O valor de ACK não é checado automaticamente;

10. Neste momento, R/W=0 e SSPIF=1, podendo gerar uma nova interrupção;

11. Deve ser gerada então uma condição de Re-Start. Para isso, basta ativar o bit SSPCON2<RSEN>=1;

12. Ao término do Re-Start, o flag da interrupção será ativado (SSPIF=1) e RSEN=0;

13. Mais uma vez devemos colocar em SSPBUF o valor 11110, seguido dos bits A9:A8 e o último bit como R/W=1. Teremos BF=1 e R/W=1;

14. Teremos novamente a transmissão do byte através de oito pulsos em SCL, a partir do momento em que nenhum periférico esteja solicitando uma pausa. No término BF=0;

15. Novamente o pino SDA aguarda um ACK (deve ser 0) no 9º pulso do clock. O valor recebido é armazenado no bit SSPCON2<ACKSTAT>. O valor de ACK não é checado automaticamente;

16. Neste momento, R/W=0 e SSPIF=1, podendo gerar outra interrupção;

17. O Master deve, então, ser colocado em modo de recepção, ajustando-se SSPCON2<RCEN>=1;

18. Assim que a linha de clock não estiver em pausa, será aguardado um byte de dados para os próximos oito pulsos do clock. Como o byte recebido é equivalente a um dado, teremos SSPSTAT<D/A>=1. O valor recebido será colocado em SSPBUF e BF=1;

19. Neste momento, RCEN=0 (automaticamente) desligando-se o modo de recepção. Também teremos SSPIF=1, gerando uma nova interrupção;

Page 126: Apostila Mosaico Pic MÓDULO4

124

20. Se um novo byte deve ser recebido, então o Master deverá responder ACK=0. Caso seja o último byte desejado, então ACK=1. Para responder o ACK, o valor desejado deve ser colocado no bit SSPCON2<ACKDT>. Liga-se a geração do sinal de ACK através de SSPCON2<ACKEN>=1;

21. Ao término do ACK teremos ACKEN=0 e SSPIF=1, gerando-se outra interrupção. Caso tenha sido respondido ACK=0, então o processo deve retornar ao item 13 para que um novo byte seja recebido. Se ACK=1, o processo deve ser finalizado por intermédio de uma condição de Stop que será gerada com SSPCON2<PEN>;

22. No final da condição de Stop teremos automaticamente PEN=0 e SSPIF=1.

Outras considerações Existem outros bits e flags envolvidos com o Master que não foram comentados até o momento. Como um sistema pode possuir mais de um Master, as condições de Start e Stop geradas na linha

acarretarão na ativação de SSPIF, podendo gerar uma interrupção em qualquer Master. Os flags SSPSTAT<S> e SSPSTAT<P> informam, respectivamente, as condições de Start e Stop. Desta forma é possível que outros Masters percebam quando a linha está ou não ocupada.

Aqui valem também os comentários para os flags SSPCON<WCOL> e SSPCON<SSPOV> que indicam, respectivamente, uma escrita inválida (na hora errada) em SSPBUF e o recebimento de um novo byte sem a leitura do byte anterior.

As condições de Start, Stop, Re-Start e ACK não podem ser geradas fora dos momentos corretos, quando o modo de comunicação não está em stand-by. A situação de stand-by acontece sempre que o hardware da I2C acaba o controle de um evento qualquer.

Detecção de colisão na linha (Bus colision)

Outro recurso que o Master possui está relacionado à colisão de informações na linha de dados (SDA). Vejamos como isso funciona.

Para que o PIC possa impor o nível baixo da linha (normalmente nós consideramos uma condição de saída) existe um transistor interno conectando esse pino ao GND. Quando essa conexão está feita, a linha realmente está em nível baixo e não há o que monitorar. No outro caso, entretanto, quando esse transistor está em aberto, o pino é considerada uma entrada e o nível alto é imposto pelo resistor de pull-up (externo). Nesta situação, o PIC monitora a linha. Caso seja necessário transmitir um bit em “1”, (nível alto / transistor aberto) e a linha esteja em zero, é porque algum outro ponto da rede está em conflito de comunicação.

Quando isso acontecer, o bit PIR2<BCLIF> será forçado para “1”, e se PIE2<BCLIE>=1 a interrupção será gerada. O sistema de comunicação será inicializado (reset), voltando ao estado de stand-by.

As colisões podem acontecer durante a transmissão de dados e as condições de Start, Stop, Re-Start e ACK.

Resumo dos registradores associados a I2C Master

Endereço Nome Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 0Bh ... INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF OCh PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF 8Ch PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE 94h SSPSTAT SMP CKE D/A P S R/W UA BF 14h SSPCON WCOL SSPOV SSPEN CKP SSPM3 SSPM2 SSPM1 SSPM0 91h SSPCON2 GCEN ACKSTAT ACKDT ACKEN RCEN PEN RSEN SEN 13h SSPBUF Buffer de transmissão / recepção 93h SSPADD Ajuste da freqüência

Page 127: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 125

Capítulo 14 - Módulo USART

Introdução

O nome USART significa Universal Synchronous Asynchronous Receiver Transmitter. Com um nome desse, o negócio parece um tanto complicado, não é mesmo? Mas não é complicado não. Acontece que esse é um protocolo universal e possui dois modos distintos de trabalho: o sincronizado e o não-sincronizado. Mas vamos logo ao que interessa e tratemos de conhecer melhor este recurso.

Teoria

Como estávamos dizendo, a USART, que também é conhecida como SCI (Serial Communications Interface), possui dois modos de funcionamento, vejamos as características de cada um deles:

Modo Assíncrono A comunicação é feita somente com duas vias; entretanto, como este modo não é sincronizado, essas

duas vias são utilizadas para dados. Uma delas para transmissão (TX) e a outra para recepção (RX). Isso possibilita que as informações sejam enviadas e recebidas ao mesmo tempo, cada qual na sua via. Este recurso é conhecido como Full Duplex. Esse modo é o utilizado, por exemplo, na porta serial dos computadores, para implementar o padrão RS-232, mas pode ser utilizado para acesso a outros sistemas também.

Mas como é possível os dados serem transmitidos entre dois pontos se não há sincronismo entre eles? Quando estudamos a comunicação SSP, vimos que uma via era perdida exatamente para essa função. Era definida como clock do sistema e servia para informar os dois lados (Master e Slave) do momento correto de transmissão de cada bit. Como aqui não há essa via, a sincronização deve ser feita pela própria via de dados. Isso será conseguido através do Baud Rate ou velocidade de transmissão. Vejamos como funciona.

Comecemos definindo exatamente o que é o Baud Rate. Para que o sistema funcione, veremos que o tamanho dos dados (intervalo de cada bit) deve ser completamente padronizado, e ambos os lados devem estar ajustados para o mesmo valor. Como essa comunicação trabalha sempre com base nos bits, essa velocidade é normalmente indicada em bits por segundo, ou bps. Com ela somos capazes de calcular o tempo de duração de cada bit.

BaudRate1TBIT =

Com isso, existe somente um sincronismo de tempo feito para a transmissão/recepção de cada byte.

Esse sincronismo é conseguido através do Start bit. Devemos entender também que ambas as vias devem ser tratadas igualmente, pois o TX de um lado

deve estar conectado ao RX do outro, e vice-versa. Em ambos os lados, TX é sempre saída e RX é sempre entrada. Desta forma, quando falarmos de transmissão ou recepção, serve para qualquer uma das vias.

As vias possuem seu estado padrão como sendo o nível alto. Temos, então, uma situação de stand- -by. Quando um lado inicia uma transmissão, ele força seu TX para nível baixo, mantendo-o assim pelo tempo TBIT. Essa borda de descida é reconhecida pelo outro lado (em RX) e é suficiente para iniciar o processo de sincronização para recebimento desse byte. Este pulso em nível baixo é chamado de Start Bit.

Depois disso, os dois lados já sabem o que fazer. TX enviará então os 8 bits de dados, todos eles com o mesmo tamanho do Start Bit. Como RX soube exatamente o momento de início do Start Bit, ele deixa passar o tempo e depois coleta os 8 bits, pegando o dado mais ou menos no meio do tempo do bit (TBIT / 2).

Por último, para garantir o processo, TX envia um Stop Bit, que nada mais é que outro bit com valor fixo em 1, garantindo assim que a linha voltará ao seu estado padrão e o sistema voltará ao stand-by, ficando apto ao próximo dado. O lado RX deve considerar a leitura do Stop Bit para garantir que nenhum erro grosseiro aconteça com a recepção. Caso o Stop Bit seja 0 (zero), pode ter acontecido um erro de temporização, e no seu lugar foi lido o bit 8 ou, então, o próximo Start.

Repare também que o erro desse processo é acumulativo. Por exemplo, caso o lado TX esteja com sua velocidade no limite superior do erro, e o RX com a velocidade menor do que devia, cada bit será lido mais perto do começo do pulso. Como existem 10 bits ao total (Start + Dado + Stop), é possível que, no final, aconteça a leitura errada de um bit.

Vejamos o processo graficamente:

Page 128: Apostila Mosaico Pic MÓDULO4

126

O primeiro caso de recepção está com a velocidade bem próxima à velocidade do transmissor, e por isso

não houve erro na recepção. Já no outro caso a velocidade está mais lenta, e houve erro no último bit e no Stop Bit. Por isso, é importante o acerto e a precisão da velocidade em ambos os lados. Quanto maior o Baud Rate, mais crítica é a situação.

Observe também que a ordem de transmissão dos bits é a inversa das comunicações SSP. Aqui, o bit menos significativo é enviado primeiro.

Esse padrão aceita também a comunicação com 9 bits, sendo que o bit adicional poder ser utilizado para dado, paridade ou endereçamento. A paridade nada mais é que uma confirmação matemática dos 8 bits de dados. Somando-se a quantidade de bits em 1 (incluindo dados e paridade), o resuldado correto deve ser um número par (quando utilizando paridade PAR) ou ímpar (quando utilizando paridade ÍMPAR). Quanto ao endereçamento, respeita-se o seguinte critério: 0 para dado e 1 para endereço.

O importante é que ambos os lados (TX e RX) estejam configurados para operar com a mesma quantidade de bits. A configuração mais comum é a de 8 bits de dado (sem paridade) com 1 bit de Stop e é normalmente chamada de padrão 8N1.

No caso de comunicações padronizadas, o Baud Rate (BR) também obedece a valores pré- -ajustados, tais como 300, 1.200, 2.400, 9.600, 19.200bps e muitos outros.

Modo síncrono Este modo pode ser considerado como uma certa mistura entre os padrões SPI e I2C. Assim como no modo assíncrono, aqui também trabalhamos com somente duas vias, só que neste caso

uma é destinada ao clock (CK) e a outra aos dados (DT). Desta forma, os dados devem trafegar em uma única via, impossibilitando a transmissão e recepção simultâneas. É o mesmo conceito utilizado no padrão I2C. Essa comunicação é chamada de Half Duplex e pode ser utilizada para a troca de dados com outros microcontroladores ou diversos periféricos existentes no mercado, tais como A/Ds, D/As, memórias, etc.

Quanto à forma em que a informação trafega na linha, é bem mais simples que o padrão I2C, não possuindo o sistema de endereçamento e parecendo-se mais com o formato SPI. Para cada pulso (borda de descida) é transmitido um bit.

Este modo também opera com Mestre e Escravo, sendo o clock sempre gerenciado pelo Mestre. Para o Mestre, a via CK é sempre uma saída e para o Escravo ela é sempre uma entrada. Quanto à via de dados, ela muda constantemente de sentido, hora para a transmissão, hora para a recepção. Assim sendo, para qualquer uma das pontas, a via DT é saída para a transmissão e entrada para recepção.

O tempo de duração de um bit também define o Baud Rate, do mesmo modo descrito na comunicação assíncrona.

Neste caso, o nível baixo (0) é o padrão para a via CK. Para a via DT, não existe um padrão obriga-tório, pois ela não opera sem CK. Porém, recomendamos mantê-la também em nível baixo quando não está sendo usada.

Observe que, neste padrão, também o bit menos significativo (bit 0) é enviado primeiro. Para o modo síncrono também é aceita a comunicação com 9 bits e, neste caso, o Mestre sempre

gerará pacotes de nove pulsos de clock. O importante é que ambos os lados da comunicação (Mestre e Escravo) estejam configurados para operar com 9 bits.

Page 129: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 127

Recursos do PIC

Vamos estudar agora como operar com a USART do PIC 18F4520. Para continuarmos com a mesma linha de raciocínio, dividiremos mais uma vez parte do assunto entre os dois modos de operação, mas antes podemos explicar a maioria dos conceitos que são compartilhados por ambos.

Os pinos da comunicação (RC6/TX/CK) e (RC7/RX/DT) são os mesmos nos dois modos e são controlados diretamente pelo sistema da USART. Somente para evitarmos possíveis conflitos, caso a USART seja desabilitada, é recomendável que ambos sejam ajustados como entrada através do TRISC.

A definição entre os modos de operação é feita através de TXSTA<SYNC>:

SYNC Descrição 0 Modo Assíncrono 1 Modo Síncrono

O ajuste do Baud Rate (BR) é feito por meio de um registrador denominado SPBRG e do bit

TXSTA<BRGH>. A combinação desses parâmetros e do modo de operação definem o cálculo do BR:

BRGH Descrição 0 Ajuste para baixa velocidade 1 Ajuste para alta velocidade

SYNC BRGH=0 BRGH=1

0 BR = FOSC/(64x(SPBRG+1))

BR = FOSC/(16x(SPBRG+1))

1 BR = FOSC/(4x(SPBRG+1)) Não válido.

Primeiramente observe que o ajuste de BRGH não tem efeito quando estamos trabalhando no modo

síncrono. Neste caso, o tempo de cada bit (TBIT) será múltiplo do tempo de ciclo de máquina (TCY). Para o menor ajuste possível (SPBRG=0), teremos TBIT = TCY. Nesta situação, a parte alta do clock é gerada nos subtempos Q4 e Q1, ficando Q2 e Q3 para a parte baixa.

Por exemplo, para uma FOSC de 4MHz, teremos: BRMÁX = 1.000.000bps BRMÍN = 3.906bps Para o modo síncrono, BRGH surte efeito alterando a fórmula para o cálculo de BR. Observe que,

quando BRGH=0, TBIT será múltiplos de 64 TCY. Isso diminui a velocidade máxima e aumenta o erro para nos aproximarmos das velocidades padronizadas. Para o segundo caso (BRGH=1), teremos um ajuste mais preciso, pois TBIT será múltiplos de 16 TCY. Agora teremos um erro menor e um aumento da velocidade máxima. Por outro lado, perdemos na velocidade mínima.

Peguemos o mesmo exemplo dado para o caso do modo síncrono (FOSC = 4MHz), primeiro para BRGH=0:

BRMÁX = 62.500bps BRMÍN = 244bps

Page 130: Apostila Mosaico Pic MÓDULO4

128

E agora para BRGH=1: BRMÁX = 250.000bps BRMÍN = 976bps Vamos, agora, calcular o valor de SPBRG para uma velocidade de 9.600bps, com cristal de 4MHz e

BRGH=0:

BR = FOSC /(64x(SPBRG+1))

SPBRG = (FOSC /(64 x BR)) - 1

SPBRG = (4.000.000 / (64 x 9.600)) - 1

SPBRG = 5,510 -> 5 Como houve um arredondamento, existirá um erro que deve ser calculado:

BR = 4.000.000 / (64 x (5+1))

BR = 10.416bps

Erro = (10.416 - 9.600) / 9.600

Erro = 8,5% (muito elevado) Vejamos o mesmo caso para BRGH=1:

BR = FOSC /(16x(SPBRG+1))

SPBRG = (FOSC /(16 x BR)) - 1

SPBRG = (4.000.000 / (16 x 9600)) - 1

SPBRG = 25,042 -> 25

BR = 4.000.000 / (16 x (25+1))

BR = 9.615bps

Erro = (9.615 - 9.600) / 9.600

Erro = 0,16% (muito bom!) Devido à grande diferença de erro, devemos adotar o segundo cálculo. Existem casos, princi-palmente

quando BR é elevado, que para melhorarmos a situação será necessário alterarmos o valor do oscilador (FOSC), tentando chegar em números mais precisos. Não esqueça de que existe ainda a tolerância de funcionamento do sistema de oscilação. O uso de cristais pode também ser obrigatório para as velocidades mais altas.

Para ativar o sistema da USART, configurando os pinos corretamente, deve-se ajustar o bit RCSTA<SPEN>:

SPEN Descrição

0 USART desabilitada. Pinos como I/Os convencionais.

1 USART habilitada. Pinos controlados automaticamente.

A partir deste ponto o usuário deve escolher entre as operações de transmissão e/ou recepção, mas,

como elas são bem diferentes para os modos assíncronos e síncronos, serão explicadas na divisão dos tópicos. Por enquanto, vejamos somente quais são e os bits que as controlam:

Page 131: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 129

Operação Bit Observações Transmissão TXSTA<TXEN> Ativa o sistema de transmissão de bytes.

Recepção unitária RCSTA<SREN> Ativa o sistema de recepção de somente 1 byte. Somente

para modo síncrono. Recepção contínua RCSTA<CREN> Ativa o sistema de recepção contínua.

O que devemos explicar, que ainda é comum aos modos de operação, diz respeito ao dado que será

transmitido e/ou recebido. Primeiramente devemos optar pela comunicação com 8 ou 9 bits. Isso é feito separadamente para a

transmissão e para a recepção, através dos bits TXSTA<TX9> e RCSTA<RX9>:

TX9 Descrição 0 Transmissão feita em 8 bits 1 Transmissão feita em 9 bits

RX9 Descrição

0 Recepção feita em 8 bits 1 Recepção feita em 9 bits

Este 9º bit deve ser escrito em TXSTA<TX9D> para a transmissão e será recebido em RCSTA<RX9D>

do lado da recepção. O PIC não possui sistema automático para implementação desse bit como sendo a paridade. Se o uso da paridade for necessária, essa implementação terá de ser feita através do software. Existe um auxílio para uso desse bit como endereçamento, mas isso será visto posteriormente.

Quanto ao dado propriamente dito, para o caso da transmissão, ele deve ser escrito no registrador TXREG. Caso o sistema de transmissão esteja ligado, a simples escrita nesse registrador irá iniciá-la. Este dado será, então, transferido a um registrador interno denominado TSR (sem acesso pelo programa) para que seja enviado pela porta serial. Neste momento, TXREG fica vazio e liberado para uma nova escrita. Desta forma, o nosso buffer de saída é duplo, podendo haver um byte em TXREG e outro em TSR. O segundo byte só será passado de TXREG para TSR quando o último bit (7 ou 8) do byte anterior for transmitido, deixando TSR vazio.

Toda vez que o valor for passado de TXREG para TSR, o bit PIR1<TXIF> será setado, podendo gerar a interrupção. O interessante é que esse bit não precisa ser limpo manualmente como os demais flags de interrupção. Ele será limpo automaticamente sempre que TXREG for escrito. Isso serve para sabermos quando TXREG está liberado para uma nova escrita. O problema é que, se não desejamos transmitir nada, não escreveremos em TXREG e não limparemos TXIF. Isso irá travar o programa entrando sem parar na interrupção. A solução, para este caso, é desligar a interrupção ou mesmo a transmissão.

O bit TXIF não pode ser utilizado para sabermos que uma transmissão já foi completada, pois, depois de TXREG ser colocado em TSR, o dado ainda precisará ser enviado pela porta serial. Para saber quando realmente a transmissão foi finalizada, devemos saber quando TSR está vazio. O bit TXSTA<TRMT> possui esta função:

TRMT Descrição

0 Transmissão finalizada. TSR liberado. 1 Transmissão em curso. TSR ocupado.

Para a recepção, o dado recebido é primeiramente armazenado em um registrador interno não acessível

(RSR). Quando esse registrador está completo, a informação é então passada para o registrador RCREG. O mais interessante é que este registrador possui dois níveis de pilha, podendo ser escrito e lido duas vezes. Com isso nosso buffer de entrada é triplo, podendo haver um dado sendo recebido em RSR e mais dois já recebidos em RCREG. O registrador RCREG trabalha com o sistema FIFO (First In / First Out), isto é, o primeiro a ser recebido será o primeiro a ser lido.

Cada vez que o valor de RSR é transferido para RCREG o bit PIR1<RCIF> é setado, podendo gerar a interrupção. Como no caso da transmissão, esse bit é limpo automaticamente pelo hardware sempre que RCREG estiver vazio. Isso significa que, se foram recebidos 2 bytes antes de ser efetuada uma conferência, RCREG terá de ser lido duas vezes (pilha) para que o bit RCIF seja limpo. Caso o terceiro byte seja completado antes da leitura dos duas já existentes em RCREG, um erro de overflow irá acontecer e o bit RCSTA<OERR> será setado. O 3º byte que se encontra em RSR será perdido. Este bit deve ser limpo manualmente. Isso também pode ser conseguido desativando-se o modo de recepção.

Para trabalhar com o 9º bit, é necessário que ele seja escrito (TX9D) antes do dado em TXREG, possibilitando a atualização correta do TSR.

Page 132: Apostila Mosaico Pic MÓDULO4

130

O sistema de recepção checa também o Stop Bit, mas não toma nenhuma atitude automática em caso de erro. A situação do Stop Bit é armazenada em RCSTA<FERR>:

FERR Descrição

0 O Stop Bit foi recebido corretamente (Stop Bit = 1). 1 O Stop Bit foi recebido errado (Stop Bit = 0).

Para que esse bit possa ser checado pelo programa, assim como o 9º (quando usado), uma leitura deve

ser feita antes em RCREG para que os mesmos sejam atualizados. Por último devemos comentar sobre o sistema de endereçamento. Estes sistema só funciona quando

ajustada a comunicação para 9 bits que é controlado através do bit RCSTA<ADDEN>:

ADDEN Descrição 0 Sistema de endereçamento desativado.1 Sistema de endereçamento ativado.

Quando esse sistema está ativo, o dado recebido só é transferido de RSR para RCREG quando o 9º for

1, podendo então gerar a interrupção. Caso seja recebido uma informação com o 9º em 0, ela será reconhecida como dado e será descartada. Para que o processo funcione corretamente é necessário, então, começarmos com o endereçamento ativo para recebermos um endereço que será tratado e comparado como o endereço da própria unidade. O endereço será o byte recebido, possibilitando 256 valores diferentes. Caso o endereço recebido corresponda à unidade em questão, o sistema de endere-çamento deve então ser desativado para que o próximo valor possa ser recebido como um dado válido.

Vejamos agora as particularidades e observações do roteiro de trabalho de cada modo.

Modo Assíncrono

Para o modo assíncrono, quando habilitamos a USART através do bit RCSTA<SPEN>, o pino TX é transformado em saída com nível alto (1) e o pino RX é transformado em entrada.

Para ativar o sistema de recepção, basta tornar RCSTA<CREN>=1. Para esse modo não é possível escolher o sistema de recepção unitária e, por isso, RCSTA<SREN> não possui função.

A partir deste momento cada byte recebido será colocado em RCREG e a interrupção será ativada através de RCIF. A lógica do sistema será, então, tratar das informações recebidas. É recomendável também a implementação da checagem do Stop Bit (FERR) e do estouro de recepção (OERR).

Para ativar o sistema de transmissão, basta tornar TXSTA<TXEN>=1. O importante é lembrar de que os sistemas de transmissão e recepção são totalmente independentes (só compartilham o mesmo Baud Rate) e, por isso, cada um deles pode ser ativado e desativado, conforme a necessidade.

Depois da ativação, basta escrever um valor em TXREG e o mesmo será enviado automaticamente pela porta serial, com a geração do Start Bit e do Stop Bit. O importante é a checagem do bit TXIF para que o sistema não sobre escreva TXREG antes de TSR ser atualizado.

Quando um dos sistemas é desativado (Transmissão ou Recepção), o pino relacionado a ele é mantido como entrada.

Este modo não pode operar em SLEEP.

Resumo dos registradores associados à USART Assíncrona

Endereço Nome Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 0Bh ... INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF OCh PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF8Ch PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE98h TXSTA CSRC TX9 TXEN SYNC - BRGH TRMT TX9D 18h RCSTA SPEN RX9 SREN CREN ADDEN FERR OERR RX9D 19h TXREG Buffer de transmissão 1Ah RCREG Buffer de recepção 99h SPBRG Acerto do Baud Rate

Page 133: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 131

Modo Síncrono Neste modo existe mais um bit de configuração relacionado ao sistema Master/Slave. Trata-se do

TXSTA<CSRC>:

CSRC Descrição 0 Slave (CK como entrada). 1 Master (CK como saída).

Com essa seleção, o sistema configura corretamente o estado do pino de clock (CK). O estado do pino de dados (DT) será variável, conforme o sistema se encontre em recepção ou transmissão. Devemos, então, escolher qual operação desejamos efetuar:

Operação Bit Observações

Transmissão TXSTA<TXEN>

O pino DT será colocado como saída e o sistema está pronto para transmitir o dado escrito em TXREG. A escolha de um modo de recepção tem prioridade sobre este modo.

Recepção unitária RCSTA<SREN> O pino DT é colocado como entrada e o sistema de

recepção de somente 1 byte é ativado. Recepção contínua RCSTA<CREN> O pino DT é colocado como entrada e o sistema de

recepção contínua é ativado.

Transmissão No caso do Master, o sistema funciona de forma muito parecida com o descrito anteriormente para o

modo assíncrono, operando da mesma forma com TXREG, TXIF e TRMT. A única diferença é que, quando escrevemos algum dado em TXREG, o mesmo será transmitido por DT, com pulsos sendo gerados em CK e sem a presença de Start ou Stop bit. CK pode gerar oito ou nove pulsos, dependendo do estado de TXSTA<TX9>.

Ao término da transmissão, o sistema ficará em stand-by, aguardando um novo dado em TXREG. Para o Slave, a diferença é que, depois de escrevermos em TXREG, o sistema ficará aguardando os

clocks enviados pelo Master.

Recepção A recepção para o Master e para o Slave também é idêntica, exceto pela geração do clock. Quando

ativada uma operação de recepção, a operação de transmissão é desligada imediatamente e o pino DT torna-se entrada.

A recepção contínua manterá a unidade recebendo dados até que o bit RCSTA<CREN> seja limpo manualmente. Já a recepção unitária (RCSTA<SREN>=1) receberá somente um byte e depois desliga- -se (RCSTA<SREN>=0). Se por acaso forem ligados as duas maneiras de recepção, o modo contínuo terá prioridade. No modo contínuo, o clock não é desativado, gerando pulsos constantes. Isso torna a operação nesse sistema mais difícil.

Ao receber um dado, o mesmo será enviado a RCREG e o flag PIR1<RCIF> será ativado, podendo gerar a interrupção.

Operação em SLEEP Somente as unidades Slaves do modo síncrono podem operar em SLEEP. Quando um dado é recebido durante o SLEEP, ao final da recepção a informação é transportada de

RSR para RCREG, ativando o flag de interrupção PIR1<RCXIF>. Deixando essa interrupção habilitada, o PIC será acordado e o dado recebido poderá ser tratado.

Uma transmissão também é possível durante o SLEEP. O primeiro dado escrito em TXREG será imediatamente escrito em TSR. O segundo byte (se houver) será mantido em TXREG. O sistema é, então, colocado em SLEEP. Quando chegar o primeiro pacote de pulsos, o dado de TSR será transmitido. Ao final, o segundo dado será colocado em TSR e o flag TXIF será setado. Se a interrupção estiver habilitada, o PIC acordará.

Page 134: Apostila Mosaico Pic MÓDULO4

132

Resumo dos registradores associados à USART Síncrona

Endereço Nome Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 0Bh ... INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF OCh PIR1 PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF 8Ch PIE1 PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE98h TXSTA CSRC TX9 TXEN SYNC - BRGH TRMT TX9D 18h RCSTA SPEN RX9 SREN CREN ADDEN FERR OERR RX9D 19h TXREG Buffer de transmissão 1Ah RCREG Buffer de recepção 99h SPBRG Acerto do Baud Rate

Page 135: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 133

Capítulo 15 - Variáveis Organizadas

Introdução

A linguagem C, possui um método para organizar os tipos de variáveis simples, que já conhecemos. Elas podem ser organizadas de três formas:

• Homogêneas: variáveis de mesmo tipo, organizada na forma de vetor ou matriz. • Heterogêneas: variáveis de tipos diferentes, organizadas em forma de estruturas. • Sobrepostas: variáveis de mesmo tipo ou tipos diferentes organizadas em forma de uniões.

Matriz

Chamamos de vetor, uma matriz unidimensional. Como já foi falado ele é formado por variáveis de mesmo tipo.

Podemos ter matrizes bidimensionais, a quantidade de dimensões de uma matriz é limitada pelo compilador C utilizado.

O MPLAB C18 nos permite criar matrizes de até 5 dimensões, quando estamos falando de matrizes em memória RAM, estas podem gastar no máximo 256 bytes. Cada banco de RAM possui 256 bytes, uma matriz não pode ultrapassar a capacidade de um banco de RAM.

Criando um Vetor Os vetores podem ser criados na memória de programa ou na memória RAM. A quantidade de memória usada em um vetor depende do tipo de variável e do tamanho do vetor,

(quantidade de células). Para criar um vetor devemos informar: tipo de variável, nome do vetor e tamanho. Podemos utilizar todos os tipos de variáveis da linguagem C para criar um vetor, para dar um nome a um

vetor, devemos seguir as mesmas regras adotadas para variáveis, o tamanho define a quantidade de células de memória do nosso vetor.

Criando um vetor na memória RAM Vejamos como criar um vetor na memória RAM: tipo_de_variável nome_da_variável [tamanho]; Exemplo: unsigned char vetor_teste [200]; No exemplo acima foram utilizados 200 bytes de memória RAM, o vetor_teste possui duzentas células, o

tipo de variável é de 1 byte, logo 1 byte x 200 células = 200 bytes.

Iniciando um Vetor Os vetores que forem criados na memória RAM podem ser inicializados, com valores já pré –

determinados. Os valores de inicialização devem ser colocados entre chaves e separados por virgula. Veja como é

feito: tipo_de_variável nome_da_variável [tamanho] = ...,...,...,...; Exemplo: unsigned char vetor_teste [5] = 10,20,30,40,50;

Criando um vetor na memória de programa Para criar um vetor na memória de programa devemos utilizar os qualificadores const e rom, logo a

sintaxe de um vetor na memória de programa será: const rom tipo_de_variável nome_da_variável [tamanho];

Page 136: Apostila Mosaico Pic MÓDULO4

134

Exemplo: const rom unsigned char tabela[16] = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16;

Este tipo de vetor pode ser utilizado, para criar tabelas na memória de programa. Desta forma podemos criar tabelas, para linearizar a curva de resposta de um sensor, para criar tabelas

de conversão do tipo binário para sete segmentos, entre outros tipos de tabela, enfim poderemos utilizar as tabelas de constantes em varias aplicações

Leitura e Escrita de um vetor Um vetor na memória RAM nos permite modificar o conteúdo de qualquer célula, a qualquer momento.

Da mesma forma acontece com a leitura podemos ler qualquer posição do vetor a qualquer momento. Um dos cuidados ao trabalhar com vetores é na utilização do índice do vetor, o índice é inserido no

campo tamanho do vetor. Ele será utilizado para informar qual posição do vetor desejamos ler ou escrever.

Leitura de uma célula do Vetor Para que possamos ler uma posição de um vetor, devemos informar através do índice a posição

desejada. Devemos tomar cuidado no momento de informar o valor do índice, este pode nos causar problemas se

apontar para uma posição que vai alem do tamanho do nosso vetor. Portanto o máximo valor do índice, deve ser o tamanho menos 1. Veja para um vetor de quatro células, teremos o índice máximo igual a três e o mínimo igual a zero.

unsigned char tabela[4] = 10, 20, 30, 40

32

10 Índice do vetor

Logo se efetuarmos está operação: auxiliar = tabela [1]; Vamos carregar no registrador auxiliar o valor da posição um do vetor tabela, portanto teremos auxiliar =

20. Para leitura de uma posição (célula) de um vetor podemos ter como índice uma constante como foi visto

no exemplo ou qualquer tipo de variável, até mesmo um vetor ou matriz.

1020304014

21243227282

0x2000x2010x2020x2030x2040x2050x2060x2070x2080x209

Vetortabela

auxiliar

102030402021243227282

0x2000x2010x2020x2030x2040x2050x2060x2070x2080x209

Vetortabela

auxiliar

Antes depois

Neste exemplo usaremos uma variável para indexar nossa tabela, o programa roda indefinidamente, a cada volta o PORTB é carregado com um dos valores da tabela.

unsigned char indice = 0; unsigned char tempo = 20; const rom unsigned char tabela [5] = 89, 97, 109, 08, 225;

Page 137: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 135

void main () while (1) //inicio do programa. PORTB = tabela[indice++]; //carrega o PORTB com o valor da tabela

//indexado pela variável indice. //1o indexa depois incrementa a variável indice

delay10TCYx(tempo); //delay de 200 ciclos de máquina. If (indice = 5) indice = 0; //indice igual ao valor máximo? //sim, zera a variável indice. //não, volta para o inicio do programa. Então para cada volta do programa teremos: Variável 1a volta 2a volta 3a volta 4a volta 5a volta 6a volta Índice = 0 1 2 3 4 5 → 0

PORTB = 89 97 109 08 225 89

Criando uma matriz multidimensional Uma matriz multidimensional é formada por uma associação de vetores (matriz unidimensional). Assim

sendo teremos um campo tamanho para cada matriz unidimensional da nossa matriz multidimensional. A sintaxe de uma matriz bidimensional ficará assim: tipo_de_variável nome_da_matriz [tamanho1] [tamanho2]; Exemplo: a)Matriz bidimensional #pragma idata MY_DATA2=0x400 // banco de RAM onde será criada a matriz unsigned char tabela_a[2][3] = 1,2,3,4,5,6;

Podemos assumir que tamanho1 representa a quantidade de linhas da matriz e tamanho2 a quantidade

de colunas. Contamos as linhas de 0 a 1 e as colunas de 0 a 2, logo temos uma matriz de 2 linhas e 3 colunas. A leitura das posições desta matriz será feita desta forma:

reg = tabela_a[0][0]; // Lê linha 0, coluna 0, reg = 1 reg = tabela_a[0][1]; // Lê linha 0, coluna 1, reg = 2 reg = tabela_a[0][2]; // Lê linha 0, coluna 2, reg = 3 reg = tabela_a[1][0]; // Lê linha 1, coluna 0, reg = 4 reg = tabela_a[1][1]; // Lê linha 1, coluna 1, reg = 5 reg = tabela_a[1][2]; // Lê linha 1, coluna 2, reg = 6

Matriz tridimensional Uma matriz tridimensional é formada por matrizes bidimensionais.A sintaxe para está matriz é: tipo_de_variável nome_da_matriz [tamanho1][ tamanho2][ tamanho3]; O campo de indicação de tamanho a matriz nos diz o seguinte: tamanho1 indica a quantidade de

matrizes bidimensionais, o tamanho2 a quantidade de linha e tamanho3 a quantidade de colunas da matriz.

No nosso exemplo temos uma matriz tridimensional formada por 3 matrizes bidimensionais, veja:

Page 138: Apostila Mosaico Pic MÓDULO4

136

int matriz [3][2][3]= 10,20,30, // matriz 0 40,50,60,

70,80,90, // matriz 1 100,110,120, 130,140,150, // matriz 2 160,170,180 ;

A leitura de cada célula desta matriz pode ser realizada desta forma: reg=matriz[0][0][0]; // matriz 0, linha 0, coluna 0, reg = 10; reg=matriz[0][0][1]; // matriz 0, linha 0, coluna 1, reg = 20; reg=matriz[0][0][2]; // matriz 0, linha 0, coluna 2, reg = 30; reg=matriz[0][1][0]; // matriz 0, linha 1, coluna 0, reg = 40; reg=matriz[0][1][1]; // matriz 0, linha 1, coluna 1, reg = 50; reg=matriz[0][1][2]; // matriz 0, linha 1, coluna 2, reg = 60; reg=matriz[1][0][0]; // matriz 1, linha 0, coluna 0, reg = 70; reg=matriz[1][0][1]; // matriz 1, linha 0, coluna 1, reg = 80; reg=matriz[1][0][2]; // matriz 1, linha 0, coluna 2, reg = 90; reg=matriz[1][1][0]; // matriz 1, linha 1, coluna 0, reg = 100; reg=matriz[1][1][1]; // matriz 1, linha 1, coluna 1, reg = 110; reg=matriz[1][1][2]; // matriz 1, linha 1, coluna 2, reg = 120; reg=matriz[2][0][0]; // matriz 1, linha 0, coluna 0, reg = 130; reg=matriz[2][0][1]; // matriz 1, linha 0, coluna 1, reg = 140; reg=matriz[2][0][2]; // matriz 1, linha 0, coluna 2, reg = 150; reg=matriz[2][1][0]; // matriz 1, linha 1, coluna 0, reg = 160; reg=matriz[2][1][1]; // matriz 1, linha 1, coluna 1, reg = 170; reg=matriz[2][1][2]; // matriz 1, linha 1, coluna 2, reg = 180;

Para criar matrizes com mais de três dimensões devemos seguir o mesmo principio. Veja para criar uma matriz de quatro dimensões precisaremos de duas matrizes tridimensionais. Cada campo adicional de dimensão, irá informar a quantidade de matrizes necessárias, para formar uma

matriz de maior dimensão.

Strings Uma string é um conjunto de caractere, representado entre aspas, por exemplo “Grupo Mosaico”,e toda

string é finalizada por \0 (nulo). Uma das aplicações dos vetores (matriz unidimensional) é a criação de vetores de strings. Devemos

sempre lembrar que um vetor deve ter capacidade de armazenar os caracteres desejados mais o caractere \0.

A biblioteca do MPLAB C18, possui diversas funções de manipulação de strings. Portanto nada de realizar operações relacionais entre strings, utilize as funções do MPLAB C18 para isso.

Estrutura de dados

As estruturas de dados são formadas por tipos de variáveis diferentes, podemos utilizar as variáveis de uma estrutura em conjunto ou individualmente.

Para criar uma estrutura usamos o comando struct. Podemos ter dois tipos de estrutura de dados, uma de variáveis e outra de bit. A estrutura de variáveis nos permitirá criar uma variável do tipo “struct”, formada por variáveis de

diversos tipos. O segundo tipo de struct, nos permitirá criar estruturas que serão formadas por variáveis com quantidade de bits diferentes, chamados de campo de bits.

Criando uma struct de variáveis Uma estrutura pode ser formada por vários tipos de variáveis, estas variáveis chamaremos de

“elementos de estrutura”.

Page 139: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 137

Uma das aplicações de uma estrutura de dados, é utiliza-la como um banco de dados. Imagine uma agenda eletrônica. Para podermos inserir, telefone, endereço, e-mail e etc, são necessários

campos de tamanhos diferentes, para a entrada destas informações. Vejamos então como criar uma struct: • Criando uma struct: struct nome_da_estrutura

declaração da variável; : : ;

• Criando uma struct e definindo uma variável deste novo tipo: struct nome_da_estrutura

declaração da variável; : : nome_da_variável;

A identificação nome_da_estrutura, pode ser utilizada para criar outras estruturadas com o mesmo

formato. Exemplo:

a) Vamos criar uma estrutura de lista de contatos: struct lista_de_contato // tipo de variável char nome[50]; char DDD [2]; char telefone [8]; ;

Para criar uma outra variável do tipo lista_de_contato, basta utilizar esta sintaxe:

struct lista_de_contato lista_de_amigos;

b) Outra maneira de criar uma estrutura é apresentada a seguir:

struct lista_de_contato // tipo de variável char nome[50]; char DDD [2]; char telefone [8]; lista_de_amigos; // variável estruturada

A estrutura lista_de_amigos terá o mesmo formato da struct lista_de_contato. O que não quer dizer que

ocuparão as mesmas posições de RAM, cada estrutura ocupara a quantidade de memória necessária. Podemos dizer que lista_de_contato é um novo tipo de variável.

Acessando elementos de uma estrutura Como nós já sabemos uma estrutura é formada por variáveis de diversos tipos, agora como faremos

para ler ou escrever em um elemento desta estrutura? A resposta para está pergunta é simples utilizaremos o operador ‘ponto’, “.”, com o auxilio deste

operador poderemos acessar qualquer elemento de uma estrutura.

Page 140: Apostila Mosaico Pic MÓDULO4

138

Escrevendo nos elementos de uma estrutura Para escrever em um elemento de estrutura devemos utilizar o operador “.”, será usado como separador

de elementos. Com o uso deste operador poderemos escrever em qualquer elemento, basta para isso indicar a

estrutura e o elemento da estrutura e igualar ao valor desejado. Sintaxe: nome_da_estrutura.elemento = valor desejado. Veja que na estrutura lista_de_amigos temos o campo DDD, para inserirmos um dado neste elemento

faremos assim:

struct lista_de_contato char nome[50]; char DDD [2]; char telefone [8]; lista_de_amigos; lista_de_amigos.DDD[0] = '2'; lista_de_amigos.DDD[1] = '3';

O elemento DDD é um vetor de duas posições, na posição zero do vetor foi carregado o caractere 2.

Leitura de um elemento de estrutura Com a mesma simplicidade que realizamos uma escrita em um elemento de estrutura, podemos ler os

elementos. Para está tarefa também utilizaremos o operador “.”, a leitura pode ser feita em qualquer elemento da estrutura a qualquer instante, veja:

unsigned char reg; struct lista_de_contato char nome[50]; char DDD [2]; char telefone [8]; lista_de_amigos; reg = lista_de_amigos.DDD[0];

Operação entre estruturas

Quando trabalhamos com estruturas ficamos tentados a realizar operações lógicas ou aritméticas entre estruturas, veja isto não é possível o que podemos fazer é igualar duas estruturas.

Qualquer operação que você deseje realizar deverá ser feita entre os elementos da estrutura. Exemplo: static struct relogio unsigned char horas; unsigned char minutos; unsigned char segundos; horario; struct relogio alarme; reg = (horario.horas == alarme.horas);

No exemplo realizamos uma operação de comparação entre o elemento horas da estrutura horário e o

elemento horas da estrutura alarme.

Page 141: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 139

Inicialização de uma estrutura Além de criar uma estrutura também é possível fazer a inicialização da mesma, veja como: #pragma idata MY_DATA2=0x400 struct lista_de_contato

char nome[50]; char DDD [2]; char telefone [8];

; struct lista_de_contato lista_de_amigos = "Rinaldo",'1','1','4','9','9','2','8','7','7','5'; struct lista_de_contato lista_de_empresas = "Grupo Mosaico",'1','1','4','9','9','2','8','7','7','5';

Matrizes de estruturas Uma matriz é a associação de variáveis do mesmo tipo, como uma estrutura é um tipo de variável

podemos então criar matrizes de estruturas. Sintaxe: struct nome_da_estrutura tipo variavel; ; struct nome_da_estrutura matriz[tamanho];

Vejamos um exemplo que irá criar na memória RAM um banco de dados para armazenar 12 nomes de

contato. A matriz agenda será formada por 12 variáveis do tipo lista_de_contato. Vamos utilizar neste exemplo 240 bytes de RAM. Exemplo: #pragma idata MY_DATA2=0x400// define banco de RAM struct lista_de_contato char nome[10]; char DDD [2]; char telefone [8]; ; struct lista_de_contato agenda[12]; // Matriz para armazenar 12 contatos.

Estrutura de Bits O MPLAB C18 não possui um tipo dado para criar variáveis de um bit. Sendo assim não é possível criar

flags. O que é um flag? Um flag nada mais é do que um sinalizador, uma bandeira, utilizaremos um bit para indicar 0 ou 1, assim

economizaremos memória RAM, como já é sabido cada posição de RAM possui 8 bits, logo com uma variável poderemos criar 8 flags. Podemos criar variáveis que com mais de um bit.

Pelo padrão ANSI uma estrutura de bit não pode ser maior do que o tamanho de um int. No entanto no MPLAB C18 podemos utilizar uma variável do tipo char e inserir quantos bits precisarmos,

o que ultrapassar a capacidade de 8 bits será alocado na posição de RAM seguinte. Se não existe este tipo de dado como faremos então? Nossa resposta está na estrutura de bits ou como

também é chamado, campo de bits. Com uma struct de bits poderemos utilizar os registradores da memória RAM e criamos os flags

necessários para o nosso programa. Com uma estrutura de bits podemos criar variáveis e definir a quantidade de bits utilizada por esta

variável, os bits são ordenados da direita para a esquerda. Observe a sintaxe do campo de bits.

Page 142: Apostila Mosaico Pic MÓDULO4

140

Sintaxe: struct nome_da_estrutura

variável: quantidade de bits da variável; bit 7 variável: quantidade de bits da variável; bit 6 : : : : : : variável: quantidade de bits da variável; bit 0

; struct nome_da_estrutura nome_da_varialvel struct nome_da_estrutura

tipo da variável variável: quantidade de bits da variável; tipo da variável variável: quantidade de bits da variável;

nome_da_variável;

Acessando uma estrutura de bits Da mesma maneira que lemos ou escrevemos em uma variável de uma estrutura, faremos com um bit

de um campo de bits. Veja no exemplo: #pragma idata MY_DATA2=0x300 struct campo_de_bits char flag15 :1; //bit 15 char flag14 :1; //bit 14 char flag13 :1; //bit 13 char flag12 :1; //bit 12 char flag11 :1; //bit 11 char flag10 :1; //bit 10 char flag9 :1; //bit 09 char flag8 :1; //bit 08 char flag7 :1; //bit 07 char flag6 :1; //bit 06 char flag5 :1; //bit 05 char flag4 :1; //bit 04 char flag3 :1; //bit 03 char flag2 :1; //bit 02 char flag1 :1; //bit 01 char flag0 :1; //bit 00 ; struct campo_de_bits reg_flags = 0x11111111; // só é possível inicializar os 8 primeiros bits do campo de bits. #define emergencia reg_flags.flag15 //O bit flags15 recebe o nome emergência. void main (void) while(1) // rotina principal reg_flags.flag0 = 0; // escrita de um bit if (reg_flags.flag1 == 1)// O bit é igual a um? reg_flags.flag2 = 0; // sim, reg_flags.flag3 = 0; reg_flags.flag4 = 0; emergencia = 1; PORTBbits.RB0 = reg_flags.flag5; // leitura do flag5 PORTC = reg_flags;

Page 143: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 141

Uniões

Uma union permite compartilhar a mesma posição de memória RAM, com outras variáveis. E uma forma de economizar memória RAM.

Já que podemos economizar espaço na memória, como definimos a quantidade de RAM usada por uma union? Já que estamos compartilhando as mesmas posições de memória entre as variáveis da union, basta saber qual é a maior variável desta union, este é define a quantidade de memória necessária para a union.

Como criamos uma union? Uma union pode ter variáveis de mesmo tipo ou tipos diferentes. Para criarmos uma union basta utilizar o

comando union, escolher um nome e definir as suas variáveis, observe sua sintaxe. Sintaxe: union nome_da_union tipo variável; tipo variável; ; ou union nome_da_union tipo variável; tipo variável; variável;

Exemplo de union.

union teste unsigned char reg1; // variável de 8 bits

unsigned int reg2; // variável de 16 bits unsigned short reg3; // variável de 24 bits

unsigned long reg4; // variável de 32 bits unsigned char reg5[4]; // matriz de 4 bytes, 32 bits

variável;

Área da memória RAM utilizada pela Union

Registradores 1o byte 2o byte 3o byte 4o byte reg1 reg2 reg3 reg4 reg5

Neste nosso exemplo utilizamos 4 bytes de RAM para 5 variáveis, obviamente uma union compartilha os

4 bytes para as 5 variáveis. Qualquer variável que tiver o seu conteúdo modificado, modificará o conteúdo do byte correspondente da

union. Veja, através da matriz reg5, teremos acesso a qualquer posição de memória da matriz.

Acessando os elementos de uma union Da mesma maneira que lemos ou escrevemos em uma variável de uma estrutura, faremos com uma

union. Veja no exemplo:

union teste

unsigned char reg1; // variável de 8 bits unsigned int reg2; // variável de 16 bits unsigned short reg3; // variável de 24 bits unsigned long reg4; // variável de 32 bits unsigned char reg5[4]; // matriz de 4 bytes, 32 bits

registrador;

Page 144: Apostila Mosaico Pic MÓDULO4

142

Escrevendo em um elemento de uma union Para realizar a escrita você deve escrever o nome da variável da union “ponto” o nome do elemento da

union e igualar ao valor desejado, pode ser uma constante ou variável. Veja: registrador.reg1 = 0x55; Podemos simplificar o trabalho, utilizando a diretiva define (substituição de texto). #define registrador_1 registrador.reg1 Agora podemos realizar a escrita em reg1 desta forma: Registrador_1 = 0x55;

Leitura de um elemento de uma union Para realizar a leitura você deve escrever o nome da variável que receberá o dado da variável da union,

igual a nome da variável da union “ponto” o nome do elemento da union. Veja: PORTB = registrador.reg1; Podemos simplificar o trabalho, utilizando a diretiva define (substituição de texto). #define registrador_1 registrador.reg1 Agora podemos realizar a escrita em reg1 desta forma: PORTB = Registrador_1;

Variáveis Enumeradas

Uma enumeração é um conjunto de constantes inteiras que utilizaremos para carregar a variável enumerada.

Pense na seguinte situação: Você está desenvolvendo um projeto que utiliza um display de LCD ,16X2 por exemplo, e este sistema terá pelo menos 20 telas de ajuste.

Para a seleção das telas você está utilizando uma variável, e de acordo com o valor da variável você sabe qual é a tela que deve ser carregada. Onde entra as enumerações neste assunto?

Ao invés de utilizar números você utilizará nomes para determinar qual é a tela que devemos carregar. Vejamos como fica a sintaxe deste tipo de variável.

enum tipo_de_enumeração

constante_1, constante_2, constante_3, constante_n variável _enumerada;

O valor de cada constante pode ser definido, podemos utilizar o valor padrão. Utilizando o valor padrão a primeira constante equivale a zero, a segunda equivale a um e assim por

diante. Veja no exemplo:

Exemplo: enum controle_de_tela

tela_configuracao; tela_setup, tela_alarme, tela_supervisorio selecao_de_tela;

Veja na tabela abaixo o valor de cada constante enemerada.

Constante enumerada Valor da constante tela_configuracao 0

tela_setup 1 tela_alarme 2

tela_supervisorio 3

Page 145: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 143

Agora em se querendo definir o valor da constante, devemos tomar o seguinte procedimento: Sintaxe: enum tipo_de_enumeração

constante_1 = valor da constante, constante_2, constante_3, constante_n variável _enumerada; Exemplo: enum controle_de_tela

tela_configuracao = 2; tela_setup, tela_alarme, tela_supervisorio selecao_de_tela; Agora veja na tabela o valor de cada constante.

Constante enumerada Valor da constante tela_configuracao 2

tela_setup 3 tela_alarme 4

tela_supervisorio 5

Operações com variáveis enumeradas Como estamos falando em variável, com uma variável enumerada podemos realizar qualquer operação

lógica ou aritmética. Desta forma podemos utilizar estas variáveis em testes condicionais, para tomada de decisão.

Ponteiros

Os ponteiros são utilizados para acesso indireto a memória RAM, são muito utilizados para acessar variáveis dinâmicas, para leitura de matrizes mais rápido e para que funções possam modificar o valor de argumento de rotinas que fizeram a chamada da função.

Definindo um ponteiro Os ponteiros são criados para apontar para um tipo especifico de variável. Para variáveis do tipo char,

criaremos um ponteiro do tipo char, para uma variável do tipo short long criaremos um ponteiro de mesmo tipo, o mesmo é valido para os outros tipos de variáveis.

Um ponteiro é definido pelo caractere “*”, assim quando estivermos criando um ponteiro o nome da variável deve vir precedido do asterisco, “*”.

A sintaxe ficará assim: tipo *nome_do_ponteiro; Exemplo: char *ponteiro_char; int * ponteiro_int; Todo ponteiro deve ser iniciado com um endereço de um local conhecido, desta forma evitamos

problemas com acesso a posições de memória indesejada.

Carregando um endereço no ponteiro Com um ponteiro já definido, devemos carregar o endereço que desejamos acessar. Esta operação será realizada através do operador “&”, aplicando este operador a uma variável teremos

como retorno o endereço da variável. Sintaxe: ponteiro = &nome_da_variável;

Page 146: Apostila Mosaico Pic MÓDULO4

144

Como podemos observar o ponteiro foi iniciado com o endereço da variável. Agora podemos acessar de forma indireta o conteúdo de uma determinado posição de memória. No exemplo que veremos, vamos carregar na variável ponteiro o endereço da variável auxiliar e através

do ponteiro, copiar o conteúdo da variável auxiliar para a variável contador. Exemplo: #pragma idata MY_DATA2=0x200 char *ponteiro; char auxiliar = 0x10; char contador = 0x00; ponteiro = &auxiliar; contador = *ponteiro;

0x000x100x300x40

0x2000x2010x2020x2030x204

auxiliarcontador

Antes ponteiro = &auxiliar;ponteiro

contador = *ponteiro;

0x40

0x2010x100x300x40

0x2000x2010x2020x2030x204

auxiliarcontador

ponteiro

0x40

0x2100x100x100x40

0x2000x2010x2020x2030x204

auxiliarcontador

ponteiro

0x40

Operações com ponteiros Aos realizar operações com ponteiros, devemos ter cuidado, pois carregando um endereço errado no

ponteiro, estaremos apontando para uma posição de memória indesejada, este erro de programação pode nos custar horas de analise para encontrar o problema.

As operações de incremento e decremento são muito utilizadas em ponteiros. Temos de tomar cuidado com quem está sendo realizada a operação, com o ponteiro ou com a posição de memória apontada por ele.

Veja o exemplo a seguir: #pragma idata MY_DATA2=0x200 char *ponteiro; char auxiliar = 0x10; char contador = 0x00; char tempo = 0x40; ponteiro = &auxiliar; *ponteiro++; contador = *ponteiro; ponteiro++; tempo = *ponteiro;

Acompanhe pelo desenho o que acontece com a memória RAM.

Page 147: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 145

0x000x100x300x40

0x2000x2010x2020x2030x204

auxiliarcontador

Antes ponteiro = &auxiliar;ponteiro

*ponteiro++;

0x40

0x2010x100x300x40

0x2000x2010x2020x2030x204

auxiliarcontador

ponteiro

0x40

0x2100x110x300x40

0x2000x2010x2020x2030x204

auxiliarcontador

ponteiro

0x40

tempo

tempo

tempo

contador = *ponteiro;0x2100x110x110x40

0x2000x2010x2020x2030x204

auxiliarcontador

ponteiro

0x40tempo

ponteiro++;0x2020x110x110x40

0x2000x2010x2020x2030x204

auxiliarcontador

ponteiro

0x40tempo

tempo = *ponteiro;0x2100x110x110x11

0x2000x2010x2020x2030x204

auxiliarcontador

ponteiro

0x40tempo

Veja na operação *ponteiro++, foi incrementado o conteúdo da posição de memória apontado, resultou em auxiliar = 11.

Agora na linha de comando ponteiro++, tivemos o conteúdo da posição de memória ponteiro incrementado, o que fez o ponteiro apontar para o endereço 0x202.

Page 148: Apostila Mosaico Pic MÓDULO4

146

Capítulo 16 - McMaster – Desenvolvimento de Sistemas com Microcontroladores PIC

Introdução

O McMaster é um equipamento para desenvolvimento de sistemas completo para o estudo da tecnologia de microcontroladores Microchip e em particular ao estudo dos microcontroladores PIC16F877A, PIC18F452, PIC18F4520 e compativeis. Na verdade, este sistema serve para muito mais que simplesmente o aperfeiçoamento dos conhecimentos da família PIC. Com ele o usuário é capaz de criar projetos completos, colocando em teste também a eficiência de seus conceitos e algoritmos.

Tudo isso é possível porque este sistema foi criado e desenvolvido pensando na didática de ensino e nos problemas mais comuns do mercado em relação ao uso de microcontroladores.

Visão Macro do Sistema

Nesta seção será abordado através de uma visão macro o conceito do sistema utilizado no McMaster. Ele é composto de um gravador para o microcontrolador, o microcontrolador PIC central, os periféricos ligados

ao microcontrolador, aos quais daremos o nome de periféricos padrão e um conector de expansão para experiências onde novos periféricos, aos quais daremos o nome de periféricos adicionais, poderão ser ligados.

Um dos periféricos padrão do MCMASTER é o módulo de comunicação serial RS232. Como o gravador também utiliza comunicação serial RS232 para se comunicar com o MPLAB e no MCMASTER existe apenas uma saída serial, este recurso deve ser compartilhado para que tanto o gravador como o módulo RS232 do sistema possam utilizar a mesma saída. Desta forma, o usuário deverá escolher, através do botão localizado acima do microcontrolador, onde a serial deverá ser aplicada, no gravador ou no microcontrolador.

Todos os I/Os do microcontrolador estão disponíveis no conector de expansão para experiências. Com exceção dos pinos RB6 e RB7 que são utilizados pela gravação in-circuit, todos os outros I/Os estão ligados diretamente ao conector, ou seja, sem nenhum tipo de proteção. Apenas os pinos RB6 e RB7 foram isolados. Por este motivo, é muito importante que o usuário configure corretamente os I/Os do microcontrolador quando for utilizar o conector de expansão, pois neste caso, uma ligação errada pode danificar o microcontrolador. Se o usuário utilizar o conector de expansão apenas com placas oficiais de experiências a preocupação com a direção dos I/Os do microcontrolador não precisa ser tomada, uma vez que as placas de experiências e todo o MCMASTER foram projetados a fim de evitar que uma configuração errada do microcontrolador coloque o sistema em risco. Portanto, mesmo que um pino do microcontrolador seja configurado como saída quando o correto seria entrada a integridade do sistema está garantida. É claro que este erro pode acarretar num mau funcionamento do sistema projetado, porém nunca existirá risco ao MCMASTER e às placas de experiências, desde que as mesmas sejam oficiais e/ou homologadas pelo fabricante.

Para evitar que módulos padrão do MCMASTER venham a atrapalhar o correto funcionamento de uma eventual placa de experiências optou-se pela utilização de jumpers de configuração para que pontos importantes do circuito possam ser desabilitados e as vias do microcontrolador possam ser utilizadas apenas pelas placas de experiências e não mais nos módulos padrão. Desta forma, foram criados 7 jumpers. Começando de cima para baixo os jumpers são:

• Comunicação TX (RC6) – Este jumper desliga o pino RC6 (TX da USART do PIC – utilizado para

comunicação padrão RS232) do microcontrolador deixando-o disponível apenas no conector de expansão. • Comunicação RX (RC7) – Da mesma forma que o jumper anterior, este jumper desliga o pino RC7 (RX da

USART do PIC – utilizado para comunicação padrão RS232) do microcontrolador deixando-o disponível apenas no conector de expansão.

• Data I2C (RC4) – Este jumper desliga o pino RC4 (via de dados para comunicação I2C) do microcontrolador deixando-o disponível apenas no conector de expansão.

• Clock I2C (RC3) – Este jumper desliga o pino RC3 (via de clock para comunicação I2C) do microcontrolador deixando-o disponível apenas no conector de expansão.

• Coluna 1 (RB0) – Este jumper desliga o pino RB0 utilizado para ler os botões da coluna 1 do teclado matricial deixando-o disponível apenas no conector de expansão.

• Linha 1 / Display Milhar (RB4) – Este jumper desliga o pino RB4 utilizado para ativar a linha 1 do teclado matricial e o display do milhar deixando-o disponível apenas no conector de expansão.

Page 149: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 147

• Leds Especiais (RC0, RC1 e RC2) – Este jumper desabilita os leds ligados aos pinos RC0, RC1 e RC2 utilizados pelos módulos CPP e TIMER1 do microcontrolador.

Módulos Padrão

Nesta seção serão abordados cada um dos módulos padrão do MCMASTER.

Microcontrolador O sistema pode utilizar os microcontroladores, PIC16F877A, ou PIC 18F452, ou ainda o PIC 18F4520, como

centro de todo o hardware. Este microcontrolador está ligado a todos os periféricos disponíveis, possibilitando o estudo de práticamente todas as suas funções. Devido também ao grande poder de recursos deste modelo de PIC, é possível, junto aos demais recursos da placa, o desenvolvimento de projetos simples e/ou complexos, como por exemplo um controlador de temperatura com algoritmo de controle PID.

LCD alfanumérico Nos dias de hoje, qualquer programador sabe da importância da interface com o usuário dentro de um sistema

qualquer. Por isso, é muito importante o aprendizado de operação de um display do tipo LCD. No caso do MCMASTER, este display possui 2 linhas de 16 caracteres cada, sendo um padrão de mercado atual. Possui um chip de controle próprio, com o qual é realizada a interface com o microcontrolador. Com este periférico os sistemas desenvolvidos no MCMASTER poderão possuir telas explicativas, informações claras e menus de navegação.

A comunicação com o LCD é paralela com 8 vias de dados. Além destas, mais duas vias são utilizadas para controlar o LCD, uma denominada de ENABLE e a outra de RS.

A comunicação com o LCD é somente de escrita, desta forma, o pino de R/W do LCD está diretamente ligado ao terra (GND), não permitindo a leitura do mesmo.

As 8 vias de dados do LCD estão ligadas ao PORTD do microcontrolador, de RD0 (LSB) até RD7 (MSB). O pino de ENABLE está conectado ao pino RE1 do PIC e o pino RS do LCD ao pino RE0 do microcontrolador.

Assim, o esquema de ligação segue a tabela abaixo:

PIC LCD RD0...RD7 D0...D7

RE0 RS RE1 ENABLE

Terra (GND) R/W Para maiores informações a respeito do LCD pode-se consultar o data sheet contido no CD que acompanha o

MCMASTER.

Displays de leds com 7 segmentos Como já visto, o LCD é uma ótima ferramenta de informação ao usuário, porém, muitas vezes ele ainda é

inviável. Pode-se comentar alguns motivos desta inviabilidade: custos, capacidade de visualização, iluminação, etc. Por isso, em muitos projetos, os velhos e práticos displays de leds ainda são a melhor alternativa. No MCMASTER optou-se pela utilização de displays de 7 segmentos, que são numéricos, mas que permitem a visualização de diversas letras através da combinação específica destes segmentos. Optou-se também por 4 dígitos, todos com os segmentos interligados e os controles (comum) independentes, possibilitando a operação por varredura.

Atualmente, é muito comum encontrar em produtos do mercado, a combinação de ambos os tipos de display, para uma visualização mais completa e eficiente. Com o MCMASTER esta combinação também é possível.

A conexão dos displays com o microcontrolador segue a tabela abaixo: PIC Segmento RD0 A RD1 B RD2 C RD3 D RD4 E RD5 F RD6 G RD7 DP

Page 150: Apostila Mosaico Pic MÓDULO4

148

E as vias de seleção de cada um dos displays, a tabela seguir:

PIC Display RB4 Milhar RB5 Centena RB6 Dezena RB7 Unidade

Para a ativação dos displays deve-se selecionar nível lógico 1 nos pinos de seleção. Os segmentos também

são ativados com nível lógico 1.

Leds O MCMASTER possui um grupo de 8 leds que compartilha o mesmo barramento que os displays de 7

segmentos e o display LCD. Desta forma, o seu acionamento deve ser feito via varredura sendo que os leds estão conectados ao PORTD e

a seleção é feita pelo pino RA4. Da mesma forma que os displays, os leds são ativados com nível lógico 1, tanto na via de seleção (RA4) como individualmente (PORTD).

Teclado matricial A maioria dos sistemas desenvolvidos atualmente utilizam algum tipo de teclado para a entrada de dados pelo

usuário. O MCMASTER está provido de um teclado matricial de 4 linhas e 4 colunas, totalizando 16 teclas. O acionamento das linhas do teclado é feito simultaneamente com os comuns dos displays de 7 segmentos. Desta forma, ao acionar o display da unidade aciona-se também a linha 4 do teclado matricial. Junto com o display da dezena a linha 3 e assim por diante.

A tabela abaixo mostra esta relação:

Pino PIC Estado Teclado Matricial Display de 7 segmentos 1 linha 4 ativada unidade ativada

RB7 0 linha 4 desativada unidade desativada

1 linha 3 ativada dezena ativada RB6

0 linha 3 desativada dezena desativada

1 linha 2 ativada centena ativada RB5

0 linha 2 desativada centena desativada

1 linha 1 ativada milhar ativada RB4

0 linha 1 desativada milhar desativada

As colunas podem ser lidas através dos pinos RB0, RB1, RB2 e RB3, conforme a tabela a seguir:

Pino PIC Estado Teclado Matricial 1 Alguma tecla pressionada na coluna 1

RB0 0 Nenhuma tecla pressionada na coluna 1

1 Alguma tecla pressionada na coluna 2 RB1

0 Nenhuma tecla pressionada na coluna 2

1 Alguma tecla pressionada na coluna 3 RB2

0 Nenhuma tecla pressionada na coluna 3

1 Alguma tecla pressionada na coluna 4 RB3

0 Nenhuma tecla pressionada na coluna 4

Vale observar que para o correto funcionamento do teclado os jumpers relacionados com os pinos RB0 e RB4

devem estar configurados na posição ON.

Page 151: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 149

Buzzer Para chamar a atenção do usuário e confirmar certas ações, cada vez mais os sistemas estão fazendo uso de

técnicas sonoras, seja através de simples bips ou por complexas melodias. Para que os usuários não fiquem sem o uso deste recurso, disponibilizou-se também um buzzer piezoelétrico com oscilação comandada diretamente pelo PIC, tornando possível a criação de sons diversos.

O microcontrolador deve então gerar (através do software) uma onda quadrada capaz de excitar o buzzer. Para gerar um simples beep pode-se utilizar uma onda quadrada com freqüência em torno de 650Hz e duração aproximada de 100ms.

O buzzer está conectado ao pino RE2 do microcontrolador.

Memória E2PROM externa Além da memória E2PROM interna do PIC, o MCMASTER possui ainda uma memória externa do tipo serial,

modelo 24LC256 com 32Kbytes disponíveis para uso. Esta memória está soquetada na placa, possibilitando a sua substituição por outros modelos compatíveis, com maior ou menor capacidade.

A comunicação com esta memória é do tipo I²C, estando diretamente ligada os pinos do PIC responsáveis por este padrão de comunicação.

Assim: PIC Memória

RC3 Clock (SCL) – pino 6

RC4 Data (SDA) – pino 5

Novamente os jumpers de configurações relacionados devem estar habilitados para a utilização da memória serial externa.

Como a memória serial compartilha o mesmo barramento I2C do relógio de tempo real (PCF8583P) se faz necessária a utilização de endereços diferentes para que o barramento seja compatível com os dois periféricos. Sendo assim, escolheu-se o endereço 7h (111b) para a memória serial. Para maiores informações sobre o protocolo de comunicação da memória serial 24LC256 pode-se consultar o data sheet disponível no CD.

Relógio de tempo real (RTC) Utilizando o mesmo barramento I2C da memória serial, o MCMASTER possui um relógio de tempo real,

modelo PCF8583P. Com este componente o usuário poderá criar sistemas que contenham informações como a hora e a data atual. O relógio utilizado é completo, ou seja, é capaz de contar dia, mês, ano (inclusive bissexto), semana, hora, minuto, segundo e milésimo de segundo. Além de poder ser configurado de formas diferentes. O data sheet deste componente está disponível no CD que acompanha o MCMASTER.

Pelo mesmo motivo já comentado na memória serial, o relógio foi configurado para utilizar o endereço 0h (000b) a fim de poder compartilhar o mesmo barramento I2C.

Como no caso da memória, os pinos responsáveis pela comunicação são:

PIC Relógio RTC RC3 Clock (SCL) – pino 6

RC4 Data (SDA) – pino 5

Comunicação serial RS-232 Quem não deseja que seu projeto se comunique com um computador atualmente? Esta é outra tendência de

mercado que os profissionais não podem deixar de lado. Seja para a configuração de parâmetros, para a coleta de dados ou a visualização gráfica de informações, a interligação entre o kit e o computador é um recurso que não poderia ser deixado de lado.

Optou-se pela comunicação serial, padrão RS-232 através de um conector DB-9. A interface e ajuste de tensões necessárias a este padrão, em relação à operação do PIC (TTL) é feita por um CI dedicado. Internamente, as vias de TX e RX podem ser ligadas aos pinos da USART do PIC, possibilitando o uso deste recurso.

Para habilitar este recurso é necessário que os jumpers apropriados estejam na posição ON. A ligação ao microcontrolador segue a tabela abaixo.

Page 152: Apostila Mosaico Pic MÓDULO4

150

PIC COM.

RC6 TX (saída)

RC7 RX (entrada)

Como a porta de comunicação é compartilhada com o gravador é necessário também selecionar a serial para

o PIC através do botão de modo de utilização. Faz parte também do módulo de comunicação serial, o conector DB9 fêmea que segue a pinagem abaixo:

Pino Função

1 -

2 TX (saída)

3 RX (entrada)

4 -

5 Terra (GND)

6 -

7 CTS (utilizado apenas pelo gravador)

8 RTS (utilizado apenas pelo gravador)

9 -

Conversão analógica / digital (A/D) É verdade que estamos considerando o mundo cada vez mais digital, principalmente nos dias de hoje, onde

vemos bilhões de informações trafegando por fibras ópticas e imagens de computador recriando o mundo real. Mas não podemos esquecer que a natureza é completamente analógica, e qualquer sistema que se baseie ou utilize informações deste meio externo precisará de um sistema de conversão para poder se comunicar. É por isso que, hoje e sempre, a conversão A/D é tão necessária.

Com o MCMASTER poderemos realizar estas conversões de duas maneiras. A primeira é através do conversor interno do PIC e a segunda é através de um pseudoconversor fundamentado no tempo de carga de um circuito RC.

Dentre os módulos padrão existem dois sistemas para trabalhar com o conversor A/D e para qualquer um deles, as duas formas de aquisição podem ser aplicadas, ou seja, tanto via A/D convencional como via RC. O primeiro sistema consiste num potenciômetro e o segundo num conjunto de jumpers que podem ser configurados como divisor resistivo ou circuito RC.

Potenciômetro O sistema com o potenciômetro segue o esquema elétrico representado a seguir.

+-

+5V

RA0

LM358

10K

4,7K 330R

1uF

A tensão de entrada presente no pino RA0 do microcontrolador pode ser ajustada entre 0 e 5V. Caso se utilize

o conversor A/D interno do PIC, o capacitor de 1uF e o resistor de 4K7 formam um filtro passa baixa útil para filtrar ruídos e deixar o sinal de entrada mais estável.

Caso se utilize o sistema de leitura via RC o conjunto de resistores e capacitores assume outra função. Neste sistema, para realizar a conversão deve-se executar as etapas a seguir:

• Inicialmente, através do software, deve-se descarregar o capacitor, colocando o pino do microcontrolador como saída em nível lógico 0. O capacitor se descarregará pelo resistor de 330R;

Page 153: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 151

• Após o capacitor estar descarregado, coloca-se o pino do microcontrolador em entrada e começa-se a contar o tempo que o capacitor leva para se carregar (através do resistor de 4K7), ou seja, quanto tempo o capacitor leva para atingir nível lógico 1;

• Como tempo de carga é inversamente proporcional à tensão aplicada pelo potenciômetro, sabendo-se o tempo de carga pode-se estimar a tensão aplicada.

Jumpers O sistema de jumpers está ligado ao pino RA5 do microcontrolador e segue o esquema elétrico representado a

seguir.

+5V

3 2 1JP4

Divisor R

esistivo

Divisor C

apacitivo

1 2 3

JP3

1 2 3

JP2

1 2 3

JP1

22K

33K

47K330R

10K100nF

Jumpers RA5

Posição 1

Posição 2

Posição 3

ON OFF

RA5

Se configurarmos o sistema para divisor resistivo, basta ler com o conversor A/D do PIC a tensão presente no

pino RA5 para estimar a posição do jumper. Se configurarmos o sistema para resistor/capacitor, devemos seguir a mesma metodologia explicada no caso

do potenciômetro, ou seja: • Inicialmente descarregar o capacitor através do resistor de 330R colocando o pino do microcontrolador

como saída em nível lógico 0. • Após o capacitor estar descarregado, colocar o pino do microcontrolador em entrada e começar a contar o

tempo que o capacitor leva para se carregar, ou seja, quanto tempo o capacitor leva para atingir nível lógico 1. • Este tempo de carga é proporcional ao valor do circuito RC e portanto, pode ser utilizado para determinar a

posição do jumper.

Page 154: Apostila Mosaico Pic MÓDULO4

152

Periféricos Adicionais

A seguir serão explanados os periféricos adicionais contidos na placa de experiências EXP01 que acompanha o kit MCMASTER.

Placa de experiências EXP01 Entre outras funções a placa de experiências EXP01 possui um sistema completo para monitoramento e

controle de temperatura, com um sensor e dois atuadores. Desta forma, tem-se um sensor de temperatura, um atuador de aquecimento (resistência controlada por PWM) e um atuador de resfriamento (ventilador controlado por PWM). Além disso, um sistema óptico ligado às hélices do ventilador é capaz de criar um tacógrafo, para monitoramento e controle de rotação.

Possui também uma lâmpada incandescente além de gerar uma tensão de referência estável em 2,5V que pode ser utilizada como referência para o conversor A/D.

Com tudo isso pode-se criar experimentos e projetos complexos de controle, começando em um simples controle ON/OFF até um avançado controlador PID.

Sensor de temperatura A placa possui um circuito que utiliza um diodo de sinal como elemento sensor do medidor de temperatura

ambiente. O sinal analógico proporcional à temperatura ambiente está presente no pino RA1 do microcontrolador e varia entre 0 e 5V.

Deve-se evitar que a temperatura ultrapasse 90ºC a fim de evitar que o sensor seja danificado.

Aquecedor O aquecedor consiste numa resistência de 68Ω com 5W de dissipação. Pode ser acionada através do pino

RC2 do microcontrolador. Veja que este pino pode ser configurado como PWM, e portanto, a potência de aquecimento pode ser regulada através deste recurso.

Ventilador O sistema de ventilação consiste num cooler de PC que pode ser ativado através do pino RC1 do

microcontrolador. Assim como no caso do aquecedor, este pino pode ser configurado como PWM, desta forma, pode-se modular a velocidade do ventilador utilizando este recurso do microcontrolador.

Tacômetro Junto ao ventilador existe um sistema formado por um transmissor e um receptor de infravermelho. Este

sistema é utilizado para medir a velocidade de rotação do ventilador. Quando não temos a passagem de luz, ou seja, quando a luz está interrompida por uma das palhetas do ventilador, o sistema de tacômetro apresentará na saída nível lógico 1. Quando se tem a passagem de luz, a saída do sistema de tacômetro será 0. O tacômetro está conectado ao pino RC0 (entrada de contador do TMR1) do microcontrolador.

Lâmpada incandescente Consiste numa lâmpada incandescente de 12V que pode ser acionada através do pino RC5 do

microcontrolador. Com nível lógico 1 a lâmpada acende e com nível lógico 0 a lâmpada apaga.

Tensão de referência O circuito medidor de temperatura ambiente utiliza uma tensão de referência fixa e estável em 2,5V e como

este recurso já estava presente na placa de experiências EXP01 resolveu-se também disponibilizar este recurso ao usuário. Assim, a tensão de referência de 2,5V foi conectada ao pino RA3 do PIC que pode ser configurado para utilizar este pino como entrada de referência externa do conversor A/D. Isto permite que o conversor A/D possa trabalhar em outra faixa de conversão e conseqüentemente com outra resolução.

Gravador

Para utilizar o gravador presente no MCMASTER basta selecionar corretamente a saída serial e utilizar o software de desenvolvimento MPLAB da Microchip. Por se tratar de um gravador in-circuit o microcontrolador não precisa ser retirado da placa.

Ao habilitar o gravador no MPLAB o software atual do PIC16F877A ou do PIC18F452 será paralisado e instantes após o final da gravação do novo software, o microcontrolador será automaticamente inicializado.

Page 155: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 153

Capítulo 17 - Experiências

Experiência 1 - Leitura de uma tecla e acionamento de um led

Objetivo

O objetivo desta experiência é ensinar ao aluno os primeiros passos sobre o microcontrolador. É apresentado o modo de configuração dos pinos de I/Os e os primeiros comandos utilizadas para testar condições nos pinos de entrada e alterações de estado nos pinos de saída, além de comandos para controle do fluxo do programa.

Descrição

Sistema muito simples para representar o estado de um botão através de um led. Com o botão pressionado o led é ligado e com o botão solto o led é apagado.

O software inicia configurando os pinos de I/Os através dos registradores TRIS e dos registradores de periféricos pertinentes. Em seguida, o software habilita a linha 4 do teclado matricial e o grupo de leds ligados ao PORTD. A partir daí, o software entra num loop infinito onde o botão da linha 1 coluna 4 é testado e seu estado reproduzido no led 0 ligado ao pino RD0.

Page 156: Apostila Mosaico Pic MÓDULO4

154

Esquema Elétrico

Page 157: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 155

Fluxograma

HABILITA LEDS

ACENDE LED

Não

Sim

ATIVA LINHA 4 DO TECLADO MATRICIAL

VETOR DE RESET PULA P/ INÍCIO DO

PROGRAMA

CONFIGURAÇÕES INICIAIS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION, ADs.

BOTÃO PRESS.?

INÍCIO

APAGA LED

Page 158: Apostila Mosaico Pic MÓDULO4

156

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 - Recursos Básicos de programação * * Exemplo 1 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 23/02/2005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este software está preparado para demonstrar o controle dos pinos de I/O // este primeiro programa demonstrará o estado de um botão por meio de um led. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //#pragma config OSC = XT //#pragma config WDT = ON //#pragma config LVP = OFF /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis Globais * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. //Este programa não utiliza nenhuma constante de usuário /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Page 159: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 157

* ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define BOTAO PORTBbits.RB0 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #define LED PORTDbits.RD0 //PORTA DO LED //0 -> APAGADO //1 -> ACESO #define C_LEDS PORTAbits.RA4 //PINO PARA ATIVAR GRUPO DE 8 LEDS //1 -> LEDS ATIVADOS //0 -> LEDS DESATIVADOS #define LINHA_4 PORTBbits.RB7 //PINO PARA ATIVAR LINHA 4 DO TECLADO //MATRICIAL //1 -> LINHA ATIVADA //0 -> LINHA DESATIVADA /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () PORTA = 0X00; //Clear PORTA PORTB = 0X00; //Clear PORTB PORTC = 0X00; //Clear PORTC PORTD = 0X00; //Clear PORTD PORTE = 0x00; //Clear PORTE LATA = 0X00; //Clear PORTA LATB = 0X00; //Clear PORTB LATC = 0X00; //Clear PORTC LATD = 0X00; //Clear PORTD LATE = 0x00; //Clear PORTE TRISA = 0b00101111; //CONFIG DIREÇÃO DOS PINOS PORTA TRISB = 0b00001111; //CONFIG DIREÇÃO DOS PINOS PORTB TRISC = 0b10011001; //CONFIG DIREÇÃO DOS PINOS PORTC TRISD = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTD TRISE = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTE ADCON1 = 0b00000111; //DESLIGA CONVERSORES A/D /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Sistema * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ C_LEDS = 1; //ATIVA LEDS LIGADOS AO PORTD LINHA_4 = 1; //ATIVA LINHA 4 DO TECLADO MATRICIAL /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(1) ClrWdt(); if (BOTAO) LED = 1; // testa botão. Se botão = 0, então led = 1 else LED = 0; // caso contrário, led = 0 // FIM DO PROGRAMA

Page 160: Apostila Mosaico Pic MÓDULO4

158

Exercícios Propostos

1. Altere a lógica do sistema, ou seja, com o botão pressionado o led deve permanecer apagado e com o botão liberado o led deve permanecer acesso.

2. Altere o software a fim de trocar a tecla ativa, passando por exemplo a utilizar a tecla da linha 4 coluna 2.

3. Altere o software para ligar/desligar outro led, por exemplo, o led ligado ao pino RD3.

Page 161: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 159

Experiência 2 – Pisca - Pisca

Objetivo

O objetivo desta experiência é ensinar ao aluno com utilizar as funções de delays além de apresentar uma técnica simples utilizada para inverter o estado de um bit.

Descrição

O software desta experiência utiliza um dos displays de 7 segmentos para implementar um pisca-pisca sendo que a freqüência é controlada através do uso da função de delay.

A função de delay é genérica é pode ser utilizada para gerar delays entre 1ms e 256ms. Na realidade, a rotina recebe um argumento passado pelo WORK para determinar o atraso que deve ser gerado, sempre em múltiplos de 1ms. Como o argumento é de 8 bits existem 256 possíveis delays, indo de 1ms até 256ms. Basta portanto, carregar o WORK com o delay desejado e chamar a rotina.

O pisca-pisca é visualizado no display de 7 segmentos na posição da unidade. Sempre que o delay é finalizado o PORTD deve ser invertido e para inverter o estado destes bits utilizou-se a operação lógica boleana XOR. Conforme a tabela verdade apresentada a seguir.

A B XOR 0 0 0 0 1 1 1 0 1 1 1 0

Pode-se verificar que sempre que a operação é realizada quando os bits da coluna A estão em 1 o resultado

fica invertido em relação à coluna B e sempre que os bits da coluna A estão em 0 o resultado se mantém em relação à coluna B. Assim, sempre que ser desejar inverter um bit, basta fazer uma operação XOR entre um bit em 1 e o bit que se deseja inverter.

Esta é uma técnica simples de inverter o estado de um bit sem testar o estado original. No software, pode-se utilizar as teclas da linha 4 colunas 1 e 2 para alterar o tempo do delay e

conseqüentemente a freqüência das piscadas do display. A tecla da coluna 1 incrementa o valor do delay enquanto a tecla da coluna 2 decrementa.

Page 162: Apostila Mosaico Pic MÓDULO4

160

Esquema Elétrico

Page 163: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 161

Fluxograma

Sim

1 Sim

Não

Não

Não

BOTÃO 2 PRESS.?

2

FIM DO MULTIPLICADOR?

HABILITA DISPLAY DA UNIDADE E LINHA 4 DO TECLADO MATRICIAL

INVERTE LEDS DO DISPLAY

Sim

CARREGA MULTIPLICADOR PARA O DELAY

VETOR DE RESET PULA P/ INÍCIO DO

PROGRAMA

CONFIGURAÇÕES INICIAIS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION, ADs.

BOTÃO 1 PRESS.?

INÍCIO

DELAY PROPORCIONAL AO VALOR DO

CONTADOR

CARREGA CONTADOR COM VALOR MÍNIMO

ATUALIZA DISPLAY3

Page 164: Apostila Mosaico Pic MÓDULO4

162

Sim

Não

Sim

Não CONTADOR<MÍN?

CONTADOR = CONTADOR - STEP

1

CONTADOR = MÍNIMO

BOTÃO 1 SOLTO?

3

Sim

Não

Sim

Não CONTADOR>MÁX?

CONTADOR = CONTADOR + STEP

2

CONTADOR = MÁXIMO

BOTÃO 2 SOLTO?

3

Page 165: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 163

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 - Recursos Básicos de programação * * Exemplo 2 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 23/02/2005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //PISCA-PISCA VARIÁVEL PARA DEMONSTRAR A IMPLEMENTAÇÃO DE DELAYS E A INVERSÃO //DE PORTAS. APENAS OS BOTÕES DA LINHA 4 ESTÃO ATIVADOS SENDO QUE O DA //COLUNA 1 É UTILIZADO PARA INCREMENTAR O TEMPO ENTRE AS PISCADAS. //O BOTÃO DA COLUNA 2 É UTILIZADO PARA DIMINUIR O TEMPO ENTRE AS PISCADAS. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config LVP = OFF /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis Globais * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário unsigned char CONTADOR; //BASE DE TEMPO PARA A PISCADA unsigned char TEMPO1; //REGISTRADORES AUXILIARES DE TEMPO /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define MIN 10 #define MAX 240 #define STEP 5 #define MULTIPLO 5

Page 166: Apostila Mosaico Pic MÓDULO4

164

//A CONSTANTE DISPLAY REPRESENTA O SÍMBOLO QUE APARECERÁ PISCANDO NO //DISPLAY. 1=LED LIGADO E 0=LED DESLIGADO. A RELAÇÃO ENTRE BITS E //SEGMENTOS É A SEGUINTE: '.GFEDCBA' // a // ********** // * * // f * * b // * g * // ********** // * * // e * * c // * d * // ********** *. #define DISPLAY 0b01110110 //(LETRA H) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define BT1 PORTBbits.RB0 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT2 PORTBbits.RB1 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #define DSP_UNIDADE PORTBbits.RB7 //PORTA DO LED //0 -> APAGADO //1 -> ACESO #define LINHA_4 PORTBbits.RB7 //PINO PARA ATIVAR LINHA 4 DO TECLADO //MATRICIAL //1 -> LINHA ATIVADA //0 -> LINHA DESATIVADA /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () PORTA = 0X00; //Clear PORTA PORTB = 0X00; //Clear PORTB PORTC = 0X00; //Clear PORTC PORTD = 0X00; //Clear PORTD PORTE = 0x00; //Clear PORTE

Page 167: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 165

LATA = 0X00; //Clear PORTA LATB = 0X00; //Clear PORTB LATC = 0X00; //Clear PORTC LATD = 0X00; //Clear PORTD LATE = 0x00; //Clear PORTE TRISA = 0b00101111; //CONFIG DIREÇÃO DOS PINOS PORTA TRISB = 0b00001111; //CONFIG DIREÇÃO DOS PINOS PORTB TRISC = 0b10011001; //CONFIG DIREÇÃO DOS PINOS PORTC TRISD = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTD TRISE = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTE ADCON1 = 0b00000111; //DESLIGA CONVERSORES A/D /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Sistema * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ DSP_UNIDADE = 1; PORTD = DISPLAY; //ACENDE O VALOR CERTO NO DISPLAY CONTADOR = MIN; //INICIA CONTADOR COM VALOR MIN. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(1) ClrWdt(); TEMPO1 = MULTIPLO; do Delay1KTCYx(CONTADOR); if (BT1) if (CONTADOR != MAX) CONTADOR = CONTADOR + STEP; //INC O CONTADOR EM STEP if (BT2) if (CONTADOR != MIN) CONTADOR = CONTADOR - STEP;//DEC. O CONTADOR EM STEP while (--TEMPO1); //VOLTA PARA O INICIO ENQUANTO //TEMPO1 DIFERENTE DE ZERO. PORTD = PORTD ^ DISPLAY; //INVERTE O PORTD // FIM DO PROGRAMA

Page 168: Apostila Mosaico Pic MÓDULO4

166

Exercícios Propostos

1. Alterar a rotina de delay para gerar um delay fundamental de 100us. 2. Alterar a rotina de delay para gerar um delay fundamental de 10ms. 3. Incluir o tratamento de debounce nas teclas

Page 169: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 167

Experiência 3 - Dimmer

Objetivo

O objetivo desta experiência é ensinar ao aluno como regular a potência fornecida a pequenas cargas através do microcontrolador. Para isso, é proposto um dimmer para uma lâmpada incandescente onde a potência de lâmpada é regulada através do uso de um PWM criado no software.

Descrição

Software que utiliza dois botões para incrementar e decrementar a intensidade da lâmpada. A interrupção de tmr0 é utilizada para controlar o PWM que aciona a lâmpada. A intensidade também é mostrada no display da unidade.

Os botões ativos são os da linha 4. O botão da coluna 1 incrementa a intensidade da lâmpada e o da coluna 2 decrementa a intensidade.

Foi criado um PWM com 4 bits de resolução de forma que existem 16 intensidades diferentes para a lâmpada. Para sua implementação, utilizou-se a interrupção de TMR0 sendo que a cada interrupção uma variável é incrementada. Esta variável é utilizada para subdividir o PWM em 16 intervalos. Comparando esta variável com o duty cycle ajustado pelo usuário, o software coloca o pino da lâmpada em nível lógico 1 ou 0, conforme a necessidade. A cada 16 interrupções o ciclo se repete e portanto o período do PWM é 16 vezes maior do que o período de uma interrupção. Este procedimento pode ser facilmente analisado pelo fluxograma da experiência.

Page 170: Apostila Mosaico Pic MÓDULO4

168

Esquema Elétrico

Page 171: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 169

Fluxograma

1 Sim

Sim

3

Não

BOTÃO 1 PRESS.?

RECARREGA FILTRO DE DEBOUNCE

HABILITA DISPLAY DA UNIDADE E LINHA 4 DO TECLADO MATRICIAL

VETOR DE RESET PULA P/ INÍCIO DO

PROGRAMA

CONFIGURA I/Os

INÍCIO

CARREGA INTENSIDADE COM VALOR MÍNIMO

Não

BOTÃO 2 PRESS.? 2

4

PRESCALER TMR0 -> 1:4

HABILITA INTERRUPÇÃO DE TMR0

ATUALIZA DISPLAY

Page 172: Apostila Mosaico Pic MÓDULO4

170

Sim

Sim

Não

Não

INTENSIDADE = MÍNIMO ?

FIM FILTRO DEBOUNCE? 4

DECREMENTA INTENSIDADE

1

3

3

Sim

Sim

Não

Não

INTENSIDADE = MÁXIMO ?

FIM FILTRO DEBOUNCE? 4

INCREMENTA INTENSIDADE

1

3

3

Page 173: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 171

Não

Sim

período de 1ms

Não

INT. TMR0

Sim

Sim

Não

INTENSIDADE = 15 ?

TEMP0 = 16 ?

RECARREGA TMR0 COM 6d

DESLIGA LÂMPADA

ZERA TEMP0

LIGA LÂMPADA

LIMPA FLAG DA INTERRUPÇÃO

SALVA CONTEXTO

SAI DA INTERRUPÇÃO

INTENSIDADE > TEMP0 ?

RECUPERA CONTEXTO

INCREMENTA TEMP0

Page 174: Apostila Mosaico Pic MÓDULO4

172

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 - Recursos Básicos de programação * * Exemplo 3 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 23/02/2005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //SOFTWARE QUE UTILIZA DOIS BOTÕES PARA INCREMENTAR E DECREMENTAR A //INTENSIDADE DA LÂMPADA. A INTERRUPÇÃO DE TMR0H É UTILIZADA PARA CONTROLAR //O PWM QUE ACIONA A LÂMPADA. A INTENSIDADE TAMBÉM É MOSTRADA NO DISPLAY //DA UNIDADE. //OS BOTÕES ATIVOS SÃO O DA LINHA 4 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config LVP = OFF /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis Globais * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário unsigned char INTENSIDADE; //ARMAZENA O VALOR DA CONTAGEM unsigned char FILTRO11; //FILTRAGEM 1 PARA O BOTÃO 1 unsigned char FILTRO12; //FILTRAGEM 2 PARA O BOTÃO 1 unsigned char FILTRO21; //FILTRAGEM 1 PARA O BOTÃO 2 unsigned char FILTRO22; //FILTRAGEM 2 PARA O BOTÃO 2 unsigned char TEMPO; //INTERVALOS DE 1 MS /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define MIN 0 #define MAX 15 #define T_FILTRO 25 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Page 175: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 173

//A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário struct unsigned BIT0:1; unsigned BIT1:1; unsigned BIT2:1; unsigned BIT3:1; unsigned BIT4:1; unsigned BIT5:1; unsigned BIT6:1; unsigned BIT7:1; FLAGSbits; //ARMAZENA OS FLAGS DE CONTROLE #define ST_BT1 FLAGSbits.BIT0 //STATUS DO BOTÃO 1 #define ST_BT2 FLAGSbits.BIT1 //STATUS DO BOTÃO 2 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void TRATA_INT_TIMER0 (void); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define BT1 PORTBbits.RB0 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT2 PORTBbits.RB1 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #define DSP_UNIDADE PORTBbits.RB7 //PORTA DO LED //0 -> APAGADO

//1 -> ACESO #define LINHA_4 PORTBbits.RB7 //PINO PARA ATIVAR LINHA 4 DO TECLADO //MATRICIAL //1 -> LINHA ATIVADA //0 -> LINHA DESATIVADA #define LAMPADA PORTCbits.RC5 //DEFINE PINO DA LAMPADA //0 -> LÂMPADA APAGADA //1 -> LÂMPADA ACESA // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * ROTINA DE TRATAMENTO DE INT DE TIMER0 * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * #pragma code TIMER0_interrupt = 0x8 void TIMER0_int (void) _asm goto TRATA_INT_TIMER0 _endasm #pragma code #pragma interrupt TRATA_INT_TIMER0 void TRATA_INT_TIMER0 (void) INTCONbits.TMR0IF = 0; //LIMPA FLAG DE INTERRUPÇÃO WriteTimer0(256 - 250); TEMPO++; if (TEMPO == 16)TEMPO = 0; if (TEMPO >= INTENSIDADE) LAMPADA = 0;

Page 176: Apostila Mosaico Pic MÓDULO4

174

else LAMPADA = 1; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * ROTINA DE CONVERSÃO BINÁRIO -> DISPLAY * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ESTA ROTINA IRÁ RETORNAR EM W, O SIMBOLO CORRETO QUE DEVE SER // MOSTRADO NO DISPLAY PARA CADA VALOR DE INTENSIDADE. O RETORNO JÁ ESTÁ // FORMATADO PARA AS CONDIÇÕES DE LIGAÇÃO DO DISPLAY AO PORTD. // a // ********** // * * // f * * b // * g * // ********** // * * // e * * c // * d * // ********** *. const rom unsigned char CONVERTE[16] = // .GFEDCBA POSIÇÃO CORRETA DOS SEGMENTOS 0b00111111, // 00 - RETORNA SÍMBOLO CORRETO 0 0b00000110, // 01 - RETORNA SÍMBOLO CORRETO 1 0b01011011, // 02 - RETORNA SÍMBOLO CORRETO 2 0b01001111, // 03 - RETORNA SÍMBOLO CORRETO 3 0b01100110, // 04 - RETORNA SÍMBOLO CORRETO 4 0b01101101, // 05 - RETORNA SÍMBOLO CORRETO 5 0b01111101, // 06 - RETORNA SÍMBOLO CORRETO 6 0b00000111, // 07 - RETORNA SÍMBOLO CORRETO 7 0b01111111, // 08 - RETORNA SÍMBOLO CORRETO 8 0b01101111, // 09 - RETORNA SÍMBOLO CORRETO 9 0b01110111, // 10 - RETORNA SÍMBOLO CORRETO A 0b01111100, // 11 - RETORNA SÍMBOLO CORRETO b 0b00111001, // 12 - RETORNA SÍMBOLO CORRETO C 0b01011110, // 13 - RETORNA SÍMBOLO CORRETO d 0b01111001, // 14 - RETORNA SÍMBOLO CORRETO E 0b01110001; // 15 - RETORNA SÍMBOLO CORRETO F /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () PORTA = 0X00; //Clear PORTA PORTB = 0X00; //Clear PORTB PORTC = 0X00; //Clear PORTC PORTD = 0X00; //Clear PORTD PORTE = 0x00; //Clear PORTE LATA = 0X00; //Clear PORTA LATB = 0X00; //Clear PORTB LATC = 0X00; //Clear PORTC LATD = 0X00; //Clear PORTD LATE = 0x00; //Clear PORTE TRISA = 0b00101111; //CONFIG DIREÇÃO DOS PINOS PORTA TRISB = 0b00001111; //CONFIG DIREÇÃO DOS PINOS PORTB TRISC = 0b10011001; //CONFIG DIREÇÃO DOS PINOS PORTC TRISD = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTD TRISE = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTE ADCON1 = 0b00000111; //DESLIGA CONVERSORES A/D /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Sistema * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ OpenTimer0(TIMER_INT_ON & T0_8BIT & T0_SOURCE_INT & T0_PS_1_4); DSP_UNIDADE = 1; ST_BT1 = 0; ST_BT2 = 0;

Page 177: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 175

INTENSIDADE = MIN; //INICIA INTENSIDADE = MIN WriteTimer0(256 - 250); //REINICIA TMR0H, SETA TIMER P/ 1ms PORTD = CONVERTE[INTENSIDADE]; //ATUALIZA O DISPLAY INICIALMENTE RCON = 0X00; INTCONbits.TMR0IE = 1; INTCONbits.GIEH = 1; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(1) ClrWdt(); FILTRO11 = 0; FILTRO21 = 0; FILTRO12 = T_FILTRO; FILTRO22 = T_FILTRO; while (BT1) if (--FILTRO11 == 0) FILTRO12--; if (FILTRO12 == 0) if (INTENSIDADE != MIN) if (!ST_BT1) INTENSIDADE--; PORTD = CONVERTE[INTENSIDADE]; ST_BT1 = 1; ST_BT1 = 0; // BOTÃO LIBERADO, LIMPA O FLAG while (BT2) if (--FILTRO21 == 0) FILTRO22--; if (FILTRO22 == 0) if (INTENSIDADE != MAX) if (!ST_BT2) INTENSIDADE++; PORTD = CONVERTE[INTENSIDADE]; ST_BT2 = 1; ST_BT2 = 0; // BOTÃO LIBERADO, LIMPA O FLAG // FIM DO PROGRAMA

Page 178: Apostila Mosaico Pic MÓDULO4

176

Dicas e Comentários

A técnica utilizada nesta experiência para implementar o PWM apresenta como inconveniente resultar em PWMs de baixa freqüência. Por exemplo, no caso desta experiência a interrupção ocorre a cada 1ms e como o PWM têm 4 bits de resolução, temos um período total de 16ms para o PWM. Isto significa que a freqüência é de 62,5Hz, ou seja, o PWM implementado via software apresenta baixa freqüência. Além disso, se ele fosse de por exemplo 8 bits, o período passaria para 256ms e, portanto, a freqüência cairia para aproximadamente 4Hz, ou seja, extremamente baixa. Note que quanto maior a resolução desejada maior é o período do PWM.

Exercícios Propostos

1. Altere a freqüência do PWM alterando a base de tempo do TMR0 para 100us. 2. Altere o PWM para trabalhar com apenas 2 bits de resolução. 3. Acrescente as rotinas de leitura e escrita na EEPROM para salvar e recuperar a intensidade da

lâmpada mesmo na falta de energia.

Page 179: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 177

Experiência 4 – Botões, Leds e Buzzer

Objetivo

O objetivo desta experiência é dar continuidade ao aprendizado das interrupções e em particular à interrupção de TMR2 utilizada nesta experiência para excitar o buzzer.

Descrição

O buzzer utilizado no MCMASTER não é do tipo auto-oscilante, ou seja, este tipo de buzzer precisa ser excitado externamente para emitir algum som. Assim, o microcontrolador deve ser responsável por gerar uma onda quadrada a fim de excitar o piezo-elétrico e fazer com que o buzzer emita algum som. Operar com este tipo de buzzer é muito mais trabalhoso do que com um buzzer auto-oscilante, já que não basta ligar-lo, é necessário aplicar uma onda quadrada para que o buzzer funcione. Porém, ele dá margem à criação de diferentes tons, pois, quem gera a freqüência da onda quadrada e conseqüentemente o tom com que o buzzer irá tocar é o microcontrolador e se este gerar freqüências adequadas, pode-se implementar até mesmo uma simples melodia.

Apesar desta experiência utilizar o TMR2 para excitar o buzzer com freqüência variável, o objetivo não é a implementação de notas musicais, embora isto seja possível.

Diferente dos outros timers do microcontrolador, o TMR2 estoura e pode gerar uma interrupção sempre que o seu valor ultrapassa o valor de um registrador especial, denominado PR2. Ou seja, o TMR2, diferentemente dos outros timers conta desde zero até o valor programado no registrador PR2 e não até 255 (a não ser que o valor do registrador PR2 seja 255).

Desta forma, o que o software faz é ler o estado das teclas da linha 4 e em função deste alterar o valor do registrador PR2. Conseqüentemente, a interrupção de TMR2 varia de período, ou seja, a freqüência com que a interrupção ocorre depende do estado das teclas da linha 4. Como é a interrupção a responsável por gerar a onda quadrada que excita o buzzer e como a freqüência pode ser alterada pelas teclas, dependendo da configuração de teclas pressionadas o buzzer emite som em diferentes tonalidades, criando, embora com freqüência erradas uma espécie de mini-teclado.

Os leds ligados ao PORTD são utilizados apenas para repetir o estado das teclas pressionadas a fim de criar um efeito visual para a experiência.

Page 180: Apostila Mosaico Pic MÓDULO4

178

Esquema Elétrico

Page 181: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 179

Fluxograma

INICIO

INICIALIZA VARIÁVEIS FILTRO DOS BOTÕES

LIGA AS INTERRUPÇÕES

ROTINA PRINCIPAL LIMPA WDT

VETOR DE RESET PULA P/ INICIO DO

PROGRAMA

CONFIGURAÇÕES INICIAS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION, ADS.

HABILITA LEDS E LINHA 4 DO TECLADO MATRICIAL

Page 182: Apostila Mosaico Pic MÓDULO4

180

Não

Sim

INTERRUPÇÕES

SAI DA INTERRUPÇÃO

Não

Sim

RECUPERA CONTEXTO

SALVA CONTEXTO

INT TMR2 ?

INT TMR0 ?

FIM INTERRUPÇÃO

TRATA TMR0

TRATA TMR2

LIMPA FLAG DA INTERRUPÇÃO

LIGA SAÍDA

FIM INTERRUPÇÃO

TRATA TMR2

SAÍDA BUZZER LIGADA ?

LIGA SAÍDA

Não

Sim

Page 183: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 181

CHECA BOTÃO 0

LIMPA FLAG DA INTERRUPÇÃO

LIMPA FLAG DE BOTÃO

PRESSIONADO

TRATA TMR0

BOTÃO PRESS. ?

Não

Não

REINICIA FILTRO

MARCA FLAG DE BOTÃO PRESSIONADO

FILTRO TERMINOU ?

Sim

Sim

CHECA BOTÃO 1

CHECA BOTÃO 2

CHECA BOTÃO 3

1

Page 184: Apostila Mosaico Pic MÓDULO4

182

ATUALIZA LEDS CONFORME FLAGS

DOS BOTÕES

CONSULTA TABELA DE FREQÜÊNCIA CONFORME BOTÕES PRESSIONADOS

INICIALIZA TMR2 COM 255d

1

ALGUM BOTÃO

PRESS. ?

Não

INICIALIZA TIMER 2

LIGA INTERRUPÇÃO DE TIMER 2

DESLIGA INTERRUPÇÃO DE

TMR2

Sim

FIM INTERRUPÇÃO

DESLIGA SAÍDA DO BUZZER

Page 185: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 183

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 - Recursos Básicos de programação * * Exemplo 4 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 10/08/2005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ESTE SOFTWARE ESTÁ PREPARADO PARA LER QUATRO BOTÕES E TOCAR O BUZZER COM DURAÇÃO VERIÁVEL CONFORME TECLA PRESSIONADA. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config WDT = ON #pragma config LVP = OFF /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis Globais * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário unsigned char filtro1; unsigned char filtro2; unsigned char filtro3; unsigned char filtro4; unsigned char status_leds; // atualiza leds conforme o botão pressionado const rom unsigned char tabela[16] = 255,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define MIN 0 #define MAX 15

Page 186: Apostila Mosaico Pic MÓDULO4

184

#define t_filtro 25 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void TRATA_HIGH_INT(void); void TRATA_INT_TIMER0(void); void TRATA_INT_TIMER2(void); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define botao1 PORTBbits.RB0 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define botao2 PORTBbits.RB1 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define botao3 PORTBbits.RB2 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define botao4 PORTBbits.RB3 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #define C_LEDS PORTAbits.RA4 //PINO PARA ATIVAR GRUPO DE 8 LEDS //1 -> LEDS ATIVADOS //0 -> LEDS DESATIVADOS #define LINHA_4 PORTBbits.RB7 //PINO PARA ATIVAR LINHA 4 DO TECLADO //MATRICIAL //1 -> LINHA ATIVADA //0 -> LINHA DESATIVADA #define buzzer PORTEbits.RE2 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * ROTINA DE TRATAMENTO DE INT DE ALTA PRIORIDADE * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * #pragma code VETOR_HIGH_PRIORITY = 0x0008 void HIGH_int (void) _asm goto TRATA_HIGH_INT _endasm #pragma code #pragma interrupt TRATA_HIGH_INT void TRATA_HIGH_INT(void)

Page 187: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 185

if(PIR1bits.TMR2IF) TRATA_INT_TIMER2(); if(INTCONbits.TMR0IF) TRATA_INT_TIMER0(); void TRATA_INT_TIMER2(void) PIR1bits.TMR2IF = 0; //LIMPA FLAG DE INTERRUPÇÃO if (buzzer != 0) // o buzzer está ligado ? buzzer = 0; // sim, então desliga else buzzer = 1; // não, então liga void TRATA_INT_TIMER0(void) INTCONbits.TMR0IF = 0; //LIMPA FLAG DE INTERRUPÇÃO /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (botao1) // testa botão 1 // botão 1 está pressionado ? filtro1--; // Sim, então decrementa o filtro if (filtro1 == 0) // acabou o filtro do botão 1 ? status_leds = status_leds | 0b00000001; // marca que o botão está pressionado else // botão 1 liberado filtro1 = t_filtro; // inicia o filtro do botão 1 status_leds = status_leds & 0b11111110; // marca que o botão foi liberado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (botao2) // testa botão 2 // botão 2 está pressionado ? filtro2--; // Sim, então decrementa o filtro if (filtro2 == 0) // fim do filtro do botão 2 ? status_leds = status_leds | 0b00000010; // marca que o botão está pressionado else // botão 2 liberado filtro2 = t_filtro; // inicia o filtro do botão 2 status_leds = status_leds & 0b11111101; // marca que o botão foi liberado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (botao3) // testa botão 3 // botão 3 está pressionado ? filtro3--; // Sim, então decrementa o filtro if (filtro3 == 0) // fim do filtro do botão 3 ?

Page 188: Apostila Mosaico Pic MÓDULO4

186

status_leds = status_leds | 0b00000100; // marca que o botão está pressionado else // botão 3 liberado filtro3 = t_filtro; // inicia o filtro do botão 3 status_leds = status_leds & 0b11111011; // marca que o botão foi liberado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 4 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (botao4) // testa botão 4 // botão 4 está pressionado ? filtro4--; // Sim, então decrementa o filtro if (filtro4 == 0) // fim do filtro do botão 4 ? status_leds = status_leds | 0b00001000; // marca que o botão está pressionado else // botão 4 liberado filtro4 = t_filtro; // inicia o filtro do botão 4 status_leds = status_leds & 0b11110111; // marca que o botão foi liberado PORTD = status_leds; if (status_leds == 0) PR2 = 0xff; CloseTimer2(); buzzer = 0; else PR2 = tabela[status_leds]; // consulta tabela e inicializa timer2. OpenTimer2(TIMER_INT_ON & T2_PS_1_1 & T2_POST_1_3); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () PORTA = 0X00; //Clear PORTA PORTB = 0X00; //Clear PORTB PORTC = 0X00; //Clear PORTC PORTD = 0X00; //Clear PORTD PORTE = 0x00; //Clear PORTE LATA = 0X00; //Clear PORTA LATB = 0X00; //Clear PORTB LATC = 0X00; //Clear PORTC LATD = 0X00; //Clear PORTD LATE = 0x00; //Clear PORTE TRISA = 0b00101111; //CONFIG DIREÇÃO DOS PINOS PORTA TRISB = 0b00001111; //CONFIG DIREÇÃO DOS PINOS PORTB

Page 189: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 187

TRISC = 0b10011001; //CONFIG DIREÇÃO DOS PINOS PORTC TRISD = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTD TRISE = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTE ADCON1 = 0b00000111; //DESLIGA CONVERSORES A/D /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Sistema * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ OpenTimer0(TIMER_INT_ON & T0_8BIT & T0_SOURCE_INT & T0_PS_1_4); PR2 = 0xff; OpenTimer2(TIMER_INT_OFF & T2_PS_1_1 & T2_POST_1_3); RCON = 0X00; C_LEDS = 1; //ATIVA LEDS LIGADOS AO PORTD LINHA_4 = 1; //ATIVA LINHA 4 DO TECLADO MATRICIAL status_leds = 0; filtro1 = t_filtro; // inicia filtro do botao1 filtro2 = t_filtro; // inicia filtro do botao2 filtro3 = t_filtro; // inicia filtro do botao3 filtro4 = t_filtro; // inicia filtro do botao4 INTCONbits.TMR0IE = 1; INTCONbits.PEIE = 1; PIE1bits.TMR2IE = 1; INTCONbits.GIEH = 1; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(1) ClrWdt(); // FIM DO PROGRAMA

Page 190: Apostila Mosaico Pic MÓDULO4

188

Dicas e Comentários

Notar que nesta experiência foi utilizada uma tabela para retornar em função do estado das teclas pressionadas o valor que deve ser carregado no registrador PR2. Ou seja, conforme comentado na experiência 4, a utilização de tabelas não se limita apenas à conversão de BCD para display de 7 segmentos. Prova disso é que nesta experiência a tabela foi útil para exercer função completamente diferente.

O software desta experiência apresenta uma particularidade. Veja que não existe nenhuma instrução, a não ser o CLRWDT, no loop principal do programa. Assim, todas as instruções do software e toda a sua lógica está implementada apenas dentro das interrupções, sendo parte na interrupção de TMR0 e parte na interrupção de TMR2.

Exercícios Propostos

1. Alterar a configuração do TMR2 para que o buzzer seja excitado em outra faixa de freqüências. 2. Utilizar a instrução boleana XOR para inverter o estado do pino do buzzer. 3. Inverter a escala de freqüências, trocando a mais alta pela mais baixa.

Page 191: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 189

Experiência 5 – Varredura de displays e utilização do TIMER 1

Objetivo

O objetivo desta experiência é o aprendizado do sistema de varredura comumente utilizado para varrer displays de 7 segmentos. Além disso, é visto o TMR1 fechando assim o estudo sobre os três times do PIC16F877A ou do PIC18F452.

Descrição

Cada display é formado por um conjunto de 8 leds, sendo 7 para a caracterização do dígito e 1 para o ponto decimal. Desta forma, precisaremos de um pino do PIC para controlar cada um dos leds e, portanto, serão necessários 8 pinos para acionar os 7 segmentos e mais o ponto decimal. Porém, o MCMASTER não possui apenas um display e sim quatro. Seriam necessários então 32 pinos do microcontrolador para acionar os quatro displays? Não, existe uma saída para isso. O segredo para minimizar a quantidade de pinos utilizados é o emprego de um conceito denominado varredura.

Para isso, interligam-se todos os displays, juntando todos os pinos de um mesmo segmento numa única via, de forma a criar um barramento de dados com as vias de A até Dp. Em seguida, utiliza-se um pino para controlar o comum de cada um dos displays (total de 4 pinos). Assim, quando se deseja escrever em um dos displays, bastar informar os segmentos a serem acionados nas vias de dados e ligar o comum do display desejado.

Utilizando o hardware desta forma é fácil notar que apenas um dos displays poderá ser acionado de cada vez. Porém, se acionarmos os displays continuamente, um após o outro e de forma rápida, nossos olhos não conseguiram perceber que apenas um display está acionado por vez dando a impressão de que todos os displays estão acionados o tempo todo.

Assim, empregando-se a técnica de varredura, consegue-se controlar os 4 displays utilizando apenas 12 pinos

do microcontrolador. O exemplo desenvolvido para esta experiência faz muito mais que simplesmente implementar a varredura dos

displays. Trata-se de um contador regressivo de segundos, ou seja, um temporizador capaz de contar até 9.999 segundos.

As teclas habilitadas são as da linha 4 e seguem as funções descritas na tabela.

Coluna Descrição 1 nenhuma função 2 Incrementa o valor inicial em 1 segundo 3 Decrementa o valor inicial em 1 segundo 4 Inicia e paralisa o temporizador

Para a contagem do tempo utilizou-se a interrupção de TMR1, configurada conforme a tabela a seguir.

A B C D E F G Dp

Display 1 Display 2 Display 3 Display 4

Via

s de

Dad

os

Page 192: Apostila Mosaico Pic MÓDULO4

190

Ciclo de Maq. Prescale Conta TMR1 Auxiliar Período Freqüência1 µs 8 62500 2 1.000.000 µs 1 Hz

Configurou-se o prescale do TMR1 em 1:8 e o contador foi inicializado com o valor total menos o desejado

para a contagem (65.536 – 62.500). Desta maneira a interrupção ocorre a cada 0,5 segundo. A fim de criar a base de tempo de 1 segundo foi utilizada uma variável auxiliar que é decrementada a cada ocorrência da interrupção.

Page 193: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 191

Esquema Elétrico

Page 194: Apostila Mosaico Pic MÓDULO4

192

Fluxograma

Não

INICIALIZA VARIÁVEIS

LIGA AS INTERRUPÇÕES

LIMPA WDT

VETOR DE RESET PULA P/ INÍCIO DO

PROGRAMA

CONFIGURAÇÕES INICIAIS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION, ADs.

1

INÍCIO

RECARREGA FILTRO E TURBO P/ TECLAS

UP PRESS.?

START/STOPPRESS.?

DOWN PRESS.?

Não

Não

TRATA BOTÃO UP

TRATA BOTÃO DOWN

TRATA BOTÃO START / STOP

Sim

Sim

Sim

Page 195: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 193

Não

LINHA 4 HABILITADA ?

Sim

Não

INTERRUPÇÕES

SAI DA INTERRUPÇÃO

Sim

RECUPERA CONTEXTO

SALVA CONTEXTO

INT TMR0 ?

RECARREGA TEMPORIZADOR

DE 1seg.

LIMPA FLAG DE TIMER LIGADO

(LED)

Não

LIMPA TODOS OS SEGMENTOS (BLANK)

ACERTA PONTEIRO DO END. INDIRETO (FSR)

INCREMENTA PONTEIRO (INDICE_VARRE_DISPLAY)

DESLIGA TODOS OS DISPLAYS

CONSULTA TABELA P/ DISPLAY DE 7 SEGMENTOS

CONSULTA TABELA E ACIONA DISPLAY CORRETO

ATUALIZA PORT LIGADO AOS SEGMENTOS

LIMPA FLAG DA INTERRUPÇÃO DE TMR0

LIMPA FLAG DA INTERRUPÇÃO DE

TMR1

PARA CONTADOR DO TIMER 1

RECARREGA CONTADORES DO

TMR1

PASSOU 1seg. ?

Sim

DECREMENTA TIMER

Não

FIM DO TIMER ?

Sim

SALVA O STATUS DOS BOTÕES

Page 196: Apostila Mosaico Pic MÓDULO4

194

INCREMENTA TIMER

TIMER LIGADO ?

Não

Não

RECARREGA TEMPORIZADOR P/ TURBO

FILTRO TERMINOU ?

Sim

Sim

TRATA BOTÃO UP

FIM DO TEMPORIZADOR

P/ TURBO ?

1

Não

Sim TIMER LIGADO ?

Não

Não

RECARREGA TEMPORIZADOR P/ TURBO

FILTRO TERMINOU ?

Sim

Sim

DECREMENTA TIMER

TRATA BOTÃO DOWN

FIM DO TEMPORIZADOR

P/ TURBO ?

1

Não

Sim

Page 197: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 195

TRATA BOTÃO START / STOP

ACÃO JÁ FOI EXEC. ?

Não

Não

LIMPA FLAG DE TIMER LIGADO (LED)

FILTRO TERMINOU ?

Sim

Sim

TIMER LIGADO ?

1

Não

Sim

PARA CONTADOR TMR1

TIMER ZERADO ?

SETA FLAG DE TIMER LIGADO (LED)

CARREGA CONTADORES DO TIMER 1

CARREGA TEMPORIZADOR P/ CONTAGEM DE 1s.

LIGA CONTADOR DO TIMER 1

1

Não

Sim

Page 198: Apostila Mosaico Pic MÓDULO4

196

INCREMENTA UNIDADE

RETURN

INCREMENTA TIMER

ZERA UNIDADE INCREMENTA DEZENA

UNIDADE= 10 ? Não

Sim

ZERA DEZENA INCREMENTA CENTENA

DEZENA = 10 ? Não

Sim

ZERA CENTENA INCREMENTA MILHAR

CENTENA = 10 ? Não

Sim

ZERA MILHAR

MILHAR = 10 ? Não

Sim

DECREMENTA UNIDADE

RETURN

DECREMENTA TIMER

UNIDADE = 9 DECREMENTA DEZENA

UNIDADE= 0xFF ? Não

Sim

DEZENA = 9 DECREMENTA CENTENA

DEZENA = 0xFF ? Não

Sim

CENTENA = 9 DECREMENTA MILHAR

CENTENA = 0xFF ? Não

Sim

MILHAR = 9

MILHAR = 0xFF ? Não

Sim

Page 199: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 197

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 - Recursos Básicos de programação * * Exemplo 5 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 10/08/2005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ESTE EXEMPLO FOI PREPARADO PARA DEMOSNTRAR O FUNCIONAMENTO DO TIMER DE 16 BITS DO PIC (TMR1) E DA VARREDURA DE DISPLAYS MAIS BARRA DE LEDS. CONSISTE NUM CONTADOR DE SEGUNDOS. DOIS BOTÕES FORAM UTILIZADOS PARA PROGRAMAR O TEMPO DA CONTAGEM. UM OUTRO BOTÃO FOI UTILIZADO PARA DISPARAR O CONTADOR. O TEMPORIZADOR CONSEGUE CONTAR ATÉ 9999 SEGUNDOS, DE FORMA QUE OS 4 DISPLAYS DE 7 SEGMENTOS FORAM NECESSÁRIOS. A CONTAGEM É REGRESSIVA. UMA BARRA DE LEDS INDICA QUE O TEMPORIZADOR ESTÁ OPERANDO. QUANDO O SISTEMA CHEGA A 0000 A BARRA DE LEDS É DESLIGADA AUTOMATICAMENTE. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config WDT = ON #pragma config WDTPS = 128 #pragma config LVP = OFF /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define t_filtro 250 // tamanho do filtro #define turbo_tecla 60 #define delta_timer1 (65536 - 62500) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis Globais * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário unsigned char display = 0 ; // atualiza os displays unsigned char contador = 2; // contador de interrupções de timer1

Page 200: Apostila Mosaico Pic MÓDULO4

198

unsigned char filtro = t_filtro; // inicia filtro dos botões unsigned char filtro1 = t_filtro; // inicia filtro dos botões unsigned char filtro2= t_filtro; // inicia filtro dos botões unsigned char filtro3 = t_filtro; // inicia filtro dos botões unsigned char filtro4 = t_filtro; // inicia filtro dos botões unsigned char turbo = 1; // inicia turbo das teclas unsigned char unidade = 9; // variável unidade do timer de 1 seg unsigned char dezena = 9; // variável dezena do timer de 1 seg unsigned char centena = 9; // variável centena do timer de 1 seg unsigned char milhar = 9; // variável milhar do timer de 1 seg unsigned char botoes = 0; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * ROTINA DE CONVERSÃO BINÁRIO -> DISPLAY * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ESTA ROTINA IRÁ RETORNAR EM W, O SIMBOLO CORRETO QUE DEVE SER // MOSTRADO NO DISPLAY PARA CADA VALOR DE INTENSIDADE. O RETORNO JÁ ESTÁ // FORMATADO PARA AS CONDIÇÕES DE LIGAÇÃO DO DISPLAY AO PORTD. // a // ********** // * * // f * * b // * g * // ********** // * * // e * * c // * d * // ********** *. const rom unsigned char converte[] = // .GFEDCBA POSIÇÃO CORRETA DOS SEGMENTOS 0b00111111, // 00 - RETORNA SÍMBOLO CORRETO 0 0b00000110, // 01 - RETORNA SÍMBOLO CORRETO 1 0b01011011, // 02 - RETORNA SÍMBOLO CORRETO 2 0b01001111, // 03 - RETORNA SÍMBOLO CORRETO 3 0b01100110, // 04 - RETORNA SÍMBOLO CORRETO 4 0b01101101, // 05 - RETORNA SÍMBOLO CORRETO 5 0b01111101, // 06 - RETORNA SÍMBOLO CORRETO 6 0b00000111, // 07 - RETORNA SÍMBOLO CORRETO 7 0b01111111, // 08 - RETORNA SÍMBOLO CORRETO 8 0b01101111, // 09 - RETORNA SÍMBOLO CORRETO 9 0b00000000; // BLANK /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário struct unsigned BIT0:1; unsigned BIT1:1; unsigned BIT2:1; unsigned BIT3:1; unsigned BIT4:1; unsigned BIT5:1; unsigned BIT6:1; unsigned BIT7:1; FLAGSbits; //ARMAZENA OS FLAGS DE CONTROLE #define estado_timer FLAGSbits.BIT0 //STATUS DO TIMER 1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void TRATA_HIGH_INT(void);

Page 201: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 199

void TRATA_INT_TIMER0(void); void TRATA_INT_TIMER1(void); void decrementa_timer(void); void incrementa_timer(void); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #define C_LEDS PORTAbits.RA4 //PINO PARA ATIVAR GRUPO DE 8 LEDS //1 -> LEDS ATIVADOS //0 -> LEDS DESATIVADOS #define LINHA_4 PORTBbits.RB4 //PINO PARA ATIVAR LINHA 4 DO TECLADO //MATRICIAL //1 -> LINHA ATIVADA //0 -> LINHA DESATIVADA #define disp0 PORTBbits.RB7 // seleção do display unidade (0) #define disp1 PORTBbits.RB6 // seleção do display dezena (1) #define disp2 PORTBbits.RB5 // seleção do display centena (2) #define disp3 PORTBbits.RB4 // seleção do display milhar (3) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de decremento do Timer * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void decrementa_timer(void) unidade --; if (unidade == 0xff) unidade = 9; dezena --; if (dezena == 0xff) dezena = 9; centena --; if (centena == 0xff) centena = 9; milhar --; if (milhar == 0xff) milhar = 9; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de incremento do Timer * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void incrementa_timer(void) unidade ++; if (unidade == 10) unidade = 0; dezena ++; if (dezena == 10) dezena = 0;

Page 202: Apostila Mosaico Pic MÓDULO4

200

centena ++; if (centena == 10) centena = 0; milhar ++; if (milhar == 10) milhar = 0; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função de tratamento de interrupção de Timer1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupcao ocorrera a cada 0,5 segundos, a rotina de tratamento e executada a // cada 2 interrupcoes. void TRATA_INT_TIMER1(void) WriteTimer1(delta_timer1); // carraga timer1 PIR1bits.TMR1IF = 0; // limpa flag de interrupção contador --; // decrementa contador de interrupções if (contador == 0) WriteTimer1(delta_timer1); // carraga timer1 contador = 2; // carrega contador de int decrementa_timer(); if ((unidade == 0)&&(dezena == 0)&&(centena == 0)&&(milhar == 0))// timer está zerado? estado_timer = 0; // sim, apaga o led e CloseTimer1(); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupção de TMR0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupção ocorrerá a cada 256us. void TRATA_INT_TIMER0(void) INTCONbits.TMR0IF = 0; //LIMPA FLAG DE INTERRUPÇÃO switch(display) // início da varredura dos display´s case 0: display++; // incrementa a variável de varredura C_LEDS = 0; // liga o display 3 PORTD = converte[unidade]; // atualiza o portd disp0 = 1; // liga o display 0 Delay1TCY(); botoes = PORTB & 0b00001111;//FOTOGRAFA O ESTADO DOS BOTÕES break; // sai case 1: display++; // incrementa a variável de varredura disp0 = 0; // desliga o display 0 PORTD = converte[dezena]; // atualiza o portd disp1 = 1; // liga o display 1 break; // sai case 2: display++; // incrementa a variável de varredura disp1 = 0; // desliga o display 1 PORTD = converte[centena]; // atualiza o portd disp2 = 1; // liga o display 2 break; // sai

Page 203: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 201

case 3: display++; // inicia a variável de varredura disp2 = 0; // desliga o display 2 PORTD = converte[milhar]; // atualiza o portd disp3 = 1; // liga o display 3 break; // sai case 4: display = 0; // inicia a variável de varredura disp3 = 0; // desliga o display 2 if(estado_timer) PORTD = 0xff; // atualiza o portd else PORTD = 0; // atualiza o portd C_LEDS = 1; // liga o display 3 break; // sai /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () PORTA = 0x00; //Clear PORTA PORTB = 0x00; //Clear PORTB PORTC = 0x00; //Clear PORTC PORTD = 0x00; //Clear PORTD PORTE = 0x00; //Clear PORTE LATA = 0x00; //Clear PORTA LATB = 0x00; //Clear PORTB LATC = 0x00; //Clear PORTC LATD = 0x00; //Clear PORTD LATE = 0x00; //Clear PORTE TRISA = 0b00101111; //CONFIG DIREÇÃO DOS PINOS PORTA TRISB = 0b00001111; //CONFIG DIREÇÃO DOS PINOS PORTB TRISC = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTC TRISD = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTD TRISE = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTE PORTA = 0x00; //Clear PORTA PORTB = 0x00; //Clear PORTB PORTC = 0x00; //Clear PORTC PORTD = 0x00; //Clear PORTD PORTE = 0x00; //Clear PORTE ADCON1 = 0b00000111; //DESLIGA CONVERSORES A/D /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Sistema * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ OpenTimer0(TIMER_INT_ON & T0_8BIT & T0_SOURCE_INT & T0_PS_1_4); OpenTimer1(TIMER_INT_OFF & T1_SOURCE_INT & T1_8BIT_RW & T1_PS_1_8); RCON = 0X00; CloseTimer1(); // desliga tratamento de interrupção de timer1 INTCONbits.GIEH = 1; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Page 204: Apostila Mosaico Pic MÓDULO4

202

loop: while(1) ClrWdt(); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if ((botoes & 0b00000001)==1) // testa botão 1 // botão 1 está pressionado ? goto trata_up; // desvia para a rotina de decremento do timer /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if ((botoes & 0b00000010)==2) // testa botão 2 // botão 2 está pressionado ? goto trata_dowm; // desvia para a rotina de decremento do timer /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if ((botoes & 0b00000100)==4) // testa botão 3 // botão 3 está pressionado ? goto trata_start_stop;// desvia para a rotina de inicio e parada do timer filtro = t_filtro; turbo = 1; trata_up: if (estado_timer == 0) // o timer está parado? filtro --; // decrementa o filtro if (filtro == 0) // fim do filtro do botão? turbo --; // decrementa o turbo da tecla if (turbo == 0) // sim, fim do turbo do botão ? turbo = turbo_tecla; // carrega o turbo incrementa_timer(); // incrementa o timer goto loop; //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * trata_dowm: if (estado_timer == 0) // o timer está parado? filtro --; // decrementa o filtro if (filtro == 0) // fim do filtro do botão? turbo --; // decrementa o turbo da tecla if (turbo == 0) // sim, fim do turbo do botão ? turbo = turbo_tecla; // carrega o turbo decrementa_timer(); // decrementa o timer goto loop; //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * trata_start_stop: if (filtro != 0) // o timer está parado?

Page 205: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 203

filtro --; // decrementa o filtro if (filtro == 0) // fim do filtro do botão? if (estado_timer != 0) // sim, o timer está ligado ? estado_timer = 0; // indica timer parado CloseTimer1(); // desliga o tratamento de interrupção de timer1 else if ((unidade!=0)||(dezena!=0)||(centena!=0)||(milhar!=0))// timer está zerado? estado_timer = 1; // não, indica que o timer está contando contador = 2; // carrega contador auxiliar WriteTimer1(delta_timer1); // carraga timer1 INTCONbits.TMR0IF = 0; // limpa flag de int tmr1 OpenTimer1(TIMER_INT_OFF & T1_SOURCE_INT & T1_8BIT_RW & T1_PS_1_8); // liga o tratamento de interrupção de timer1 goto loop; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * ROTINA DE TRATAMENTO DE INT DE ALTA PRIORIDADE * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * #pragma code VETOR_HIGH_PRIORITY = 0x0008 void HIGH_int (void) _asm goto TRATA_HIGH_INT _endasm #pragma code #pragma interrupt TRATA_HIGH_INT void TRATA_HIGH_INT(void) if(INTCONbits.TMR0IF) TRATA_INT_TIMER0(); if(PIR1bits.TMR1IF) TRATA_INT_TIMER1();

Page 206: Apostila Mosaico Pic MÓDULO4

204

Dicas e Comentários

Observar que nesta experiência, ao entrar no tratamento das interrupções, a operação de salvar contexto é maior que nas experiências anteriores. Isto por que agora salva-se também os valores de FSR e PCLATH pois os mesmos podem ser alterados dentro da interrupção.

Exercícios Propostos

1. Implemente o quarto botão, para resetar o temporizador (voltar a zero). 2. Implemente uma segunda velocidade para os botões de incremento e decremento, de forma que facilite o

ajuste de valores maiores. 3. Em vez de fazer um timer somente de segundos, utilize os dois dígitos da esquerda para mostrar o tempo

em minutos e os da direita para mostrar o tempo em segundos. O ponto do display da centena pode ser usado para marcar a separação. Não se esqueça que agora os displays da direita devem contar somente de 0 a 59 e não mais de 0 a 99.

Page 207: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 205

Experiência 6 – Display de cristal líquido LCD

Objetivo

O objetivo desta experiência é o aprendizado da utilização de display de cristal líquido.

Descrição

Esta experiência foi elaborada para explicar o funcionamento do display LCD e o exemplo de software proposto é bastante reduzido. Simplesmente utilizou-se o LCD para informar ao usuário qual tecla está pressionada.

Para isso elaborou-se uma rotina chamada ESCREVE que envia a informação passada pelo Work ao display. Esta rotina pode ser utilizada tanto para enviar comandos quanto dados. Foi criada também, a rotina de inicialização do LCD. Esta rotina configura o sistema para comunicação com 8 vias, 2 linhas, sem cursor visível e com movimento automático do cursor para a direita. Além disso, ela já limpa a tela e posiciona o cursor na primeira linha, primeiro caractere da esquerda.

Para cada botão pressionado, posicionou-se o cursor em um local diferente da tela e escreveu-se o número do botão em questão. Após a liberação, uma tela padrão é visualizada.

Page 208: Apostila Mosaico Pic MÓDULO4

206

Esquema Elétrico

Page 209: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 207

Fluxograma

INICIALIZA VARIÁVEIS

ENVIA COMANDO 0x30 P/ DISPLAY

VETOR DE RESET PULA P/ INICIO DO

PROGRAMA

CONFIGURAÇÕES INICIAS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION, ADS.

1

INICIO

DELAY DE 4ms

ENVIA COMANDO 0x38 P/ DISPLAY

ENVIA COMANDO 0x30 P/ DISPLAY

INICIALIZAÇÃO COM 4 VIAS DE DADOS

ENVIA COMANDO 0x30 P/ DISPLAY

INICIALIZA DISPLAY P/ 8 VIAS DE DADOS

ENVIA COMANDO 0x01 P/ DISPLAY

DELAY DE 1ms

ENVIA COMANDO 0x06 P/ DISPLAY

ENVIA COMANDO 0x0C P/ DISPLAY DISPLAY S/ CURSOR

DESLOCAR CURSOR À ESQUERDA

INICIALIZAÇÃO DISPLAY

LIMPA DISPLAY

Page 210: Apostila Mosaico Pic MÓDULO4

208

Não

LIMPA WDT

1

RECARREGA FILTRO

BOTÃO 0 PRESS.?

Não

Não

TRATA BOTÃO 0

TRATA BOTÃO 1

Sim

Sim

Sim

BOTÃO 3 PRESS.?

BOTÃO 2 PRESS.?

BOTÃO 1 PRESS.?

TRATA BOTÃO 3

TRATA BOTÃO 2

Sim

Não

MOSTRAR TELA

PRINCIPAL.?

MOSTRA TELA PRINCIPAL

Não

Sim

HABILITA LINHA 4

DESABILITA LINHA 4

Page 211: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 209

TRATA BOTÃO 1

ACÃO JÁ FOI EXEC. ?

Não

POSICIONA CURSOR NA LINHA 0 COLUNA 8

FILTRO TERMINOU ?

Sim

1

Não

Sim

SELECIONA DISPLAY PARA DADOS

ENVIA COMANDO P/ LIMPAR DISPLAY

ESCREVE TECLA 1 NO DISPLAY

LIMPA BARRAMENTO DE DADOS

SETA FLAG PARA MOSTRAR TELA

PRINCIPAL

TRATA BOTÃO 0

ACÃO JÁ FOI EXEC. ?

Não

POSICIONA CURSOR NA LINHA 0 COLUNA 0

FILTRO TERMINOU ?

Sim

1

Não

Sim

SELECIONA DISPLAY PARA DADOS

ENVIA COMANDO P/ LIMPAR DISPLAY

ESCREVE TECLA 0 NO DISPLAY

LIMPA BARRAMENTO DE DADOS

SETA FLAG PARA MOSTRAR TELA

PRINCIPAL

DESABILITA TECLADO MATRICIAL

DESABILITA TECLADO MATRICIAL

Page 212: Apostila Mosaico Pic MÓDULO4

210

TRATA BOTÃO 3

ACÃO JÁ FOI EXEC. ?

Não

POSICIONA CURSOR NA LINHA 1 COLUNA 8

FILTRO TERMINOU ?

Sim

1

Não

Sim

SELECIONA DISPLAY PARA DADOS

ENVIA COMANDO P/ LIMPAR DISPLAY

ESCREVE TECLA 3 NO DISPLAY

LIMPA BARRAMENTO DE DADOS

SETA FLAG PARA MOSTRAR TELA

PRINCIPAL

TRATA BOTÃO 2

ACÃO JÁ FOI EXEC. ?

Não

POSICIONA CURSOR NA LINHA 1 COLUNA 0

FILTRO TERMINOU ?

Sim

1

Não

Sim

SELECIONA DISPLAY PARA DADOS

ENVIA COMANDO P/ LIMPAR DISPLAY

ESCREVE TECLA 2 NO DISPLAY

LIMPA BARRAMENTO DE DADOS

SETA FLAG PARA MOSTRAR TELA

PRINCIPAL

DESABILITA TECLADO MATRICIAL

DESABILITA TECLADO MATRICIAL

Page 213: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 211

LIMPA FLAG DE MOSTRAR TELA

PRINCIPAL

RETURN

MOSTRA TELA PRINCIPAL

ENVIA COMANDO P/ LIMPAR DISPLAY

SELECIONA DISPLAY PARA DADOS

ESCREVE “Sistema Didatico”

SELECIONA DISPLAY PARA COMANDOS

POSICIONA CURSOR NA LINHA 1 COLUNA 6

ESCREVE “MCMASTER”

SELECIONA DISPLAY PARA DADOS

LIMPA BARRAMENTO DE DADOS

CARREGA ARGUMENTO PASSADO PELO Work NO BARRAMENTO DE DADOS

DO DISPLAY

ESCREVE

ENVIA PULSO DE ENABLE AO LCD

DELAY DE 1ms

RETURN

[3us]

Não

Sim

Não

1ms

Sim

RETURN

CARREGA ARGUMENTO PASSADO PELO Work EM

TEMPO1

NOP [1us]

INICIALIZA TEMPO0 COM 250d

FIM DO TEMPO1 ?

DELAY_MS

FIM DO TEMPO0 ?

Page 214: Apostila Mosaico Pic MÓDULO4

212

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 - Recursos Básicos de programação * * Exemplo 6 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 23/02/2005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ESTE EXEMPLO FOI ELABORADO PARA EXPLICAR O FUNCIONAMENTO DO MÓDULO DE LCD. FOI CRIADA UMA ROTINA PARA ESCREVER COMANDOS OU CACACTRES NO LCD. EXISTE TAMBÉM UMA ROTINA DE INICIALIZAÇÃO NECESSÁRIA PARA A CORRETA CONFIGURAÇÃO DO LCD. OS BOTÕES CONTINUAM SENDO MONITORADOS. UMA MENSAGEM É ESCRITA NO LCD PARA CADA UM DOS BOTÕES, QUANDO O MESMO É PRESSIONADO. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config WDT = ON #pragma config LVP = OFF /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis Globais * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário unsigned char FILTRO11; //FILTRAGEM 1 PARA O BOTÃO 1 unsigned char FILTRO12; //FILTRAGEM 2 PARA O BOTÃO 1 unsigned char FILTRO21; //FILTRAGEM 1 PARA O BOTÃO 2 unsigned char FILTRO22; //FILTRAGEM 2 PARA O BOTÃO 2 unsigned char FILTRO31; //FILTRAGEM 1 PARA O BOTÃO 3 unsigned char FILTRO32; //FILTRAGEM 2 PARA O BOTÃO 3 unsigned char FILTRO41; //FILTRAGEM 1 PARA O BOTÃO 4 unsigned char FILTRO42; //FILTRAGEM 2 PARA O BOTÃO 4 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define T_FILTRO 25

Page 215: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 213

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário struct unsigned BIT0:1; unsigned BIT1:1; unsigned BIT2:1; unsigned BIT3:1; unsigned BIT4:1; unsigned BIT5:1; unsigned BIT6:1; unsigned BIT7:1; FLAGSbits; //ARMAZENA OS FLAGS DE CONTROLE #define ST_BT1 FLAGSbits.BIT0 //STATUS DO BOTÃO 1 #define ST_BT2 FLAGSbits.BIT1 //STATUS DO BOTÃO 2 #define ST_BT3 FLAGSbits.BIT2 //STATUS DO BOTÃO 3 #define ST_BT4 FLAGSbits.BIT3 //STATUS DO BOTÃO 4 #define ST_NO_BOTS FLAGSbits.BIT4 //STATUS DOS BOTÕES LIBERADOS /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter); void escreve_lcd(unsigned char caracter); void limpa_lcd(void); void inicializa_lcd(void); void tela_principal(void); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define BT1 PORTBbits.RB0 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT2 PORTBbits.RB1 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT3 PORTBbits.RB2 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT4 PORTBbits.RB3 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #define LINHA_4 PORTBbits.RB7 //PINO PARA ATIVAR LINHA 4 DO TECLADO //MATRICIAL //1 -> LINHA ATIVADA //0 -> LINHA

Page 216: Apostila Mosaico Pic MÓDULO4

214

DESATIVADA #define rs PORTEbits.RE0 // via do lcd que sinaliza recepção de dados ou comando #define enable PORTEbits.RE1 // enable do lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter) rs = 0; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1 ; // gera pulso no enable Delay10TCYx(1); // espera 3 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(unsigned char caracter) rs = 1; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1; // gera pulso no enable Delay10TCYx(1); // espera 10 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd(void) comando_lcd(0x01); // limpa lcd Delay1KTCYx(2); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd(void) comando_lcd(0x30); // envia comando para inicializar display Delay1KTCYx(4); // espera 4 milisengundos comando_lcd(0x30); // envia comando para inicializar display Delay10TCYx(10); // espera 100 microsengundos comando_lcd(0x30); // envia comando para inicializar display comando_lcd(0x38); // liga o display, sem cursor e sem blink limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Page 217: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 215

* Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_principal(void) limpa_lcd(); // limpa lcd comando_lcd(0x80); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('S'); // imprime mensagem no lcd escreve_lcd ('i'); escreve_lcd ('s'); escreve_lcd ('t'); escreve_lcd ('e'); escreve_lcd ('m'); escreve_lcd ('a'); escreve_lcd (' '); escreve_lcd ('D'); escreve_lcd ('i'); escreve_lcd ('d'); escreve_lcd ('a'); escreve_lcd ('t'); escreve_lcd ('i'); escreve_lcd ('c'); escreve_lcd ('o'); comando_lcd(0xC4); // posiciona o cursor na linha 1, coluna 4 escreve_lcd ('M'); // imprime mensagem no lcd escreve_lcd ('C'); escreve_lcd ('M'); escreve_lcd ('A'); escreve_lcd ('S'); escreve_lcd ('T'); escreve_lcd ('E'); escreve_lcd ('R'); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Tecla 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_tecla_1(void) limpa_lcd(); // limpa lcd comando_lcd(0x80); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('T'); // imprime mensagem no lcd escreve_lcd ('E'); escreve_lcd ('C'); escreve_lcd ('L'); escreve_lcd ('A'); escreve_lcd (' '); escreve_lcd ('1'); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Tecla 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_tecla_2(void) limpa_lcd(); // limpa lcd comando_lcd(0x89); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('T'); // imprime mensagem no lcd escreve_lcd ('E'); escreve_lcd ('C'); escreve_lcd ('L'); escreve_lcd ('A'); escreve_lcd (' '); escreve_lcd ('2');

Page 218: Apostila Mosaico Pic MÓDULO4

216

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Tecla 3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_tecla_3(void) limpa_lcd(); // limpa lcd comando_lcd(0xC0); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('T'); // imprime mensagem no lcd escreve_lcd ('E'); escreve_lcd ('C'); escreve_lcd ('L'); escreve_lcd ('A'); escreve_lcd (' '); escreve_lcd ('3'); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Tecla 4 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_tecla_4(void) limpa_lcd(); // limpa lcd comando_lcd(0xC9); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('T'); // imprime mensagem no lcd escreve_lcd ('E'); escreve_lcd ('C'); escreve_lcd ('L'); escreve_lcd ('A'); escreve_lcd (' '); escreve_lcd ('4'); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () PORTA = 0x00; //Clear PORTA PORTB = 0x00; //Clear PORTB PORTC = 0x00; //Clear PORTC PORTD = 0x00; //Clear PORTD PORTE = 0x00; //Clear PORTE LATA = 0x00; //Clear PORTA LATB = 0x00; //Clear PORTB LATC = 0x00; //Clear PORTC LATD = 0x00; //Clear PORTD LATE = 0x00; //Clear PORTE TRISA = 0b00101111; //CONFIG DIREÇÃO DOS PINOS PORTA0 TRISB = 0b00001111; //CONFIG DIREÇÃO DOS PINOS PORTB TRISC = 0b10011001; //CONFIG DIREÇÃO DOS PINOS PORTC TRISD = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTD TRISE = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTE ADCON1 = 0b00000111; //DESLIGA CONVERSORES A/D /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Sistema * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ RCON = 0X00; LINHA_4 = 1; //ATIVA LINHA 4 DO TECLADO MATRICIAL

Page 219: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 217

inicializa_lcd(); // configura o lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(1) ClrWdt(); FILTRO11 = 0; //BT1 FILTRO12 = T_FILTRO; //BT1 FILTRO21 = 0; //BT2 FILTRO22 = T_FILTRO; //BT2 FILTRO31 = 0; //BT3 FILTRO32 = T_FILTRO; //BT3 FILTRO41 = 0; //BT4 FILTRO42 = T_FILTRO; //BT4 if(!ST_NO_BOTS) tela_principal(); ST_NO_BOTS = 1; while(BT1) ClrWdt(); if (--FILTRO11 == 0) FILTRO12--; if (FILTRO12 == 0) if (!ST_BT1) tela_tecla_1(); ST_BT1 = 1; ST_NO_BOTS = 0; ST_BT1 = 0; // BOTÃO LIBERADO, LIMPA O FLAG while(BT2) ClrWdt(); if (--FILTRO21 == 0) FILTRO22--; if (FILTRO22 == 0) if (!ST_BT2) tela_tecla_2(); ST_BT2 = 1; ST_NO_BOTS = 0; ST_BT2 = 0; // BOTÃO LIBERADO, LIMPA O FLAG while(BT3) ClrWdt(); if (--FILTRO31 == 0)

Page 220: Apostila Mosaico Pic MÓDULO4

218

FILTRO32--; if (FILTRO32 == 0) if (!ST_BT3) tela_tecla_3(); ST_BT3 = 1; ST_NO_BOTS = 0; ST_BT3 = 0; // BOTÃO LIBERADO, LIMPA O FLAG while(BT4) ClrWdt(); if (--FILTRO41 == 0) FILTRO42--; if (FILTRO42 == 0) if (!ST_BT4) tela_tecla_4(); ST_BT4 = 1; ST_NO_BOTS = 0; ST_BT4 = 0; // BOTÃO LIBERADO, LIMPA O FLAG // FIM LAÇO PRINCIPAL

Page 221: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 219

Dicas e Comentários

Apesar da estrutura do sistema ficar muito simples com a implementação da rotina ESCREVE, nunca se deve esquecer de confirmar o estado da saída RS (define comando ou dado) antes de utilizá-la.

Notar que para enviar um caractere ao LCD deve-se utilizar o código ASCII do caractere. Apesar do sistema MCMASTER possuir ligação com o módulo de LCD através de 8 vias de dados é possível

utilizá-lo para testar e implementar a comunicação com 4 vias. Basta modificar a rotina de inicialização e a de escrita de um byte.

Exercícios Propostos

1. Altere a comunicação para 4 vias. 2. Mantenha a tela principal disponível somente quando o sistema é ligado. Após alguns segundos, mostre

uma tela com o nome das quatro teclas e indique a tecla pressionada através de um caractere de seta (←) ou outro qualquer.

Page 222: Apostila Mosaico Pic MÓDULO4

220

Experiência 7 – Conversor A/D

Objetivo

Nesta experiência será estudado o módulo de conversão A/D interno do PIC16F877A ou do PIC18F452.

Descrição

Este exemplo foi elaborado para explicar o funcionamento do módulo de conversão analógico digital interno do PIC16F877A ou do PIC18F452. É convertido o valor analógico presente no pino RA0 do microcontrolador, sendo que este valor pode ser alterado através do potenciômetro presente na placa do sistema MCMASTER.

A conversão é feita diretamente no loop principal, sem a utilização de nenhuma interrupção, nem para checar o término da conversão nem para definir uma freqüência de amostragem. Desta forma, a conversão será feita uma após a outra, na freqüência definida pelo período do loop principal.

Uma vez terminada a conversão, descarta-se os 2 bits menos significativos e considera-se somente o resultado armazenado em ADRESH. Com isso já se está executando uma espécie de filtragem, evitando assim que o valor final fique oscilando.

Aplica-se então uma regra de 3 para converter o valor do A/D para a unidade desejada: Volts. Considerando-se que quando o A/D resulta em 0 (zero) a entrada possui 0,0V, e quando o A/D resulta em 255 a entrada é equivalente a 5,0V, aplica-se a regra de 3 é mostra-se o valor da tensão, já em Volts, no LCD.

Para a execução da regra de 3 foram utilizadas rotinas de multiplicação de 8x8 e divisão de 16x16 retiradas de Aplication Notes da própria Microchip.

Page 223: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 221

Esquema Elétrico

Page 224: Apostila Mosaico Pic MÓDULO4

222

Fluxograma

INÍCIO

INICIALIZA DISPLAY

VETOR DE RESET PULA P/ INÍCIO DO

PROGRAMA

CONFIGURAÇÕES INICIAIS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION.

1

PREPARA TELA PRINCIPAL“ A/D Int. (RA0) ”

“ Volts ”

CONFIGURA REGISTRADOR ADCON1 RA0, RA1 e RA3 COMO ENTRADAS ANALÓGICAS

RA2, RA4 E RA5 COMO I/Os DIGITAIS PORTE COMO I/O DIGITAL

8 BITS EM ADRESH E 2 BITS EM ADRESL Vref+ = VDD (+5V) Vref- = GND ( 0V)

CONFIGURA REGISTRADOR ADCON0 MÓDULO A/D LIGADO FREQÜÊNCIA - Fosc/8

MUX SELECIONADO P/ CANAL1 (RA1)

Page 225: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 223

Sim

Não

1

LIMPA WDT

INICIA CONVERSÃO (ADCON0,G0=1)

FIM CONVERSÃO?

MULTIPLICA VALOR DA CONVERSÃO POR 50d

DIVIDE RESULTADO POR 255d

AJUSTE DECIMAL

Aguarda que o bit GO do registrador

ADCON0 seja 0

POSICIONA CURSOR DO LCD

CONVERTE DEZENA EM ASCII

ENVIA “,” AO DISPLAY

ENVIA DEZENA AO DISPLAY

ENVIA UNIDADE AO DISPLAY

CONVERTE UNIDADE EM ASCII

FUNDO DE ESCALA = 5,0V ESTÃO SENDO

CONSIDERADOS APENAS OS 8 BITS MAIS

SIGNIFICATIVOS DA CONVERSÃO A/D

(ADRESH)

Page 226: Apostila Mosaico Pic MÓDULO4

224

AJUSTE DECIMAL

AUX = 0 ?

Não

INCREMENTA UNIDADE

UNIDADE = 10d ?

Sim

Não

Sim

ZERA UNIDADE INCREMENTA DEZENA

DECREMENTA AUXILIAR

SALVA ARGUMENTO EM AUXZERA UNIDADE ZERA DEZENA

Testa fim da conversão

Sim

Não

RETURN

AUX = 0?

Testa se o valor a ser convertido é igual a zero

Page 227: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 225

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - Recursos Avançados de programação * * Exemplo 7 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 10/08/2005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Este exemplo foi elaborado para explicar o funcionamento do módulo de // conversão analógico digital interno do PIC. É convertido o valor analógico // presente no pino RA2 do microcontrolador, sendo que este valor pode ser // alterado através do potenciômetro P2 da placa MCLAB2. O valor da conversão // A/D é ajustado numa escala de 0 à 5V e mostrado no LCD. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // O arquivo de definições do pic utilizado deve ser referenciado para que //os nomes definidos pela Microchip possam ser utilizados, sem a necessidade //de redigitação. #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config WDT = ON #pragma config WDTPS = 128 #pragma config LVP = OFF #pragma config PWRT = ON #pragma config BORV = 42 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter); void escreve_lcd(unsigned char caracter); void limpa_lcd(void); void inicializa_lcd(void); void tela_principal(void); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis *

Page 228: Apostila Mosaico Pic MÓDULO4

226

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. unsigned int conversao = 0; // armazena o resultado da conversão AD unsigned char conversao1 = 0; // armazena o resultado da conversão AD unsigned char unidade; unsigned char dezena; unsigned char centena; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As saídas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define rs PORTEbits.RE0 // via do lcd que sinaliza recepção de dados ou comando #define enable PORTEbits.RE1 // enable do lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter) rs = 0; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1 ; // gera pulso no enable Delay10TCYx(1); // espera 3 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(unsigned char caracter) rs = 1; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1; // gera pulso no enable Delay10TCYx(1); // espera 10 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd(void) comando_lcd(0x01); // limpa lcd Delay1KTCYx(2); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Page 229: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 227

void inicializa_lcd(void) comando_lcd(0x30); // envia comando para inicializar display Delay1KTCYx(4); // espera 4 milisengundos comando_lcd(0x30); // envia comando para inicializar display Delay10TCYx(10); // espera 100 microsengundos comando_lcd(0x30); // envia comando para inicializar display comando_lcd(0x38); // liga o display, sem cursor e sem blink limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_principal(void) comando_lcd(0x83); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('V'); escreve_lcd ('o'); escreve_lcd ('l'); escreve_lcd ('t'); escreve_lcd ('i'); escreve_lcd ('m'); escreve_lcd ('e'); escreve_lcd ('t'); escreve_lcd ('r'); escreve_lcd ('o'); // imprime mensagem no lcd void converte_bcd(unsigned char aux) unidade = 0; dezena = 0; centena = 0; if (aux == 0)return; while(aux--) unidade++; if(unidade != 10)continue; unidade = 0; dezena++; if (dezena != 10)continue; dezena = 0; centena++; if (centena != 10)continue; centena = 0; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Pic * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() // configura microcontrolador OpenADC(ADC_FOSC_8 & ADC_LEFT_JUST & ADC_3ANA_0REF, ADC_CH0 & ADC_INT_OFF); PORTA=0x00; // limpa porta

Page 230: Apostila Mosaico Pic MÓDULO4

228

PORTB=0x00; // limpa portb PORTC=0x00; // limpa portc PORTD=0x00; // limpa PORTD PORTE=0x00; // limpa porte LATA=0x00; // limpa porta LATB=0x00; // limpa portb LATC=0x00; // limpa portc LATD=0x00; // limpa PORTD LATE=0x00; // limpa porte TRISA=(0b11111111); // configuração da direção dos pinos de I/O TRISB=(0b11111111); TRISC=(0b11111111); TRISD=(0b00000000); TRISE=(0b00000100); inicializa_lcd(); // configura o lcd tela_principal(); // imprime a tela principal no LCD /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(1) // rotina principal ClrWdt(); //Inicia o watch-dog timer ConvertADC(); //Inicia conversão AD while (BusyADC()); //Aguarda Fim da conversão AD conversao = ADRESH; //lê resultado da conversão AD conversao = (conversao * 50); //faz regra de 3 para converter o valor, conversao = (conversao / 255); //das unidades de AD em Volts. conversao1 = conversao; converte_bcd(conversao1); comando_lcd(0xC5); //posiciona o cursor na linha 1, coluna 2 escreve_lcd (dezena + 0x30); //escreve no display de LCD escreve_lcd (','); escreve_lcd (unidade + 0x30); //escreve no display de LCD escreve_lcd ('V');

Page 231: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 229

Dicas e Comentários

Inicialmente notar que toda a estrutura e rotinas utilizadas para a escrita no LCD são as mesmas já aplicadas na experiência anterior.

Observar também que não foi utilizada nenhuma interrupção neste programa. Por isso, o programa permanece parado em um pequeno loop enquanto a conversão não termina. Isto é checado através do bit ADCON0<GO/DONE>.

Outra rotina bem interessante que aparece neste sistema é a de conversão de um número qualquer (limitado entre 0 e 99) em dois dígitos separados, facilitando assim a escrita no LCD. Esta rotina devolve os dígitos nas variáveis UNIDADE e DEZENA. Não esquecer que antes de transmitir um valor decimal ao LCD, deve-se converte-lo em um caractere ASCII.

Para facilitar as contas e não utilizarmos números fracionários, a conversão para Volts é feita considerando-se 50 no lugar de 5,0 de forma que ao enviar o valor final ao LCD é simplesmente colocada uma vírgula entre os dois dígitos.

Exercícios Propostos

1. Simule que a entrada analógica é um sensor de temperatura linear que deve marcar de 10 a 80°C; 2. Altere o exemplo para indicar a tensão entre 0 e 5,00V, utilizando 10 bits de resolução.

Page 232: Apostila Mosaico Pic MÓDULO4

230

Experiência 8 – Modulo PWM

Objetivo

O objetivo desta experiência é ensinar ao aluno como utilizar o módulo PWM do microcontrolador PIC18F452.

Descrição

Este PIC possui 2 canais de PWMs (CCP1 e CCP2), cada um com resolução máxima de 10 bits. Isto significa que o duty cycle poderá ser regulado de 0 a 100% com uma resolução máxima de 1024 pontos. No entanto, dependendo da configuração adotada, esta resolução não será atingida.

O período do PWM é controlado diretamente pelo TMR2, através do registrador PR2. Como já foi visto, sempre que TMR2 = PR2, o timer é zerado e neste momento, um novo período do PWM é iniciado. Desta forma, pode-se definir o período e a freqüência do PWM pelas seguintes fórmulas:

T = [(PR2) + 1] x 4 x Tosc x (Prescale do TMR2)

PWMFreq = 1 / T

O duty cycle normalmente é definido em porcentagem, porém, o PIC não define o valor do duty cycle e sim o tempo do pulso em nível alto. Desta forma, o tempo do pulso pode ser calculado por:

tp = CCPRxL:CCPxCON<CCPxX:CCPxY> x Tosc x (Prescale do TMR2)

Repare que a largura do pulso é ajustada em dois registradores: CCPRxL que armazena os 8 bits mais

significativos e CCPxCON que armazena os dois bits menos significativos. Assim, obtêm-se os 10 bits que controlam o duty cycle do PWM.

Apesar do PIC não definir o duty cycle, ele pode ser calculado dividindo o tempo do pulso em nível alto pelo período total do PWM.

Verifica-se então que apesar do período e o do tempo de pulso dependerem do cristal (Tosc) e do ajuste do prescale do TMR2, o duty cycle depende única e exclusivamente dos valores ajustados nos registradores PR2, CCPRxL e CCPxCON (bits 5 e 4).

Veja que o registrador PR2 (8 bits) que controla o período do PWM é multiplicado por 4 para poder igualar-se aos 10 bits que controlam o duty cycle. É justamente este o problema da resolução máxima atingida. Se o registrador PR2 for ajustado com um valor menor que 8 bits, ou seja, menor do que 255, serão necessários menos do que 10 bits para atingir um PWM com 100% de duty cycle. Portanto, o número de pontos para ajuste do duty cycle é 4 vezes maior do que o valor ajustado em (PR2+1). Em termos de bits, podemos dizer que a resolução do duty cycle é 2 bits maior do que o número de bits que formam o valor ajustado em PR2. Repare também que caso PR2 seja ajustado com 255 nunca será atingido um duty cycle de 100%, pois o período atingirá o valor máximo de 1024 ([PR2+1]x4) enquanto o tempo do pulso em nível alto (<DCxB9:DCxB0>) será no máximo 1023.

No software da experiência ativou-se a saída do módulo CCP2 para controlar a rotação do ventilador que está ligado ao pino RC1.

tp =

[(PR2) + 1] x 4 x TOSC x (Prescale do TMR2)

CCPRxL:CCPxCON<DCxB1:DCxB0> x TOSC x (Prescale do TMR2)

T

tp =

[(PR2) + 1] X 4

CCPRxL:CCPxCON<DCxB1:DCxB0>

T

Page 233: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 231

O registrador PR2 foi ajustado com valor máximo, ou seja, 255 e o prescale do timer foi configurado para 1:16. Com isso a freqüência do PWM ficou em 244,14Hz (PWMPeríodo = 4,096ms), considerando-se que o microcontrolador do sistema MCMASTER está trabalhando a 4MHz.

As teclas da linha 4 foram habilitadas e receberam as seguintes funções:

Coluna Duty Cycle 1 0% 2 50% 3 75% 4 100%

A fim de deixar o sistema mais interativo, utilizou-se o LCD para mostrar o valor atual ajustado para o PWM.

Page 234: Apostila Mosaico Pic MÓDULO4

232

Esquema Elétrico

Page 235: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 233

Fluxograma

INÍCIO

INICIALIZA DISPLAY

VETOR DE RESET PULA P/ INÍCIO DO

PROGRAMA

CONFIGURAÇÕES INICIAIS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION, ADs.

1

PREPARA TELA PRINCIPAL“ MCMASTER ”

“ PWM: 0FF ”

CONFIGURA REGISTRADOR PR2 (PERIODO DO PWM)

T=((PR2)+1)*4*Tosc*TMR2 Prescale T=((255)+1)*4*250ns*16 T=4,096ms -> 244,14Hz

CONFIGURA REGISTRADOR T2CON TIMER 2 LIGADO

PRESCALER -> 1:16 POSTSCALE -> 1:1

CONFIGURAÇÕES CCP2CON P/ PWMZERA DUTY CYCLE (CCPR2L)

Page 236: Apostila Mosaico Pic MÓDULO4

234

Não

LIMPA WDT

1

RECARREGA FILTRO

BOTÃO 0 PRESS.?

Não

Não

TRATA BOTÃO 0

TRATA BOTÃO 1

Sim

Sim

Sim

BOTÃO 3 PRESS.?

BOTÃO 2 PRESS.?

BOTÃO 1 PRESS.?

TRATA BOTÃO 3

TRATA BOTÃO 2

Sim

Não

Page 237: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 235

ESCREVE “OFF” NO LCD

CCPR2L = 0x00 LIMPA BITS 4 E 5 DE CCP2CON tp = CCPR2L:CCPR2CON<5,4>*

*Tosc*TMR2 Prescale tp = 0*250ns*16

tp = 0ms PWM -> Duty Cycle = 0% -> OFF

Sim

TRATA BOTÃO 0

ACÃO JÁ FOI EXEC. ?

Não

FILTRO TERMINOU ?

Sim

1

Não

ESCREVE “50%” NO LCD

CCPR2L = 0x80 LIMPA BITS 4 E 5 DE CCP2CON tp = CCPR2L:CCPR2CON<5,4>*

*Tosc*TMR2 Prescale tp = 512*250ns*16

tp = 2,048ms PWM -> Duty Cycle = 50%

Sim

TRATA BOTÃO 1

ACÃO JÁ FOI EXEC. ?

Não

FILTRO TERMINOU ?

Sim

1

Não

ESCREVE “75%” NO LCD

CCPR2L = 0XC0 LIMPA BITS 4 E 5 DE CCP2CON tp = CCPR2L:CCPR2CON<5,4>*

*Tosc*TMR2 Prescale tp = 768*250ns*16

tp = 3,072ms PWM -> Duty Cycle = 75%

Sim

TRATA BOTÃO 2

ACÃO JÁ FOI EXEC. ?

Não

FILTRO TERMINOU ?

Sim

1

Não

ESCREVE “100%” NO LCD

CCPR2L = 0xFF SETA BITS 4 E 5 DE CCP2CON tp = CCPR2L:CCPR2CON<5,4>*

*Tosc*TMR2 Prescale tp = 1023*250ns*16

tp = 4,092ms PWM -> Duty Cycle = 99,90%

Sim

TRATA BOTÃO 3

ACÃO JÁ FOI EXEC. ?

Não

FILTRO TERMINOU ?

Sim

1

Não

Page 238: Apostila Mosaico Pic MÓDULO4

236

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 - Recursos Básicos de programação * * Exemplo 8 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 10/08/2005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ESTE EXEMPLO FOI ELABORADO PARA EXPLICAR O FUNCIONAMENTO DO MÓDULO PWM DO PIC18F452. ELE MONITORA OS QUATRO BOTÕES E CONFORME O BOTÃO SELECIONADO APLICA UM VALOR DIFERENTE NO PWM, FAZENDO ASSIM UM CONTROLE SOBRE A VELOCIDADE DO VENTILADOR. NO LCD É MOSTRADO O VALOR ATUAL DO DUTY CYCLE. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config WDT = ON #pragma config LVP = OFF /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis Globais * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário unsigned char FILTRO11; //FILTRAGEM 1 PARA O BOTÃO 1 unsigned char FILTRO12; //FILTRAGEM 2 PARA O BOTÃO 1 unsigned char FILTRO21; //FILTRAGEM 1 PARA O BOTÃO 2 unsigned char FILTRO22; //FILTRAGEM 2 PARA O BOTÃO 2 unsigned char FILTRO31; //FILTRAGEM 1 PARA O BOTÃO 3 unsigned char FILTRO32; //FILTRAGEM 2 PARA O BOTÃO 3 unsigned char FILTRO41; //FILTRAGEM 1 PARA O BOTÃO 4 unsigned char FILTRO42; //FILTRAGEM 2 PARA O BOTÃO 4 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define T_FILTRO 25 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Page 239: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 237

* Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário struct unsigned BIT0:1; unsigned BIT1:1; unsigned BIT2:1; unsigned BIT3:1; unsigned BIT4:1; unsigned BIT5:1; unsigned BIT6:1; unsigned BIT7:1; FLAGSbits; //ARMAZENA OS FLAGS DE CONTROLE #define ST_BT1 FLAGSbits.BIT0 //STATUS DO BOTÃO 1 #define ST_BT2 FLAGSbits.BIT1 //STATUS DO BOTÃO 2 #define ST_BT3 FLAGSbits.BIT2 //STATUS DO BOTÃO 3 #define ST_BT4 FLAGSbits.BIT3 //STATUS DO BOTÃO 4 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter); void escreve_lcd(unsigned char caracter); void limpa_lcd(void); void inicializa_lcd(void); void tela_principal(void); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define BT1 PORTBbits.RB0 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT2 PORTBbits.RB1 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT3 PORTBbits.RB2 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT4 PORTBbits.RB3 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #define LINHA_4 PORTBbits.RB7 //PINO PARA ATIVAR LINHA 4 DO TECLADO //MATRICIAL //1 -> LINHA ATIVADA //0 -> LINHA DESATIVADA #define rs PORTEbits.RE0 // via do lcd que sinaliza recepção de dados ou comando #define enable PORTEbits.RE1 // enable do lcd

Page 240: Apostila Mosaico Pic MÓDULO4

238

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter) rs = 0; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1 ; // gera pulso no enable Delay10TCYx(1); // espera 3 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(unsigned char caracter) rs = 1; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1; // gera pulso no enable Delay10TCYx(1); // espera 10 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd(void) comando_lcd(0x01); // limpa lcd Delay1KTCYx(2); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd(void) comando_lcd(0x30); // envia comando para inicializar display Delay1KTCYx(4); // espera 4 milisengundos comando_lcd(0x30); // envia comando para inicializar display Delay10TCYx(10); // espera 100 microsengundos comando_lcd(0x30); // envia comando para inicializar display comando_lcd(0x38); // liga o display, sem cursor e sem blink limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_principal(void)

Page 241: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 239

limpa_lcd(); // limpa lcd comando_lcd(0x84); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('M'); // imprime mensagem no lcd escreve_lcd ('C'); escreve_lcd ('M'); escreve_lcd ('A'); escreve_lcd ('S'); escreve_lcd ('T'); escreve_lcd ('E'); escreve_lcd ('R'); comando_lcd(0xC4); // posiciona o cursor na linha 1, coluna 4 escreve_lcd ('P'); // imprime mensagem no lcd escreve_lcd ('W'); escreve_lcd ('M'); escreve_lcd (':'); escreve_lcd (' '); escreve_lcd ('O'); escreve_lcd ('F'); escreve_lcd ('F'); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Tecla 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_tecla_1(void) comando_lcd(0xC9); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('O'); // imprime mensagem no lcd escreve_lcd ('F'); escreve_lcd ('F'); escreve_lcd (' '); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Tecla 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_tecla_2(void) comando_lcd(0xC9); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('5'); // imprime mensagem no lcd escreve_lcd ('0'); escreve_lcd ('%'); escreve_lcd (' '); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Tecla 3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_tecla_3(void) comando_lcd(0xC9); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('7'); // imprime mensagem no lcd escreve_lcd ('5'); escreve_lcd ('%'); escreve_lcd (' '); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Tecla 4 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_tecla_4(void)

Page 242: Apostila Mosaico Pic MÓDULO4

240

comando_lcd(0xC9); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('1'); // imprime mensagem no lcd escreve_lcd ('0'); escreve_lcd ('0'); escreve_lcd ('%'); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () PORTA = 0x00; //Clear PORTA PORTB = 0x00; //Clear PORTB PORTC = 0x00; //Clear PORTC PORTD = 0x00; //Clear PORTD PORTE = 0x00; //Clear PORTE LATA = 0x00; //Clear PORTA LATB = 0x00; //Clear PORTB LATC = 0x00; //Clear PORTC LATD = 0x00; //Clear PORTD LATE = 0x00; //Clear PORTE TRISA = 0b00101111; //CONFIG DIREÇÃO DOS PINOS PORTA0 TRISB = 0b00001111; //CONFIG DIREÇÃO DOS PINOS PORTB TRISC = 0b10011001; //CONFIG DIREÇÃO DOS PINOS PORTC TRISD = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTD TRISE = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTE ADCON1 = 0b00000111; //DESLIGA CONVERSORES A/D OpenPWM2(255); OpenTimer2(TIMER_INT_OFF & T2_PS_1_16 & T2_POST_1_1); SetDCPWM2(0); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Sistema * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ RCON = 0X00; LINHA_4 = 1; //ATIVA LINHA 4 DO TECLADO MATRICIAL inicializa_lcd(); // configura o lcd tela_principal(); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(1) ClrWdt(); FILTRO11 = 0; //BT1 FILTRO12 = T_FILTRO; //BT1 FILTRO21 = 0; //BT2 FILTRO22 = T_FILTRO; //BT2 FILTRO31 = 0; //BT3 FILTRO32 = T_FILTRO; //BT3 FILTRO41 = 0; //BT4 FILTRO42 = T_FILTRO; //BT4

Page 243: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 241

while(BT1) ClrWdt(); if (--FILTRO11 == 0) FILTRO12--; if (FILTRO12 == 0) if (!ST_BT1) tela_tecla_1(); SetDCPWM2(0); ST_BT1 = 1; ST_BT1 = 0; // BOTÃO LIBERADO, LIMPA O FLAG while(BT2) ClrWdt(); if (--FILTRO21 == 0) FILTRO22--; if (FILTRO22 == 0) if (!ST_BT2) tela_tecla_2(); SetDCPWM2(512); ST_BT2 = 1; ST_BT2 = 0; // BOTÃO LIBERADO, LIMPA O FLAG while(BT3) ClrWdt(); if (--FILTRO31 == 0) FILTRO32--; if (FILTRO32 == 0) if (!ST_BT3) tela_tecla_3(); SetDCPWM2(767); ST_BT3 = 1; ST_BT3 = 0; // BOTÃO LIBERADO, LIMPA O FLAG while(BT4) ClrWdt(); if (--FILTRO41 == 0) FILTRO42--; if (FILTRO42 == 0) if (!ST_BT4) tela_tecla_4(); SetDCPWM2(1023); ST_BT4 = 1;

Page 244: Apostila Mosaico Pic MÓDULO4

242

ST_BT4 = 0; // BOTÃO LIBERADO, LIMPA O FLAG // FIM LAÇO PRINCIPAL

Page 245: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 243

Dicas e Comentários

Para calcular o valor que deve ser carregado nos registradores que controlam o tempo do pulso em nível alto (duty cycle) a partir de um determinado valor de duty cycle expresso em porcentagem pode-se utilizar a formula a seguir:

CCPRx = [(PR2)+1] x 4 x Porcentagem desejada

Vejamos como exemplo o valor de 50% adotado nesta experiência. A porcentagem desejada é de 50% e o

valor de PR2 é 255, assim,

CCPRx = 256 * 4 * 0,5 CCPRx = 512

Ou seja, se carregarmos os registradores que controlam o tempo do pulso em nível alto com 512, obteremos

um duty cycle de 50%

Exercícios Propostos

1. Corrija o problema encontrado no nível 100%, evitando que a saída seja colocada em zero, mesmo que por um período de tempo muito curto.

2. Em vez de trabalhar com somente 4 níveis de PWM, altere o sistema para que um botão ligue e desligue a saída e outros dois botões incremente e decremente o PWM, de 50 a 100% com passos de 5%.

3. Ative as duas saídas PWMs ao mesmo tempo, uma para o ventilador e outra para a resistência. Utilize dois botões para controlar o ajuste de cada uma delas.

Page 246: Apostila Mosaico Pic MÓDULO4

244

Experiência 9 – Master I2C

Objetivo

O objetivo desta experiência é mostrar ao aluno como acessar a memória de dados EEPROM externa (24LC256) utilizando os recursos de hardware do PIC para implementar o protocolo de comunicação I2C.

Descrição

Conforme comentado na descrição do hardware, está memória está mapeada no endereço 7h (111b) da rede de comunicação I2C a fim de evitar conflitos com o relógio de tempo real. Além disso, como a memória utilizada no MCMASTER é de 256Kbits, ou seja, 32Kbytes, são necessários 15 bits, ou seja, 2 bytes, para o correto endereçamento.

Levando-se isso em consideração, para a escrita de dados na memória o microcontrolador deverá enviar a seguinte seqüência de informações:

• Envia o byte de controle que deve incorporar o endereço de hardware da memória na rede I2C além

do bit de R/W, que neste caso deve ser enviado em 0 a fim de sinalizar uma operação de escrita. Assim, o byte de controle completo considerando o mapeamento adotado no MCMASTER é 10101110b;

• Envia um start bit; • Recebe o bit de acknowledge (ACK); • Envia a parte mais significativa do endereço onde o dado será gravado; • Recebe o bit de acknowledge (ACK); • Envia a parte menos significativa do endereço onde o dado será gravado; • Recebe o bit de acknowledge (ACK); • Envia o dado a ser gravado; • Recebe o bit de acknowledge (ACK); • Envia um stop bit.

Já para uma operação de leitura a seqüência deverá ser:

• Envia um start bit; • Envia o byte de controle que deve incorporar o endereço de hardware da memória na rede I2C além

do bit de R/W, que neste caso deve ser enviado em 0 a fim de sinalizar uma operação de escrita. Note que inicialmente o endereço que se deseja ler deve ser escrito na memória. Assim, o byte de controle completo considerando o mapeamento adotado no MCMASTER é 10101110b;

• Recebe o bit de acknowledge (ACK); • Envia a parte mais significativa do endereço de o dado será lido; • Recebe o bit de acknowledge (ACK); • Envia a parte menos significativa do endereço de onde o dado será lido; • Recebe o bit de acknowledge (ACK); • Envia outro start bit; • Envia novamente o byte de controle, porém agora alterando o bit R/W para sinalizar a operação de

leitura. Assim, o byte de controle completo fica 10101111b; • Recebe o bit de acknowledge (ACK); • Recebe o byte lido da memória; • Envia um bit em 1 sinalizando que deseja encerrar leitura (sinal de NACK); • Envia um stop bit.

Page 247: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 245

O exemplo da experiência foi elaborado utilizando os procedimentos descritos acima. São utilizados os botões da linha 4 para manipular um valor de 8 bits mostrado no display LCD. Este valor pode ser salvo e lido na memória EEPROM. Os botões das colunas 1 e 2 são utilizados para incrementar e decrementar o valor mostrado no display. O botão da coluna 3 salva o valor do display na memória serial enquanto o botão da coluna 4 é utilizado para ler o valor salvo na memória serial.

Page 248: Apostila Mosaico Pic MÓDULO4

246

Esquema Elétrico

Page 249: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 247

Fluxograma

INÍCIO

INICIALIZA DISPLAY

Não

Sim

TRAVA O PROGRAMA AGUARDA ESTOURO

DO WDT

VETOR DE RESET PULA P/ INÍCIO DO

PROGRAMA

CONFIGURAÇÕES INICIAIS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION, ADs.

RESET WDT ?

1

MONTA TELA PRINCIPAL DO LCD

CARREGA ENDEREÇO A SER LIDO DA MEMÓRIA EEPROM

I2C E2PROM READ

SALVA DADO LIDO NA VARIÁVEL CORRETA

(VALOR_DADOS)

CONFIGURA FREQUÊNCIA DO CLOCK DO BARRAMENTO I2C

EM 100kHz

HABILITA MODO MASTER I2C

Page 250: Apostila Mosaico Pic MÓDULO4

248

Não

LIMPA WDT

1

BOTÃO 0 PRESS.?

Não

Não

TRATA BOTÃO 0

TRATA BOTÃO 1

Sim

Sim

Sim

BOTÃO 3 PRESS.?

BOTÃO 2 PRESS.?

BOTÃO 1 PRESS.?

TRATA BOTÃO 3

TRATA BOTÃO 2

Sim

Não

CARREGA ENDEREÇO ONDE O DADO SERÁ SALVO NA E2PROM

TRATA BOTÃO 2

1

CARREGA DADO A SER SALVO NA E2PROM

I2C EEPROM WRITE Não

Sim ERRO DE LEITURA?

CARREGA ENDEREÇO ONDE O DADO SERÁ

LIDO DA E2PROM

TRATA BOTÃO 3

1

CARREGA DADO LIDO DA E2PROM NA

VARIÁVEL CORRETA (VALOR_DADO)

I2C EEPROM READ

Page 251: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 249

INCREMENTA VALOR_DADOS

TRATA BOTÃO 0

1

ATUALIZA LCD

DECREMENTA VALOR_DADOS

TRATA BOTÃO 1

1

ATUALIZA LCD

Sim

Não

Não

EVENTO I2C EM ANDAMENTO?

AGUARDA I2C LIVRE

RETURN

TODOS OS EVENTO I2C

FINALIZADOS?

ACK OUT

CARREGA ACK = 0 (SSPCON2,ACKDT=0)

ENVIA ACK (SSPCON2,ACKEN=1)

RETURN

NACK OUT

CARREGA ACK = 1 (SSPCON2,ACKDT=1)

ENVIA ACK (SSPCON2,ACKEN=1)

RETURN

Page 252: Apostila Mosaico Pic MÓDULO4

250

I2C EEPROM READ

ENVIA START BIT (SSPCON2,SEN=1)

ENVIA CONTROLE+END.COMP.+WRITE

(10101110b -> SSPBUF)

RETURN

RECEBE BYTE (SSPCON2,RCEN=1

AGUARDA I2C LIVRE

AGUARDA I2C LIVRE

ENVIA ENDEREÇO HIGH (xxxxxxxxb->SSPBUF)

AGUARDA I2C LIVRE

ENVIA START BIT (SSPCON2,SEN=1)

ENVIA CONTROLE+END.COMP.+READ

(10101111b -> SSPBUF)

AGUARDA I2C LIVRE

AGUARDA I2C LIVRE

AGUARDA I2C LIVRE

NACK OUT

ENVIA STOP BIT (SSPCON2,PEN=1)

AGUARDA I2C LIVRE

ENVIA ENDEREÇO LOW (xxxxxxxxb->SSPBUF)

AGUARDA I2C LIVRE

Page 253: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 251

I2C EEPROM WRITE

ENVIA START BIT (SSPCON2,SEN=1)

ENVIA CONTROLE+END.COMP.+WRITE

(10101110b -> SSPBUF)

RETURN

AGUARDA I2C LIVRE

AGUARDA I2C LIVRE

ENVIA ENDEREÇO HIGH (xxxxxxxxb -> SSPBUF)

AGUARDA I2C LIVRE

ENVIA DADO A SER GRAVADO (xxxxxxxxb -> SSPBUF)

AGUARDA I2C LIVRE

ENVIA STOP BIT (SSPCON2,PEN=1)

AGUARDA I2C LIVRE

ENVIA ENDEREÇO LOW (xxxxxxxxb -> SSPBUF)

AGUARDA I2C LIVRE

Page 254: Apostila Mosaico Pic MÓDULO4

252

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 - Recursos Básicos de programação * * Exemplo 6 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 10/08/2006 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ESTE EXEMPLO FOI ELABORADO PARA EXPLICAR O FUNCIONAMENTO DA LEITURA/ESCRITA NA MEMÓRIA E2PROM SERIAL EXTERNA, UTILIZANDO O MASTER I2C. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config WDT = ON #pragma config WDTPS = 4 #pragma config LVP = OFF /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis Globais * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário unsigned char FILTRO11; //FILTRAGEM 1 PARA O BOTÃO 1 unsigned char FILTRO12; //FILTRAGEM 2 PARA O BOTÃO 1 unsigned char FILTRO21; //FILTRAGEM 1 PARA O BOTÃO 2 unsigned char FILTRO22; //FILTRAGEM 2 PARA O BOTÃO 2 unsigned char FILTRO31; //FILTRAGEM 1 PARA O BOTÃO 3 unsigned char FILTRO32; //FILTRAGEM 2 PARA O BOTÃO 3 unsigned char FILTRO41; //FILTRAGEM 1 PARA O BOTÃO 4 unsigned char FILTRO42; //FILTRAGEM 2 PARA O BOTÃO 4 unsigned char valor_dados = 0; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção.

Page 255: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 253

#define T_FILTRO 25 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário struct unsigned BIT0:1; unsigned BIT1:1; unsigned BIT2:1; unsigned BIT3:1; unsigned BIT4:1; unsigned BIT5:1; unsigned BIT6:1; unsigned BIT7:1; FLAGSbits; //ARMAZENA OS FLAGS DE CONTROLE #define ST_BT1 FLAGSbits.BIT0 //STATUS DO BOTÃO 1 #define ST_BT2 FLAGSbits.BIT1 //STATUS DO BOTÃO 2 #define ST_BT3 FLAGSbits.BIT2 //STATUS DO BOTÃO 3 #define ST_BT4 FLAGSbits.BIT3 //STATUS DO BOTÃO 4 #define ST_I2C FLAGSbits.BIT4 //STATUS DO I2C /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter); void escreve_lcd(unsigned char caracter); void limpa_lcd(void); void inicializa_lcd(void); void tela_principal(void); void I2C_EEPROM_WRITE(unsigned int endereco, unsigned char dado); unsigned char I2C_EEPROM_READ(unsigned int endereco); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define BT1 PORTBbits.RB0 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT2 PORTBbits.RB1 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT3 PORTBbits.RB2 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO #define BT4 PORTBbits.RB3 //PORTA DO BOTÃO //1 -> PRESSIONADO //0 -> LIBERADO /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #define LINHA_4 PORTBbits.RB7 //PINO PARA ATIVAR LINHA 4 DO TECLADO //MATRICIAL //1 -> LINHA

Page 256: Apostila Mosaico Pic MÓDULO4

254

ATIVADA //0 -> LINHA DESATIVADA #define rs PORTEbits.RE0 // via do lcd que sinaliza recepção de dados ou comando #define enable PORTEbits.RE1 // enable do lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter) rs = 0; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1 ; // gera pulso no enable Delay10TCYx(1); // espera 3 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(unsigned char caracter) rs = 1; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1; // gera pulso no enable Delay10TCYx(1); // espera 10 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd(void) comando_lcd(0x01); // limpa lcd Delay1KTCYx(2); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd(void) comando_lcd(0x30); // envia comando para inicializar display Delay1KTCYx(4); // espera 4 milisengundos comando_lcd(0x30); // envia comando para inicializar display Delay10TCYx(10); // espera 100 microsengundos comando_lcd(0x30); // envia comando para inicializar display comando_lcd(0x38); // liga o display, sem cursor e sem blink limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita

Page 257: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 255

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void atualiza_linha_1(void) comando_lcd(0x83); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('M'); // imprime mensagem no lcd escreve_lcd ('A'); escreve_lcd ('S'); escreve_lcd ('T'); escreve_lcd ('E'); escreve_lcd ('R'); escreve_lcd (' '); escreve_lcd ('I'); escreve_lcd ('2'); escreve_lcd ('C'); void atualiza_linha_2(unsigned char aux) unsigned char hexa_high; unsigned char hexa_low; hexa_low = aux & 0b00001111; hexa_high = (aux >> 4) & 0b00001111; comando_lcd(0xC6); // posiciona o cursor na linha 0, coluna 0 if(hexa_high <= 9) escreve_lcd (hexa_high + 0x30); // imprime mensagem no lcd else escreve_lcd(hexa_high + 0x37); if(hexa_low <= 9) escreve_lcd (hexa_low + 0x30); // imprime mensagem no lcd else escreve_lcd(hexa_low + 0x37); escreve_lcd ('h'); // imprime mensagem no lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ESCRITA DA EEPROM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para escrita na EEPROM externa I2C * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void I2C_EEPROM_WRITE(unsigned int endereco, unsigned char dado) unsigned char endereco_high; unsigned char endereco_low; endereco_high = endereco >> 8; endereco_low = endereco; StartI2C(); while(SSPCON2bits.SEN); WriteI2C(0b10100110); // controle de escrita IdleI2C(); // espera fim do evento I2C WriteI2C(endereco_high); IdleI2C(); // espera fim do evento I2C WriteI2C(endereco_low); IdleI2C(); // espera fim do evento I2C WriteI2C(dado); // controle de leitura StopI2C(); // fim de comunicação while(SSPCON2bits.PEN); ClrWdt(); Delay100TCYx(100); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Page 258: Apostila Mosaico Pic MÓDULO4

256

* Função para leitura na EEPROM externa I2C * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ unsigned char I2C_EEPROM_READ(unsigned int endereco) unsigned char endereco_high; unsigned char endereco_low; unsigned char dado; endereco_high = endereco >> 8; endereco_low = endereco; StartI2C(); while(SSPCON2bits.SEN); WriteI2C(0b10100110); // controle de escrita IdleI2C(); // espera fim do evento I2C WriteI2C(endereco_high); IdleI2C(); // espera fim do evento I2C WriteI2C(endereco_low); IdleI2C(); // espera fim do evento I2C RestartI2C(); while(SSPCON2bits.SEN); WriteI2C(0b10100111); // controle de leitura IdleI2C(); // espera fim do evento I2C SSPCON2bits.RCEN = 1; while(SSPCON2bits.RCEN); NotAckI2C(); while(SSPCON2bits.ACKEN); StopI2C(); // fim de comunicação while(SSPCON2bits.PEN); return((unsigned char) SSPBUF); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () OpenI2C(MASTER,SLEW_OFF); SSPADD = 0b00001001; PORTA = 0x00; //Clear PORTA PORTB = 0x00; //Clear PORTB PORTC = 0x00; //Clear PORTC PORTD = 0x00; //Clear PORTD PORTE = 0x00; //Clear PORTE LATA = 0x00; //Clear PORTA LATB = 0x00; //Clear PORTB LATC = 0x00; //Clear PORTC LATD = 0x00; //Clear PORTD LATE = 0x00; //Clear PORTE TRISA = 0b00101111; //CONFIG DIREÇÃO DOS PINOS PORTA0 TRISB = 0b00001111; //CONFIG DIREÇÃO DOS PINOS PORTB TRISC = 0b10010001; //CONFIG DIREÇÃO DOS PINOS PORTC TRISD = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTD TRISE = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTE ADCON1 = 0b00000111; //DESLIGA CONVERSORES A/D while(RCONbits.NOT_TO); //aguarda estouro do WDT /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Sistema * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ RCON = 0X00; LINHA_4 = 1; //ATIVA LINHA 4 DO TECLADO MATRICIAL

Page 259: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 257

inicializa_lcd(); // configura o lcd atualiza_linha_1(); valor_dados = I2C_EEPROM_READ(0x0100); atualiza_linha_2(valor_dados); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(1) ClrWdt(); FILTRO11 = 0; //BT1 FILTRO12 = T_FILTRO; //BT1 FILTRO21 = 0; //BT2 FILTRO22 = T_FILTRO; //BT2 FILTRO31 = 0; //BT3 FILTRO32 = T_FILTRO; //BT3 FILTRO41 = 0; //BT4 FILTRO42 = T_FILTRO; //BT4 while(BT1) ClrWdt(); if (--FILTRO11 == 0) FILTRO12--; if (FILTRO12 == 0) if (!ST_BT1) //função valor_dados++; atualiza_linha_2(valor_dados); ST_BT1 = 1; ST_BT1 = 0; // BOTÃO LIBERADO, LIMPA O FLAG while(BT2) ClrWdt(); if (--FILTRO21 == 0) FILTRO22--; if (FILTRO22 == 0) if (!ST_BT2) //função valor_dados--; atualiza_linha_2(valor_dados); ST_BT2 = 1; ST_BT2 = 0; // BOTÃO LIBERADO, LIMPA O FLAG while(BT3) ClrWdt();

Page 260: Apostila Mosaico Pic MÓDULO4

258

if (--FILTRO31 == 0) FILTRO32--; if (FILTRO32 == 0) if (!ST_BT3) //função I2C_EEPROM_WRITE(0x0100,valor_dados); atualiza_linha_2(valor_dados); ST_BT3 = 1; ST_BT3 = 0; // BOTÃO LIBERADO, LIMPA O FLAG while(BT4) ClrWdt(); if (--FILTRO41 == 0) FILTRO42--; if (FILTRO42 == 0) if (!ST_BT4) //função valor_dados = I2C_EEPROM_READ(0x0100); atualiza_linha_2(valor_dados); ST_BT4 = 1; ST_BT4 = 0; // BOTÃO LIBERADO, LIMPA O FLAG // FIM LAÇO PRINCIPAL

Page 261: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 259

Dicas e Comentários

Este programa não utiliza as interrupções de leitura e escrita relacionadas ao protocolo I2C. Desta forma, ele possui uma rotina (AGUARDA_I2C_LIVRE) para saber se o sistema está liberado para a próxima ação.

Exercícios Propostos

1. Faça três modificações no primeiro exercício proposto da experiência 7. • Utilize a memória externa; • Limite os dados mostrados no display entre 0x41 e 0x5A; • Mostre os dados em ASCII, ou seja, entre A (0x41) e Z (0x5A);

2. Utilizando o exercício anterior grave na memória uma mensagem de até 16 caracteres. Depois, crie um programa que ao ser inicializado leia os 16 caracteres da memória e mostre a mensagem lida no LCD;

Page 262: Apostila Mosaico Pic MÓDULO4

260

Experiência 10 – Comunicação serial RS232 via USART

Objetivo

O objetivo desta experiência é o aprendizado do módulo USART do microcontrolador PIC16F877A ou do PIC18F452 utilizado para implementar a comunicação padrão RS232, geralmente utilizada para estabelecer um canal de comunicação entre um microcontrolador e um computador.

Descrição

Para tornar o sistema versátil e simples, criou-se um programa capaz de testar a transmissão e recepção de dados de modo isolado, ou seja, apenas com o MCMASTER sem necessariamente conecta-lo ao computador. Embora nada impeça que a comunicação com o PC seja efetivamente realizada.

Para atender esta necessidade, o software da experiência implementa uma comunicação assíncrona Full duplex, isto é, com a transmissão e a recepção ativadas simultaneamente.

O valor transmitido é obtido a partir da leitura da tensão do potenciômetro através do conversor A/D limitando este valor entre 0 e 255 (8-bits). O valor do A/D é então enviado para a porta serial e para o LCD. Desta forma é possível visualizar o dado transmitido. Para facilitar ainda mais o usuário, mostra-se o valor em decimal (d) e em hexadecimal (h). A comunicação é realizada no padrão 8N1 com uma velocidade de 9.600bps.

Quanto à recepção, o valor obtido pela porta serial é diretamente impresso no display de LCD, através do código ASCII.

Para que o sistema funcione sem o PC, basta interligar os pinos 2 e 3 do conector DB9. Isto fará com que tudo que seja transmitido por TX seja imediatamente recebido em RX. Tanto a transmissão quanto a recepção são contínuas.

Não se deve esquecer de habilitar a porta RS232 para o microcontrolador através do botão de modo de operação após.

Page 263: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 261

Esquema Elétrico

Page 264: Apostila Mosaico Pic MÓDULO4

262

Fluxograma

INÍCIO

INICIALIZA DISPLAY

Não

Sim

TRAVA O PROGRAMA AGUARDA ESTOURO

DO WDT

VETOR DE RESET PULA P/ INÍCIO DO

PROGRAMA

CONFIGURAÇÕES INICIAIS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION, ADs.

RESET WDT ?

1

PREPARA TELA PRINCIPAL“USART:9600,8,n,1”

“TX: d h RX: ”

CONFIGURA REGISTRADOR TXSTA HABILITA TRANSMISSÃO

MODO ASSÍNCRONO TRANSMISSÃO DE 8 BITS HIGH SPEED BAUD RATE

CONFIGURA BAUD RATE SPBRG = 25d -> 9600 bps

CONFIGURA REGISTRADOR RCSTA HABILITA RECEPÇÃO RECEPÇÃO DE 8 BITS RECEPÇÃO CONTÍNUA

DESABILITA ADDRESS DETECT

Page 265: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 263

Testa bit RCIF do registrador

PIR1

Aguarda que o bit GO do registrador

ADCON0 seja 0

Sim

Não

1

LIMPA WDT

INICIA CONVERSÃO (ADCON0,G0=1)

FIM CONVERSÃO?

Sim

Não

ALGUM DADO RECEBIDO?

2

3

4

Testa bit TRMT do registrador

TXSTA

MOSTRA O VALOR DA CONVERSÃO A/D EM DECIMAL E HEXADECIMAL NO

DISPLAY LCD

3

Sim

Não BUFFER DE TX ESTÁ VAZIO?

TRANSMITE VALOR DA CONVERSÃO A/D PELA USART

INICIA UMA NOVA CONVERSÃO(ADCON0,GO=1)

2

MOSTRA O DADO RECEBIDO NO DISPLAY LCD

4

2

Page 266: Apostila Mosaico Pic MÓDULO4

264

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 - Recursos Básicos de programação * * Exemplo 10 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 10/08/2005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ESTE EXEMPLO FOI ELABORADO PARA EXPLICAR O FUNCIONAMENTO DA USART DO PIC. O SOFTWARE CONVERTE O CANAL 1 DO CONVERSOR A/D (POTENCIÔMETRO P2) E MOSTRA NO DISPLAY O VALOR CONVERTIDO EM DECIMAL E HAXADECIMAL. ALÉM DE MOSTRAR O VALOR NO DISPLAY, O SOFTWARE TRANSMITE PELA USART O VALOR DA CONVERSÃO. OS VALORES RECEBIDOS PELA USART TAMBÉM SÃO MOSTRADOS NO LCD COMO CARACTERES ASCII. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config WDT = ON #pragma config WDTPS = 4 #pragma config LVP = OFF /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis Globais * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário unsigned char unidade; unsigned char dezena; unsigned char centena; unsigned char hexa_low; unsigned char hexa_high; unsigned char converte; char usart_rx; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Page 267: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 265

//A definição de constantes facilita a programação e a manutenção. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. //Este programa não utiliza nenhum flag de usuário /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter); void escreve_lcd(unsigned char caracter); void limpa_lcd(void); void inicializa_lcd(void); void tela_principal(void); void converte_bcd(unsigned char aux); void converte_hexadecimal(unsigned char aux); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #define rs PORTEbits.RE0 // via do lcd que sinaliza recepção de dados ou comando #define enable PORTEbits.RE1 // enable do lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter) rs = 0; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1 ; // gera pulso no enable Delay10TCYx(1); // espera 3 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(unsigned char caracter) rs = 1; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1; // gera pulso no enable Delay10TCYx(1); // espera 10 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Page 268: Apostila Mosaico Pic MÓDULO4

266

void limpa_lcd(void) comando_lcd(0x01); // limpa lcd Delay1KTCYx(2); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd(void) comando_lcd(0x30); // envia comando para inicializar display Delay1KTCYx(4); // espera 4 milisengundos comando_lcd(0x30); // envia comando para inicializar display Delay10TCYx(10); // espera 100 microsengundos comando_lcd(0x30); // envia comando para inicializar display comando_lcd(0x38); // liga o display, sem cursor e sem blink limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_principal(void) comando_lcd(0x80); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('U'); // imprime mensagem no lcd escreve_lcd ('S'); escreve_lcd ('A'); escreve_lcd ('R'); escreve_lcd ('T'); escreve_lcd (':'); escreve_lcd ('9'); escreve_lcd ('6'); escreve_lcd ('0'); escreve_lcd ('0'); escreve_lcd (','); escreve_lcd ('8'); escreve_lcd (','); escreve_lcd ('n'); escreve_lcd (','); escreve_lcd ('1'); comando_lcd(0xC0); // posiciona o cursor na linha 1, coluna 4 escreve_lcd ('T'); // imprime mensagem no lcd escreve_lcd ('X'); escreve_lcd (':'); escreve_lcd (' '); escreve_lcd (' '); escreve_lcd (' '); escreve_lcd ('d'); escreve_lcd (' '); escreve_lcd (' '); escreve_lcd (' '); escreve_lcd ('h'); escreve_lcd (' '); escreve_lcd ('R'); escreve_lcd ('X'); escreve_lcd (':');

Page 269: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 267

escreve_lcd (' '); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void converte_bcd(unsigned char aux) unidade = 0; dezena = 0; centena = 0; if (aux == 0)return; while(aux--) unidade++; if(unidade != 10)continue; unidade = 0; dezena++; if (dezena != 10)continue; dezena = 0; centena++; if (centena != 10)continue; centena = 0; void converte_hexadecimal(unsigned char aux) hexa_low = aux & 0b00001111; hexa_high = (aux >> 4) & 0b00001111; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main () OpenADC(ADC_FOSC_32 & ADC_LEFT_JUST & ADC_3ANA_0REF, ADC_CH0 & ADC_INT_OFF ); OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH,25); PORTA = 0x00; //Clear PORTA PORTB = 0x00; //Clear PORTB PORTC = 0x00; //Clear PORTC PORTD = 0x00; //Clear PORTD PORTE = 0x00; //Clear PORTE LATA = 0x00; //Clear PORTA LATB = 0x00; //Clear PORTB LATC = 0x00; //Clear PORTC LATD = 0x00; //Clear PORTD LATE = 0x00; //Clear PORTE TRISA = 0b00101111; //CONFIG DIREÇÃO DOS PINOS PORTA TRISB = 0b00001111; //CONFIG DIREÇÃO DOS PINOS PORTB TRISC = 0b10011001; //CONFIG DIREÇÃO DOS PINOS PORTC TRISD = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTD TRISE = 0b00000000; //CONFIG DIREÇÃO DOS PINOS PORTE while(RCONbits.NOT_TO); //aguarda estouro do WDT /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Sistema * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Page 270: Apostila Mosaico Pic MÓDULO4

268

RCON = 0X00; inicializa_lcd(); // configura o lcd tela_principal(); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ConvertADC(); //Inicia conversão AD while(1) ClrWdt(); if(BusyADC()) converte = ADRESH; converte_bcd(converte); comando_lcd(0xC3); // posiciona o cursor na linha 1, coluna 4 escreve_lcd (centena + 0x30); // imprime mensagem no lcd escreve_lcd (dezena + 0x30); escreve_lcd (unidade + 0x30); converte_hexadecimal(ADRESH); comando_lcd(0xC8); // posiciona o cursor na linha 1, coluna 4 if(hexa_high <= 9) escreve_lcd (hexa_high + 0x30); // imprime mensagem no lcd else escreve_lcd(hexa_high + 0x37); if(hexa_low <= 9) escreve_lcd (hexa_low + 0x30); // imprime mensagem no lcd else escreve_lcd(hexa_low + 0x37); while(BusyUSART()) ClrWdt(); WriteUSART(converte); continue; if(DataRdyUSART()) usart_rx = ReadUSART(); comando_lcd(0xCF); // posiciona o cursor na linha 1, coluna 4 escreve_lcd(usart_rx); ConvertADC(); //Inicia conversão AD // FIM LAÇO PRINCIPAL

Page 271: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 269

Dicas e Comentários

A rotina de conversão Hex >>> Decimal deste exemplo é mais completa do que nos casos anteriores, pois trabalha com 3 dígitos (CENTENA, DEZENA e UNIDADE). Desta forma, ela pode converter todo o range do argumento de entrada (W) que vai de 0 a 255.

O sistema de conversão A/D é o mesmo apresentado na experiência 11, onde utilizou-se o conversor interno considerando apenas os 8 bits mais significativos. Com isso o valor a ser transmitido já fica limitado a um byte.

Devido a simplicidade do sistema não foi necessário o uso das interrupções, deixando-as desabilitadas. Para o caso da recepção o bit RCIF é testando toda vez dentro do loop principal. Quanto a transmissão, sempre que um novo valor foi convertido, checa-se se o buffer de saída está vazio para poder escrever o novo valor.

Exercícios Propostos

1. Ative o uso da interrupção de recebimento. Quanto à transmissão, em vez de deixá-la contínua, crie uma interrupção de timer como base de tempo. Por exemplo, transmita o valor atual convertido a cada 1 segundo;

2. Crie um programa no PC que receba o valor convertido, efetue alguma operação e devolva outro valor. Por exemplo, divida o valor por 25, pegue a parte inteira e some 30h para imprimir no LCD um valor de 0 a 9;

3. Mude a rotina de recepção e escrita no LCD para poder receber um número de 0 a 50 e mostrá-lo como 0.0 a 5.0. Altere o programa do PC para efetuar a regra de 3 necessária para converter um valor de 0 a 255 para 0 a 50. Com isso você voltou ao multímetro da experiência 7, só que com as contas de multiplicação e divisão não mais sendo feitas no PIC.

Page 272: Apostila Mosaico Pic MÓDULO4

270

Experiência 11 – Teclado matricial 4x4

Objetivo

O objetivo desta experiência é mostrar ao aluno um método simples para implementação de um teclado matricial.

Descrição

O teclado matricial do MCMASTER é composto por 4 linhas e 4 colunas formando assim uma matriz de 16 teclas. Desta forma, utilizam-se 8 pinos do microcontrolador para realizar a leitura do teclado.

Os conceitos adotados na experiência de varredura de displays de leds não são muito diferentes dos adotados para varrer os estados de um teclado matricial.

Analisando o esquema elétrico nota-se que todas as teclas de uma mesma coluna estão interligadas. Além disso, nota-se um resistor de pull-down em cada uma das vias. Veja também que todas as teclas de uma mesma linha também encontram-se interligadas. A idéia de varredura aplicada aqui é habilitar uma linha de cada vez e analisar se alguma tecla da linha habilitada está pressionada.

Para isso, deve-se configurar o microcontrolador com os pinos das linhas como saída e os pinos das colunas como entrada. Note que se todas as linhas estiverem em nível lógico 0, ou seja, se nenhuma linha estiver habilitada, ao ler o estado das colunas sempre será lido o valor 0, estando as teclas pressionadas ou não. Na verdade o microcontrolador estará lendo o estado dos resistores que no caso são de pull-down, ou seja, leitura em 0.

Porém, se habilitarmos uma das linhas (e apenas uma) colocando-a em nível lógico 1 e pressionarmos uma tecla dessa linha, ao lermos o estado das colunas encontraremos um bit em 1, sendo que a posição do bit em 1 sinalizará a coluna na qual a tecla foi pressionada. Como foi o próprio microcontrolador que habilitou a linha, o número da linha é conhecido e como a posição do bit em 1 define a coluna da tecla é fácil determinar a linha e coluna da tecla pressionada.

O conceito de varredura continua válido, pois apenas uma linha deve ser habilitada de cada vez e o microcontrolador deve ficar o tempo todo alterando (varrendo) a linha habilitada e lendo o estado das colunas. Enquanto nenhum bit das colunas valer 1, a varredura das linhas continua sendo executada. Ao encontrar uma coluna com tecla pressionada o software deve executar o filtro de debounce mantendo a linha atual habilitada até que o filtro de debounce seja finalizado.

No fluxograma apresentado fica fácil de entender o conceito da varredura do teclado matricial. O exemplo da experiência analisa o teclado e caso alguma tecla seja pressionada, mostra a linha e coluna da

mesma é mostrado no display LCD.

Page 273: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 271

Esquema Elétrico

Page 274: Apostila Mosaico Pic MÓDULO4

272

Fluxograma

INÍCIO

INICIALIZA DISPLAY

VETOR DE RESET PULA P/ INÍCIO DO

PROGRAMA

CONFIGURAÇÕES INICIAIS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION, ADs.

1

MONTA TELA PRINCIPAL DO LCD “ TECLADO 4x4 ” “LINHA: COLUNA: “

ATIVA UMA DAS LINHAS

Page 275: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 273

LINHA 4 ATIVA?

LINHA 3 ATIVA?

LINHA 2 ATIVA?

Não

LIMPA WDT

1

ALGUM BOTÃO

PRESS. ?

Não

Não

Sim

Sim

Sim CARREGA NÚMERO DA LINHA NO WORK

(W=1) LINHA 1 ATIVA?

Sim

Não

ATIVA A PRÓXIMA LINHA

CARREGA NÚMERO DA LINHA NO WORK

(W=2)

CARREGA NÚMERO DA LINHA NO WORK

(W=3)

CARREGA NÚMERO DA LINHA NO WORK

(W=4)

SALVA O NÚEMRO DA LINHA ATIVA

2

Page 276: Apostila Mosaico Pic MÓDULO4

274

Sim

Sim

Sim

Sim

Não

Não

Não

Não

ALGUM BOTÃO DA COLUNA 1 PRESS. ?

CARREGA WORK COM 1

ALGUM BOTÃO DA COLUNA 2 PRESS. ?

CARREGA WORK COM 2

ALGUM BOTÃO DA COLUNA 3 PRESS. ?

CARREGA WORK COM 3

ALGUM BOTÃO DA COLUNA 4 PRESS. ?

CARREGA WORK COM 4

RECARREGA FILTRO DE DEBOUNCE

ATUALIZA DISPLAY LCD

1

3

3

3

3

2

Page 277: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 275

Não

SALVA O NÚMERO DA COLUNA

3

FIM DEBOUNCE DA TECLA ?

Sim

ATUALIZA O NÚMERO DA LINHA E DA COLUNA

NO DISPLAY LCD

1

Page 278: Apostila Mosaico Pic MÓDULO4

276

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 * * Exemplo 11 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * E-MAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 10/08/2005 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Este exemplo foi elaborado para explicar o funcionamento do teclado matricial4x4. O número da linha e coluna da tecla pressionada e mostrado no LCD.*/ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // O arquivo de definições do pic utilizado deve ser referenciado para que //os nomes definidos pela Microchip possam ser utilizados, sem a necessidade //de redigitação. #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config WDT = ON #pragma config WDTPS = 64 #pragma config LVP = OFF #pragma config PWRT = ON #pragma config BORV = 42 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter); void escreve_lcd(unsigned char caracter); void limpa_lcd(void); void inicializa_lcd(void); void tela_principal(void); void trata_coluna(void); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis *

Page 279: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 277

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. unsigned char filtro; // Filtro para teclas unsigned char num_linha; // Armazena o número da linha ativada unsigned char num_coluna; // Armazena o número da coluna // unsigned char linha; // Registrador auxiliar para ativar as linhas do teclado 4x4 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. union Linhas_teclado struct unsigned BIT0:1; unsigned BIT1:1; unsigned BIT2:1; unsigned BIT3:1; unsigned BIT4:1; unsigned BIT5:1; unsigned BIT6:1; unsigned BIT7:1; ; //ARMAZENA OS FLAGS DE CONTROLE unsigned char linha_teclado; linha_ativa; #define linha1 linha_ativa.BIT4 /* LINHA_ATIVA,4, BIT 4 DO REGISTRADOR LINHA_ATIVA REPRESENTA A LINHA 1 DO TECLADO 4x4 1 -> LINHA ESTÁ ATIVADA 0 -> LINHA ESTÁ DESATIVADA */ #define linha2 linha_ativa.BIT5 /* LINHA_ATIVA,5, BIT 5 DO REGISTRADOR LINHA_ATIVA REPRESENTA A LINHA 2 DO TECLADO 4x4 1 -> LINHA ESTÁ ATIVADA 0 -> LINHA ESTÁ DESATIVADA */ #define linha3 linha_ativa.BIT6 /* LINHA_ATIVA,6, BIT 6 DO REGISTRADOR LINHA_ATIVA REPRESENTA A LINHA 3 DO TECLADO 4x4 1 -> LINHA ESTÁ ATIVADA 0 -> LINHA ESTÁ DESATIVADA */ #define linha4 linha_ativa.BIT7 /* LINHA_ATIVA,7, BIT 7 DO REGISTRADOR LINHA_ATIVA REPRESENTA A LINHA 4 DO TECLADO 4x4 1 -> LINHA ESTÁ ATIVADA 0 -> LINHA ESTÁ DESATIVADA */ #define fim linha_ativa.BIT3 /* REPRESENTA O FINAL DA VARREDURA 1 -> LINHA ESTÁ ATIVADA -> LINHA ESTÁ DESATIVADA */ #define linha linha_ativa.linha_teclado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define coluna1 PORTBbits.0 /* PINO DE ENTRADA DA COLUNA 1 1 -> ALGUMA TECLA DESTA COLUNA ESTÁ PRESSIONADA 0 -> NENHUMA TECLA DESTA COLUNA ESTÁ PRESSIONADA */ #define coluna2 PORTBbits.1 /* PINO DE ENTRADA DA COLUNA 2 1 -> ALGUMA TECLA DESTA COLUNA ESTÁ PRESSIONADA 0 -> NENHUMA TECLA DESTA COLUNA ESTÁ PRESSIONADA */

Page 280: Apostila Mosaico Pic MÓDULO4

278

#define coluna3 PORTBbits.2 /* PINO DE ENTRADA DA COLUNA 3 1 -> ALGUMA TECLA DESTA COLUNA ESTÁ PRESSIONADA 0 -> NENHUMA TECLA DESTA COLUNA ESTÁ PRESSIONADA */ #define coluna4 PORTBbits.3 /* PINO DE ENTRADA DA COLUNA 4 1 -> ALGUMA TECLA DESTA COLUNA ESTÁ PRESSIONADA 0 -> NENHUMA TECLA DESTA COLUNA ESTÁ PRESSIONADA */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As saídas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define rs PORTEbits.RE0 // via do lcd que sinaliza recepção de dados ou comando #define enable PORTEbits.RE1 // enable do lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter) rs = 0; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1 ; // gera pulso no enable Delay10TCYx(1); // espera 3 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(unsigned char caracter) rs = 1; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1; // gera pulso no enable Delay10TCYx(1); // espera 10 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd(void) comando_lcd(0x01); // limpa lcd Delay1KTCYx(2); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd(void) comando_lcd(0x30); // envia comando para inicializar display Delay1KTCYx(4); // espera 4 milisengundos comando_lcd(0x30); // envia comando para inicializar display Delay10TCYx(10); // espera 100 microsengundos

Page 281: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 279

comando_lcd(0x30); // envia comando para inicializar display comando_lcd(0x38); // liga o display, sem cursor e sem blink limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_principal(void) comando_lcd(0x82); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('T'); // imprime mensagem no lcd escreve_lcd ('e'); escreve_lcd ('c'); escreve_lcd ('l'); escreve_lcd ('a'); escreve_lcd ('d'); escreve_lcd ('o'); escreve_lcd (' '); escreve_lcd ('4'); escreve_lcd ('X'); escreve_lcd ('4'); comando_lcd(0xC0); // posiciona o cursor na linha 1, coluna 0 escreve_lcd ('L'); // imprime mensagem no lcd escreve_lcd ('i'); escreve_lcd ('n'); escreve_lcd ('h'); escreve_lcd ('a'); escreve_lcd (':'); escreve_lcd (' '); escreve_lcd (' '); escreve_lcd ('C'); escreve_lcd ('o'); escreve_lcd ('l'); escreve_lcd ('u'); escreve_lcd ('n'); escreve_lcd ('a'); escreve_lcd (':'); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina para tratamento das colunas do Teclado 4X4 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void trata_coluna(void) if(filtro) filtro--; if (filtro)return; PORTB = 0; comando_lcd(0xC6); // posiciona o cursor na linha 1, coluna 6 escreve_lcd (0x30 + num_linha); // comando_lcd(0xCF); // posiciona o cursor na linha 1, coluna 15 escreve_lcd (0x30 + num_coluna);// PORTD = 0; PORTB = linha;

Page 282: Apostila Mosaico Pic MÓDULO4

280

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Pic * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() // configura microcontrolador PORTA=0x00; // limpa porta PORTB=0x00; // limpa portb PORTC=0x00; // limpa portc PORTD=0x00; // limpa PORTD PORTE=0x00; // limpa porte LATA=0x00; // limpa porta LATB=0x00; // limpa portb LATC=0x00; // limpa portc LATD=0x00; // limpa PORTD LATE=0x00; // limpa porte TRISA=(0b00101111); // configuração da direção dos pinos de I/O TRISB=(0b00001111); TRISC=(0b10011000); TRISD=(0b00000000); TRISE=(0b00000000); ADCON1=0b00000111; inicializa_lcd(); // configura o lcd tela_principal(); // imprime a tela principal no LCD /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ linha = 0b00010000; while(1) // rotina principal ClrWdt(); //Inicia o watch-dog timer ativa_proxima_linha: if (filtro == 100) linha = linha >> 1; if (fim) linha = 0b10000000; PORTB = linha; if (linha4) num_linha = 4; // verifica qual é a linha ativa if (linha3) num_linha = 3; if (linha2) num_linha = 2; if (linha1) num_linha = 1; switch(PORTB & 0b00001111) case 1: num_coluna = 1; // verifica qual é a linha ativa trata_coluna(); break; case 2: num_coluna = 2; // verifica qual é a linha ativa trata_coluna(); break; case 4: num_coluna = 3; // verifica qual é a linha ativa trata_coluna(); break; case 8:

Page 283: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 281

num_coluna = 4; // verifica qual é a linha ativa trata_coluna(); break; default: filtro = 100; PORTB = 0; // Desativa todos os displays de 7 segmentos comando_lcd(0xC6); // posiciona o cursor na linha 1, coluna 6 escreve_lcd (' '); // comando_lcd(0xCF); // posiciona o cursor na linha 1, coluna 15 escreve_lcd (' '); // PORTD = 0; PORTB = linha;

Page 284: Apostila Mosaico Pic MÓDULO4

282

Dicas e Comentários

Notar que ao habilitar uma linha do teclado matricial também se habilita um dos displays de 7 segmentos, ou seja, foram utilizados os mesmos pinos do microcontrolador para habilitar as linhas e os displays. Esta é uma forma econômica de varrer os displays e ao mesmo tempo varrer o teclado. Veja que com apenas 16 I/Os do microcontrolador foi possível ligar 4 displays de 7 segmentos e 16 teclas. Foram utilizados 8 I/Os para segmentos mais o ponto decimal, 4 I/Os de seleção (linhas e displays) e 4 I/Os de colunas.

Exercícios Propostos

1. Alterar o mapeamento do software invertendo a numeração das linhas e colunas. 2. Mostrar no display LCD o número da tecla pressionada e não o número da linha e da coluna. 3. Sem utilizar o display LCD, fazer um software que utilize a varredura do teclado e dos displays ao mesmo

tempo, mostrando o número da tecla pressionada nos displays.

Page 285: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 283

Experiência 12 – Relógio de tempo real (RTC)

Objetivo

O objetivo desta experiência é mostrar como utilizar o relógio de tempo real (RTC).

Descrição

No MCMASTER optou-se pela utilização do relógio de tempo real (RTC) modelo PCF8583P da Philips. O protocolo de comunicação é do tipo I2C e para maiores informações a respeito do componente deve-se consultar o data sheet disponível no CD.

As rotinas de acesso ao relógio seguem o padrão adotado na experiência 16 (Master I2C) com apenas algumas modificações. Na realidade as alterações são que o relógio está mapeado no endereço 0h (000b) para evitar conflitos com a memória e ao invés de serem utilizados dois bytes para compor o endereço foi utilizado apenas um o que já é suficiente.

O software da experiência apenas lê a hora atual do relógio e mostra o resultado no LCD. Vale lembrar que o relógio é completo, ou seja, dispõe de hora, minuto, segundo, dia, mês e ano, inclusive

bissexto.

Page 286: Apostila Mosaico Pic MÓDULO4

284

Esquema Elétrico

Page 287: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 285

Fluxograma

INÍCIO

INICIALIZA DISPLAY

VETOR DE RESET PULA P/ INÍCIO DO

PROGRAMA

CONFIGURAÇÕES INICIAIS PORTAS, TIMERS,

INTERRUPÇÕES, OPTION, ADs.

1

MONTA TELA PRINCIPAL DO LCD

CONFIGURA FREQUÊNCIA DO CLOCK DO BARRAMENTO I2C

EM 100kHz

HABILITA MODO MASTER I2C

Page 288: Apostila Mosaico Pic MÓDULO4

286

LIMPA WDT

1

CARREGA ENDEREÇO DA LEITURA DA HORA

ATUALIZA A HORA NO DISPLAY LCD

SALVA A HORA NA RAM

I2C_READ_RTC

CARREGA ENDEREÇO DA LEITURA DOS MINUTOS

SALVA OS MINUTOS NA RAM

I2C_READ_RTC

CARREGA ENDEREÇO DA LEITURA DOS SEGUNDOS

SALVA OS REGUNDOS NA RAM

I2C_READ_RTC

Page 289: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 287

Sim

Não

Não

EVENTO I2C EM ANDAMENTO?

AGUARDA I2C LIVRE

RETURN

TODOS OS EVENTO I2C

FINALIZADOS?

ACK OUT

CARREGA ACK = 0 (SSPCON2,ACKDT=0)

ENVIA ACK (SSPCON2,ACKEN=1)

RETURN

NACK OUT

CARREGA ACK = 1 (SSPCON2,ACKDT=1)

ENVIA ACK (SSPCON2,ACKEN=1)

RETURN

Sim

Não RECEBEU ACK?

TESTA ACK

RETURN

LIMPA FLAG DE ERRO

SETA FLAG DE ERRO

Page 290: Apostila Mosaico Pic MÓDULO4

288

I2C_READ_RTC

Não

Sim

ENVIA START BIT (SSPCON2,SEN=1)

ENVIA CONTROLE+END.COMP.+WRITE

(10100000b -> SSPBUF)

OCORREU ERRO?

RETURN

RECEBE BYTE (SSPCON2,RCEN=1

AGUARDA I2C LIVRE

AGUARDA I2C LIVRE

TESTA ACK

Não

Sim

ENVIA ENDEREÇO (xxxxxxxxb->SSPBUF)

OCORREU ERRO?

AGUARDA I2C LIVRE

TESTA ACK

ENVIA START BIT (SSPCON2,SEN=1)

2

2

Não

Sim

ENVIA CONTROLE+END.COMP.+READ

(10100001b -> SSPBUF)

OCORREU ERRO?

AGUARDA I2C LIVRE

TESTA ACK

2

AGUARDA I2C LIVRE

AGUARDA I2C LIVRE

NACK OUT

ENVIA STOP BIT (SSPCON2,PEN=1)

AGUARDA I2C LIVRE

ENVIA STOP BIT (SSPCON2,PEN=1)

RETURN

2

Page 291: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 289

Código /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C18 * * Exemplo 12 * * * * CENTRO DE TREINAMENTO - MOSAICO ENGENHARIA * * * * TEL: (0XX11) 4992-8775 SITE: www.mosaico-eng.com.br * * EMAIL: [email protected] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // O arquivo de definições do pic utilizado deve ser referenciado para que //os nomes definidos pela Microchip possam ser utilizados, sem a necessidade //de redigitação. #include <p18F452.h> // Register definitions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #pragma config OSC = XT #pragma config WDT = ON #pragma config WDTPS = 128 #pragma config LVP = OFF #pragma config PWRT = ON #pragma config BORV = 42 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INCLUDES DAS FUNÇÕES DE PERIFÉRICOS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <pwm.h> //PWM library functions #include <adc.h> //ADC library functions #include <timers.h> //Timer library functions #include <delays.h> //Delay library functions #include <i2c.h> //I2C library functions #include <stdlib.h> //Library functions #include <usart.h> //USART library functions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PROTOTIPAGEM DE FUNÇÕES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter); void escreve_lcd(unsigned char caracter); void limpa_lcd(void); void inicializa_lcd(void); void tela_principal(void); void LE_RELOGIO(unsigned char endereco); void ESCREVE_RELOGIO(unsigned char endereco); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define END_HORA 4 // ENDEREÇO DA HORA NO RELOGIO RTC #define END_MINUTO 3 // ENDEREÇO DO MINUTO NO RELOGIO RTC #define END_SEGUNDO 2 // ENDEREÇO DO SEGUNDO NO RELOGIO RTC /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis *

Page 292: Apostila Mosaico Pic MÓDULO4

290

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. unsigned char dez_hora; unsigned char uni_hora; unsigned char dez_min; unsigned char uni_min; unsigned char dez_seg; unsigned char uni_seg; unsigned char buffer; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As saídas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #define rs PORTEbits.RE0 // via do lcd que sinaliza recepção de dados ou comando #define enable PORTEbits.RE1 // enable do lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(unsigned char caracter) rs = 0; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1 ; // gera pulso no enable Delay10TCYx(1); // espera 3 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(unsigned char caracter) rs = 1; // seleciona o envio de um comando PORTD = caracter; // carrega o PORTD com o caracter enable = 1; // gera pulso no enable Delay10TCYx(1); // espera 10 microsegundos enable = 0; // desce o pino de enable Delay10TCYx(4); // espera mínimo 40 microsegundos /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd(void) comando_lcd(0x01); // limpa lcd Delay1KTCYx(2); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD *

Page 293: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 291

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd(void) comando_lcd(0x30); // envia comando para inicializar display Delay1KTCYx(4); // espera 4 milisengundos comando_lcd(0x30); // envia comando para inicializar display Delay10TCYx(10); // espera 100 microsengundos comando_lcd(0x30); // envia comando para inicializar display comando_lcd(0x38); // liga o display, sem cursor e sem blink limpa_lcd(); // limpa lcd comando_lcd(0x0c); // display sem cursor comando_lcd(0x06); // desloca cursor para a direita /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LEITURA DO RELÓGIO * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void LE_RELOGIO(unsigned char endereco) StartI2C(); IdleI2C(); // espera fim do evento I2C WriteI2C(0b10100000); // controle de escrita IdleI2C(); // espera fim do evento I2C WriteI2C(endereco); // lê o relógio IdleI2C(); // espera fim do evento I2C RestartI2C(); // restart IdleI2C(); // espera fim do evento I2C WriteI2C(0b10100001); // controle de leitura IdleI2C(); // espera fim do evento I2C buffer = ReadI2C(); // recebe dado do relógio IdleI2C(); // espera fim do evento I2C StopI2C(); // fim de comunicação IdleI2C(); // espera fim do evento I2C /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ESCRITA NO RELÓGIO * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void ESCREVE_RELOGIO(unsigned char endereco) StartI2C(); IdleI2C(); // espera fim do evento I2C WriteI2C(0b10100000); // controle de escrita IdleI2C(); // espera fim do evento I2C WriteI2C(endereco); // escreve dado no relógio IdleI2C(); // espera fim do evento I2C WriteI2C(buffer); // escreve dado no relógio IdleI2C(); // espera fim do evento I2C StopI2C(); IdleI2C(); // espera fim do evento I2C /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tela Principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void tela_principal(void) comando_lcd(0x83); // posiciona o cursor na linha 0, coluna 0 escreve_lcd ('R'); escreve_lcd ('e'); escreve_lcd ('l'); escreve_lcd ('o'); escreve_lcd ('g');

Page 294: Apostila Mosaico Pic MÓDULO4

292

escreve_lcd ('i'); escreve_lcd ('o'); // imprime mensagem no lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Pic * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main() // configura microcontrolador PORTA=0x00; // limpa porta PORTB=0x00; // limpa portb PORTC=0x00; // limpa portc PORTD=0x00; // limpa PORTD PORTE=0x00; // limpa porte LATA=0x00; // limpa porta LATB=0x00; // limpa portb LATC=0x00; // limpa portc LATD=0x00; // limpa PORTD LATE=0x00; // limpa porte TRISA=(0b11111111); // configuração da direção dos pinos de I/O TRISB=(0b11111111); TRISC=(0b11110111); TRISD=(0b00000000); TRISE=(0b00000100); ADCON1=0b00000111; OpenI2C(MASTER,SLEW_OFF); SSPADD = 9; buffer = 0x23; // acerta hora ESCREVE_RELOGIO(END_HORA); buffer = 0x40; // acerta minuto ESCREVE_RELOGIO(END_MINUTO); buffer = 0x00; // acerta segundos ESCREVE_RELOGIO(END_SEGUNDO); inicializa_lcd(); // configura o lcd tela_principal(); // imprime a tela principal no LCD /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(1) // rotina principal ClrWdt(); //Inicia o watch-dog timer LE_RELOGIO(END_HORA); dez_hora = buffer >> 4; dez_hora = (dez_hora & 0b00000011) + 0x30; uni_hora = buffer; uni_hora = (uni_hora & 0b00001111) + 0x30; LE_RELOGIO(END_MINUTO); dez_min = buffer >> 4; dez_min = (dez_min & 0b00001111) + 0x30; uni_min = buffer; uni_min = (uni_min & 0b00001111) + 0x30; LE_RELOGIO(END_SEGUNDO); dez_seg = buffer >> 4; dez_seg = (dez_seg & 0b00001111) + 0x30; uni_seg = buffer; uni_seg = (uni_seg & 0b00001111) + 0x30;

Page 295: Apostila Mosaico Pic MÓDULO4

Curso Módulo 4 –Família 18F e MpLab C18 293

comando_lcd(0xC3); // posiciona o cursor na linha 0, coluna 3 escreve_lcd (dez_hora); // DEZ. HORA escreve_lcd (uni_hora); // UNID. HORA escreve_lcd (':'); // escreve_lcd (dez_min); // DEZ. MINUTO escreve_lcd (uni_min); // UNID. MINUTO escreve_lcd (':'); // escreve_lcd (dez_seg); // DEZ. SEGUNDO escreve_lcd (uni_seg); // UNID. SEGUNDO

Page 296: Apostila Mosaico Pic MÓDULO4

294

Dicas e Comentários

Além do relógio RTC o componente PCF8583 da Philips apresenta também uma região da memória que pode ser utilizada com uma RAM convencional, porém com acesso via I2C. Como geralmente o relógio sempre é utilizado junto com uma bateria, como no MCMASTER, este recurso da RAM pode ser útil para armazenar informações enquanto o microcontrolador não está energizado.

Exercícios Propostos

1. Altere o software para mostrar a data e a hora no display LCD. 2. Crie um software para ajustar a data e hora do relógio utilizando o teclado matricial.