Page 1

INTRODUÇÃO A PROGRAMAÇÃO

E MICROCONTROLADORES PIC

Prof. Fabiano F. Saldanha


Tópicos

3 – Introdução 3 – O que é programação 4 – Tipos de programação 7 – Passos para elaborar um projeto 7 – A lógica de programação 12 – Compiladores e Interpretadores 14 – Visualg 38 – Compilador C PCWHD da CCS versão estudante 39 – Esclarecimentos e agradecimentos

[2] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Introdução Meu objetivo em escrever esta apostila introdutória sobre programação e microcontroladores é apresentar ao aluno um conteúdo no qual ele possa se apoiar para esclarecer suas primeiras dúvidas com relação ao mundo dos sistemas embarcados. Não quero adentrar demasiadamente no assunto em minúcias pelo fato de que este material possa servir como primeiro contato com esta maravilhosa profissão chamada DESENVOLVEDOR DE SISTEMAS EMBARCADOS.

QUEM COMEÇA EM PROGRAMAÇÃO QUER RESULTADOS SEM ESFORÇOS, MAS SABER O PORQUÊ DAS COISAS É MUITO IMPORTANTE PARA SE TORNAR UM ÓTIMO PROGRAMADOR-PROFISSIONAL E NÃO APENAS UM RECORTADOR E COLADOR DE CÓDIGO!!!

O que é Programação? A programação é a arte de fazer com que o computador (microcontrolador) faça exatamente o que desejamos que ele fizesse. Um programa de computador(microcontrolador) é simplesmente um conjunto de instruções para dizer ao computador(microcontrolador) como executar uma determinada tarefa em particular.

[3] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Assim como existem vários idiomas diferentes em nosso mundo, na programação também existem muitas “Linguagens” PARA CONVERSARMOS COM O COMPUTADOR (MICROCONTROLADOR).

O resultado da programação (ou escrever um programa) são os chamados softwares e firmwares. Software é uma seqüência de instruções organizadas de maneira que, ao iniciá-lo tem como objetivo executar, manipular ou modificar um dado, informação ou acontecimento. Firmware é um software que foi escrito para um microcontrolador. Exemplo: Word, Excel etc são softwares, já o programa responsável por fazer seu computador iniciar ou até mesmo seu celular iniciar é chamado de firmware, pois você não o vê nem o controla ele já foi “escrito” e está contido dentro do processador do seu equipamento. O software (ou firmware) é considerado um produto que inclui além do programa, manuais e especificações. A linguagem de programação é responsável por converter o código em linguagem de maquina, ou seja, em um formato que será compreendido pelo processador ou microcontrolador. TIPOS DE PROGRAMAÇÃO Existem basicamente duas classificações para a linguagem de programação: Estruturada = códigos em formato de blocos que se interligam através de três métodos básicos: 1- Seqüência: onde os passos são seguidos de forma seqüencial (tarefa 1 finaliza entra tarefa2). 2- Seleção: onde os passos podem ser executados baseados em um tratamento lógico (IF, THEN, ELSE). 3- Interação: Onde os passos podem ser repetitivos até uma condição ser atingida (WHILE, FOR).

[4] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Orientada a Objeto = códigos em formato de objetos que se interligam, utiliza reutilização dos chamados componentes (espécie de mini programas que podem ser reutilizados). Esse tipo de programação pode ser visto como uma evolução da programação estruturada e por isso usamos a mesma lógica da programação estruturada, mas temos também os conceitos de classes, uma classe instanciada representa um objeto (dai o nome desse tipo de programação).

VAMOS ESTUDAR A PROGRAMAÇÃO ESTRUTURADA, POIS A MAIORIA DOS DISPOSITIVOS MICROCONTROLADOS UTILIZAM ESTA METODOLOGIA DE PROGRAMAÇÃO.

[5] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Para se ter uma idéia veja abaixo que a programação orientada a objeto é voltada para desenvolvimento de programas visuais, trabalhamos com botões, janelas, caixa de texto etc.

E a programação estruturada é voltada para o desenvolvimento de firmware, pois como o programa ficará integrado ao microcontrolador, precisamos apenas informar ao mesmo os comandos que ele deve executar POR ISSO A ESTRUTURADA É TODA ESCRITA!

[6] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


PASSOS PARA ELABORAR UM PROJETO Antes de iniciarmos com o estudo da programação você deve saber que todo desenvolvimento possui alguns passos mínimos que devem ser seguidos, são eles: - ENTREVISTA COM QUESTIONARIO: por exemplo, Qual o seu problema ou como podemos resolvê-lo? - BRAINSTORM: Levantamento da idéias técnicas principais (o que será utilizado e como será utilizado, por exemplo: tipo de linguagem, escolha de qual microcontrolador utilizar e ETC). - FLUXOGRAMA - ALGORITMO EM PORTUGOL OU ESCRITO - CODIFICAÇÃO DO ALGORITMO NA LINGUAGEM ESCOLHIDA - TESTES - DOCUMENTAÇÃO E MANUAIS - ENTREGA AO CLIENTE Para se escrever um programa temos que ter idéia principal o conceito de LÓGICA DE PROGRAMAÇÃO. A LÓGICA DE PROGRAMAÇÃO A LOGICA DE PROGRAMAÇÃO PARTE DO CONCEITO DA PREMISSA Uma premissa é uma sentença que afirma algo (positiva ou negativamente), no contexto de um silogismo. Um silogismo é composto por duas premissas e uma conclusão, no caso: 1) Todo homem é ser vivo 2) Todo ser vivo é mortal 3) Logo, todo homem é mortal 1 e 2 são premissas que levam à conclusão 3. 1, 2 e 3 formam o silogismo. Ou seja, premissa é uma função atribuída a uma sentença num contexto silogístico. Na Programação temos que ser totalmente lógicos!

[7] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Em computação utilizamos os ALGORITMOS para transcrever nossa lógica para a lógica da máquina (LÓGICA DE PROGRAMAÇÃO). Quando você olha uma receita de bolo, por exemplo, aquilo é um algoritmo, então podemos dizer que Algoritmo “São os passos a serem seguidos para se obter um determinado resultado”. Podemos narrar de forma descritiva um algoritmo simples de receita de bolo.

O que temos que entender é que um algoritmo seja ele qual for possui INICIO e FIM.

[8] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


CONSEGUIU PERCEBER QUE OS ALGORITMOS POSSUEM INICIO E FIM? Para se escrever algoritmo em um computador e vê-lo funcionar na prática, utilizamos algumas ferramentas para isto chamadas “Interpretadores de Algoritmos”. Existem vários interpretadores tais como: UAL, PORTUGOL, VISUALG etc. Utilizaremos o visualg por ser mais popular e possuir mais recursos. QUANDO ESCREVEMOS NUNCA MAIS ESQUECEMOS E TODO PROGRAMADOR DEVE GOSTAR DE ESCREVER PORQUE NÃO EXISTE PROGRAMA SEM TER QUE ESCREVERMOS ALGUM!

[9] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


O estudo de Estruturas de Dados é basicamente o estudo de métodos de organização de grandes quantidades de dados. Estes métodos incluem: 1. Formas de organizá-los (estruturas) e 2. Técnicas para manipulá-los (algoritmos básicos). Para manipular estas estruturas, como inserir elementos, retirar elementos, ordenar elementos, necessitamos de algoritmos. Estes algoritmos podem ser implementados de muitas formas. Essas formas podem ser simples e diretas e outras não tão simples, porém engenhosas e outras ainda complicadas e envolvendo muitas operações. Quando trabalhamos com quantidades muito grandes de dados, um projeto ruim de um algoritmo para manipular uma estrutura de dados pode resultar num programa que tem um tempo de execução inviável. Quando estudamos algoritmos, um aspecto que devemos considerar, além de sua correção, é a análise da sua eficiência. A análise de algoritmos pode ser definida como o estudo da estimativa do tempo de execução dos algoritmos. A - Um algoritmo é um conjunto finito de passos que devem ser seguidos com um conjunto de dados de entrada para se chegar a solução de um problema. B - Um problema pode geralmente ser resolvido por muitos algoritmos diferentes. O fato de existir um algoritmo para resolver um problema, não implica necessariamente que este problema possa realmente ser resolvido na prática. Há restrições de tempo ou de espaço de memória. Ex.: Calcular todas as possíveis partidas de xadrez. Um programa está sujeito às limitações físicas da máquina onde será executado, como capacidade de memória, velocidade do processador e dos periféricos, etc, exemplo no microcontrolador pic temos limitações visto que este dispositivo embora seja um sistema computacional ele é bem mais limitado que um computador. NA ESCRITA DE UM ALGORITMO TEMOS QUE TOMAR CUIDADO COM ERROS DE SINTAXE E SEMÃNTICA, pois muitas vezes ao executar um algoritmo o mesmo poderá apresentar erros, caso isto aconteça teremos que rever todo texto digitado para verificar se não houve os referidos erros. Antes de colocar culpa no algoritmo ou no interpretador, lembre-se quem está digitando o algoritmo é você!

[10] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


ERROS DE SINTAXE

[11] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Veremos agora o interpretador de algoritmos chamado VISUALG, ele é chamado de interpretador pois ao contrario do compilador o VISUALG é um programa que “lê” o algoritmo e já converte diretamente para código de maquina para que possa ser executada pelo computador, mas afinal de contas o que é COMPILADOR e INTERPRETADOR ?

COMPILADORES E INTERPRETADORES

O compilador é um software básico de computador capaz de traduzir uma linguagem, como por exemplo C, C++, Pascal, Delphi etc (código fonte) em outra na qual a máquina será capaz de compreender (código de maquina). O objetivo inicial do compilador é verificar se o programa está sintaticamente correto; por exemplo, na linguagem C os comandos devem ser terminados por ponto e vírgula, se isto não for feito a análise sintática emitirá uma mensagem de erro e a compilação do programa não terá sucesso. As etapas de uma forma geral para compilação são as mostradas a seguir:

[12] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


O processo de compilação de um microcontrolador utilizando o compilador que veremos mais adiante é bastante simples.

Para computadores depois de compilado o arquivo apresenta a extensão “.exe” (para plataforma Windows), e quando compilamos um programa para microcontrolador PIC o arquivo gerado possui a extensão “.HEX”, como mostrado acima. Os interpretadores não exigem a criação de um novo arquivo. Ele opera a partir do arquivo original (fonte) produzido pelo programador. O que o interpretador faz é ler o texto do programa e proceder conforme um vocabulário de palavras-chave. Com esta filosofia, o interpretador passa a maior parte do tempo lendo e traduzindo textos. Se o programa executa certa instrução mais de uma vez, o interpretador traduz a instrução cada vez que a encontra tantas vezes quantas forem necessárias. As maiorias dos microcontroladores utilizam arquivos compilados e não interpretados.

[13] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


VISUALG Para aprendermos programação temos que entender primeiramente algoritmos, como já foi dito anteriormente então vamos utilizar o interpretador VISUALG para criarmos algoritmos que serão executados pelo seu PC. Visualg desenvolvida por Cláudio Morgado de Souza. E-mail: cmorgado@apoioinformatica.com.br. Para programar em Visualg, utiza-se o Portugol (ou Português Estruturado), ele é, na verdade uma simplificação do português, limitado à um conjunto de palavras e regras que definem o que chamamos de sintaxe da linguagem, esta sintaxe será apresentada aos poucos.

[14] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


VisuAlg - Editor e Interpretador de Pseudocódigos Objetivos A idéia de escrever este programa nasceu a partir de uma necessidade: uma ferramenta que permitisse aos alunos iniciantes em programação o exercício dos seus conhecimentos num ambiente próximo da realidade. Em minha experiência como professor desta disciplina, tenho notado que a abstração de "rodar o chinês", ou seja, de executar um programa apenas no papel, é um grande obstáculo (quase intransponível para alguns) no aprendizado das técnicas de elaboração de algoritmos. Por outro lado, submeter um iniciante aos rigores de uma linguagem de programação como Pascal ou ao “esoterismo” do C também me parecia exagerado. O ideal seria uma linguagem mais simples, parecida com o "Portugol", de grande popularidade nos meios acadêmicos e presente nos livros mais utilizados; com ela, os princípios básicos da programação estruturada poderiam ser ensinados sem que a curva de aprendizagem fosse íngreme. Além disso, esta ferramenta deveria também ser capaz de simular o que acontece na tela do computador com o uso dos famosos comandos "leia" e "escreva", bem como possibilitar a verificação dos valores das variáveis, o acompanhamento passo a passo da execução de um algoritmo (pelo seu grande valor didático), e até mesmo suportar um modo simples de depuração. Aliado a tudo isto, deveria estar um editor de texto com recursos razoáveis (tais como abrir e salvar arquivos) e que dispusesse de todos os principais recursos de um ambiente gráfico. O VisuAlg é para mim a concretização desta idéia. Espero que, colocando-o em domínio público (numa versão freeware), possa ajudar professores e alunos de programação, e também ser ajudado por eles através de sugestões e críticas que visem sempre a sua melhoria. A idéia básica é manter o VisuAlg simples: deve ser como as rodinhas de apoio que uma criança usa ao aprender a andar de bicicleta, e que são retiradas quando deixam de ser necessárias. Isto não quer dizer que o VisuAlg não possa ou deva ser melhorado: conto com a colaboração de todos que vierem a utilizá-lo. Instalação e Requerimentos de Hardware O VisuAlg é um programa simples, que não depende de DLLs, OCXs ou outros componentes. Sua instalação não copia arquivos para nenhuma outra pasta a não ser aquela em que for instalado, e exige cerca de 1 MB de espaço em disco. Pode ser executado sob Windows 95 ou posterior, e tem melhor aparência com resolução de vídeo de 800x600 ou maior.

[15] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


A Tela Principal do VisuAlg A tela do VisuAlg compõe-se da barra de tarefas, do editor de textos (que toma toda a sua metade superior), do quadro de variáveis (no lado esquerdo da metade inferior), do simulador de saída (no correspondente lado direito) e da barra de status. Quando o programa é carregado, já apresenta no editor um "esqueleto" de pseudocódigo, com a intenção de poupar trabalho ao usuário e de mostrar o formato básico que deve ser seguido. Explicaremos a seguir cada componente da interface do VisuAlg.

A Barra de Tarefas Contém os comandos mais utilizados no VisuAlg (estes comandos também podem ser acessados pelo menu ou por atalhos no teclado).

[16] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Abrir (Ctrl-A): Abre um arquivo anteriormente gravado, substituindo o texto presente no editor. Se este tiver sido modificado, o VisuAlg pedirá sua confirmação para salvá-lo antes que seja sobreposto. Novo (Ctrl-N): Cria um novo "esqueleto" de pseudocódigo, substituindo o texto presente no editor. Se este tiver sido modificado, o VisuAlg pedirá sua confirmação para salvá-lo antes que seja sobreposto. Salvar (Ctrl-S): Grava imediatamente o texto presente no editor. Na primeira vez que um novo texto é gravado, o VisuAlg pede seu nome e localização. Imprimir: Imprime imediatamente na impressora padrão o texto presente no editor. Para configurar a impressão, use o comando Imprimir do menu Arquivo (acessível também pelo atalho Ctrl-P). Cortar (Ctrl-X): Apaga texto selecionado, armazenando-o em uma área de transferência. Copiar (Ctrl-C): Copia o texto selecionado para a área de transferência. Colar (Ctrl-V): Copia texto da área de transferência para o local em que está o cursor. Gravar bloco de texto: Permite a gravação em arquivo de um texto selecionado no editor. A extensão sugerida para o nome do arquivo é .inc. Inserir bloco de texto: Permite a inserção do conteúdo de um arquivo. A extensão sugerida para o nome do arquivo é .inc. Desfazer (Ctrl-Z): Desfaz último comando efetuado. Refazer (Shift-Ctrl-Z): Refaz último comando desfeito. Localizar (Ctrl-L): Localiza no texto presente no editor determinada palavra especificada. Substituir (Ctrl-U): Localiza no texto presente no editor determinada palavra especificada, substituindo-a por outra. Corrigir Indentação (Ctrl-G): Corrige automaticamente a indentação (ou tabulação) do pseudocódigo, tabulando cada comando interno com espaços à esquerda. Numerar linhas: Ativa ou desativa a exibição dos números das linhas na área à esquerda do editor. A linha e a coluna do editor em que o cursor está em um determinado momento também são mostradas na barra de status (parte inferior da tela). Por motivos técnicos, esta opção é automaticamente desativada durante a execução do pseudocódigo, mas volta a ser ativada logo em seguida. Mostrar variáveis modificadas: Ativa ou desativa a exibição da variável que está sendo modificada. Como o número de variáveis pode ser grande, muitas podem estar fora da janela de visualização; quando esta característica está ativada, o VisuAlg rola a grade de exibição de modo que cada variável fique visível no momento em está sendo modificada. Este recurso é especialmente útil quando se executa um pseudocódigo passo a passo. Por questões de desempenho, a configuração padrão desta característica é desativada, quando o pseudocódigo está sendo executado automaticamente. No entanto, basta clicar este botão para executá-lo automaticamente com a exibição ativada. No final da execução, a configuração volta a ser desativada. Restaurar tela inicial: Retorna a divisão da tela ao formato inicial, caso você tenha mudado o tamanho da área do editor de texto, quadro de variáveis ou simulador de saída.

Executar (F9): Inicia (ou continua) a execução automática do pseudocódigo. Executar com timer (Shift-F9):: Insere um atraso (que pode ser especificado no intervalo ao lado) antes da execução de cada linha. Também realça em fundo azul o comando que está sendo executado, da mesma forma que na execução passo a passo. Intervalo do timer: Atraso em cada linha, para quando se deseja executar o pseudocódigo com timer. Passo (F8): Inicia (ou continua) a execução linha por linha do pseudocódigo, dando ao usuário a oportunidade de acompanhar o fluxo de execução, os valores das variáveis e a pilha de ativação dos subprogramas. Parar (Ctrl-F2): Termina imediatamente a execução do pseudocódigo. Evidentemente, este botão fica desabilitado quando o pseudocódigo não está sendo executado. Liga/desliga breakpoint (F5): Insere/remove um ponto de parada na linha em que esteja o cursor. Estes pontos de parada são úteis para a depuração e acompanhamento da execução dos pseudocódigos, pois

[17] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


permitem a verificação dos valores das variáveis e da pilha de ativação de subprogramas. Desmarcar todos os breakpoints (Ctrl-F5): Desativa todos os breakpoints que estejam ativados naquele momento. Executar em modo DOS: Com esta opção ativada, tanto a entrada como a saída-padrão passa a ser uma janela que imita o DOS, simulando a execução de um programa neste ambiente. Gerar valores aleatórios: Ativa a geração de valores aleatórios que substituem a digitação de dados. A faixa padrão de valores gerados é de 0 a 100 inclusive, mas pode ser modificada (basta alterar intervalo ao lado). Para a geração de dados do tipo caractere, não há uma faixa pré-estabelecida: os dados gerados serão sempre strings de 5 letras maiúsculas. Intervalo dos valores aleatórios: Faixa de valores que serão gerados automaticamente, quando esta opção estiver ativada. Perfil (F7): Após a execução de um pseudocódigo, exibe o número de vezes que cada umas das suas linhas foi executada. É útil para a análise de eficiência (por exemplo, nos métodos de ordenação). Mostrar pilha de ativação (Ctrl-F3): Exibe a pilha de subprogramas ativados num dado momento. Convém utilizar este comando em conjunto com breakpoints ou com a execução passo a passo. Ajuda (F1): Possibilita acesso às páginas de ajuda e às informações sobre o VisuAlg. Quadro de Variáveis É formado por uma grade na qual são mostrados o escopo de cada variável (se for do programa principal, será global; se for local, será apresentado o nome do subprograma onde foi declarada), seus nomes (também com os índices, nos casos em que sejam vetores), seu tipo ("I" para inteiro, "R" para real, "C" para caractere e "L" para lógico) e o seu valor corrente. A versão atual do VisuAlg permite a visualização de até 500 variáveis (contando individualmente cada elemento dos vetores). A Barra de Status Situada na parte inferior da tela, esta barra contém dois painéis: o primeiro mostra a linha e a coluna onde o cursor está, e o segundo mostra a palavra Modificado no caso em que o pseudocódigo tenha sido alterado desde que foi carregado ou salvo pela última vez. Nesta barra, há ainda um terceiro painel disponível, que ainda não tem um uso específico na atual versão.

[18] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Menu do VisuAlg Este menu compõe-se de 7 partes: Arquivo: Possui os comandos para se abrir, salvar e imprimir algoritmos: Novo: Cria um novo "esqueleto" de pseudocódigo, substituindo o texto existente no editor. Se este texto anterior tiver sido modificado, o VisuAlg pedirá sua confirmação para salvá-lo antes que seja sobreposto. Abrir: Abre o texto de um pseudocódigo anteriormente gravado, substituindo o texto existente no editor. Se este tiver sido modificado, o VisuAlg pedirá sua confirmação para salvá-lo antes que seja sobreposto. Salvar: Salva imediatamente o texto presente no editor. Caso seja a primeira vez que um novo texto é gravado, o VisuAlg pedirá o nome do arquivo e sua localização. Salvar como: Permite salvar o texto presente no editor exibindo antes uma janela na qual se pode escolher o nome do arquivo e sua localização. Enviar por email: Permite o envio por email do texto presente no editor. Imprimir: Permite a impressão do algoritmo corrente, mostrando antes a janela de configuração de impressão (o correspondente botão da barra de tarefas imprime imediatamente o texto do pseudocódigo na impressora padrão). Sair: Abandona o VisuAlg. Além destes comandos, há ainda a lista dos 5 últimos algoritmos utilizados, que podem ser abertos diretamente ao se escolher o seu nome. Editar: Além dos conhecidos comandos de um editor de texto (copiar, cortar, colar, desfazer, refazer, selecionar tudo, localizar, localizar de novo, substituir), há também as seguintes opções: Corrigir indentação: Corrige automaticamente a indentação do pseudocódigo, tabulando cada comando interno com espaços à esquerda. Gravar bloco de texto: Permite a gravação em arquivo de um texto selecionado no editor. A extensão sugerida para o nome do arquivo é .inc. Inserir bloco de texto: Permite a inserção do conteúdo de um arquivo. A extensão sugerida para o nome do arquivo é .inc. Exibir: Possui os comandos para ativar/desativar as seguintes características: Número de linhas: Ativa/desativa a exibição da numeração das linhas na área à esquerda do editor. A numeração corrente da posição do cursor também é mostrada na primeira parte da barra de status, situada na parte inferior da tela. Por motivos técnicas, a numeração é desativada durante a execução do pseudocódigo, voltando à situação anterior logo em seguida. Variáveis modificadas: Ativa/desativa a exibição da variável que está sendo modificada. Como o número de variáveis pode ser grande, muitas podem estar fora da janela de visualização; quando esta característica está ativada, o VisuAlg rola a grade de exibição de modo que cada variável fique visível no momento em está sendo modificada. Este recurso é especialmente útil quando se executa um pseudocódigo passo a passo. Por questões de desempenho, a configuração padrão desta característica é desativada, quando o pseudocódigo está sendo executado automaticamente. No entanto, basta clicar este botão para executá-lo automaticamente com a exibição ativada. No final da execução, a configuração volta a ser desativada. Pseudocódigo: Contém os comandos relativos à execução do algoritmo: Executar: Inicia (ou continua) a execução automática do pseudocódigo. Passo a passo: Inicia (ou continua) a execução linha por linha do pseudocódigo, dando ao usuário a oportunidade de acompanhar o fluxo de execução, os valores das variáveis e a pilha de ativação dos subprogramas. Executar com timer: Insere um atraso (que pode ser especificado) antes da execução de cada linha. Também realça em fundo azul o comando que está sendo executado, da mesma forma que na execução passo a passo. Parar: Termina imediatamente a execução do pseudocódigo. Evidentemente, este item fica desabilitado quando o pseudocódigo não está sendo executado. Liga/desliga breakpoint: Insere/remove um ponto de parada na linha em que esteja o cursor. Estes pontos

[19] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


de parada são úteis para a depuração e acompanhamento da execução dos pseudocódigos, pois permitem a verificação dos valores das variáveis e da pilha de ativação de subprogramas. Desmarcar todos os breakpoints: Desativa todos os breakpoints que estejam ativados naquele momento. Executar em modo DOS: Com esta opção ativada, tanto a entrada como a saída-padrão passa a ser uma janela que imita o DOS, simulando a execução de um programa neste ambiente. Gerar valores aleatórios: Ativa a geração de valores aleatórios que substituem a digitação de dados. A faixa padrão de valores gerados é de 0 a 100 inclusive, mas pode ser modificada. Para a geração de dados do tipo caractere, não há uma faixa pré-estabelecida: os dados gerados serão sempre strings de 5 letras maiúsculas. Perfil: Após a execução de um pseudocódigo, exibe o número de vezes que cada umas das suas linhas foi executada. É útil para a análise de eficiência (por exemplo, nos métodos de ordenação). Pilha de ativação: Exibe a pilha de subprogramas ativados num dado momento. Convém utilizar este comando em conjunto com breakpoints ou com a execução passo a passo. Linguagens: Permite a tradução automático do pseudocódigo presente no editor para outras linguagens de programação. Atualmente, apenas a tradução para Pascal está implementada, mas ainda em fase de testes. Ferramentas: Neste menu, é possível configurar algumas opções do VisuAlg: cores e tipos de letras na exibição do pseudocódigo, número de espaços para indentação automática, etc. Ajuda: Entre outras coisas, possibilita acesso às páginas de ajuda e às informações sobre o VisuAlg.

[20] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Menu do VisuAlg Este menu compõe-se de 7 partes: Arquivo: Possui os comandos para se abrir, salvar e imprimir algoritmos: Novo: Cria um novo "esqueleto" de pseudocódigo, substituindo o texto existente no editor. Se este texto anterior tiver sido modificado, o VisuAlg pedirá sua confirmação para salvá-lo antes que seja sobreposto. Abrir: Abre o texto de um pseudocódigo anteriormente gravado, substituindo o texto existente no editor. Se este tiver sido modificado, o VisuAlg pedirá sua confirmação para salvá-lo antes que seja sobreposto. Salvar: Salva imediatamente o texto presente no editor. Caso seja a primeira vez que um novo texto é gravado, o VisuAlg pedirá o nome do arquivo e sua localização. Salvar como: Permite salvar o texto presente no editor exibindo antes uma janela na qual se pode escolher o nome do arquivo e sua localização. Enviar por email: Permite o envio por email do texto presente no editor. Imprimir: Permite a impressão do algoritmo corrente, mostrando antes a janela de configuração de impressão (o correspondente botão da barra de tarefas imprime imediatamente o texto do pseudocódigo na impressora padrão). Sair: Abandona o VisuAlg. Além destes comandos, há ainda a lista dos 5 últimos algoritmos utilizados, que podem ser abertos diretamente ao se escolher o seu nome. Editar: Além dos conhecidos comandos de um editor de texto (copiar, cortar, colar, desfazer, refazer, selecionar tudo, localizar, localizar de novo, substituir), há também as seguintes opções: Corrigir indentação: Corrige automaticamente a indentação do pseudocódigo, tabulando cada comando interno com espaços à esquerda. Gravar bloco de texto: Permite a gravação em arquivo de um texto selecionado no editor. A extensão sugerida para o nome do arquivo é .inc. Inserir bloco de texto: Permite a inserção do conteúdo de um arquivo. A extensão sugerida para o nome do arquivo é .inc. Exibir: Possui os comandos para ativar/desativar as seguintes características: Número de linhas: Ativa/desativa a exibição da numeração das linhas na área à esquerda do editor. A numeração corrente da posição do cursor também é mostrada na primeira parte da barra de status, situada na parte inferior da tela. Por motivos técnicas, a numeração é desativada durante a execução do pseudocódigo, voltando à situação anterior logo em seguida. Variáveis modificadas: Ativa/desativa a exibição da variável que está sendo modificada. Como o número de variáveis pode ser grande, muitas podem estar fora da janela de visualização; quando esta característica está ativada, o VisuAlg rola a grade de exibição de modo que cada variável fique visível no momento em está sendo modificada. Este recurso é especialmente útil quando se executa um pseudocódigo passo a passo. Por questões de desempenho, a configuração padrão desta característica é desativada, quando o pseudocódigo está sendo executado automaticamente. No entanto, basta clicar este botão para executá-lo automaticamente com a exibição ativada. No final da execução, a configuração volta a ser desativada. Pseudocódigo: Contém os comandos relativos à execução do algoritmo: Executar: Inicia (ou continua) a execução automática do pseudocódigo. Passo a passo: Inicia (ou continua) a execução linha por linha do pseudocódigo, dando ao usuário a oportunidade de acompanhar o fluxo de execução, os valores das variáveis e a pilha de ativação dos subprogramas. Executar com timer: Insere um atraso (que pode ser especificado) antes da execução de cada linha. Também realça em fundo azul o comando que está sendo executado, da mesma forma que na execução passo a passo. Parar: Termina imediatamente a execução do pseudocódigo. Evidentemente, este item fica desabilitado quando o pseudocódigo não está sendo executado. Liga/desliga breakpoint: Insere/remove um ponto de parada na linha em que esteja o cursor. Estes pontos de parada são úteis para a depuração e acompanhamento da execução dos pseudocódigos, pois permitem a verificação dos valores das variáveis e da pilha de ativação de subprogramas.

[21] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Desmarcar todos os breakpoints: Desativa todos os breakpoints que estejam ativados naquele momento. Executar em modo DOS: Com esta opção ativada, tanto a entrada como a saída-padrão passa a ser uma janela que imita o DOS, simulando a execução de um programa neste ambiente. Gerar valores aleatórios: Ativa a geração de valores aleatórios que substituem a digitação de dados. A faixa padrão de valores gerados é de 0 a 100 inclusive, mas pode ser modificada. Para a geração de dados do tipo caractere, não há uma faixa pré-estabelecida: os dados gerados serão sempre strings de 5 letras maiúsculas. Perfil: Após a execução de um pseudocódigo, exibe o número de vezes que cada umas das suas linhas foi executada. É útil para a análise de eficiência (por exemplo, nos métodos de ordenação). Pilha de ativação: Exibe a pilha de subprogramas ativados num dado momento. Convém utilizar este comando em conjunto com breakpoints ou com a execução passo a passo. Linguagens: Permite a tradução automático do pseudocódigo presente no editor para outras linguagens de programação. Atualmente, apenas a tradução para Pascal está implementada, mas ainda em fase de testes. Ferramentas: Neste menu, é possível configurar algumas opções do VisuAlg: cores e tipos de letras na exibição do pseudocódigo, número de espaços para indentação automática, etc. Ajuda: Entre outras coisas, possibilita acesso às páginas de ajuda e às informações sobre o VisuAlg.

[22] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Menu do VisuAlg Este menu compõe-se de 7 partes: Arquivo: Possui os comandos para se abrir, salvar e imprimir algoritmos: Novo: Cria um novo "esqueleto" de pseudocódigo, substituindo o texto existente no editor. Se este texto anterior tiver sido modificado, o VisuAlg pedirá sua confirmação para salvá-lo antes que seja sobreposto. Abrir: Abre o texto de um pseudocódigo anteriormente gravado, substituindo o texto existente no editor. Se este tiver sido modificado, o VisuAlg pedirá sua confirmação para salvá-lo antes que seja sobreposto. Salvar: Salva imediatamente o texto presente no editor. Caso seja a primeira vez que um novo texto é gravado, o VisuAlg pedirá o nome do arquivo e sua localização. Salvar como: Permite salvar o texto presente no editor exibindo antes uma janela na qual se pode escolher o nome do arquivo e sua localização. Enviar por email: Permite o envio por email do texto presente no editor. Imprimir: Permite a impressão do algoritmo corrente, mostrando antes a janela de configuração de impressão (o correspondente botão da barra de tarefas imprime imediatamente o texto do pseudocódigo na impressora padrão). Sair: Abandona o VisuAlg. Além destes comandos, há ainda a lista dos 5 últimos algoritmos utilizados, que podem ser abertos diretamente ao se escolher o seu nome. Editar: Além dos conhecidos comandos de um editor de texto (copiar, cortar, colar, desfazer, refazer, selecionar tudo, localizar, localizar de novo, substituir), há também as seguintes opções: Corrigir indentação: Corrige automaticamente a indentação do pseudocódigo, tabulando cada comando interno com espaços à esquerda. Gravar bloco de texto: Permite a gravação em arquivo de um texto selecionado no editor. A extensão sugerida para o nome do arquivo é .inc. Inserir bloco de texto: Permite a inserção do conteúdo de um arquivo. A extensão sugerida para o nome do arquivo é .inc. Exibir: Possui os comandos para ativar/desativar as seguintes características: Número de linhas: Ativa/desativa a exibição da numeração das linhas na área à esquerda do editor. A numeração corrente da posição do cursor também é mostrada na primeira parte da barra de status, situada na parte inferior da tela. Por motivos técnicas, a numeração é desativada durante a execução do pseudocódigo, voltando à situação anterior logo em seguida. Variáveis modificadas: Ativa/desativa a exibição da variável que está sendo modificada. Como o número de variáveis pode ser grande, muitas podem estar fora da janela de visualização; quando esta característica está ativada, o VisuAlg rola a grade de exibição de modo que cada variável fique visível no momento em está sendo modificada. Este recurso é especialmente útil quando se executa um pseudocódigo passo a passo. Por questões de desempenho, a configuração padrão desta característica é desativada, quando o pseudocódigo está sendo executado automaticamente. No entanto, basta clicar este botão para executá-lo automaticamente com a exibição ativada. No final da execução, a configuração volta a ser desativada. Pseudocódigo: Contém os comandos relativos à execução do algoritmo: Executar: Inicia (ou continua) a execução automática do pseudocódigo. Passo a passo: Inicia (ou continua) a execução linha por linha do pseudocódigo, dando ao usuário a oportunidade de acompanhar o fluxo de execução, os valores das variáveis e a pilha de ativação dos subprogramas. Executar com timer: Insere um atraso (que pode ser especificado) antes da execução de cada linha. Também realça em fundo azul o comando que está sendo executado, da mesma forma que na execução passo a passo. Parar: Termina imediatamente a execução do pseudocódigo. Evidentemente, este item fica desabilitado quando o pseudocódigo não está sendo executado. Liga/desliga breakpoint: Insere/remove um ponto de parada na linha em que esteja o cursor. Estes pontos de parada são úteis para a depuração e acompanhamento da execução dos pseudocódigos, pois permitem a verificação dos valores das variáveis e da pilha de ativação de subprogramas.

[23] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Desmarcar todos os breakpoints: Desativa todos os breakpoints que estejam ativados naquele momento. Executar em modo DOS: Com esta opção ativada, tanto a entrada como a saída-padrão passa a ser uma janela que imita o DOS, simulando a execução de um programa neste ambiente. Gerar valores aleatórios: Ativa a geração de valores aleatórios que substituem a digitação de dados. A faixa padrão de valores gerados é de 0 a 100 inclusive, mas pode ser modificada. Para a geração de dados do tipo caractere, não há uma faixa pré-estabelecida: os dados gerados serão sempre strings de 5 letras maiúsculas. Perfil: Após a execução de um pseudocódigo, exibe o número de vezes que cada umas das suas linhas foi executada. É útil para a análise de eficiência (por exemplo, nos métodos de ordenação). Pilha de ativação: Exibe a pilha de subprogramas ativados num dado momento. Convém utilizar este comando em conjunto com breakpoints ou com a execução passo a passo. Linguagens: Permite a tradução automático do pseudocódigo presente no editor para outras linguagens de programação. Atualmente, apenas a tradução para Pascal está implementada, mas ainda em fase de testes. Ferramentas: Neste menu, é possível configurar algumas opções do VisuAlg: cores e tipos de letras na exibição do pseudocódigo, número de espaços para indentação automática, etc. Ajuda: Entre outras coisas, possibilita acesso às páginas de ajuda e às informações sobre o VisuAlg.

[24] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


A Linguagem de Programação do VisuAlg (3) Comandos de Repetição O VisuAlg implementa as três estruturas de repetição usuais nas linguagens de programação: o laço contado para...ate...faca (similar ao for...to...do do Pascal), e os laços condicionados enquanto...faca (similar ao while...do) e repita...ate (similar ao repeat...until). A sintaxe destes comandos é explicada a seguir. Para ... faça Esta estrutura repete uma seqüência de comandos um determinado número de vezes. para <variável> de <valor-inicial> ate <valor-limite> [passo <incremento>] faca <seqüência-de-comandos> fimpara

<variável >

É a variável contadora que controla o número de repetições do laço. Na versão atual, deve ser necessariamente uma variável do tipo inteiro, como todas as expressões deste comando.

<valor-inicial>

É uma expressão que especifica o valor de inicialização da variável contadora antes da primeira repetição do laço.

<valor-limite >

É uma expressão que especifica o valor máximo que a variável contadora pode alcançar.

<incremento >

É opcional. Quando presente, precedida pela palavra passo, é uma expressão que especifica o incremento que será acrescentado à variável contadora em cada repetição do laço. Quando esta opção não é utilizada, o valor padrão de <incremento> é 1. Vale a pena ter em conta que também é possível especificar valores negativos para <incremento>. Por outro lado, se a avaliação da expressão <incremento > resultar em valor nulo, a execução do algoritmo será interrompida, com a impressão de uma mensagem de erro.

fimpara

Indica o fim da seqüência de comandos a serem repetidos. Cada vez que o programa chega neste ponto, é acrescentado à variável contadora o valor de <incremento >, e comparado a <valor-limite >. Se for menor ou igual (ou maior ou igual, quando <incremento > for negativo), a seqüência de comandos será executada mais uma vez; caso contrário, a execução prosseguirá a partir do primeiro comando que esteja após o fimpara.

<valor-inicial >, <valor-limite > e <incremento > são avaliados uma única vez antes da execução da primeira repetição, e não se alteram durante a execução do laço, mesmo que variáveis eventualmente presentes nessas expressões tenham seus valores alterados. No exemplo a seguir, os números de 1 a 10 são exibidos em ordem crescente. algoritmo "Números de 1 a 10" var j: inteiro inicio para j de 1 ate 10 faca escreva (j:3) fimpara fimalgoritmo Importante: Se, logo no início da primeira repetição, <valor-inicial > for maior que <valor-limite > (ou menor, quando <incremento> for negativo), o laço não será executado nenhuma vez. O exemplo a seguir não imprime nada.

[25] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


algoritmo "Numeros de 10 a 1 (não funciona)" var j: inteiro inicio para j de 10 ate 1 faca escreva (j:3) fimpara fimalgoritmo Este outro exempo, no entanto, funcionará por causa do passo -1: algoritmo "Numeros de 10 a 1 (este funciona)" var j: inteiro inicio para j de 10 ate 1 passo -1 faca escreva (j:3) fimpara fimalgoritmo Enquanto ... faça Esta estrutura repete uma seqüência de comandos enquanto uma determinada condição (especificada através de uma expressão lógica) for satisfeita. enquanto <expressão-lógica> faca <seqüência-de-comandos> fimenquanto

<expressão-lógica>

Esta expressão que é avaliada antes de cada repetição do laço. Quando seu resultado for VERDADEIRO, <seqüência-de-comandos> é executada.

fimenquanto

Indica o fim da <seqüência-de-comandos> que será repetida. Cada vez que a execução atinge este ponto, volta-se ao início do laço para que <expressão-lógica> seja avaliada novamente. Se o resultado desta avaliação for VERDADEIRO, a <seqüência-de-comandos> será executada mais uma vez; caso contrário, a execução prosseguirá a partir do primeiro comando após fimenquanto.

O mesmo exemplo anterior pode ser resolvido com esta estrutura de repetição: algoritmo "Números de 1 a 10 (com enquanto...faca)" var j: inteiro inicio j <- 1 enquanto j <= 10 faca escreva (j:3) j <- j + 1 fimenquanto fimalgoritmo Importante: Como o laço enquanto...faca testa sua condição de parada antes de executar sua seqüência de comandos, esta seqüência poderá ser executada zero ou mais vezes. Repita ... até Esta estrutrura repete uma seqüência de comandos até que uma determinada condição (especificada através de uma expressão lógica) seja satisfeita. repita <seqüência-de-comandos> ate <expressão-lógica>

[26] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


repita

Indica o início do laço.

ate <expressãológica>

Indica o fim da <seqüência-de-comandos> a serem repetidos. Cada vez que o programa chega neste ponto, <expressão-lógica> é avaliada: se seu resultado for FALSO, os comandos presentes entre esta linha e a linha repita são executados; caso contrário, a execução prosseguirá a partir do primeiro comando após esta linha.

Considerando ainda o mesmo exemplo: algoritmo "Números de 1 a 10 (com repita)" var j: inteiro inicio j <- 1 repita escreva (j:3) j <- j + 1 ate j > 10 fimalgoritmo Importante: Como o laço repita...ate testa sua condição de parada depois de executar sua seqüência de comandos, esta seqüência poderá ser executada uma ou mais vezes. Comando Interrompa As três estruturas de repetição acima permitem o uso do comando interrompa, que causa uma saída imediata do laço. Embora esta técnica esteja de certa forma em desacordo com os princípios da programação estruturada, o comando interrompa foi incluído no VisuAlg por ser encontrado na literatura de introdução à programação e mesmo em linguagens como o Object Pascal (Delphi/Kylix), Clipper, VB, etc. Seu uso é exemplificado a seguir: algoritmo "Números de 1 a 10 (com interrompa)" var x: inteiro inicio x <- 0 repita x <- x + 1 escreva (x:3) se x = 10 entao interrompa fimse ate falso fimalgoritmo O VisuAlg permite ainda uma forma alternativa do comando repita...ate, com a seguinte sintaxe: algoritmo "Números de 1 a 10 (com interrompa) II" var x: inteiro inicio x <- 0 repita x <- x + 1 escreva (x:3) se x = 10 entao interrompa fimse fimrepita fimalgoritmo Com esta sintaxe alternativa, o uso do interrompa é obrigatório, pois é a única maneira de se sair do laço repita...fimrepita; caso contrário, este laço seria executado indeterminadamente.

[27] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


A Linguagem de Programação do VisuAlg (4) Subprograma é um programa que auxilia o programa principal através da realização de uma determinada subtarefa. Também costuma receber os nomes de sub-rotina, procedimento, método ou módulo. Os subprogramas são chamados dentro do corpo do programa principal como se fossem comandos. Após seu término, a execução continua a partir do ponto onde foi chamado. É importante compreender que a chamada de um subprograma simplesmente gera um desvio provisório no fluxo de execução. Há um caso particular de subprograma que recebe o nome de função. Uma função, além de executar uma determinada tarefa, retorna um valor para quem a chamou, que é o resultado da sua execução. Por este motivo, a chamada de uma função aparece no corpo do programa principal como uma expressão, e não como um comando. Cada subprograma, além de ter acesso às variáveis do programa que o chamou (são as variáveis globais), pode ter suas próprias variáveis (são as variáveis locais), que existem apenas durante sua chamada. Ao se chamar um subprograma, também é possível passar-lhe determinadas informações que recebem o nome de parâmetros (são valores que, na linha de chamada, ficam entre os parênteses e que estão separados por vírgulas). A quantidade dos parâmetros, sua seqüência e respectivos tipos não podem mudar: devem estar de acordo com o que foi especificado na sua correspondente declaração. Para se criar subprogramas, é preciso descrevê-los após a declaração das variáveis e antes do corpo do programa principal. O VisuAlg possibilita declaração e chamada de subprogramas nos moldes da linguagem Pascal, ou seja, procedimentos e funções com passagem de parâmetros por valor ou referência. Isso será explicado a seguir. Procedimentos Em VisuAlg, procedimento é um subprograma que não retorna nenhum valor (corresponde ao procedure do Pascal). Sua declaração, que deve estar entre o final da declaração de variáveis e a linha inicio do programa principal, segue a sintaxe abaixo: procedimento <nome-de-procedimento> [(<seqüência-de-declarações-de-parâmetros>)] // Seção de Declarações Internas inicio // Seção de Comandos fimprocedimento O <nome-de-procedimento> obedece as mesmas regras de nomenclatura das variáveis. Por outro lado, a <seqüência-de-declarações-de-parâmetros> é uma seqüência de [var] <seqüência-de-parâmetros>: <tipo-de-dado> separadas por ponto e vírgula. A presença (opcional) da palavra-chave var indica passagem de parâmetros por referência; caso contrário, a passagem será por valor. Por sua vez, <seqüência-de-parâmetros> é uma seqüência de nomes de parâmetros (também obedecem a mesma regra de nomenclatura de variáveis) separados por vírgulas. De modo análogo ao programa principal, a seção de declaração internas começa com a palavra-chave var, e continua com a seguinte sintaxe: <lista-de-variáveis> : <tipo-de-dado> Nos próximos exemplos, através de um subprograma soma, será calculada a soma entre os valores 4 e –9 (ou seja, será obtido o resultado 13) que o programa principal imprimirá em seguida. No primeiro caso, um procedimento sem parâmetros utiliza uma variável local aux para armazenar provisoriamente o resultado deste cálculo (evidentemente, esta variável é desnecessária, mas está aí apenas para ilustrar o exemplo), antes de atribuí-lo à variável global res:

[28] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


procedimento soma var aux: inteiro inicio // n, m e res são variáveis globais aux <- n + m res <- aux fimprocedimento No programa principal deve haver os seguintes comandos: n <- 4 m <- -9 soma escreva(res) A mesma tarefa poderia ser executada através de um procedimento com parâmetros, como descrito abaixo: procedimento soma (x,y: inteiro) inicio // res é variável global res <- x + y fimprocedimento No programa principal deve haver os seguintes comandos: n <- 4 m <- -9 soma(n,m) escreva(res) A passagem de parâmetros do exemplo acima chama-se passagem por valor. Neste caso, o subprograma simplesmente recebe um valor que utiliza durante sua execução. Durante essa execução, os parâmetros passados por valor são análogos às suas variáveis locais, mas com uma única diferença: receberam um valor inicial no momento em que o subprograma foi chamado. Funções Em VisuAlg, função é um subprograma que retorna um valor (corresponde ao function do Pascal). De modo análogo aos procedimentos, sua declaração deve estar entre o final da declaração de variáveis e a linha inicio do programa principal, e segue a sintaxe abaixo: funcao <nome-de-função> [(<seqüência-de-declarações-de-parâmetros>)]: <tipo-dedado> // Seção de Declarações Internas inicio // Seção de Comandos fimfuncao O <nome-de-função> obedece as mesmas regras de nomenclatura das variáveis. Por outro lado, a <seqüência-de-declarações-de-parâmetros> é uma seqüência de [var] <seqüência-de-parâmetros>: <tipo-de-dado> separadas por ponto e vírgula. A presença (opcional) da palavra-chave var indica passagem de parâmetros por referência; caso contrário, a passagem será por valor. Por sua vez, <seqüência-de-parâmetros> é uma seqüência de nomes de parâmetros (também obedecem a mesma regra de nomenclatura de variáveis) separados por vírgulas.

[29] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


O valor retornado pela função será do tipo especificado na sua declaração (logo após os dois pontos). Em alguma parte da função (de modo geral, no seu final), este valor deve ser retornado através do comando retorne. De modo análogo ao programa principal, a seção de declaração internas começa com a palavra-chave var, e continua com a seguinte sintaxe: <lista-de-variáveis> : <tipo-de-dado> Voltando ao exemplo anterior, no qual calculamos e imprimimos a soma entre os valores 4 e –9, vamos mostrar como isso poderia ser feito através de uma função sem parâmetros. Ela também utiliza uma variável local aux para armazenar provisoriamente o resultado deste cálculo, antes de atribuí-lo à variável global res: funcao soma: inteiro var aux: inteiro inicio // n, m e res são variáveis globais aux <- n + m retorne aux fimfuncao No programa principal deve haver os seguintes comandos: n <- 4 m <- -9 res <- soma escreva(res) Se realizássemos essa mesma tarefa com uma função com parâmetros passados por valor, poderia ser do seguinte modo: funcao soma (x,y: inteiro): inteiro inicio retorne x + y fimfuncao No programa principal deve haver os seguintes comandos: n <- 4 m <- -9 res <- soma(n,m) escreva(res) Passagem de Parâmetros por Referência Há ainda uma outra forma de passagem de parâmetros para subprogramas: é a passagem por referência. Neste caso, o subprograma não recebe apenas um valor, mas sim o endereço de uma variável global. Portanto, qualquer modificação que for realizada no conteúdo deste parâmetro afetará também a variável global que está associada a ele. Durante a execução do subprograma, os parâmetros passados por referência são análogos às variáveis globais. No VisuAlg, de forma análoga a Pascal, essa passagem é feita através da palavra var na declaração do parâmetro. Voltando ao exemplo da soma, o procedimento abaixo realiza a mesma tarefa utilizando passagem de parâmetros por referência: procedimento soma (x,y: inteiro; var result: inteiro) inicio result <- x + y fimprocedimento

[30] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


No programa principal deve haver os seguintes comandos: n <- 4 m <- -9 soma(n,m,res) escreva(res) Recursão e Aninhamento A atual versão do VisuAlg permite recursão, isto é, a possibilidade de que um subprograma possa chamar a si mesmo. A função do exemplo abaixo calcula recursivamente o fatorial do número inteiro que recebe como parâmetro: funcao fatorial (v: inteiro): inteiro inicio se v <= 2 entao retorne v senao retorne v * fatorial(v-1) fimse fimfuncao Em Pascal, é permitido o aninhamento de subprogramas, isto é, cada subprograma também pode ter seus próprios subprogramas. No entanto, esta característica dificulta a elaboração dos compiladores e, na prática, não é muito importante. Por este motivo, ela não é permitida na maioria das linguagens de programação (como C, por exemplo), e o VisuAlg não a implementa.

[31] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


A Linguagem de Programação do VisuAlg (5) O VisuAlg implementa algumas extensões às linguagens "tradicionais" de programação, com o intuito principal de ajudar o seu uso como ferramenta de ensino. Elas são mostradas a seguir. Comando Aleatório Muitas vezes a digitação de dados para o teste de um programa torna-se uma tarefa entediante. Com o uso do comando aleatorio do VisuAlg, sempre que um comando leia for encontrado, a digitação de valores numéricos e/ou caracteres é substituída por uma geração aleatória. Este comando não afeta a leitura de variáveis lógicas: com certeza, uma coisa pouco usual em programação... Este comando tem as seguintes sintaxes:

aleatorio [on]

Ativa a geração de valores aleatórios que substituem a digitação de dados. A palavra-chave on é opcional. A faixa padrão de valores gerados é de 0 a 100 inclusive. Para a geração de dados do tipo caractere, não há uma faixa pré-estabelecida: os dados gerados serão sempre strings de 5 letras maiúsculas.

aleatorio <valor1 > [, <valor2 > ]

Ativa a geração de dados numéricos aleatórios estabelecendo uma faixa de valores mínimos e máximos. Se apenas < valor1> for fornecido, a faixa será de 0 a <valor1> inclusive; caso contrário, a faixa será de <valor1> a <valor2> inclusive. Se <valor2> for menor que <valor1>, o VisuAlg os trocará para que a faixa fique correta. Importante: <valor1> e <valor2> devem ser constantes numéricas, e não expressões.

aleatorio off

Desativa a geração de valores aleatórios. A palavra-chave off é obrigatória.

Comando Arquivo Muitas vezes é necessário repetir os testes de um programa com uma série igual de dados. Para casos como este, o VisuAlg permite o armazenamento de dados em um arquivo-texto, obtendo deles os dados ao executar os comandos leia. Esta característica funciona da seguinte maneira: 1) Se não existir o arquivo com nome especificado, o VisuAlg fará uma leitura de dados através da digitação, armazenando os dados lidos neste arquivo, na ordem em que forem fornecidos. 2) Se o arquivo existir, o VisuAlg obterá os dados deste arquivo até chegar ao seu fim. Daí em diante, fará as leituras de dados através da digitação. 3) Somente um comando arquivo pode ser empregado em cada pseudocódigo, e ele deverá estar na seção de declarações (dependendo do "sucesso" desta característica, em futuras versões ela poderá ser melhorada...). 4) Caso não seja fornecido um caminho, o VisuAlg irá procurar este arquivo na pasta de trabalho corrente (geralmente, é a pasta onde o programa VISUALG.EXE está). Este comando não prevê uma extensão padrão; portanto, a especificação do nome do arquivo deve ser completa, inclusive com sua extensão (por exemplo, .txt, .dat, etc.). A sintaxe do comando é: arquivo <nome-de-arquivo> <nome-de-arquivo> é uma constante caractere (entre aspas duplas). Veja o exemplo a seguir:

[32] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


algoritmo "lendo do arquivo" arquivo "teste.txt" var x,y: inteiro inicio para x de 1 ate 5 faca leia (y) fimpara fimalgoritmo Comando Timer Embora o VisuAlg seja um interpretador de pseudocódigo, seu desempenho é muito bom: o tempo gasto para interpretar cada linha digitada é apenas uma fração de segundo. Entretanto, por motivos educacionais, pode ser conveniente exibir o fluxo de execução do pseudocódigo comando por comando, em "câmera lenta". O comando timer serve para este propósito: insere um atraso (que pode ser especificado) antes da execução de cada linha. Além disso, realça em fundo azul o comando que está sendo executado, da mesma forma que na execução passo a passo. Sua sintaxe é a seguinte: timer on

Ativa o timer.

timer <tempo-deatraso>

Ativa o timer estabelecendo seu tempo de atraso em milissegundos. O valor padrão é 500, que equivale a meio segundo. O argumento <tempo-deatraso> deve ser uma constante inteira com valor entre 0 e 10000. Valores menores que 0 são corrigidos para 0, e maiores que 10000 para 10000.

timer off

Desativa o timer.

Ao longo do pseudocódigo, pode haver vários comandos timer. Todos eles devem estar na seção de comandos. Uma vez ativado, o atraso na execução dos comandos será mantido até se chegar ao final do pseudocódigo ou até ser encontrado um comando timer off. Comandos de Depuração Nenhum ambiente de desenvolvimento está completo se não houver a possibilidade de se inserir pontos de interrupção (breakpoints) no pseudocódigo para fins de depuração. VisuAlg implementa dois comandos que auxiliam a depuração ou análise de um pseudocódigo: o comando pausa e o comando debug. Comando Pausa Sua sintaxe é simplesmente: pausa Este comando insere uma interrupção incondicional no pseudocódigo. Quando ele é encontrado, o VisuAlg pára a execução do pseudocódigo e espera alguma ação do programador. Neste momento, é possível: analisar os valores das variáveis ou das saídas produzidas até o momento; executar o pseudocódigo passo a passo (com F8); prosseguir sua execução normalmente (com F9); ou simplesmente terminá-lo (com CtrlF2). Com exceção da alteração do texto do pseudocódigo, todas as funções do VisuAlg estão disponíveis. Comando Debug Sua sintaxe é: debug <expressão-lógica> Se a avaliação de <expressão-lógica> resultar em valor VERDADEIRO, a execução do pseudocódigo será interrompida como no comando pausa. Dessa forma, é possível a inserção de um breakpoint condicional no pseudocódigo.

[33] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Comando Eco Sua sintaxe é: eco on | off Este comando ativa (eco on) ou desativa (eco off) a impressão dos dados de entrada na saída-padrão do VisuAlg, ou seja, na área à direita da parte inferior da tela. Esta característica pode ser útil quando houver uma grande quantidade de dados de entrada, e se deseja apenas analisar a saída produzida. Convém utilizá-la também quando os dados de entrada provêm de um arquivo já conhecido. Comando Cronômetro Sua sintaxe é: cronometro on | off Este comando ativa (cronometro on) ou desativa (cronometro off) o cronômetro interno do VisuAlg. Quando o comando cronometro on é encontrado, o VisuAlg imprime na saída-padrão a informação "Cronômetro iniciado.", e começa a contar o tempo em milissegundos. Quando o comando cronometro off é encontrado, o VisuAlg imprime na saída-padrão a informação "Cronômetro terminado. Tempo decorrido: xx segundo(s) e xx ms". Este comando é útil na análise de desempenho de algoritmos (ordenação, busca, etc.). Comando Limpatela Sua sintaxe é limpatela Este comando simplesmente limpa a tela DOS do Visualg (a simulação da tela do computador). Ele não afeta a "tela" que existe na parte inferior direita da janela principal do Visualg.

[34] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Auto-digitação e Sugestão de Digitação Auto-digitação O VisuAlg tem uma característica para a criação de pseudocódigos que pode aumentar a rapidez da digitação e também diminuir a possibilidade de erros: é a auto-digitação. Para utilizar esta característica, basta escrever uma abreviatura da palavra-chave ou do comando a ser diigtado e teclar Ctrl-Espaço. O VisuAlg completa então o comando automaticamente, colocando o cursor no ponto adequado para se continuar a digitação (nos exemplos abaixo, este ponto é indicado através de um *). Eis a lista de abreviaturas com os respectivos comandos: ! - (Ponto de exclamação) Cria um modelo de pseudocódigo. algoritmo "semnome" * inicio fimalgoritmo # - Cria um cabeçalho de programa. // // // //

Algoritmo : * Função : Autor : Data :

ale, aof, aon - Inserem os comandos aleatorio, aleatorio off ou aleatorio on, respectivamente. alg - Insere a linha algoritmo e pede a digitação do seu nome. algoritmo "*" arq - Insere o comando arquivo e pede a digitação do seu nome. arquivo "*" cof, con - Inserem os comandos cronometro off ou cronometro on, respectivamente. dcc - Insere uma declaração de variáveis caracteres. var

* : caractere

dcl - Insere uma declaração de variáveis lógicas. var

* : logico

dcr - Insere uma declaração de variáveis reais. var * : real deb - Insere o comando debug. eof, eon - Inserem os comandos eco off ou eco on, respectivamente. esc - Insere o comando escreva. escl - Insere o comando escolha (sem a cláusula outrocaso).

[35] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


escolha * caso fimescolha esco - Insere o comando escolha (com a cláusula outrocaso). escolha * caso outrocaso fimescolha enq - Insere o comando enquanto. enquanto * faca fimenquanto fal - Insere a linha fimalgoritmo. ini - Insere a linha inicio. int - Insere o comando interrompa. lep - Insere o comando leia. leia (*) par - Insere o comando para. para * de 1 ate faca fimpara parp - Insere o comando para com passo. para * de ate passo faca fimpara rep - Insere o comando repita. repita * ate repf - Insere o comando repita com fimrepita. repita * fimrepita see - Insere o comando se sem a alternativa senao. se * entao fimse ses - Insere o comando se completo. se * entao senao fimse

[36] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


tim - Insere os comandos timer on e timer off. timer on * timer off tof, ton - Inserem os comandos timer on ou timer off, respectivamente. Sugestão de Digitação A sugestão de digitação é disponibilizada através das teclas Ctrl-J. Basta começar a digitação de uma palavra e teclar Ctrl-J para que o VisuAlg mostre uma lista com sugestões de palavras-chave que completam o que foi digitado. Para escolher, é necessário dar um duplo-clique sobre a opção desejada, ou então selecioná-la com as setas e teclar Enter. Se o usuário continua escrevendo depois que o VisuAlg apresentou a lista de sugestões, o programa continuará procurando palavras que ainda complementem o que foi digitado. Ao se teclar Esc ou clicar "fora da lista", ela desaparece.

[37] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Compilador C PCWHD da CCS versão estudante

Utilizaremos a linguagem C para desenvolvermos programas para nossos microcontroladores PIC. O compilador que utilizaremos chama-se PCWHD CCS C Compiler da fabricante CCS®, que pode ser baixado gratuitamente para demonstração aqui: http://www.ccsinfo.com/ccsfreedemo.php Iremos também trabalhar com um ambiente de simulação chamado Proteus®, que pode ser baixado também para demonstração no link a seguir. http://www.labcenter.com/download/prodemo_autodl_general.cfm

Compilador C da CCS

Simulador eletrônico e de microcontroladores PIC PROTEUS Abaixo seguem apostilas de outros autores do Compilador e do PROTEUS.

[38] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


ESCLARECIMENTOS E AGRADECIMENTOS Primeiramente gostaria de esclarecer que devido ao extenso conteúdo apresentado por este tema (Desenvolvedor de dispositivos embarcados), julguei desnecessário desenvolver todo um material e conteúdo que já existe pela internet, procurei adicionar ao meu sucinto tutorial, materiais de terceiros gratuitos que encontramos pela internet, razão pela qual não precisamos reinventar a roda ! Com isto gostaria de agradecer às pessoas que contribuem de forma direta e indireta na internet pela disseminação do conhecimento através de seus tutoriais, apostilas e até livros gratuitos, com isto estamos enviando conhecimento os mais longínquos lugares tornando o mundo um lugar melhor!

[38] Introdução a programação e Microcontroladores PIC: Prof. Fabiano F. Saldanha


Linguagem C para microcontroladores PIC

Linguagem ´C´ para microcontroladores

PIC

VIDAL Projetos Personalizados Eng. Vidal Pereira da Silva Júnior

Última revisão: 25/11/1999

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br


Linguagem C para microcontroladores PIC

Objetivo: Iniciar o projetista no uso da linguagem C para sistemas dedicados baseados na família PIC 16CXXX.

Metodologia: O curso esta dividido em 3 partes: w Iniciação à Linguagem C w Implementação da CCS para a linha microchip w Exemplos práticos de hardware e software

Parte I - Iniciação à linguagem C A principal vantagem de se usar linguagens de alto nível (no nosso caso a linguagem C) esta na menor interação do projetista com o hardware, no que diz respeito ao controle do mesmo (ajuste de bancos de registradores, seqüências de inicialização, ...). Desta forma o projetista dedica seu tempo basicamente à lógica do problema e não aos detalhes internos do chip. Como exemplo vamos ver a seqüência de escrita na EEPROM do 16F84 (gravar no endereço 20H o valor 12H, pág. 27 do livro): Em assembler:

Em ‘C’

bcf movlw movwf movlw movwf bsf bcf bsf movlw movwf movlw movwf bsf

write_eeprom(0x20,0x12);

STATUS,RP0 20H EEADR 12H EEDATA STATUS,RP0 INTCON,GIE EECON1,WREN 55H EECON2 0AAH EECON2 EECON1,WR

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 2


Linguagem C para microcontroladores PIC

I.1 - Modelo básico de um programa em C Quatro elementos estão presentes em um programa C: Ÿ Ÿ Ÿ Ÿ

Comentários Diretivas de compilação Definições de dados Blocos com instruções e funções

Modelo básico #include <....> #fuses ......

Diretivas de compilação

// comentário ocupando uma linha

Comentários

/* comentários entre ‘/ *’ e ‘* /’ podem ocupar mais de uma linha */

char i , j ; float Tempo;

Variáveis

void main() { instruções do programa principal }

void delay() { instruções da função (rotina) delay }

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 3


Linguagem C para microcontroladores PIC

I.2 - Comentários Comentários são informações anexadas ao programa fonte (*) que permitem ao programador ou outros entenderem o significado do que esta sendo feito. É boa prática comentar todas as linhas, pois após um certo tempo, nem mesmo o criador do programa lembrará de tudo o que estava pensando no momento da escrita. O compilador ignora tudo que estiver definido como comentário (*) O programa fonte em C deve ter terminação “.C” Exemplo: teste.c Existem dois tipos de comentários: Ÿ

Comentários que ocupam apenas 1 linha

Este tipo de comentário é iniciado com duas barras conjuntas: // Neste caso, tudo que estiver após as duas barras será ignorado pelo compilador. Exemplo: x = x + 2; Ÿ

// soma 2 à variável x

Comentários com múltiplas linhas

Este tipo de comentário é iniciado com a seqüência /* e finalizado pela seqüência */. Neste caso, tudo que estiver ENTRE estas duas seqüências será ignorado pelo compilador. Ideal para excluir temporariamente trechos de código. Exemplo:

/*

x = x + 2; tempo++; a = SQRT(25); x = 0;

*/

No exemplo acima, as linhas tempo++; e a=SQRT(25); serão ignoradas no momento da compilação.

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 4


Linguagem C para microcontroladores PIC

I.3 - Diretivas de compilação São instruções para o compilador, e não para o programa que será gerado. As diretivas informam, por exemplo, o processador para o qual o código deverá ser gerado, o valor do clock que será usado pela cpu,..). As diretivas sempre começam com ‘ # ’. Um bom exemplo é a diretiva que inclui no processo de compilação as definições do chip. #include <16F84.H> A terminação .H indica um Header File da linguagem C, ou seja, um cabeçalho. Equivale ao P16F84.INC usado no assembler.

I.4 - Indicador de fim de instrução O compilador C não é um compilador de linha, como o assembler. O compilador C procura o sinal de que a instrução ou o bloco de instruções já acabou. Este sinal é o “ponto e virgula” para uma instrução ou o ‘ } ‘ para o bloco (mais tarde falaremos sobre blocos de instruções). No exemplo abaixo, as duas maneiras são corretas, pois o ‘ ; ‘ é que sinaliza o fim da instrução. x = x + 25;

VIDAL

x= x + 25 ;

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 5


Linguagem C para microcontroladores PIC

I.5 - Definição de variáveis, constantes e identificadores Todas as variáveis e constantes usadas no programa devem ser devidamente definidas, com um nome e um tipo. O mesmo vale para identificadores de funções e rotinas. Os dados básicos podem ser de 8, 16 e 32 bits de comprimento, e devido as características peculiares dos microcontroladores, variáveis de 1 bit também podem ser definidas. Variáveis:

tamanho

faixa

Ÿ Ÿ Ÿ Ÿ

CHAR LONG INT FLOAT SHORT

( de 0 à 255) ( de 0 à 65535 * ) (____________________________) ( pode assumir 0 ou 1)

variável de 8 bits: variável de 16 bits: variável de 32 bits: variável de 1 bit:

(*) Variáveis com valores negativos: As variáveis do tipo LONG INT podem ou não ter sinal negativo. Para garantir que a variável seja sempre positiva, usamos unsigned antes da definição da mesma. Caso seja necessário tratar números negativos, usaremos signed. Ex.:

unsigned long int tempo; signed long int espaco;

// tempo irá de 0 à 65535 // espaco irá de -32768 à 32767

Observe que o indicativo signed diminui o alcance da variável pela metade. O padrão da linguagem, quando não indicado, é o tipo UNSIGNED. CHAR é sempre UNSIGNED. FLOAT não admite os indicativos mas pode ser positivo ou negativo. I.5.1 - Seqüência de declaração de variáveis e constantes Para se declarar uma variável temos a seguinte ordem das definições: Tipo char

Nome tempo;

// a variável ‘tempo’ vai de 0 à 255

Um grupo de variáveis de mesmo tipo pode ser declarada na mesma linha. char

i, j, k;

// declara que i, j e k são do tipo char.

Constantes: CONST define um ‘label’ para valores que não serão alterados pelo programa: Exemplo:

FLOAT CONST PI = 3.14;

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 6


Linguagem C para microcontroladores PIC

I.5.2 - Como escrever os nomes de variáveis, constantes e funções Todo ‘label’ (nome ou identificador), seja de variável, constante ou função, deve começar por letra, ter no máximo 32 caracteres e não usar caracteres especiais ou de controle ( ! \ ? % ....). Nomes de funções e rotinas internas também não podem ser utilizados. - Exemplos de definições: Corretas

Incorretas

Teste teste TESTE _12A x_2_5

0local começa com número parte!dois ^ caracter inválido ( ! )

IMPORTANTE: O compilador diferencia letras minúsculas de maiúsculas. Nos exemplos acima, Teste, teste e TESTE são 3 variáveis diferentes para o compilador. Uma boa prática esta em diferenciar variáveis, labels e registros com tipos diferentes de letras. Exemplo:

PORTB TempoMs quantos

registro da CPU Rotina de tempo em ms variável em RAM

I.5.3 - Atribuindo valores A atribuição de valores é feita pelo sinal de igualdade, tempo = 123; aqui a variável tempo passa a ter o valor 123 decimal.

I.5.4 - IMPORTANTE

Valores iniciais das variáveis

Devemos sempre ajustar os valores iniciais de cada variável do programa antes de usa-las, pois nada garante que estão em “0 “ no reset.

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 7


Linguagem C para microcontroladores PIC

I.5.5 - Variáveis locais e variáveis globais Existem duas maneiras principais para a alocação de variáveis em memória: Variáveis Globais: As variáveis globais tem “alcance” para todas as rotinas e funções existentes no programa. Isto significa que qualquer rotina ou função poderá utiliza-la. Variáveis Locais: As variáveis locais tem “alcance” apenas dentro das rotinas ou funções onde foram criadas. Isto significa que apenas a rotina ou função onde a mesma foi criada poderá utiliza-la. Vamos ver um fragmento de código como exemplo: char A,B,C; main () { A = 0; Tempo(); Espera(); } Tempo() { char J;

// A, B e C são variáveis globais, pois estão fora de // qualquer função ou rotina.

// Faz A=0 // chama rotina Tempo // chama rotina Espera

// cria uma variável chamada J. // Somente a rotina Tempo() poderá utiliza-la

J = A; } Espera() { char X;

// cria uma variável chamada X. // Somente a rotina Espera() poderá utiliza-la

X = A; X = J;

// Erro: A variável J não existe para esta rotina

} A principal vantagem no uso das variáveis locais esta em que a memória RAM ocupada pela mesma será compartilhada por outras variáveis locais, permitindo um “aumento” no espaço de memória.

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 8


Linguagem C para microcontroladores PIC

I.6 - Funções, Procedimentos e Rotinas Chamamos função um trecho de programa que realiza determinada operação, bem como as funções pré-definidas (SQRT, ABS, ACOS, ...). A principal característica da função é a capacidade de retornar um valor ao ponto de chamada da mesma. Procedimentos são trechos de programa que não retornam valor. Podemos as vezes nos refrir as funções e aos procedimentos como ‘rotinas’. No exemplo abaixo, temos a função MAIN (falaremos dela depois) que é a rotina executada no reset do programa. A função MAIN chama uma ROTINA para ler teclas, e a rotina de ler teclas chama uma FUNÇÃO para calcular o valor absoluto da tecla. main ( ) { --LeTeclas( ); --} LeTeclas( ) { --X = ABS(tecla_lida); --} I.6.1 - Funções especialmente desenvolvidas para os PIC’s Na parte II, referente ao compilador da CCS, veremos quais as funções que existem para os PIC’s e como funcionam. I.6.2 - Retorno de funções A idéia básica da função esta em retornar um valor para o ponto de chamada. Todas as funções não definidas como VOID (*) retornam um valor. Para que o valor seja retornado, devemos usar a instrução return seguida do valor a ser retornado, que encerra a função e faz com que o programa volte ao ponto de origem. Uma função pode ter vários return, mas somente um será executado. Podemos assim criar vários pontos de saída da função, um para cada situação. Se não colocarmos o return, o valor retornado sera “0”. (*) Veremos os tipos de função depois VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 9


Linguagem C para microcontroladores PIC

Exemplo: Função para dividir dois numeros. Se o divisor for “0”, retorna “0” main( ) { ........... x = 100; y = getchar( );

valor = DIVID (x,y); if ( valor == 0 ) { . . . } ..........

// fax x = 100 // faz y = ao valor recebido via serial // para o programa o valor recebido é // indetermionado // chama a funcao DIVID e ao retornar atribui a // ‘valor’ o resultado da divisão // ação caso y = 0

} long int DIVID ( long int A , B) { if ( B == 0 ) return (0); else return ( A / B ); }

// se B=0 retorna 0, // senao retorna a divisão

OBSERVAÇÃO: Este programa da forma acima é apenas ilustrativo. A listagem apresentada ao final nos exemplos esta completa, com todos os detalhes para permitir a compilação.

I.6.3 - Variáveis como parâmetros Outra facilidade da linguagem C esta na passagem de valores de uma rotina ou função para outra. Estes valores são conhecidos por “parâmetros” Como exemplo, temos o programa acima, onde enviamos dois números para a função que calcula a divisão.

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 10


Linguagem C para microcontroladores PIC

I.7 - Expressões numéricas e de string (caracteres) Vamos ver neste item os tipos de expressão permitidas para valores numéricos e para a manipulação de caracteres. Não podem começar por ‘ 0 ’ (zero)

Números Decimais:

Exemplos:

Números Octais: (Pouco utilizados)

123; 2; 14534; 3.14; ...

Devem começar por ‘ 0 ’ (zero) Exemplos:

Números Binários:

045; 09;...

Devem iniciar por ‘ 0b ‘ Exemplo:

Números Hexadecimais:

0b10101010

Devem iniciar por ‘ 0x ‘ Exemplo:

String de 1 caractere:

0x32; 0xA9; ...

Entre Apóstrofos ‘ ‘ Exemplo:

String de vários caracteres:

Entre aspas “ “ Exemplo:

VIDAL

‘z’; ‘A’; ....

“teste de escrita”

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 11


Linguagem C para microcontroladores PIC

I.8 - Operadores lógicos e aritméticos básicos da linguagem C Principais operadores lógico-relacionais e aritméticos da linguagem C. Ÿ Ÿ Ÿ Ÿ Ÿ Ÿ Ÿ Ÿ

+ ++ -* / % ^

Adição Incremento da variável indicada ( D++ é equivalente a D = D + 1) Subtração Decremento da variável indicada ( X-- é equivalente a X = X - 1) Multiplicação Divisão (parte inteira da divisão para variáveis inteiras) Resto da divisão (se for divisão de inteiros) Exponencial

Ÿ Ÿ Ÿ Ÿ Ÿ Ÿ

< > <= >= == !=

Comparador lógico “menor que” Comparador lógico “maior que” Comparador lógico “menor ou igual que” Comparador lógico “maior ou igual que” Comparador lógico “igual a” (*) Comparador lógico “diferente de”

Ÿ Ÿ Ÿ

&& || !

AND lógico ou relacional (todas as condições verdadeiras) OR lógico ou relacional (uma das condições é verdadeira) NOT lógico ou relacional (vê se a condição é TRUE ou FALSE)

Ÿ Ÿ Ÿ

& | ~

AND binário (bit a bit nas variáveis) OR binário (bit a bit nas variáveis) NOT binário (inverte o estado de cada bit da variável)

(*) IMPORTANTE: Se numa comparação usarmos ‘ = ‘, o compilador fará uma atribuição, gerando um programa errado logicamente. Exemplo correto:

SE A == 5 .....

// Verifica se A é igual a 5

Exemplo errado:

SE A = 5 ......

// Primeiro faz A igual a 5, o que não é o // objetivo do teste

O compilador não avisa deste erro. Cuidado ! Exemplo para inverter a variável X e escrever no portb: portb = ~ X;

// operador NOT binário

Exemplo para ver se o bit T0IF ainda não chegou a 1: if ( ! T0IF ) ....

VIDAL

// Se T0IF NÃO (not) TRUE ( true = 1),.... // operador NOT lógico

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 12


Linguagem C para microcontroladores PIC

I.9 - Matrizes Define-se como matriz um grupo de dados que podem ser agrupados num mesmo nome, diferenciando-se apenas pela posição no grupo. Como exemplo temos uma rua com várias casas. A rua seria nossa matriz, por exemplo, Rua Paraná. Cada casa tem um número que indica sua posição na rua (na matriz). Exemplo:

casa 32 da Rua Paraná

Poderíamos escrever Rua Parana[32] Em C, a definição de uma variável ou de uma constante como matriz é feita apenas pela inclusão de seu tamanho entre colchetes [ ]. Exemplo: Matriz para os 20 valores de temperatura lidos, variáveis tipo char: char temperatura[20];

// reserva espaço de memória para // 20 bytes que indicarão a temperatura // O primeiro elemento é temperatura[0] // O último elemento é temperatura[19]

Para acessar os elementos da matriz basta escrever o nome da variável com o índice do valor desejado. Exemplo: valor = temperatura[12];

// o 13o elemento da matriz temperatura // é copiado para a variável valor.

IMPORTANTE: 1)

O índice da matriz pode ser outra variável. Ex.: H = temperatura [contador];

2)

O índice de acesso a matriz vai de 0 até tamanho-1. No nosso exemplo, irá de 0 à 19.

Se voce tentar acessar um elemento de endereco maior que o existente, o compilador usara uma posição de RAM que provavelmente esta em uso por outra variavel. O compilador não tem condições de alertar sobre este erro. 3) Muito cuidado com o uso de matrizes, pois temos pouca memória RAM nos chips. VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 13


Linguagem C para microcontroladores PIC

I.10 - Controle do programa em C Um dos pontos mais importantes do aprendizado da linguagem C esta na sua sintaxe, isto é, como o programa deve ser escrito. Até agora vimos apenas teorias sobre variáveis, dados, e funções. Veremos a partir de agora como tudo isto é integrado de forma a produzir um resultado útil. Para tal vamos estudar as estruturas de montagem de programas e ver como se controla o fluxo de “ações” que o programa deve tomar. Para facilitar o aprendizado não vamos nos preocupar agora com o PIC e nem com as funções criadas para o mesmo, mas apenas com a forma como escrevemos o programa em C.

I.10.1 - Blocos de declarações Sempre que mais de uma instrução tiver de ser executada para uma certa rotina, as mesmas deverão estar contidas dentro de um BLOCO de declarações. Um bloco tem início com a abertura de uma chave ‘ { ‘ e é finalizado pelo fechamento da chave ‘ } ‘. Como um bloco não termina no fim da linha, mas sim ao fechar a chave, podemos escrever o mesmo de forma mais clara, colocando seus elementos em várias linhas e permitindo melhor colocação de comentários.. Exemplo 1:

{ x = 1;

Exemplo 2:

{

tempo = x * 2; }

x = 1; tempo = x * 2; }

// posso colocar um // comentário para cada // linha

Os dois exemplos acima realizam a mesma tarefa, mas o exemplo 2 é mais fácil de ser lido e posteriormente entendido.

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 14


Linguagem C para microcontroladores PIC

I.10.2 - Bloco IF (executa se a condição for verdadeira) Podemos entender o bloco IF como um teste simples. Temos duas opções básicas, sendo que a condição de teste deverá estar entre parênteses: -

SE (teste == ok!) “executa esta(s) declaração(ões)”

-

SE (teste == ok!) “executa esta(s) declaração(ões)” SENÃO “executa esta(s) outras declaração(ões)” Temos vários formatos possíveis para o IF

Ÿ

IF simples, com apenas uma declaração caso o teste seja verdadeiro if ( A == 0 ) A = 10;

Ÿ

// SE a variável A estiver zerada, atribui 10 // à mesma. // Veja teoria dos operadores lógicos para o “ == “

IF com mais de uma declaração caso o teste seja verdadeiro. Neste caso o grupo de declarações deverá estar num BLOCO, isto é, entre chaves ‘ { } ‘. if ( tempo > 10 ) { tempo = 0; contador = contador + 1; }

Ÿ

IF com exceção (se o teste falha, executa outra declaração ou bloco). Pode na exceção executar uma instrução apenas ou um bloco if ( teste == sim )

declaração individual ou bloco

else declaração individual ou bloco da exceção

Importante: A instrução (declaração) simples não precisa estar na mesma linha do IF ou do ELSE. (Ver item I.10.2.1, nos exemplos de IF’s aninhados).

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 15


Linguagem C para microcontroladores PIC

Podemos então resumir numa tabela todas as combinações dos IF’s:

Ÿ

if

(teste desejado)

Ÿ

if {

(teste desejado)

instrução para teste “OK”

grupo de instruções para teste “OK” } Ÿ

if else

(teste desejado)

Ÿ

if {

(teste desejado)

instrução para teste “OK” instrução para teste “NÃO OK”

grupo de instruções para teste “OK” } else Ÿ

if else {

instrução para teste “NÃO OK”

(teste desejado)

instrução para teste “OK”

grupo de instruções para teste “NÃO OK” } Ÿ

if {

(teste desejado) grupo de instruções para teste “OK”

} else { grupo de instruções para teste “NÃO OK” }

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 16


Linguagem C para microcontroladores PIC

I.10.2.1 - IF’s aninhados (embutidos um no outro) Chamamos a estrutura de “IF’s aninhados” quando a instrução a ser executada para um teste (seja verdadeiro ou falso) é na verdade outro IF. Vamos ver dois exemplos que ajudarão a esclarecer o assunto. Exemplo 1:

Observe os dois trechos de programa a seguir: if ( X ) if (Y) a = a * 2; else a = a * 4;

| | | | | | |

if ( X ) { if (Y) a = a * 2; } else a=a*4

No trecho da esquerda, o else refere-se ao if (Y), pois esta “mais próximo” deste. Somente se o if (Y) resultar falso é que a linha a = a * 4 será executada. Se o if (X) resultar falso, nenhuma operação será realizada. No trecho da direita, o else refere-se ao if (X), pois o if (Y) esta dentro de um bloco, não sendo visível para o else. Se o if (X) resultar verdadeiro mas o if(Y) resultar falso, nenhuma operação será realizada.

Exemplo 2:

Vários IF’s seqüênciais

if ( posição == 1) peso = 1;

// Vê se posição = 1. // É 1. Faz peso = 1.

else

if (posição == 2) peso = 2;

// Não é 1. Vê se posição = 2. // É 2. Faz peso = 2.

else if (posição == 3) peso = 4;

// Não é 2. Vê se posição = 3. // É 3. Faz peso = 4.

else if (posição == 4) peso = 8; else peso = 0;

VIDAL

// Não é 3. Vê se posição = 4. // É 4. Faz peso = 8. // Não é 4. Faz peso = 0.

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 17


Linguagem C para microcontroladores PIC

I.10.3 - Bloco FOR (loop para executar por um certo número de vezes) A idéia do bloco FOR é executar uma instrução ou um bloco de instruções repetidamente, por um número de vezes determinado pela chamado do loop. Sua sintaxe é a seguinte: for ( ajustes iniciais ; condições de teste ; ajustes dos parâmetros ) instrução ; ou for ( ajustes iniciais ; condições de teste ; ajustes dos parâmetros ) { ( grupo de instruções ) } Para melhor entendimento, vejamos um exemplo para escrever na variável PORTB os números de 1 a 100 e ainda somar estes números: char

PORTB;

// declarei PORTB como variável de 1 byte // Não é a porta B do PIC // declarei a variável soma como 16 bits. /* a variável que é usada no loop também precisa ser declarada. Neste caso, 1 byte é suficiente */

long int soma; char i;

soma = 0; for ( i = 1; i < 101; i++) { PORTB = i; soma = soma + i; }

// faço soma = 0 para inicializar a variável

// escreve ‘ i ‘ em PORTB // a soma anterior é somada a ‘ i ‘

I.10.3.1 - Loop infinito com FOR Podemos criar um loop infinito com a declaração for ( ; ; )

instrução que será executada indefinidamente

ou for ( ; ; ) { Instruções que serão executadas indefinidamente } Lembre-se que o programa de um microcontrolador não tem fim, sempre esta rodando, geralmente dentro de um loop infinito.

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 18


Linguagem C para microcontroladores PIC

I.10.4 - O condicional WHILE (enquanto) O WHILE executa a instrução ou o bloco de instruções “enquanto” a condição de teste for verdadeira. ”Se logo no inicio do teste a condição resultar falsa, nada será executado”. Sintaxe: while ( teste )

instrução para teste verdadeiro

ou while ( teste ) { ( grupo de instruções para teste verdadeiro) } Vamos proceder novamente a soma dos números de 1 a 100 como no exemplo anterior. i = 0; soma = 0; while ( i < 101 ) { soma = soma + 1; i++;

// nunca esquecer de inicializar // todas as variáveis do programa. // faça enquanto I<101

/* como o WHILE apenas faz o teste devo incrementar a variável */

}

I.10.4.1 - Loop infinito com WHILE while (true) { ( declarações executadas eternamente ) } A condição booleana “true” sempre será verdadeira (true). OBSERVAÇÃO: As condições TRUE e FALSE já estão pré-definidas no compilador.

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 19


Linguagem C para microcontroladores PIC

I.10.5 - O condicional DO / WHILE (faça ... enquanto) O condicional DO / WHILE funciona de forma semelhante ao WHILE, exceto pelo fato de que “pelo menos uma vez a instrução ou o bloco serão executados”. Sua sintaxe é: do instrução para teste verdadeiro while ( teste ) ; ou do { ( grupo de instruções para teste verdadeiro) } while ( teste ) ;

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 20


Linguagem C para microcontroladores PIC

I.10.5 - O condicional SWITCH O SWITCH testa a variável e conforme seu valor pula diretamente para o grupo de instruções conforme a cláusula CASE. Caso nenhuma das condições previstas nos vários CASE sejam satisfeitas, executa o bloco DEFAULT, se houver (não é obrigatório). Mesmo que apenas uma instrução seja usada para um certo CASE, sempre teremos um bloco ( entre chaves ‘ { } ‘ ) pois além da instrução a ser executada devemos incluir a instrução BREAK, que faz com que o programa vá imediatamente para o fim do SWITCH, continuando a partir dai. Caso o BREAK não seja colocado, o programa continuará pelo CASE logo abaixo do que foi chamado (ou no DEFAULT). Seu formato geral é: switch ( variável ) { case constante1 { ( instrução ou grupo de instruções ) break; } case constante2 { ( instrução ou grupo de instruções ) break; } . . . default: { ( instrução ou grupo de instruções para falso geral ) break; } }

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 21


Linguagem C para microcontroladores PIC

Vamos ver um exemplo que faz o mesmo que o IF aninhado que vimos anteriormente.

switch ( posição ) { case 1: { peso = 1; break; } case 2: { peso = 2; break; } case 3: { peso = 4; break; } case 4: { peso = 8; break; } default: { peso = 0; break; } }

// CASO posição = 1 ....

// sai do CASE.

// CASO posição NÃO seja 1, 2, 3 ou 4, // executa este bloco

Para ilustrar vamos escrever várias declarações em uma só linha. switch ( posição ) { case 1: { peso = 1; break; } case 2: { peso = 2; break; } case 3: { peso = 4; break; } case 4: { peso = 8; break; } default: { peso = 0; break; } }

VIDAL

// CASO peso=1, .... // CASO peso=2, ....

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 22


Linguagem C para microcontroladores PIC

I.11 - Abreviações úteis para instruções aritméticas I.11.1 - Incremento e Decremento Duas delas foram mostradas no item I.8 (Operadores lógicos e aritméticos básicos da linguagem C), a saber: Ÿ

++

Incremento da variável indicada

O operador ‘++’ facilita a escrita de instruções para o incremento de variáveis. Ao invés de escrever: a = a + 1; podemos escrever: a++; ou ++a; (*) Ÿ

--

Decremento da variável indicada

O operador ‘--’ facilita a escrita de instruções para o decremento de variáveis. Ao invés de escrever: a = a - 1; podemos escrever: a--; ou --a; (*) Soma ou subtração de valores maiores que ‘1’ à uma variável Instrução normal

Instrução abreviada

X = X + 10; G = G - 25;

X + = 10; G - = 25;

I.11.2 - Combinando abreviações Podemos combinar numa única linha abreviações e atribuições, de forma a facilitar a escrita do programa. Importante: Os iniciantes na linguagem devem usar inicialmente as instruções básicas para não se confundirem. Vamos explicar com alguns exemplos: X = X + 1; Y = X;

--->

Y = ++X;

(*) Como o ++ esta ‘antes’ do X, primeiro o X será incrementado para depois Y receber o valor. Se fizermos Y = X++;

o equivalente será Y = X; X = X + 1;

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 23


Linguagem C para microcontroladores PIC

I.12 - A variável tipo VOID Existe um tipo de variável especial chamada VOID. Seu significado seria mais ou menos do tipo VAZIO. É usada principalmente na chamada de rotinas ou no retorna das mesmas, para indicar que nenhum valor foi “enviado” ou será “retornado” da função. Para melhor entendimento, vejamos uma rotina que não precisa de parâmetros e nada retorna: ......... ......... LeTeclas( ); ......... .........

void LeTeclas( ) { ......... ......... ......... }

// trecho de programa // chama a rotina sem enviar nada

// este void indica que a rotina não envia // parâmetros de volta // O parenteses vazio informa que a rotina não // recebeu parâmetros

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 24


Linguagem C para microcontroladores PIC

I.13 - Protótipos de funções No inicio do programa devemos informar ao compilador todas as rotinas que serão usadas e seus parâmetros. Isto serve para evitar que quando usarmos a rotina a mesma seja chamada de forma errônea. Serve ainda para o compilador montar o programa ja reservando as posições de memória RAM e estimativa de pilha usada. Esta declaração da rotina é feita da mesma forma da rotina em sí, mas sem as instruções e finalizada pelo “ ; “. Esta declaração é conhecida por protótipo. Exemplos de protótipos: void LeTeclas (void);

// a rotina LeTeclas não receberá parâmetros // e também não retornará valores.

float DIVID (long int A, B);

// a rotina DIVID receberá duas variáveis do tipo // long int, que receberão o nome de A e B para seu // uso, e retornará um valor float.

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 25


Linguagem C para microcontroladores PIC

I.14 - A função MAIN ( ) Todo programa em C deve ter uma função chamada MAIN ( ), que é a rotina que será executada quando o programa for chamado. No caso do PIC, o compilador vai gerar um código de inicialização e depois desviar para o MAIN propriamente dito. Exemplo de um programa que nada faz, mas que teoricamente pode ser compilado: void main ( void) {

// a função MAIN não recebe ou devolve valores

}

I.15 - Exemplos de programas simples Veremos neste item alguns programas pequenos e simples, sem função técnica específica, apenas para ilustrar os conceitos vistos até agora. Todos os conceitos vistos são genéricos para a linguagem C, servindo inclusive para usar em outros microprocessadores e computadores pessoais.

Programa 1: Calcula a soma dos números de 1 a 100. char

i;

// variável i usada no loop (0 a 255)

long int soma;

// soma de 0 a 65535

void main( void) { soma = 0; for ( i = 0; i < 101; i++) soma = soma + i; }

VIDAL

// devo sempre inicializar as variáveis

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 26


Linguagem C para microcontroladores PIC

Programa 2: Conta indefinidamente de 1 a 10. Sempre que chegar a 10 incrementa a variável X e recomeça. char

i, x;

// declarei que i e x são variáveis do // tipo char

void main ( void) { i = 0; x = 0; while (1) { i++; if ( i == 10 ) { x++; i = 0; } } }

// inicializei as variáveis // fica eternamente neste loop // incrementa i // vê se i = 10. // É. Incrementa x e faz i = 0.

Programa 3: Incrementa indefinidamente a variável chamada PORTB ( na parte II veremos como executar no PIC ). char

PORTB;

// declarei que PORTB é variável do // tipo char (8 bits)

void main ( void) { PORTB = 0; while (true) { PORTB++; } }

// inicio em 0 // fica eternamente neste loop // incrementa PORTB

ANEXO Temos a seguir um programa ilustrativo do que foi estudado até agora. Este programa foi compilado para o 16F84 e não de modo genérico porque o compilador sempre precisa saber a quantidade de RAM e de ROM disponível.

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 27


Linguagem C para microcontroladores PIC

Listagem do programa “REGRAS.C” /**************************************************************************************** Programa demo para o compilador C da CCS. Compila blocos e instruções apenas para ver a compilação. Aqui já temos um exemplo de comentários em varias linhas ***************************************************************************************** */ // Cabeçalho inicial com diretivas de compilação #CASE

// COMPILADOR CASE SENSITIVE. // Padrão da linguagem C

#include <16F84.H>

// Define processador // Necessário para informar a // quantidade de RAM e ROM disponível

// ********************************************************************************************* // protótipos de rotinas void _while(void); void _do_while(void); void _switch(void); void _ifs(void);

// nao recebe e nao devolve // nao recebe e nao devolve parametros // nao recebe e nao devolve parametros // nao recebe e nao devolve parametros

void _for(char j);

// recebe um char como parametro // mas nao devolve nada

float quadrado(char q);

// recebe char e deve devolver float

// ********************************************************************************************* // constantes e variaveis char long int float short

a,b,c,d,e; aa,bb,cc,dd,ee; VarFloat; Led;

// variaveis de 8 bits // variaveis de 16 bits // variavel de 32 bits // Led será um pino de I/O

float

const PI = 3.14;

// definicao de constante tipo float

char

Temperatura[20];

// definiçao de uma matriz de 20 elementos

// *********************************************************************************************

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 28


Linguagem C para microcontroladores PIC

void main() { while (1) { a = 65; b = 0b01000001; c = 0x41; d = 'A'; _ifs(); _while(); _do_while(); _switch(); _for(20);

// Programa Principal // loop infinito // atribuicao de variavel decimal 65 // atribuicao de variavel 65 em binario // atribuicao de variavel 65 em hexa // atribuicao de variavel 65 em ascii // chamada de rotinas sem parametros

// chama rotina com parametro de valor 20

VarFloat = quadrado(4); } } // ********************************************************************************************* void _ifs() { if (a == 0) { e = 100; } else { e = 90; } } // ********************************************************************************************* void _while() { a = 0; while (a < 10) { b = 5; c = b * 10; a++; } }

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 29


Linguagem C para microcontroladores PIC

// ********************************************************************************************* void _do_while() { char VarLocal; VarLocal = 0; e = 0; do e += 3; while ( e < 100 ); } // ********************************************************************************************* void _switch() { switch (d) { case 1: { a = 1; break; } case 2: { a = 2; break; } default: { a = 5; break; } } } // ********************************************************************************************* void _for(char j) { for (e=1; e<j+1; e++) // 'e' varia de 1 a 'j' Temperatura[e] = e; } // ********************************************************************************************* float quadrado(char q) { return (q*q); } VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 30


Linguagem C para microcontroladores PIC

Parte II - O compilador C da CCS Inc. Veremos nesta parte como escrever programa em C para os PIC’s, acessando registros, portas e memória, alem de estudar as principais funções criadas pela CCS para facilitar o trabalho do desenvolvedor de sistemas. Não vamos estudar todas as funções criadas, apenas as mais usadas de forma a permitir ao estudante aprofundar-se com facilidade posterior quando do uso do software completo e sem limitações. Para este estudo usaremos uma versão de demonstração do compilador PCM, funcional por 30 dias, que compila apenas para o 16C63. Nota importante: para manter compatibilidade com chips e usuários mais antigos da linha PIC, em algumas funções o TIMER 0 é chamado pelo seu nome antigo, RTCC.

II.1 - Diretivas de compilação Ver item I.3 para teoria sobre as diretivas de compilação.

II.1.1 - #asm

#endasm

Permite a inclusão de trechos em assembler dentro do programa em C. Muito cuidado deve ser tomado com o uso desta diretiva, pois toda ação gerada em assembler é de inteira responsabilidade do usuário, e pode vir a prejudicar outras variáveis ou posições de RAM usadas pelo compilador. Exemplo: . . x = a; b = x / 3; #asm bsf bcf #endasm

PORTB,3 PORTB,3

// estas duas instruções geram um pulso // no pino RB3.

x = sqrt(a); . . IMPORTANTE: Observe que embora seja um trecho em assembler o comentário esta no formato da linguagem C. VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 31


Linguagem C para microcontroladores PIC

II.1.2 - #case Indica para o compilador ser “sensitivo” a diferenças entre letras maiúsculas e minúsculas. Embora a linguagem C de forma padrão seja sensivel ao tipo de letra, sem esta diretiva, o compilador ignora as diferenças. Exemplo:

com o #case Teste, teste e TESTE são variáveis diferentes

Exemplo:

sem o #case Teste, teste e TESTE são a mesma variável

II.1.3 - #define ‘nome’ ‘seqüência’ Permite a substituição, no momento da compilação, do ‘nome’ pela cadeia de caracteres (string) definida em ‘seqüência’. Exemplo: #define largura portb = largura;

4

largura = 5;

// será visto pelo compialdor como // portb = 4 // ERRO. Nao é uma variável.

Sua principal vantagem esta em não precisarmos trocar constantes em todo o programa, bastando alterar na definição, ou ainda para facilitar a escrita de funções mais complexas. (Mais exemplos serão vistos ao final)

II.1.4 - #include <arquivo> O arquivo indicado será adicionado ao fonte no momento da compilação. Ideal para incluir trechos pré-definidos, evitando sua digitação a cada programa novo. Exemplo típico é o arquivo PIC16F84.H que contém as definições sobre o processador. Exemplo:

#include <pic16f84.H>

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 32


Linguagem C para microcontroladores PIC

II.1.5 - #fuses ’opções’ Avisa ao compilador para incluir no arquivo .HEX informações sobre os fusíveis de configuração, facilitando na hora de se gravar o chip. Para cada chip devemos ver em seu arquivo .H quais as opções do mesmo. Devemos cuidar para que não haja repetição de uma mesma opção. As principais opções são: Oscilador:

XT (cristal até 4 MHz), LP (cristal baixa potência), HS (cristal alta velocidade), RC (oscilador RC) WatchDog: WDT (ligado) e NOWDT (desligado) Código: PROTECT (protegido) e NOPROTECT (não protegido) Power-up: PUT (Com power-up) e NOPUT (Sem power-up)

Exemplo:

#fuses

XT,NOWDT,NOPROTECT,PUT

Indica ao gravador que o modo é cristal, sem watch dog, código desprotegido e com power-up timer ligado.

II.1.6 - #ifdef

#endif

Permite selecionar se o trecho entre as duas diretivas será incluido no momento da compilação ou não. Exemplo: #define OK . . #ifdef OK delay_ms(200); #endif

No exemplo, caso o #define OK exista, a chamada para a rotina de tempo será incluida no programa final. Caso contrario não será incluida. Neste caso poderia servir para tirarmos o atraso durante os testes no simulador. II.1.7 - #ifndef

#endif

Funciona de forma similar, incluindo o trecho edntro da diretiva se a definição NÃO existir

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 33


Linguagem C para microcontroladores PIC

II.1.8 - #inline Informa ao compilador para repetir o trecho de código da rotina indicada sempre que a mesma for chamada. Evita a criação de sub-rotinas (call’s) economizando espaço da pilha e executando o programa mais rapidamente. Em compensação ocupa mais espaço de memória de programa. Exemplos: 1 - Sem o #inline tempo() // definimos uma rotina { for ( i=0; i<100; i++) {} } Se na seqüência de programa tivermos: tempo(); LeTeclas(); tempo();

// chamamos a rotina de tempo // leitura de teclas // chamamos a rotina de tempo novamente

o compilador gerará a seguinte sub-rotina em ASM: tempo: movlw movwf

100 i

decfsz goto return

i espera_i

// valor apenas ilustrativo

espera_i;

// retorna da rotina

e as chamadas serão: call tempo; call LeTeclas; call tempo;

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 34


Linguagem C para microcontroladores PIC

2 - Com o #inline #inline tempo() // definimos uma rotina { for ( i=0; i<100; i++) {} } Se na seqüência de programa tivermos: tempo(); LeTeclas(); tempo();

// chamamos a rotina de tempo // leitura de teclas // chamamos a rotina de tempo novamente

o compilador NÃO gerará uma sub-rotina em ASM, mas fará o seguinte para o trecho exemplificado tempo_A: movlw movwf

100 i

decfsz goto

i espera_i_A

espera_i_A;

call LeTeclas; tempo_B: movlw movwf

100 i

decfsz goto

i espera_i_B

espera_i_B;

Veja que ao invés de criar uma sub-rotina, o trecho que realiza a função de tempo foi repetido a cada chamada para o mesmo. Deve-se tomar muito cuidado com este recurso !! Embora ajude a economizar posições de pilha em casos críticos, aumenta o tamanho do programa final

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 35


Linguagem C para microcontroladores PIC

II.1.9 - #INT_?????

(observe o “ _ “ entre as palavras)

Indica para o compilador que o trecho a seguir refere-se a uma rotina de interrupção. O compilador vai gerar um código padrão para entrar e sair da rotina, salvando o estado da máquina e zerando o flag de requisição de interrupção ao sair da mesma. Algumas das interrupções reconhecidas são: Ÿ Ÿ Ÿ Ÿ Ÿ Ÿ

INT_EXT INT_RTCC INT_RB INT_EEPROM INT_AD INT_DEFAULT

(RB0/Int) (Timer 0) (RB4~7) (Eeprom interna) (Conversor A/D interno) (Caso entre na rotina de interrupção por engano)

Para uma lista completa do nome das diretivas de interrupção das várias dezenas de chips existentes, consultar o manual da CCS. O nome da rotina é definido pelo programa. Exemplo: #INT_EXT EntradaRede() { ....... ..... {

// avisa que a rotina a seguir é a da interrup. externa

II.1.10 - #Priority Permite ao programador escolher a prioridade das interrupções habilitadas. A primeira da lista é a mais prioritária. Exemplo para o 16F84: #priority

rtcc, eeprom, ext

VIDAL

// definimos que a interrupção do // Timer 0 é mais prioritária que a da // eeprom interna, que por sua vez é // mais prioritária que a interrupção // externa.

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 36


Linguagem C para microcontroladores PIC

II.1.11 - #ROM Permite a gravação de constantes na memoria de programa ou na EEPROM de dados interna (F84 e F87X). Não influencia no programa, apenas informa ao gravador para gravar os valores indicados no endereço indicado. Exemplo: Determinando os 10 primeiros bytes da eeprom de dados (inicio em 2100H): #ROM

0x2100 = { 0,1,2,3,4,5,6,7,8,9 }

II.1.12 - #use delay (clock = ‘valor do clock em Hz’ ) Informa ao compilador o valor do clock da CPU em Hertz. Serve para permitir o uso de funções de tempo baseadas no clock da máquina. Caso o watch dog seja usado, devemos informar por esta diretiva, para que o mesmo seja resetado nas rotinas de tempo. Exemplos: 1) Sem o watch dog: #use delay(clock = 4000000)

// clock de 4 MHz

2) Com o watch dog: #use delay(clock = 10000000, Restart_Wdt)

II.1.13 - #use Fast_IO( port )

// clock de 10 MHz // com watch dog

(observe o “ _ “ entre as palavras)

Informa ao compilador que o controle do TRIS do port indicado será executado pelo programa. Gera operações de entrada e saída mais rápidas. Exemplo: #use fast_io(porta)

// quem deve controlar o trisa é o programa.

II.1.14 - #use standard_IO( port )

(observe o “ _ “ entre as palavras)

A cada acesso as portas ou pinos de I/O o compilador gerará código para o controle do tris correspondente. Permite maior flexibilidade nos casos de bits com dupla função, mas consome mais tempo e memória de programa. VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 37


Linguagem C para microcontroladores PIC

II.1.15 - #use rs232 (BAUD = taxa, XMIT = pinoTx, RCV = pinoRx, BITS = n ) Ajusta os pinos indicados como pinoRX e pinoTX para funcionarem como entrada e saída serial com velocidade indicada em taxa, e com palavra de n bits. O compilador tem incorporado rotinas que permitem a transmissão e recepção no formato assíncrono típico da comunicação serial. Para o uso destas rotinas a diretiva acima deve ser utilizada. Embora o nome da diretiva sugira RS232, devemos lembrar que os sinais do PIC são de nível TTL. Importante: antes do uso desta diretiva o #use delay é obrigatório. Exemplo: Recebo um byte pelo pino RB7 e transmito o mesmo valor pelo pino RA4, a 9600 bps e palavra de 8 bits: #use delay (clock=4000000) #use rs232 (BAUD = 9600, XMIT = pin_A4, RCV = pin_B7, BITS = 8 ) X = getchar ();

// fica esperando um byte chegar pelo serial // e então escreve na variável X // e depois envia o mesmo de volta.

putchar ( X );

Observação: os nomes de pinos e outras constantes serão vistos ao final e estão no arquivo .H correspondente ao chip utilizado.

II.1.16 - #byte

nome = endereço

E

#bit

nome =

endereço

Permite o acesso a posições de RAM (Registros e memória geral) pela indicação de seu endereço real (lembre-se de que o gerenciamento das variáveis é realizado pelo compilador). Exemplo: Sabemos que o PORTB esta no endereço 6, e se desejarmos acessar o PORTB como se fosse uma variável devemos usar: #byte portb = 6 Vale o mesmo para variáveis representando bits: #bit

T0IF = 0x0B.2

Exemplo:

// T0IF agora é uma variável em C

espera o overflow do timer 0 --> while ( !T0IF );

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 38


Linguagem C para microcontroladores PIC

II.2 - Funções escritas para os PIC’s Neste ítem veremos algumas das funções escritas especialmente para a família PIC. Uma descrição completa de todas as funções pode ser encontrado no manual do usuário da CCS.

II.2.1 - Funções matemáticas f = ACOS (x);

// ArcoCosseno.

f deve ser float e -1 < x , +1

f = ASIN (x);

// ArcoSeno.

f deve ser float e -1 < x , +1

f = ATAN (x);

// ArcoTangente.

f deve ser float e -PI/2 < x , +PI/2

f = LOG (x);

// Lob base E

f deve ser float e x > 0 (limitado)

f = LOG10 (x);

// Log base 10.

f deve ser float e x > 0 (limitado)

f = SQRT(x);

// Raiz quadrada.

f deve ser float e x > 0

f = FLOAT EXP(x); // Exponencial E^x f deve ser float e x > 0

II.2.2 - Funções de manipulação de bit 1)

bit_clear (variável , bit)

(observe o “ _ “ entre as palavras)

Zera o bit indicado na variável indicada. Como podemos ter variáveis de 8 ou 16 bits, o número do bit pode ir de 0~7 ou de 0~15. Exemplo: char x; x = 0b10001000 bit_clear(x,7);

2)

bit_set (variável , bit)

// x = 00001000

(observe o “ _ “ entre as palavras)

Seta o bit indicado na variável indicada. Como podemos ter variáveis de 8 ou 16 bits, o número do bit pode ir de 0~7 ou de 0~15. Exemplo: char x; x = 0b10001000 bit_set(x,0); // x = 10001001

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 39


Linguagem C para microcontroladores PIC

3)

bit_test (variável , bit)

(observe o “ _ “ entre as palavras)

Efetua um teste no bit indicado na variável indicada. Como podemos ter variáveis de 8 ou 16 bits, o número do bit pode ir de 0~7 ou de 0~15. Se o bit estiver em ‘1’ a função retorna um verdadeiro (true) e caso contrário retorna falso (false). Para o caso de desejamos testar se esta em ‘0’ basta usarmos um ! (NOT lógico) antes do teste. Exemplo: if ( bit_test(x,1) || ! bit_test(x,0) ) { ...... } 4)

// Se o bit 1 de x for // OU (||) // o bit 0 de x for 0 // executa o bloco.

1

b = input( pino ) Lê o estado do pino indicado. Exemplo:

espera o pino RB0 ir de 0 para 1.

while ( ! input (pin_b0) );

// realiza bit test . É o teste Ideal.

while ( pin_b0 == 0);

// realiza teste logico em byte

ou

Observação: os nomes de pinos e outras constantes serão vistos ao final e estão no arquivo .H correspondente ao chip utilizado. 5)

output_bit( pino, valor )

(observe o “ _ “ entre as palavras)

Escreve 0 ou 1 no pino indicado. Exemplo:

gera um pulso positivo em RA2

output_bit ( pin_a2 , 1); output_bit ( pin_a2 , 0 );

// faz RA2 = 1 // faz RA2 = 0

Observação: os nomes de pinos e outras constantes serão vistos ao final e estão no arquivo .H correspondente ao chip utilizado. 6) Output_High( pino ) e Output _Low ( pino )

(observe o “ _ “ entre as palavras)

Equivalem ao bsf e ao bcf do assembler. Servem para setar ou zerar um pino de I/O. VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 40


Linguagem C para microcontroladores PIC

II.2.3 - Funções de tempo

(observe o “ _ “ entre as palavras)

1)

Gera um delay equivalente a ‘x’ ciclos de instrução.

Delay_cycles ( x );

Exemplo:

2)

delay_cycles (1); delay_cycles (4);

Delay_Ms ( x ) Ÿ Ÿ

// equivale a 1 nop // equivale a 4 nop’s

Gera um delay de ‘x’ milissegundos.

Se ‘x’ for constante, pode variar de 1 à 65535. Se ‘x’ for uma variável, seu valor pode variar de 1 à 255.

O programa deve conter a diretiva #use delay vista em II.1.12 antes de se usar esta função. Exemplo:

Pulsa o pino RB2 com frequência de 100 Hz while (1) { output_high (pin_b2); delay_ms (5); output_low (pin_b2); delay_ms (5); }

2)

Delay_Us ( x ) Ÿ Ÿ

// RB2 = 1 // espera 5 ms // RB2 = 0 // espera 5 ms

Gera um delay de ‘x’ microsegundos.

Se ‘x’ for constante, pode variar de 1 à 65535. Se ‘x’ for uma variável, seu valor pode variar de 1 à 255.

O programa deve conter a diretiva #use delay antes de se usar esta função. Exemplo:

Gera um sinal em RB2 com nível alto de 150 us e nível baixo de 50 us. x = 150; y = 50; while (1) { output_high (pin_b2); // RB2 = 1 delay_us (x); // espera ‘x’ us output_low (pin_b2); // RB2 = 0 delay_us (y); // espera ‘y’ us }

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 41


Linguagem C para microcontroladores PIC

II.2.4 - Funções para interrupções

1) enable_interrupts ( nível )

(observe o “ _ “ entre as palavras)

Permite habilitar interrupções individualmente ou globalmente. quando habilitando globalmente apenas o GIE será afetado, e não as habilitações individuais. Os principais níveis são os seguintes: global (GIE), int_rb (RB4~7),

int_ext (RB0), int_ad (16C7x),

int_rtcc (timer 0), int_eeprom (16F84).

Exemplo: habilitando a interrupção do timer 0 e do A/D do 16C711. enable_interrupts (int_rtcc); enable_interrupts (int_ad); enable_interrupts (global);

2) disable_interrupts ( nível )

// faz T0IE = 1 // faz ADIE = 1 // faz GIE = 1

(observe o “ _ “ entre as palavras)

Funciona de forma semelhante ao “enable_interrupts ()”, desabilitando individualmente ou globalmente as interrupções. Exemplo: desabilitando todas, desabilitando a do timer 0 e habilitando a externa e reabilitando todas. disable_interrupts (global); disable_interrupts (int_rtcc); enable_interrupts (int_ext); enable_interrupts (global);

3) ext_int_edge ( tipo )

// faz GIE = 0 // faz T0IE = 0 // faz INTE = 1 // faz GIE = 1

(observe o “ _ “ entre as palavras)

A variável tipo indica se a interrupção externa será reconhecida na descida do sinal em RB0 ( tipo = H_TO_L ) ou na subida do sinal ( tipo = L_TO_H ). Exemplo: reconhece interrupção externa na subida. ext_int_edge (L_TO_H); enable_interrupts (int_ext);

VIDAL

// faz INTEDG = 1 // faz INTE = 1

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 42


Linguagem C para microcontroladores PIC

II.2.5 - Funções para o canal A/D 1)

read_adc()

(apenas 16C7X e 16F87X) (observe o “ _ “ entre as palavras)

Lê o canal analógico do chip. Antes de usar esta função devemos usar “setup_adc()” e “set_adc_channel()” e setup_adc_ports(). Exemplo: Temperatura = read_adc();

2)

setup_adc ( modo )

// lê o canal já ajustado e escreve // na variável Temperatura.

(observe o “ _ “ entre as palavras)

Ajusta o conversor A/D. Os modos possíveis são: adc_off, adc_clock_div_32,

3)

adc_clock_div_2, adc_clock_div_internal,

set_adc_channel ( canal )

adc_clock_div_8,

(observe o “ _ “ entre as palavras)

Especifica qual o canal que será lido pela função read_adc(). 4)

setup_adc_ports ( ajuste )

(observe o “ _ “ entre as palavras)

Ajusta os pinos para serem entradas analógicas ou não. Seu ajuste depende de cada chip em particular, devendo o programador cuidar para não escolher um ajuste errado para um certo modelo (consultar o arquivo .H correspondente). Para o 16C711, temos os seguintes ajustes: NO_ANALOGS ALL_ANALOG ANALOG_RA3_REF RA0_RA1_ANALOG

Pinos RA0~RA3 I/O digital Pinos RA0~RA3 entradas analógicas Vref = Vdd Pinos RA0~RA2 entradas analógicas Vref = Tensão em RA3 Pinos RA0 e RA1 analogicos, RA2 e RA3 I/O digital. Vref = Vdd

Exemplo: Lendo o canal 2 do 16C711 setup_port_a( ALL_ANALOG ); setup_adc( ADC_CLOCK_INTERNAL ); set_adc_channel( 2 ); value = Read_ADC(); VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 43


Linguagem C para microcontroladores PIC

II.2.6 - Funções para EEPROM interna (apenas 16F8X e 16F87X)

1)

Read_Eeprom ( endereço )

(observe o “ _ “ entre as palavras)

Lê o dado presente na posição endereço da eeprom interna. O endereço vai de 0 à 3. Exemplo:

2)

Posicao_0 = read_eeprom(0);

Write_Eeprom ( endereço , valor )

(observe o “ _ “ entre as palavras)

Escreve no endereço da eeprom interna o valor indicado. Importante: Esta instrução leva em média 10 ms para ser finalizada. Para cada processador ou versões mais atualizadas consultar o manual apropriado.

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 44


Linguagem C para microcontroladores PIC

II.2.7 - Funções de uso geral Veremos neste item várias funções de uso geral desenvolvidas para os pic’s, como entrada e saída serial por software, ajuste de registros e outros.

1)

get_timer0()

(observe o “ _ “ entre as palavras)

Le o valor atual do registro TMR0. Exemplos:

2)

if ( get_timer0() == 0 ) { ..... }

// executa o bloco se o registro // TMR0 = 0

Valor_do_timer = get_timer0();

// copia o registro TMR0 para a variável

set_timer0 ( valor )

(observe o “ _ “ entre as palavras)

Ajusta o valor do registro TMR0. Lembre-se que sempre que escrevemos no registro TMR0 a contagem fica suspensa por dois ciclos de instrução. Exemplo:

Se o registro TMR0 for maior que 100 zera o registro.

if ( get_timer0( ) > 100 ) set_timer0( 0 );

3)

port_b_pullups ( opção )

(observe o “ _ “ entre as palavras)

Controla os pull-ups da porta B ( apenas para os bits ajustados entrada). Temos como opção TRUE, ligando os pull-ups ( RBPU\ = 0) e FALSE, desligando os pull-ups ( RBPU\ = 1 ).

4)

restart_wdt()

(observe o “ _ “ entre as palavras)

Reseta o watch dog. Equivale ao clrwdt do assembler.

5)

Sleep()

(observe o “ _ “ entre as palavras)

Equivale a instrução sleep do assembler. VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 45


Linguagem C para microcontroladores PIC

6)

getc(), getch() OU getchar()

(*)

São a mesma função. Entra numa rotina para esperar a chegada de um caractere pelo pino RCV definido na diretiva #use RS232. Exemplo: espera a chegada do caractere ‘A’ while ( getchar() != ‘A’ );

7)

putc( valor ) OU putchar(valor )

(*)

São a mesma função. Envia “valor” serialmente pelo pino XMIT definido na diretiva #use RS232. Exemplo: Enviar a palavra ‘OLA’ pelo serial. putchar ( ‘O’ ); putchar ( ‘L’ ); putchar ( ‘A’ ); ( * ) Observação: Estas funções não usam o canal serial de hardware presente em alguns modelos, mas sim funções escritas para este fim. Desta forma devemos levar em conta que embora ocupem apenas uma linha de código, podem demorar vários milissegundos para serem executadas.

8)

set_tris_X ( ajuste )

(observe o “ _ “ entre as palavras)

Ajusta o registro TRIS do port X indicado. Deve ser usado sempre que a diretiva #fast_io ( port ) for utilizada, pois estas determinam nosso controle sobre os ports. Exemplo:

Ajustando todos os bits do PORTB como saída set_tris_b ( 0 ); Ajustando os bits 0, 1 e 4 do PORTA como saída set_tris_a ( 0b11101100 );

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 46


Linguagem C para microcontroladores PIC

9)

restart_cause()

(observe o “ _ “ entre as palavras)

Esta função retorna o motivo do último reset. Seus valores são: wdt_from_sleep mclr_from_sleep

wdt_timeout normal_power_up

Exemplo: switch ( restart_cause ) { case wdt_from_sleep: { “Instruções para este caso” Break; // necessário } case wdt_timeout: { “Instruções para este caso” Break; // necessário } case mclr_from_sleep: { “Instruções para este caso” Break; // necessário } case normal_power_up: { “Instruções para este caso” Break; // necessário } }

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 47


Linguagem C para microcontroladores PIC

11)

Setup_counters ( ajuste_do_timer_0 , ajuste_do_prescaler ) (observe o “ _ “ entre as palavras)

Ajusta o modo de funcionamento do timer 0 (aqui chamado de rtcc) e o direcionamento / divisão do prescaler. Lembre-se que com o prescaler direcionado para o timer 0 o período nominal do watch dog é de 18 ms, e se o prescaler estiver direcionado para o watch dog o clock do timer não será dividido ( 1:1 ). Constantes para ajuste do timer 0: rtcc_internal rtcc_ext_h_to_l rtcc_ext_l_to_h

--> timer 0 clock interno --> timer 0 clock externo, transição de 1 para 0 --> timer 0 clock externo, transição de 0 para 1

Constantes para ajustes do prescaler: rtcc_div_2 rtcc_div_4 rtcc_div_8 rtcc_div_16 rtcc_div_32 rtcc_div_64 rtcc_div_128 rtcc_div_256

--> Prescaler para o timer 0, dividindo por 2 --> Prescaler para o timer 0, dividindo por 4 --> Prescaler para o timer 0, dividindo por 8 --> Prescaler para o timer 0, dividindo por 16 --> Prescaler para o timer 0, dividindo por 32 --> Prescaler para o timer 0, dividindo por 64 --> Prescaler para o timer 0, dividindo por 128 --> Prescaler para o timer 0, dividindo por 256

(*) (*) (*) (*) (*) (*) (*) (*)

(*) watch dog em 18 ms wdt_18ms

--> watch dog em 18 ms e timer 0 em 1:1

wdt_36ms wdt_72ms wdt_144ms wdt_288ms wdt_576ms wdt_1152ms wdt_2304ms

--> watch dog em 36 ms e timer 0 em 1:1 --> watch dog em 72 ms e timer 0 em 1:1 --> watch dog em 144 ms e timer 0 em 1:1 --> watch dog em 288 ms e timer 0 em 1:1 --> watch dog em 576 ms e timer 0 em 1:1 --> watch dog em 1152 ms e timer 0 em 1:1 --> watch dog em 2304 ms e timer 0 em 1:1

Exemplo: Ajustando o timer modo interno em 1:4, teremos watch dog com período de 18 ms. setup_counters ( rtcc_internal, rtcc_div_4 );

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 48


Linguagem C para microcontroladores PIC

II.4 - Personalizando o compilador Vamos estudar aqui como personalizar o compilador para nossas preferencias, como por exemplo renomear os pinos de I/O do chip e ajustar funções pré-definidas para serem mais faceis de escrever. II.4.1 - Redefinindo os nomes dos pinos de I/O Conforme já vimos, os pinos são chamados de PIN_xx, onde ‘xx’ define o nome do mesmo. Para o nosso estudo e para o pic 16C63, que é o pic da versão demo, vamos renomea-los para os nomes usuais. #define RA0 #define RA1 #define RA2 #define RA3 #define RA4

40 41 42 43 44

// original PIN_A0 // original PIN_A1 // original PIN_A2 // original PIN_A3 // original PIN_A4

#define RB0 #define RB1 #define RB2 #define RB3 #define RB4 #define RB5 #define RB6 #define RB7

48 49 50 51 52 53 54 55

// original PIN_B0 // original PIN_B1 // original PIN_B2 // original PIN_B3 // original PIN_B4 // original PIN_B5 // original PIN_B6 // original PIN_B7

#define RC0 #define RC1 #define RC2 #define RC3 #define RC4 #define RC5 #define RC6 #define RC7

56 57 58 59 60 61 62 63

// original PIN_C0 // original PIN_C1 // original PIN_C2 // original PIN_C3 // original PIN_C4 // original PIN_C5 // original PIN_C6 // original PIN_C7

De agora em diante podemos apenas chama-los de RA3, RB2, ...

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 49


Linguagem C para microcontroladores PIC

II.4.2 - Redefinindo algumas funções para nomes mais simples Para facilitar a escrita e a memorização vamos redefinir algumas funções mais usuais (ver arquivo mudancas.inc em ‘\0DiscoEx’. #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define

TrisA(X) TrisB(X) TrisC(X) ClearBit(x) SetBit(x) ReadBit(x) timer0(modo,presc) Enable(X) EnableAll DisableAll NOP Ms(x) Us(x) PullUpOn PullUpOff ext_0 ext_1

VIDAL

set_tris_A (X) set_tris_B (X) set_tris_C (X) output_low (x) output_high (x) input (x) setup_counters(modo,presc) enable_interrupts(X) enable_interrupts(global) disable_interrupts(global) delay_cycles(1) delay_ms(x) delay_us(x) port_b_pullups(true) port_b_pullups(false) ext_int_edge(h_to_l) ext_int_edge(l_to_h)

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 50


Linguagem C para microcontroladores PIC

II.4.3 - Anexo 1 - Arquivo 16F84.H

//////// Standard Header file for the PIC16F84 device //////// #device PIC16F84 #nolist /////////////////////////////// I/O definitions for INPUT() and OUTPUT_xxx() #define PIN_A0 40 #define PIN_A1 41 #define PIN_A2 42 #define PIN_A3 43 #define PIN_A4 44 #define PIN_B0 #define PIN_B1 #define PIN_B2 #define PIN_B3 #define PIN_B4 #define PIN_B5 #define PIN_B6 #define PIN_B7

48 49 50 51 52 53 54 55

/////////////////////////////// Useful defines #define FALSE 0 #define TRUE 1 #define BYTE int #define BOOLEAN short int #define getc getch #define getchar getch #define puts(s) {printf(s); putchar(13); putchar(10);} #define putc putchar /////////////////////////////// Constants used for RESTART_CAUSE() #define WDT_FROM_SLEEP 0 #define WDT_TIMEOUT 8 #define MCLR_FROM_SLEEP 16 #define NORMAL_POWER_UP 24 /////////////////////////////// Constants used for SETUP_COUNTERS() #define RTCC_INTERNAL 0 #define RTCC_EXT_L_TO_H 32 #define RTCC_EXT_H_TO_L 48

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 51


Linguagem C para microcontroladores PIC

#define RTCC_DIV_2 0 #define RTCC_DIV_4 1 #define RTCC_DIV_8 2 #define RTCC_DIV_16 3 #define RTCC_DIV_32 4 #define RTCC_DIV_64 5 #define RTCC_DIV_128 6 #define RTCC_DIV_256 7 #define WDT_18MS 8 #define WDT_36MS 9 #define WDT_72MS 10 #define WDT_144MS 11 #define WDT_288MS 12 #define WDT_576MS 13 #define WDT_1152MS 14 #define WDT_2304MS 15 #define L_TO_H 0x40 #define H_TO_L 0 #define RTCC_ZERO #define INT_RTCC #define RB_CHANGE #define INT_RB #define EXT_INT #define INT_EXT #define GLOBAL #undef GLOBAL #define GLOBAL #define INT_EEPROM

0x0B20 // Used for ENABLE/DISABLE INTERRUPTS 0x0B20 // Used for ENABLE/DISABLE INTERRUPTS 0x0B08 // Used for ENABLE/DISABLE INTERRUPTS 0x0B08 // Used for ENABLE/DISABLE INTERRUPTS 0x0B10 // Used for ENABLE/DISABLE INTERRUPTS 0x0B10 // Used for ENABLE/DISABLE INTERRUPTS 0x0B80

// Used for ENABLE/DISABLE INTERRUPTS

0x0B80 // Used for ENABLE/DISABLE INTERRUPTS 0x0B40 // Used for ENABLE/DISABLE INTERRUPTS

#list

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 52


Linguagem C para microcontroladores PIC

II.4.4 - Anexo 2 - Arquivo 16C63.H //////// Standard Header file for the PIC16C63 device //////// #device PIC16C63 #nolist /////////////////////////////// I/O definitions for INPUT() and OUTPUT_xxx() #define PIN_A0 40 #define PIN_A1 41 #define PIN_A2 42 #define PIN_A3 43 #define PIN_A4 44 #define PIN_A5 45 #define PIN_B0 #define PIN_B1 #define PIN_B2 #define PIN_B3 #define PIN_B4 #define PIN_B5 #define PIN_B6 #define PIN_B7

48 49 50 51 52 53 54 55

#define PIN_C0 #define PIN_C1 #define PIN_C2 #define PIN_C3 #define PIN_C4 #define PIN_C5 #define PIN_C6 #define PIN_C7

56 57 58 59 60 61 62 63

/////////////////////////////// Useful defines #define FALSE 0 #define TRUE 1 #define BYTE int #define BOOLEAN short int #define getc getch #define getchar getch #define puts(s) {printf(s); putchar(13); putchar(10);} #define putc putchar

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 53


Linguagem C para microcontroladores PIC

/////////////////////////////// Constants used for RESTART_CAUSE() #define WDT_FROM_SLEEP 0 #define WDT_TIMEOUT 8 #define MCLR_FROM_SLEEP 16 #define NORMAL_POWER_UP 24 /////////////////////////////// Constants used for SETUP_COUNTERS() #define RTCC_INTERNAL 0 #define RTCC_EXT_L_TO_H 32 #define RTCC_EXT_H_TO_L 48 #define RTCC_DIV_2 0 #define RTCC_DIV_4 1 #define RTCC_DIV_8 2 #define RTCC_DIV_16 3 #define RTCC_DIV_32 4 #define RTCC_DIV_64 5 #define RTCC_DIV_128 6 #define RTCC_DIV_256 7 #define WDT_18MS 8 #define WDT_36MS 9 #define WDT_72MS 10 #define WDT_144MS 11 #define WDT_288MS 12 #define WDT_576MS 13 #define WDT_1152MS 14 #define WDT_2304MS 15 #define L_TO_H 0x40 #define H_TO_L 0 #define RTCC_ZERO #define INT_RTCC #define RB_CHANGE #define INT_RB #define EXT_INT #define INT_EXT #define GLOBAL

0x0B20 // Used for ENABLE/DISABLE INTERRUPTS 0x0B20 // Used for ENABLE/DISABLE INTERRUPTS 0x0B08 // Used for ENABLE/DISABLE INTERRUPTS 0x0B08 // Used for ENABLE/DISABLE INTERRUPTS 0x0B10 // Used for ENABLE/DISABLE INTERRUPTS 0x0B10 // Used for ENABLE/DISABLE INTERRUPTS 0x0BC0

// Used for ENABLE/DISABLE INTERRUPTS

///////////////////////////////////// Constants used for Timer1 and Timer2 #define T1_DISABLED 0 #define T1_INTERNAL 5 #define T1_EXTERNAL 7 #define T1_EXTERNAL_SYNC 3 #define T1_CLK_OUT 8 #define T1_DIV_BY_1 0 #define T1_DIV_BY_2 0x10 #define T1_DIV_BY_4 0x20 #define T1_DIV_BY_8 0x30 VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 54


Linguagem C para microcontroladores PIC #byte TIMER_1_LOW= 0x0e #byte TIMER_1_HIGH= 0x0f #define T2_DISABLED 0 #define T2_DIV_BY_1 4 #define T2_DIV_BY_4 5 #define T2_DIV_BY_16 6 #byte TIMER_2= 0x11 #define INT_TIMER1 #define INT_TIMER2

0x8C01 0x8C02

// Used for ENABLE/DISABLE INTERRUPTS // Used for ENABLE/DISABLE INTERRUPTS

//////////////////////////////////// Constants used for SETUP_CCP1() #define CCP_OFF 0 #define CCP_CAPTURE_FE 4 #define CCP_CAPTURE_RE 5 #define CCP_CAPTURE_DIV_4 6 #define CCP_CAPTURE_DIV_16 7 #define CCP_COMPARE_SET_ON_MATCH 8 #define CCP_COMPARE_CLR_ON_MATCH 9 #define CCP_COMPARE_INT 0xA #define CCP_COMPARE_RESET_TIMER 0xB #define CCP_PWM 0xC #define CCP_PWM_PLUS_1 0x1c #define CCP_PWM_PLUS_2 0x2c #define CCP_PWM_PLUS_3 0x3c long CCP_1; #byte CCP_1 = 0x15 #byte CCP_1_LOW= 0x15 #byte CCP_1_HIGH= 0x16 #define INT_CCP1

0x8C04

// Used for ENABLE/DISABLE INTERRUPTS

//////////////////////////////////// Constants used for SETUP_CCP2() long CCP_2; #byte CCP_2 = 0x1B #byte CCP_2_LOW= 0x1B #byte CCP_2_HIGH= 0x1C #define INT_CCP2

0x8D01

// Used for ENABLE/DISABLE INTERRUPTS

//////////////////////////////////// Constants used in SETUP_SSP() #define SPI_MASTER 0x20 #define SPI_SLAVE 0x24 #define SPI_L_TO_H 0 #define SPI_H_TO_L 0x10 #define SPI_CLK_DIV_4 0 #define SPI_CLK_DIV_16 1 #define SPI_CLK_DIV_64 2 #define SPI_CLK_T2 3 VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 55


Linguagem C para microcontroladores PIC #define SPI_SS_DISABLED 1 #define SPI_SAMPLE_AT_END 0x80 // Only for some parts #define SPI_XMIT_L_TO_H 0x40 // Only for some parts #define INT_SSP 0x8C08 // Used for ENABLE/DISABLE INTERRUPTS

#define INT_RDA #define INT_TBE

0x8C20 // Used for ENABLE/DISABLE INTERRUPTS 0x8C10 // Used for ENABLE/DISABLE INTERRUPTS

#list

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 56


Linguagem C para microcontroladores PIC

Parte III - Exemplos Nesta parte teremos vários exemplos com o objetivo de fixar os conceitos vistos até agora, inclusive a personalização do compilador. Estes exemplos tem como objetivo apenas mostrar a facilidade de projeto usando-se a linguagem C, e não o desenvolvimento de sistemas práticos ou comerciais.

III.1 - Exemplo 1: Acessando as portas de I/O. Vamos fazer um exemplo simples, que apenas fica incrementando o port B indefinidamente, sendo a taxa de incremento definida pelo overflow do timer 0 em seu minimo de tempo, isto é, clock interno e prescaler 1:1. Não usamos o watch dog e nem rotinas de interrupção. O overflow do timer 0 será detectado por varredura no bit T0IF. Em assembler: list p=16F84

; processador 16F84

__config

_XT_OSC & _CP_OFF & _WDT_OFF & _PWRTE_ON

radix dec include

<P16F84.INC>

org clrf bsf clrf movlw movwf bcf espera: btfss goto estourou: incf bcf goto

; define padrao DECIMAL

0 PORTB STATUS,RP0 TRISB B'11011111' OPTION_REG STATUS,RP0

; portb zerado ; banco 1 ; portb saida ; timer interno 1:1 ; escreve em option ; banco 0

INTCON,T0IF espera

; ve se timer estourou ; nao estourou, volta

PORTB INTCON,T0IF espera

; zera bit de interr ; espera outro estouro

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 57


Linguagem C para microcontroladores PIC

Em C:

( arquivo fonte: incpb.c )

#include <16F84.H> #include <c:\0ccs\mudancas.inc> #fuses XT,NOWDT,NOPROTECT,PUT #use delay(clock=4000000) #use FAST_IO(B)

// Define processador // minhas personalizações // Define os fusíveis // Informa o clock para rotinas // de tempo. // portB sob meu controle

#byte portb = 6 #bit T0IF = 0x0B.2 // ************************************************************************************

main() { portb = 0; set_tris_b ( 0 ); setup_counters ( rtcc_internal, wdt_18ms ); while ( 1 ) { while ( !T0IF ); // espera enquanto T0IF NÃO é 1 T0IF = 0; // zera o flag portb = ++; } } ==============//=============

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 58


Linguagem C para microcontroladores PIC

III.2 - Exemplo 2: Usando a interrupção do Timer 0 Neste exemplo incrementamos o port B indefinidamente, sendo a taxa de incremento definida pela interrupção do timer 0. Para simulação no MpLab, devemos manter a definição ESTUDOS no momento da compilação, de forma a ajustar o prescaler para o timer em 1:4. Para execução real na placa, devemos eliminar ou comentar a definição ESTUDOS no momento da compilação, de forma a ajustar o prescaler para o timer em 1:256, tornando visível a variação do port B. Listagem:

( arquivo fonte: timer0.c )

// ***************************************************************************************** // // Programa para o estudo do compilador C da CCS // // Incrementa o PORTB a cada overflow do timer 0 // Para uso real, "comentar" a definicao ESTUDOS (Timer 1:4). // Para uso no MpLab, manter a definicao ESTUDOS (Timer 1:256). // // Usamos FAST_IO, programando os regs TRIS conforme as necessidades, // gerando codigo menor e com menos uso da RAM interna do que o // STANDARD_IO. // Ajustar FUSES e DELAY conforme necessario. // // ***************************************************************************************** // cabecalho inicial #include <16F84.H> #include <c:\0ccs\mudancas.inc> // minhas personalizações #fuses XT,NOWDT,NOPROTECT,PUT #use delay(clock=4000000) #use fast_io(A) #use fast_io(B) // ***************************************************************************************** #define ESTUDOS #byte portb = 6

VIDAL

// comentar esta linha para gravar no chip

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 59


Linguagem C para microcontroladores PIC

// ***************************************************************************************** void main() { portb = 0; TrisB(0);

// inicia variรกvel em 0

#ifdef ESTUDOS timer0 (RTCC_internal,rtcc_div_4); #else timer 0(RTCC_internal,rtcc_div_256); #endif set_rtcc(0); enable_interrupts(RTCC_ZERO); EnableAll;

// timer 1:4 // timer 1:256

// tmr0 inicia em 0

for(;;) { // nada faz no programa principal } } // ***************************************************************************************** #int_rtcc void TmrOvf() { portb ++; } ==============//=============

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 60


Linguagem C para microcontroladores PIC

III.3 - Exemplo 3: Usando a EEPROM interna do 16F84 Este exemplo é similar ao exemplo 5 do livro. Ao ligar indica nos leds o endereço 32 ( no meio da eeprom ). Pela tecla S0 diminuímos o endereço da eeprom até chegar ao 0. Pela tecla S1 aumentamos o endereço da eeprom até chegar ao 63. Pela tecla S2 gravamos no endereço indicado o valor “endereço OR 128”, fazendo então o bit 7 = 1. Pela tecla S3 lemos o endereço indicado nos leds. Se a gravação foi efetuada com sucesso, devemos enquanto a tecla estiver pressionada ver o endereço COM o led 7 aceso. Listagem:

( arquivo fonte: eeprom.c )

// **************************************************************************************** // // Programa exemplo para o compilador C da CCS. // Gravar e ler da eeprom do 16F84 // // **************************************************************************************** //

Cabeçalho inicial com diretivas de compilação

#include <16F84.H> #include <c:\0ccs\mudancas.inc> #fuses XT,NOWDT,NOPROTECT,PUT

// Define processador // minhas personalizações // Define os fusiveis

#use delay(clock=4000000)

// Informa o clock para rotinas // de tempo.

#use FAST_IO(A) #use FAST_IO(B)

// portA sob meu controle // portB sob meu controle

#byte #byte #bit #bit #bit #bit

// declaracoes de registros de hardware

porta = 5 portb = 6 S0 = porta.0 S1 = porta.1 S2 = porta.2 S3 = porta.3

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 61


Linguagem C para microcontroladores PIC

// **************************************************************************************** main() { valor = 32; leds = valor; portb = leds; TrisB ( 0 );

// endereco inicial da eep // escrevo no port b para visualizacao. // portb saida

while (1) { if ( (S0 == 0) && (valor < 64) ) // se puder, incrementa { valor++; portb = valor; // escrevo no port b para visualizacao. Delay_Ms(250); // bounce } if ( (S1 == 0) && (valor > 0) ) // se puder, decrementa { valor--; portb = valor; // escrevo no port b para visualizacao. Delay_Ms(250); // bounce } if (S2 == 0) write_eeprom(valor, valor | 128); if (S3 == 0) { portb = read_eeprom(valor); while (S3 == 0); portb = valor;

// le e escreve nos leds // espera soltar S3 // recupera os leds // anteriores.

} } } //===========

FIM

VIDAL

===================================

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 62


Linguagem C para microcontroladores PIC

III.3.4 - Exemplo 4:

LCD inteligente com tabela de mensagens em ROM

Neste exemplo temos um display com controlador Hitachi 44780. Devido ao fato do pic não permitir ponteiros para posições em ROM, cada tabela deve ser separadamente escrita. Listagem:

( arquivo fonte: lcd_rom.c )

// ************************************************************************************ // // LCD ligado a PLACA PicLab 1 // Fica mostrando várias mensagens alternadamente // // Data: 18/08/98 // // ************************************************************************************ #include <16F84.H> #include <\0CCS\mudancas.inc> #fuses XT,NOWDT,NOPROTECT,PUT #use delay(clock=4000000) #use FAST_IO(A) #use FAST_IO(B)

// Define processador // minha personalizacao // Define os fusiveis // Informa o clock para rotinas // de tempo. // portA sob meu controle // portB sob meu controle

#byte porta = 5 #byte display = 6

// endereco do port a // display no endereco do port b

#bit #bit

// sinal ENABLE // sinal RS

ENB = porta.2 RS = porta.3

// ************************************************************************************ // Prototipos obrigatorios com ";" no final. void Inicializa(void); void Limpa(void); void Escreve(void); void Mensagem(void); void Linha1(char coluna); void Linha2(char coluna);

// nao recebem e nem devolvem valores

// recebem um char, ja indicando o nome

// ************************************************************************************ // Declaracao de variaveis em RAM char i, posicao, dado; char MensRam [32]; // devo copiar da ROM para a RAM porque // no pic nao posso fazer ponteiros para // a memoria ROM. VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 63


Linguagem C para microcontroladores PIC

// ************************************************************************************ // Declaracao de tabelas constantes em ROM // a string deve ter +1 alem do tamanho real byte const Mensg_1 [33] = { "VIDAL Projetos Personalizados " }; byte const Mensg_2 [33] = { "Cursos sobre PIC com material " }; byte const Mensg_3 [33] = { "1- Basico, ideal para iniciantes" }; byte const Mensg_4 [33] = { "2- Linguagem C para usuarios" }; byte const Mensg_5 [33] = { "3- Especiais sob consulta " }; byte const Mensg_6 [33] = { "Ligue: (011) 6451-8994 " }; // ************************************************************************************ void main() { TRISA(0b11110011); // PortA: Bits 2 e 3 saidas. TRISB(0); // PortB: Saida dados LCD RS = 0; ENB = 0; Inicializa();

// inicializa o display

while(1) { for (i=0; i<32; i++) // copio a mensagem da ROM MensRam[i] = Mensg_1 [i];// para a RAM Mensagem(); // escrevo a mensagem Delay_Ms(1000); // espero 1 seg Limpa(); // limpo o display for (i=0; i<32; i++) MensRam[i] = Mensg_2 [i]; Mensagem(); Delay_Ms(1000); Limpa(); for (i=0; i<32; i++) MensRam[i] = Mensg_3 [i]; Mensagem(); Delay_Ms(1000); Limpa(); for (i=0; i<32; i++) MensRam[i] = Mensg_4 [i]; Mensagem(); Delay_Ms(1000); Limpa(); VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 64


Linguagem C para microcontroladores PIC

for (i=0; i<32; i++) MensRam[i] = Mensg_5 [i]; Mensagem(); Delay_Ms(1000); Limpa(); for (i=0; i<32; i++) MensRam[i] = Mensg_6 [i]; Mensagem(); Delay_Ms(1000); Limpa(); } } // ************************************************************************************ void Inicializa() // sequencia de inicializacao do LCD { RS = 0; display = 56; Delay_Ms(5);

ENB = 1;

ENB = 0;

display = 56; Delay_Ms(5);

ENB = 1;

ENB = 0;

display = 6; Delay_Ms(5);

ENB = 1;

ENB = 0;

display = 14; Delay_Ms(5);

ENB = 1;

ENB = 0;

display = 1; Delay_Ms(5);

ENB = 1;

ENB = 0;

// várias instruções numa // só linha

} // ************************************************************************************ void Mensagem() { Linha1(1); // vou para a linha 1 coluna 1 for (posicao=0;posicao<32;posicao++) { // loop de 32 vezes para Delay_Us(50); // escrever byte a byte display = MensRam [posicao]; RS = 1; ENB = 1; ENB = 0; VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 65


Linguagem C para microcontroladores PIC

Delay_Ms(50);

// 1 ms entre caracteres

if (posicao == 15) // deve ir para a linha 2 { Delay_Us(50); Linha2(1); } } Delay_Us(50); } // ************************************************************************************ void Limpa() { display = 1; // apaga display RS = 0; ENB = 1; ENB = 0; Delay_Ms(2); // 2 ms apos limpar display } // ************************************************************************************ void escreve() { RS = 1; ENB = 1; ENB = 0; Delay_Us(50); } // ************************************************************************************ void Linha1(Coluna) { display = 127+Coluna; // posiciona linha 1 col X RS = 0; ENB = 1; ENB = 0; Delay_Us(50); } // ************************************************************************************ void Linha2(Coluna) { display = 191+Coluna; // posiciona linha 2 col X RS = 0; ENB = 1; ENB = 0; Delay_Us(50); } // >>>>>>>>>>>>>>>>>>>>>>>>>>>>> FIM

VIDAL

<<<<<<<<<<<<<<<<<<<<<<<<<<

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 66


Linguagem C para microcontroladores PIC

III.3.5 - Exemplo 5:

Teste da funcao “Putchar()”

Neste exemplo veremos a facilidade de se enviar dados na forma serial com o uso de um função especialmente desenvolvida para este fim. Listagem:

( arquivo fonte: trx_byte.c )

// ********************************************************************** // Programa para enviar serialmente a 9600 bps um byte. // Usa funcao 'putchar' da diretiva #use rs232 // // A cada press de teclas, envia um byte: // S0: envia 55H (01010101) // S1: envia 66H (01100110) // S2: envia ccH (11001100) // S3: envia bbH (10111011) // // 18/08/97 // ********************************************************************** #include <16F84.H> // Define processador #include <\0CCS\mudancas.inc> // minha personalizacao #fuses XT,NOWDT,NOPROTECT,PUT // Define os fusiveis #use delay(clock=4000000) // Informa o clock para rotinas // de tempo. #use FAST_IO(A) // portA sob meu controle #use FAST_IO(B) // portB sob meu controle #use rs232(baud=9600,XMIT=RB7,RCV=RB6,bits=8)

// indispensável

#byte porta = 5 #byte portb = 6

// endereco do port a // endereco do port b

#bit S3 = PORTA.3 #bit S2 = PORTA.2 #bit S1 = PORTA.1 #bit S0 = PORTA.0

// Teclas S0 a S3

#bit Trigger = PORTB.0

// Saida Trigger p/ scope

// ********************************************************************** // Prototipos obrigatorios com ";" no final. void VeTeclas(void); // ********************************************************************** // Declaracao de variaveis em RAM char TrxReg; VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 67


Linguagem C para microcontroladores PIC

// ********************************************************************** void main() { TRISA(255); // PortA: Entrada teclas TRISB(0b01111110); // PortB: RB7 e RB0 saidas Trigger = 0;

// reseta trigger para 0

for (;;) { Delay_Ms(2); VeTeclas(); if (TrxReg < 255) { Trigger = 1; NOP; Trigger = 0; putchar(TrxReg);

// aciona o trigger

// envia o byte

} } } // ********************************************************************** void VeTeclas() { TrxReg = 255; // padrao para nenhuma tecla acionada if (S0 == 0) TrxReg = 0b10101010; if (S1 == 0) TrxReg = 0b01100110; if (S2 == 0) TrxReg = 0b11001100; if (S3 == 0) TrxReg = 0b10111011; }

VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 68


Linguagem C para microcontroladores PIC

III.3.6 - Exemplo 6:

Ligação pic à pic serial.

Este exemplo será dividido em dois módulos: A) Transmissão Ao reset a variável valor é inicializada com o 64. A cada toque na tecla S0 este valor é incrementado, e se chegar a 128 recomeça do 0 (varia de 0 à 127 = 7 bits). Ao pressionar a tecla S1, a variável valor será transmitida serialmente a 9600 bps. Para permitir visualização no osciloscópio um pulso de trigger será gerado a cada byte enviado, no pino RA2. B) Recepção A placa receptora ficará na espera com a função GetChar( ). O dado recebido será escrito no port B, leds 0 à 6, reproduzindo então o dado enviado pela placa transmissora.

Transmissão Listagem:

( arquivo fonte: enviap2p.c )

// ********************************************************************** // // Programa para enviar serialmente a 9600 bps um byte para outra // placa PicLab 2. // // Funcao dos pinos: // RB7: nao usada // RB6~RB0: mostra o valor de 0 a 127 // RA0: incrementa valor (tecla S0) // RA1: envia o valor (tecla S1) // RA2: saida trigger para o scope // RA3: XMIT // RA4: entrada RCV, nao usada // // 18/08/97 // // ********************************************************************** #include <16F84.H> #include <\0CCS\mudancas.inc> #fuses XT,NOWDT,NOPROTECT,PUT #use delay(clock=4000000)

VIDAL

// Define processador // minha personalizacao // Define os fusiveis // Informa o clock para rotinas // de tempo.

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 69


Linguagem C para microcontroladores PIC

#use FAST_IO(A) #use FAST_IO(B)

// portA sob meu controle // portB sob meu controle

#use rs232(baud=9600,XMIT=RA3,RCV=RA4,bits=8)

// INDISPENSĂ VEL

#byte porta = 5 #byte portb = 6

// endereco do port a // endereco do port b

#bit S1 = PORTA.1 #bit S0 = PORTA.0

// teclas S0 e S1 no portA

#bit Trigger = PORTA.2

// Saida Trigger p/ scope

// ********************************************************************** char valor, leds; void main() { TRISA(0b11110011); TRISB(0b10000000); Trigger = 0; valor = 64; leds = valor; portb = leds;

// PortA: 2 e 3 entrada de teclas // PortB: RB7 entrada, RB6~RB0 saidas // reseta trigger para 0

for (;;) { if (S0 == 0) { valor++; if (valor == 128) valor = 0; leds = valor; portb = leds; Delay_Ms(150); } while (S1 == 0) { Trigger = 1; NOP; Trigger = 0; putchar(valor); Delay_Ms(5); }

// aciona o trigger

// envia o byte

} } VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 70


Linguagem C para microcontroladores PIC

Recepção Listagem:

( arquivo fonte: getchar.c )

// ********************************************************************** // // Programa para receber serialmente a 9600 bps um byte vindo de outra placa // Fica esperando chegar (funcao Getchar() do compilador) // // Funcao dos pinos: // RB7: RCV // RB6~RB0: mostra o valor recebido // RA4: XMIT, nao usada // ********************************************************************** #include <16F84.H> #include <\0CCS\mudancas.inc> #fuses XT,NOWDT,NOPROTECT,PUT #use delay(clock=4000000) #use FAST_IO(A) #use FAST_IO(B)

// Define processador // minha personalizacao // Define os fusiveis // Informa o clock para rotinas // de tempo. // portA sob meu controle // portB sob meu controle

#use rs232(baud=9600,XMIT=RA4,RCV=RB7,bits=8) #byte porta = 5 #byte portb = 6

// INDISPENSÁVEL

// endereco do port a // endereco do port b

// ********************************************************************** // Declaracao de variaveis em RAM char valor, leds; void main() { TRISB(0b10000000); // PortB: RB7 entrada, RB6~RB0 saida leds valor = 255; leds = valor; portb = leds;

// leds todos apagados

for (;;) { valor = getchar(); leds = valor; portb = leds; Ms(10); } } VIDAL

Projetos Personalizados - (011) - 6451 - 8994 - www.vidal.com.br 71


Professor Fabiano Saldanha


Professor Fabiano Saldanha


CENTRO FEDERAL DE EDUCAÇÃO TECNOLOGICA DO ESPIRITO SANTO UNED – SERRA / AUTOMAÇÃO INDUSTRIAL

APOSTILA DE: PROGRAMAÇÃO DE MICROCONTROLADORES PIC USANDO LINGUAGEM C

PROF: MARCO ANTONIO

VITORIA, AGOSTO 2006


MICROCONTROLADORES PIC EM C

INTRODUÇÃO ....................................................................................................................... 2 1. INTRODUÇÃO AOS MICROCONTROLADORES ...................................................... 3 1.1. O que é um Microcontrolador? ................................................................................. 3 1.2. Qual a diferença do Microcontroladores e dos Microprocessadores? ...................... 3 1.3. O que significa PIC? ................................................................................................. 3 1.4. Programação do PIC ................................................................................................. 5 1.5. O que é o MpLab?..................................................................................................... 6 2. O PIC 16F877A ................................................................................................................ 7 2.1. NOMENCLATURA DOS PINOS ........................................................................... 8 2.2. QUE É SCHMITT-TRIGGER?.............................................................................. 10 2.3. GERADOR DE RELÓGIO – OSCILADOR ......................................................... 12 2.4. Oscilador XT........................................................................................................... 12 2.5. Oscilador RC........................................................................................................... 13 3. AMBIENTE INTEGRADO DE DESENVOLVIMENTO (IDE) .................................. 16 3.1. CRIAÇÃO DE UM PROJETO:.............................................................................. 17 4. INTRODUÇÃO À LINGUAGEM C – O PRIMEIRO PROGRAMA........................... 25 5. USO DO MPSIM PARA SIMULAÇÃO ....................................................................... 29 6. AS VARIÁVEIS NO COMPILADOR CCS .................................................................. 43 6.1. O que são Variáveis? .............................................................................................. 43 6.2. Tipos de variáveis ................................................................................................... 43 6.3. OS MODIFICADORES.......................................................................................... 43 6.4. Declaração de Variáveis ......................................................................................... 44 6.5. Inicializando Variáveis ........................................................................................... 45 6.6. Variáveis Locais e Globais ..................................................................................... 46 6.7. Constantes ............................................................................................................... 46 Exercícios 6.1:..................................................................................................................... 47 7. OPERADORES EM C.................................................................................................... 48 7.1. O Operador de Atribuição....................................................................................... 48 7.2. Os Operadores Aritméticos..................................................................................... 48 7.3. Operadores Relacionais e Lógicos.......................................................................... 50 7.4. Operadores de Incremento e Decremento............................................................... 51 7.5. Operadores Aritméticos de Atribuição ................................................................... 52 7.6. Operadores Bit a Bit................................................................................................ 53 7.7. Interface com os interruptores ................................................................................ 55 Exercícios 7.1: .............................................................................................................. 59 8. TEMPORIZAÇÃO NO PIC ........................................................................................... 61 8.1. A função Delay:...................................................................................................... 61 8.2. Interrupção Temporizador: ..................................................................................... 64 8.3. O temporizador TIMER 0....................................................................................... 64 Exercícios 8.1: .............................................................................................................. 68 9. SINAIS ANALÓGICOS NO PIC................................................................................... 70 9.1. CONCEITOS BÁSICOS DOS CONVERSORES ................................................. 70 9.2. Tratamento de Entradas Analógicas no PIC ........................................................... 72 Exemplo 9.2: ....................................................................................................................... 74 Exercícios:........................................................................................................................... 76 10. COMUNICAÇÃO SERIAL ....................................................................................... 79 10.1. Comunicação Serial Síncrona x Comunicação Serial Assíncrona...................... 79 10.2. O RS232 no PIC.................................................................................................. 80 EXEMPLO:........................................................................................................................ 81 Exercícios: ....................................................................................................................... 82 Microcontroladores - PIC

1


MICROCONTROLADORES PIC EM C

INTRODUÇÃO Esta pequena apostilha esta orientada para os profissionais técnicos que necessitam de conhecimentos básicos do PIC. Abordaremos noções da estrutura do PIC16F877A e depois nosso foco será o estudo da linguagem C para microcontroladores. A linguagem C provavelmente é a linguagem mais conhecida e tem muitas vantagens sobre a linguagem assembler no nível técnico. Primeiramente trataremos sobre a instalação dos programas necessários para poder trabalhar. O compilar CCS será o escolhido e o entorno ou editor será o MatLab V 7.4. Uma vez com nosso ambiente instalado abordaremos as características básicas do PIC 16F877A. È importante mencionar que usaremos o módulo de desenvolvimento SD-1700 que atualmente esta descontinuado, mas é considerado pelo autor como uma excelente ferramenta. O estudo da linguagem C será focado à compreensão das funções básicas e sua relação com o circuito de teste. Com esses espera-se que o leitor consiga entender a infinita utilizada destes magníficos dispositivos.

Microcontroladores - PIC

2


MICROCONTROLADORES PIC EM C

1. INTRODUÇÃO AOS MICROCONTROLADORES

1.1.

O que é um Microcontrolador?

Podemos definir o microcontrolador como um "pequeno" componente eletrônico, dotado de uma "inteligência" programável, utilizado no controle de processos lógicos. O controle de processos deve ser entendido como o controle de periféricos, tais como: led´s, botões, display's de cristal líquido (LCD), resistências, relês, sensores diversos (pressão, temperatura, etc.) e muitos outros. São chamados de controles lógicos pois a operação do sistema baseia-se nas ações lógicas que devem ser executadas, dependendo do estado dos periféricos de entrada e/ou saída.

1.2.

Qual a diferença do Microcontroladores e dos Microprocessadores?

Um microcontrolador difere de um microprocessador em vários aspectos. Primeiro e o mais importante, é a sua funcionalidade. Para que um microprocessador possa ser usado, outros componentes devem-lhe ser adicionados, tais como memória e componentes para receber e enviar dados. Em resumo, isso significa que o microprocessador é o verdadeiro coração do computador. Por outro lado, o microcontrolador foi projectado para ter tudo num só. Nenhuns outros componentes externos são necessários nas aplicações, uma vez que todos os periféricos necessários já estão contidos nele. Assim, nós poupamos tempo e espaço na construção dos dispositivos.

1.3.

O que significa PIC?

É o nome que a Microchip adotou para a sua família de microcontroladores, sendo que a sigla significa Controlador Integrado de Periféricos. O PIC é um circuito integrado produzido pela Microchip Technology Inc., que pertence da categoria dos microcontroladores, ou seja, um componente integrado

Microcontroladores - PIC

3


MICROCONTROLADORES PIC EM C

que em um único dispositivo contem todos os circuitos necessários para realizar um completo sistema digital programável. Internamente dispõe de todos os dispositivos típicos de um sistema microprocessado, ou seja: Uma CPU (Central Processor Unit ou seja Unidade de Processamento Central) e sua finalidade é interpretar as instruções de programa. Uma memória PROM (Programmable Read Only Memory ou Memória Programavel Somente para Leitura) na qual ira memorizar de maneira permanente as instruções do programa. Uma memória RAM (Random Access Memory ou Memoria de Accesso Aleatório) utilizada para memorizar as variáveis utilizadas pelo programa. Uma serie de LINHAS de I/O para controlar dispositivos externos ou receber pulsos de sensores, chaves, etc. Uma serie de dispositivos auxiliares ao funcionamento, ou seja gerador de clock, bus, contador, etc. A presença de todos estes dispositivos em um espaço extremamente pequeno, da ao projetista ampla gama de trabalho e enorme vantagem em usar um sistema microprocessado, onde em pouco tempo e com poucos componentes externos podemos fazer o que seria oneroso fazer com circuitos tradicionais. O PIC esta disponível em uma ampla gama de modelos para melhor adaptar-se as exigencias de projetos especificos, diferenciando-se pelo numero de linha de I/O e pelo conteudo do dispositivo. Inicia-se com modelo pequeno identificado pela sigla PIC12Cxx dotado de 8 pinos, até chegar a modelos maiores com sigla PIC17Cxx dotados de 40 pinos. Uma descrição detalhada da tipologia do PIC é disponivel no site da Microchip acessavel via , onde conseguimos encontrar grandes e variadas quantidades de informações tecnicas, software de apoio, exemplos de aplicações e atualizações disponiveis. Para o nosso curso usaremos um modelo de PIC o PIC16F877. Este é dotado de 40 pinos.

Microcontroladores - PIC

4


MICROCONTROLADORES PIC EM C

1.4.

Programação do PIC

Como o PIC é um dispositivo programável, o programa tem como objetivo deixar instruções para que o PIC possa fazer atividades definidas pelo programador. Um programa é constituído por um conjunto de instruções em seqüência, onde cada uma identificara precisamente a função básica que o PIC ira executar. Um programa escrito em linguagem assembler ou em C pode ser escrito em qualquer PC utilizando-se qualquer processador de texto que possa gerar arquivos ASCII(Word, Notpad etc). Um arquivo de texto que contenha um programa em assembler é denominado de source ou codigo assembler. Uma vez preparado o nosso código assembler ou C(veremos mais adiante), iremos precisar de um programa para traduzir as instruções mnemônicas e todas as outras formas convencionais com que escrevemos o nosso código em uma serie de números (o opcode) reconhecível diretamente pelo PIC. Este programa se chama compilador assembler ou assemblador, o compilador usado neste curso será o PCWH. Na figura seguinte está esquematizado o fluxograma de operações e arquivos que devera ser realizado para passar um código assembler a um PIC a ser programado.

Ilustração 1: Fluxograma de compilação de um programa e gravação de um PIC

Microcontroladores - PIC

5


MICROCONTROLADORES PIC EM C

Para poder programar um PIC precisaremos de um Editor (Mplab ou o PCWH), um compilador (PCWH) e um programador (PICStar Plus). 1.5.

O que é o MpLab?

O MpLab é um ambiente integrado de desenvolvimento (I.D.E.: Integrated Development Environment). No mesmo ambiente o usuário pode executar todos os procedimentos relativos ao desenvolvimento de um software para o PIC (edição, compilação, simulação, gravação), tornando o trabalho do projetista mais produtivo. Este programa é totalmente gratuito e pode ser pego no site www.microchip.com. Edição O MpLab possui um editor de texto para seus programas que possui diversas ferramentas de auxílio como localizar, substituir, recortar, copiar e colar. Compilação Compilar significa traduzir um programa escrito em assembly (mneumônicos) para linguagem de máquina (números). A compilação gera um arquivo com extensão .hex (hexadecimal) a partir dos arquivos de código fonte (.asm) e de projeto (.pjt). É o conteúdo do arquivo hexadecimal que é gravado na memória de programa do PIC. Simulação O MpLab possui ferramentas para simulação do programa no próprio computador, possibilitando a execução passo a passo, visualização e edição do conteúdo dos registradores, edição de estímulos (entradas), contagem de tempo de execução, etc. Gravação Para que o programa seja executado no microcontrolador, o arquivo hexadecimal deve ser gravado no PIC. O MpLab oferece suporte aos gravadores fabricados pela Microchip. Emulação A Emulação é um recurso de desenvolvimento que possibilita testes em tempo real. O MpLab oferece suporte ao hardware necessário para estar emulando um determinado programa. Esta emulação é feita conectando-se (através do hardware mencionado) o computador ao sistema projetado, no lugar do PIC

Microcontroladores - PIC

6


MICROCONTROLADORES PIC EM C

2. O PIC 16F877A Dentro de todos os PICs este é um dos que apresenta mais recursos e se adpata as necessidades de nosso curso, entre suas caraterísticas principais podemos citar: •

Microcontrolador de 40 pinos, o que possibilita a montagem de um hardware complexo e capaz de interagir com diversos recursos e funções ao mesmo tempo.

33 portas configuráveis como entrada ou saída.

15 interrupções disponíveis.

Memória de programação E²PROM FLASH, que permite a gravação rápida do programa diversas vezes no mesmo chip, sem a necessidade de apagá-lo por meio de luz ultravioleta, como acontece nos microcontroladores de janela;

Memória de programa com 8Kwoeds, com capacidade de escrita e leitura pelo própio código interno;

Memória E²PROM (não volátil) interna com 256 bytes;

Memória RAM com 368 bytes;

Tês timers (2x8bits e 1x16 bits);

Comunicações seriais: SPI, I²C e USART;Conversores analógicos de 10 bits (8x) e comparadores analógicos (2x);

Conversores analógicos de 10 bits (8x) e comparadores analógicos (2x);

Dois módulos CCP: Capture, Compare e PWM;

Microcontroladores - PIC

7


MICROCONTROLADORES PIC EM C

2.1.

NOMENCLATURA DOS PINOS

Nome do Pino

I/O/P

TIPO

OSC1/CLKIN

Núm. Pino 13

Descrição

I

ST/CMOS

OSC2/CLKOUT

14

O

-

Entrada para cristal. Osciladores externos(RC) Saída para cristal. Os cristais ou resonadores devem ser ligados aos pinos OSC1 e OSC2. Saída com onda quadrada em ¼ da frequencia imposta em OSC1 quando em modo RC. Essa frequencia equivale aos ciclos de máquina internos.

MCLR/Vpp

1

I/P

ST

Master Clear (reset) externo. O uC só funciona quando este pino encontra-se em nível alto. Entrada para tensão de programação 13V.

Vss

12/31

P

-

GND

Vdd

11/32

P

-

Alimentação positiva PORTA (I/O digitais bidirecionais e sistema analógico)

RA0/AN0

2

I/0

TTL

RA0: I/O digital ou entrada analógica AN0

RA1/AN1

3

I/0

TTL

RA1: I/O digital ou entrada analógica AN1

RA2/AN2/VREF/CVREF

4 -

I/0 -

TTL -

RA2: I/O digital ou entrada analógica AN2 ou tensão negativa de referência analógica.

RA3/AN3 /VREF+

5 -

I/0 -

TTL -

RA3: I/O digital ou entrada analógica AN3 ou tensão positiva de referência analógica.

RA4/TOCKI /C10OUT

6 -

I/0 -

ST -

RA4: I/O digital (open drayn), ou entrada externa do contador TMR0 ou saída do comparador 1.

RA5/SS/AN4 /C2OUT

7

I/0

TTL

RA5: I/O digital ou entrada analógica AN4 ou habilitação externa (slave select) para comunicação SPI ou saída do comparador 2. PORTB: (I/Os digitais bidirecionais). Todos os pinos deste PORT possuem pull-up que podem ser ligado ou desligados pelo software:

RB0/INT

33

I/O

TTL/ST(1)

RB1

34

I/O

TTL

RB1: I/O digital.

RB2

35

I/O

TTL

RB2: I/O digital.

RB3/PGM

36

TTL

RB3: I/O digital ou entrada para programação em baixa tensão (5v).

RB4

37

TTL

RB4: I/O digital com interrupção por mudança de estado

RB5

38

TTL

RB6/PGC

39

RB7/PGD

40

I/O

Microcontroladores - PIC

RB0: I/O digital com interrupção externa.

RB5: I/O digital com interrupção por mudança de estado (2)

TTL/ST

RB6: I/O digital com interrupção por mudança de estado ou clock da programação serial ou pino de in-circuit debugger.

TTL/ST(2)

RB7: I/O digital com interrupção por mudança de estado ou data da programação serial ou pino de in-circuit debugger.

8


MICROCONTROLADORES PIC EM C PORTC (I/Os digitais bidirecionais): RC0/T1OSO /TICK1

15

I/O

ST

RC0: I/O digital ou saída do oscilador externo para TMR1 ou entrada de incremento para TMR1.

RC1/T1OSI /CCPS

16

I/O

ST

RC1: I/O digital ou saída do oscilador externo para TMR1 ou entrada de Capture2 ou saídas para Compare2/PWM2.

RC2/CCP1

17

I/O

ST RC2: I/O digital ou entrada do Capture1 ou saídas para Compare1/PWM1.

RC3/SCK/SCL

18

I/O

ST

RC3: I/O digital ou entrada/saída de clock para comunicação serial SPI/I²C.

RC4/SDI/DAS

23

I/O

ST

RC4: I/O digital ou entrada de dados para SPI ou via de dados (entrada/saída) para I²C.

RC5/SDO

24

I/O

ST

RC5: I/O digital ou saída de dados para SPI.

RC6/TX/CK

25

I/O

ST

RC6: I/O digital ou TX (transmissão) para comunicação USART assíncrona ou data para comunicação síncrona.

RC7/RX/DT

26

I/O

ST

RD0/PSP0

19

I/O

TTL/ST(3)

RD0: I/O digital ou dado 0 (comunicação paralela).

RD1/PSP1

20

I/O

TTL/ST(3)

RD1: I/O digital ou dado 1 (comunicação paralela).

RD2/PSP2

21

I/O

TTL/ST(3)

RD2: I/O digital ou dado 2 (comunicação paralela).

RD3/PSP3

22

I/O

TTL/ST(3)

RD3: I/O digital ou dado 3 (comunicação paralela).

RD4/PSP4

27

I/O

TTL/ST(3)

RD4: I/O digital ou dado 4 (comunicação paralela).

RD5/PSP5

28

I/O

TTL/ST(3)

RD5: I/O digital ou dado 5 (comunicação paralela).

RD6/PSP6

29

I/O

TTL/ST(3)

RD6: I/O digital ou dado 6 (comunicação paralela).

RD7/PSP7

30

I/O

TTL/ST(3)

RD7: I/O digital ou dado 7 (comunicação paralela). PORTE (I/Os digitais bidirecionais e sistema analógico):

RE0/RD/AN5

8

I/O

TTL/ST(3)

RE0: I/O digital ou controle de leitura da porta paralela ou entrada analógica AN5.

RE0/RD/AN6

9

I/O

TTL/ST(3)

RE1: I/O digital ou controle de leitura da porta paralela ou entrada analógica AN6.

RE0/RD/AN7

10

I/O

TTL/ST(3)

RE2: I/O digital ou controle de leitura da porta paralela ou entrada analógica AN7.

RC7: I/O digital ou RX (recepção) para comunicação USART assíncrona ou data para comunicação síncrona. PORTD (I/Os digitais bidirecionais) ou porta de comunicação paralela:

Legenda: I =Input (entrada) I/O = Input/OutPut (entrada ou saída) - = não utilizado ST = Entrada tipo Schmitt trigger

Microcontroladores - PIC

O = Output(saída) P = Power(Alimentação) TTL = Entrada tipo TTL

9


MICROCONTROLADORES PIC EM C

Notas: (1): Esta entrada é do tipo ST, somente quando configurado como interrupção externa. (2): Esta entrada é do tipo ST, somente durante o modo de programação serial. (3): Esta entrada é do tipo ST, quando configurado como I/O de uso geral e TTL quando usado em modo de porta paralela. (4): Esta entrada é ST quando em modo RC e CMOS nos demais casos. 2.2.

QUE É SCHMITT-TRIGGER?

Observe o gráfico de transição da porta lógica "NÃO" abaixo.

Verifica-se pelo gráfico que a transição de nível lógico baixo (LOW) para alto (HIGH) é muito longa, implicando na oscilação da saída da porta lógica "NÃO" à medida que o sinal de entrada passa pelo intervalo indefinido (1 ou 0), transportando para saída o mesmo efeito.

Microcontroladores - PIC

10


MICROCONTROLADORES PIC EM C

Um dispositivo interessante para a solução deste problema lógico, são as portas Schmitt-trigger. Portanto fica claro que não existe apenas porta lógica "NÃO" Schmitt-trigger, existem outras portas com essa tecnologia. Porta lógica Schmitt-trigger é projetada para aceitar sinais cuja a transição é lenta e garante na saída nível lógico livre de oscilações.

Analisando o gráfico da figura anterior observa-se que a saída muda de nível lógico alto (HIGH) para baixo (LOW) quando a tensão de transição é superior a VT + (Positive-going threshold - limiar de tenso positiva de transição).

Microcontroladores - PIC

11


MICROCONTROLADORES PIC EM C

2.3.

GERADOR DE RELÓGIO – OSCILADOR

O circuito do oscilador é usado para fornecer um relógio (clock), ao microcontrolador. O clock é necessário para que o microcontrolador possa executar um programa ou as instruções de um programa. Tipos de osciladores O PIC pode trabalhar com quatro configurações de oscilador. Uma vez que as configurações com um oscilador de cristal e resistência-condensador (RC) são aquelas mais frequentemente usadas, elas são as únicas que vamos mencionar aqui. Quando o oscilador é de cristal, a designação da configuração é de XT, se o oscilador for uma resistência em série com um condensador, tem a designação RC. Isto é importante, porque há necessidade de optar entre os diversos tipos de oscilador, quando se escolhe um microcontrolador.

2.4.

Oscilador XT

O oscilador de cristal está contido num envólucro de metal com dois pinos onde foi escrita a freqüência a que o cristal oscila. Dois condensadores cerâmicos devem ligar cada um dos pinos do cristal à massa. Casos há em que cristal e condensadores estão contidos no mesmo encapsulamento, é também o caso do ressonador cerâmico ao lado representado. Este elemento tem três pinos com o pino central ligado à massa e os outros dois pinos ligados aos pinos OSC1 e OSC2 do microcontrolador. Quando projetamos um dispositivo, a regra é colocar o oscilador tão perto quanto possível do microcontrolador, de modo a evitar qualquer interferência nas linhas que ligam o oscilador ao microcontrolador.

Microcontroladores - PIC

12


MICROCONTROLADORES PIC EM C

Ilustração 3: Clock de um microcontrolador com Ilustração 2: Clock de um microcontrolador a partir um ressonador de um cristal de quartzo

2.5.

Oscilador RC

Em aplicações em que a precisão da temporização não é um fator crítico, o oscilador RC torna-se mais econômico. A freqüência de ressonância do oscilador RC depende da tensão de alimentação, da resistência R, capacidade C e da temperatura de funcionamento.

Ilustração 4: Ligação de umoscilador RC

O diagrama acima, mostra como um oscilador RC deve ser ligado a um PIC16F877A. Com um valor para a resistência R abaixo de 2,2 K, o oscilador pode tornar-se instável ou pode mesmo parar de oscilar. Para um valor muito grande R (1M, por exemplo), o oscilador torna-se muito sensível à umidade e ao ruído. É recomendado que o valor da resistência R esteja compreendido entre 3K e 100K. Apesar de o oscilador poder trabalhar sem condensador externo (C = 0 pF), é conveniente, ainda assim, usar um condensador acima de 20 pF para evitar o ruído e aumentar a estabilidade. Qualquer que seja o oscilador que se está a utilizar, a freqüência de trabalho do microcontrolador é a do oscilador dividida por quatro. A freqüência de oscilação dividida por 4 também é fornecida no pino OSC2/CLKOUT e, pode ser usada, para testar ou sincronizar outros circuitos lógicos pertencentes ao sistema.

Microcontroladores - PIC

13


MICROCONTROLADORES PIC EM C

Ilustração 5:Relação entre o sinal de clock e os ciclos de instrução

Ao ligar a alimentação do circuito, o oscilador começa a oscilar. Primeiro com um período de oscilação e uma amplitude instável, mas, depois de algum tempo, tudo estabiliza.

Ilustração 6:Sinal de clock do oscilador do microcontrolador depois de ser ligada a alimentação

Para evitar que esta instabilidade inicial do clock afete o funcionamento do microcontrolador, nós necessitamos de manter o microcontrolador no estado de reset enquanto o clock do oscilador não estabiliza. O diagrama em cima, mostra uma forma típica do sinal fornecido por um oscilador de cristal de quartzo ao microcontrolador quando se liga a alimentação. Para ter um controle sobre o reset é conveniente instalar um botão como se mostra na figura.

Microcontroladores - PIC

14


MICROCONTROLADORES PIC EM C

Ilustração 7: Circuito de Reset através de um botão

Microcontroladores - PIC

15


MICROCONTROLADORES PIC EM C

3. AMBIENTE INTEGRADO DE DESENVOLVIMENTO (IDE) Como ambiente de desenvolvimentos será usado o compilador PCWH da CCS. Este é constituído de um IDE gráfico que pode ser executado em qualquer plataforma Windows. Este ambiente permitirá uma programação dos PICs em linguagem C. Existe a possibilidade de se fazer uma integração com o ambiente MPLAB da própria microchip. Como vantagem do uso desse compilador pode-se citar a grande eficiência do código gerado, compatibilidade com o padrão ANSI e ISSO salvo algumas exceções e a sua grande diversidade de funções e bibliotecas desenvolvidas em linguagem C. O objetivo deste capítulo é a compreensão do ambiente de programação e da seqüência para poder criar um novo projeto usando o MpLab como editor e o CCS como compilador.

Ilustração 8: Ambiente de desenvolvimento PCWH Atualmente, a maioria dos microcontroladores disponíveis no mercado conta com compiladores de linguagem C para o desenvolvimento de software. O desenvolvimento em C permite uma grande velocidade na criação de novos projetos permite que o programador preocupe-se mais com a programação da aplicação em si, já que o compilador asssume para si tarefas como o controle e localização das variáveis, operações matemáticas e lógicas, verificação de bancos de memória, etc. Existe outra linguagem muito usada chamado Assembly que é bastante eficiente, mas o programador terá que se preocupar pela localização das variáveis, Microcontroladores - PIC

16


MICROCONTROLADORES PIC EM C

pelos estados dos registros controladores de hardware, exigindo do programador o conhecimento do hardware usado. Sendo nosso curso Técnico escolho-se como principal opção a linguagem C para que o aluno possa aproveitar ao máximo o seu tempo, ampliando desta forma suas habilidades na programação de PICs. Quando um programa se faça crítico no sentido de precisar mais eficiência o programador deverá escolher a linguagem Assembler. È importante também sinalizar que este programa tem um excelente ambiente de programação (EDITOR), mas nosso curso usará como editor ou ambiente de escrita de programa o MPLAB, programa gratuito da MICROCHIP. O MPLAB como foi dito tem também um ambiente de simulação que será bastante usado. O compilador PCW é necessário na medida em que o MPLAB usará este.

3.1. •

CRIAÇÃO DE UM PROJETO: Nesta sessão serão explicados os passos para poder criar um projeto: Abrir o MPLAB

Ilustração 9: Abrindo o MPLAB

Também é possível abrir o MPLAB através do ícone no DESKOP.

Microcontroladores - PIC

17


MICROCONTROLADORES PIC EM C

Criar um projeto novo usando o assistente (Wizard), para isto clicar no menu Project / Project Wizard .... como é mostrado na seguinte figura.

Ilustração 10: Criação de um projeto usando o Assistente (Wizard)

Avançar

Ilustração 11: Bem vinda do assistente para criação de projeto

Microcontroladores - PIC

18


MICROCONTROLADORES PIC EM C

Escolher o tipo de PIC e clicar em avançar

Ilustração 12: Seleção do PIC usando o assistente (wizard)

Escolha o compilar “CCS C compiler for PIC12/14/16/18” e depois em avançar.

Ilustração 13: Escolha do Compilador CCS no assistente (wizard)

A localização do arquivo Ccsc.exe é muito importante. Neste caso esta localizado na pasta “C:\Arquivos de programas\PICC\Ccsc.exe”.

Microcontroladores - PIC

19


MICROCONTROLADORES PIC EM C

Escrever o nome do projeto e sua localização, logo clicar em avançar.

Ilustração 14: Nome do Projeto - Assistente (Wizard)

Incrementar algum arquivo existente no projeto em caso de ter. Para este curso por enquanto não incrementaremos nenhum arquivo e clicaremos em avançar diretamente.

Ilustração 15: Incremento de Arquivos no Assistente - (Wizard)

Microcontroladores - PIC

20


MICROCONTROLADORES PIC EM C

Clicar em concluir para criar o projeto com os parâmetros mostrados na tela.

Ilustração 16: Sumário do Projeto - Fim do Assistente (Wizard)

Finalmente temos o projeto, mas precisamos de um arquivo onde possamos escrever o código, para isto clicamos no menu File/New

Ilustração 17: Criação de um novo arquivo C

Microcontroladores - PIC

21


MICROCONTROLADORES PIC EM C

Escrevemos o programa em código C

Ilustração 18: Escrita do programe em C

Depois de escrever o programa deverá salvar este. Clicar em salvar e escrever em nome do arquivo “Ejemplo1.c” e clicar no botão Salvar.

Ilustração 19: Gravação do arquivo "C"

Microcontroladores - PIC

22


MICROCONTROLADORES PIC EM C

Até aqui o seu projeto esta vazio sem nenhum programa. O programa criado ainda não esta associado ao projeto. •

Com o mouse sobre Source Files clicar no botão direito do mouse, depois clicar na opção “Add Files”.

Ilustração 20: Incremento de arquivos ao projeto

Em examinar escolha o caminho aonde foi gravado o arquivo anteriormente, neste caso C:\Temp\picc. Escolha o arquivo e clicar no botão Abrir.

Microcontroladores - PIC

23


MICROCONTROLADORES PIC EM C

Ilustração 21:Seleção do arquivo.C para ser incrementado no projeto

Microcontroladores - PIC

24


MICROCONTROLADORES PIC EM C

4. INTRODUÇÃO À LINGUAGEM C – O PRIMEIRO PROGRAMA Agora estamos em condições de poder começar a escrever um programa no ambiente de desenvolvimento, chegou a hora de estudar os fundamentos da linguagem C. No projeto criado, abrimos, salvamos e incrementamos um arquivo chamado Ejemplo1.C, neste arquivo podemos escrever o seguinte programa: EXEMPLO 1: Neste exemplo iremos desenvolver um exercício e explicar a primeira parte do programa e a funcionalidade das funções. Desta forma não será necessário explicar nos exemplos posteriores os itens explicados neste exemplo. #include <16f877A.h> #use delay(clock=4000000, RESTART_WDT) #fuses xt,nowdt,noprotect,put,brownout,nolvp,nocpd,nowrt #use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

#bit #bit

botao = portb.0 led = portb.1

void main () { set_tris_a(0b11111111); set_tris_b(0b11111001); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00; while(TRUE) { RESTART_WDT(); if(!botao) led = 1; else led=0; } }

Microcontroladores - PIC

25


MICROCONTROLADORES PIC EM C

Vejamos o significado de cada linha do programa. #include

<16f877A.h>

È uma diretiva do compilador. Neste caso está determinando ao compilador que anexe ao programa o arquivo especificado 16f877A.h. Arquivos .h são chamados de arquivos de cabeçalho e são utilizados em C para definir variáveis, tipos, símbolos e funções úteis ao programa. O 16f877A.h. é um arquivo com as definições relativas ao processador lavo, para o qual o programa será compilado. #use

delay(clock=4000000, RESTART_WDT)

A seqüência #use especifica uma diretiva interna do compilador. Aqui é determinado o valor de 4 MHz para a freqüência do clock. #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt

Configuração dos fusíveis. XT: O oscilador, da maioria dos PIC, é externo, sem ele nada funciona. Existem vários tipos de osciladores como o RC composto por uma resistência e um capacitor e o cristal XT que é mais preciso sendo também os mais caros. NOWDT: Watchdog timer ou cão de guarda é um recurso poderosíssimo que deve ser utilizado. É um contador automático incrementado por meio de um oscilador próprio, independente do oscilador principal. Caso o WDT estoure, um reset do sistema irá ocorrer imediatamente. noprotect: permite reprogramar o PIC e enxergar o código. put: prevê que o programa não comece antes que a alimentação seja inicializada. Esta opção irá fazer com que o PIC comece a operar cerca de 72 ms após o pino /MCLR seja colocado em nível alto. Brown-Out: é utilizado para forçar um reset quando a tensão de alimentação sofre uma pequena queda. Ele é extremamente recomendado em projetos que possibilitam ao usuário desligar e religar rapidamente a alimentação. NOLVP Low Voltage Programming disabled Trabalho 4.1: Pesquisar para a próxima aula as outras diretivas não comentadas.

#use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

Afeta como o compilador gerará código para as instruções de entrada ou saída que seguem. Esta diretiva tem efeito até que uma nova diretiva #use xxxx_IO seja encontrado. Este método rápido de configuração de configuração de I/O a configurar corretamente a direção de I/O usando a instrução set_tris_X(). #byte #byte

porta = 0x05 portb = 0x06

Microcontroladores - PIC

26


MICROCONTROLADORES PIC EM C #byte #byte #byte

portc = 0x07 portd = 0x08 porte = 0x09

No data sheet do PIC 16F877A podemos observar que as portas a,b,c,d, e estão associados a um endereço de memória. Depois destas linhas as portas terão como identificador as variáveis porta, portb até porte. #bit #bit

botao = portb.0 led = portb.1

As entradas devem ser associadas a nomes para facilitar a programação e futuras alterações do hardware. De aqui em diante podemos nomear o pino portb.0 como botão por exemplo. void main ()

A declaração main() especifica o nome de uma função. No caso, a função main() é padronizada na linguagem C e é utilizada para definir a função principal, ou corpo principal do programa. O sinal de abertura de chave “{“ é utilizado para delimitar o início da função e o sinal de fechamento de chave “}” indica o final da função. Na verdade, as chaves delimitam o que chamamos de bloco de programa, ou bloco de código. set_tris_a(0b11111111); set_tris_b(0b11111001); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111);

Esta função permite direcionar as I/O. Deve de ser usado com o comando “fast_io” e quando as portas de I/O estão acessíveis, para isto deve ser usada a diretiva #BYTE para o acesso da porta. Cada bit no valor representa um pino. O “1”(um) representa entrada e o zero saída. Exemplo: SET_TRIS_B( 0x0F ); similar a SET_TRIS_B( 0b00001111 ) // B7,B6,B5,B4 are outputs // B3,B2,B1,B0 are inputs porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00;

Inicializando as portas, todos os pinos das portas na execução destas linhas tomarão o valor de zero ou desligado. while(TRUE)

Este é um comando de controle utilizado na repetição de um determinado bloco de instruções. Esse bloco será repetido enquanto a avaliação da condição especificada entre parênteses for verdadeira. No caso, a avaliação é explicitamente verdadeira (true). O bloco de instruções que será repetido é aquele especificado dentro das chaves que seguem o comando while. if(!botao) led = 1; else

Microcontroladores - PIC

27


MICROCONTROLADORES PIC EM C led=0;

O comando if (em português “se”) é utilizado para avaliar a condição que esta entre parênteses. Em caso de que esta condição seja verdadeira o comando seguinte será executado. Em caso de ser falsa (else) o comando depois da instrução “else” será executado. Neste exemplo o a variável booleana botão esta negada (!botao) quer disser se o botão estivesse em estado zero a condição será falsa e o led será igual a 1. Em caso que o botão seja 1 a condição será falsa e o led será igual a zero. Trabalho 4.2: Responda as seguintes perguntas: • No programa do exemplo 1 disser como esta configurado o pino portb.4?. è uma entrada ou uma saída e por quê? • A variável led esta associada a que pino do PIC?. Responder com o número do pino. • Porque no exemplo 1 foram consideradas 5 portas?. Explicar olhando o desenho do PIC. • No programa em que linha decide o tipo de PIC a ser usado? • Que mudaria no programa para que quando botão = 1 o led seja 1? • Incremente no exemplo1 a variável botao1 e led1. Quando botão1 seja igual a 1 led1 deverá de ser zero e quando botão1 seja zero, led1 será 1. • Esquematize o circuito eletrônico para testar este programa. Utilize um oscilador de cristal e lembre que o limite de corrente oscila entre os 20mA por cada pino de saída. A tensão de alimentação do PIC é de 5 v. Instale um botão que aoi ser pressionado reiniciará o PIC (reset). Até aqui se espera que o leitor consiga associar o pino do PIC às portas mencionadas no programa, e que possa entender este exemplo que mesmo sendo básico é o início do aprendizado de um recurso sem limites. Até a próxima aula onde aprenderemos a simular programas sem a necessidade de um hardware.

Microcontroladores - PIC

28


MICROCONTROLADORES PIC EM C

5. USO DO MPSIM PARA SIMULAÇÃO Neste capítulo o objetivo é que o leitor consiga aprender a simular o seu projeto. Em outras palavras sem necessidade do circuito eletrônico podemos conferir se o programa pode compilar, (esta sem erros de sintaxe) e responde da forma que se quer (sem erros lógicos). O MpSim é um utilitário do MpLab e tem a finalidade de simular o projeto. Para poder fazer uso deste deverá de seguir os seguintes passos: 1. Escolher a ferramenta MpLab SIM no menu Debugger/Select Tool/MpLab SIM.

Ilustração 22: Escolha da ferramenta MpLab SIM

2. Compilar o seu projeto, clicando no ícone mostrado no gráfico ou pressionando F10.

Ilustração 23: Compilação do projeto

Microcontroladores - PIC

29


MICROCONTROLADORES PIC EM C

3. Observe na janela OutPut o resultado da compilação, neste caso a compilação foi bem sucedida (build succeeded), mostrando o caminho aonde foram copiados os arquivos produto desta compilação. Também mostra o número de erros da compilação e de avisos (warnings). Em caso de erro este será mostrado, e indicado em que linha se encontra. Se sua compilação contiver algum erro, proceda a sua localização e correção.

Ilustração 24: Visualização do resultado da compilação

Exercícios 5.1: 1. Incremente a palavra Brasil depois da linha de programa “while(TRUE)” e compile o projeto. 2. Em que linha se apresentou o erro?. Verifique a barra de indicação inferior na janela do Mplab que mostra a linha e a coluna na qual se encontra o cursor. 3. Porque ao incrementar esta palavra provocou ao compilador o erro? Nos programas é comum o uso de comentários para poder incrementar um comentário é necessário escrever while(TRUE) //Brasil. Estes caracteres “//” antecedem a um comentário de linha simples. São utilizados para descrever o funcionamento ao final de cada linha de código. 4. Agora é hora de aprender a usar as ferramentas deste utilitário, no seguinte gráfico podemos observar que temos 7 botões que controlam a simulação.

Microcontroladores - PIC

30


MICROCONTROLADORES PIC EM C

Ilustração 25: Botões de controle da simulação no MPSIM

Run: Executa o programa, começa a simulação. Halt: Para a simulação. Animate: Anima a simulação, executa linha por linha o programa e é indicado por uma zeta. Step Into: Executa linha, e se houver uma função entra nela. Step Over: Executa a linha, e se houver uma função executa o bloco todo e pula para a seguinte linha. Step out: Saí da função Reset: reinicia a simulação a partir da primeira linha. Exercícios 5.2: 1. Pressionar o botão Animate e anotar suas observações. Para parar a animação clicar no botão halt. 2. Clicar no botão Run e anotar suas observações, que esta acontecendo? 3. Clicar várias vezes o botão Step over e anotar suas observações?

Microcontroladores - PIC

31


MICROCONTROLADORES PIC EM C

5. Não tem sentido visualizar a simulação do programa se não conseguir estimular as entradas para poder observar o comportamento das saídas. Para isto existe uma ferramenta no MPSIM, clicar na opção do menu Debugger/Stimulus Controller/New Scenario como se mostra na ilustração seguinte.

Ilustração 26: Criação de um controle de estimulo

Microcontroladores - PIC

32


MICROCONTROLADORES PIC EM C

6. Como as entradas têm que ser simuladas neste ambiente, criamos as entradas que serão estimuladas ou controladas nesta janela.

Ilustração 27: Parametrização de um estimulo ou entrada digital no simulador MPSIM

Escolhemos RB0 porque no exemplo 1 este representa a variável botão, e o tipo de ação do estimulo terá retenção. Em outras palavras botão será uma chave com retenção. Este ambiente pode ser salvo e aberto. Na ilustração anterior observa-se que existem 5 tipos de ação: • Set High: O Pino de referência tomará o valor de 1. Para que seja novamente zero necessariamente terá que ser executada a ação Set Low. • Set Low: O Pino de referência tomará o valor de 0. Para que seja novamente um(1) necessariamente terá que ser executada a ação Set High. • Toggle: Ao ser executada esta ação o pino de referência mudará de estado, se estiver em zero este irá para um, se estiver em um irá para zero. Esta ação atua como uma chave com retenção. • Pulse high: Ação que manterá ligado o pino respectivo só um instante. Em outras palavras enviará um pulso. • Pulse low: Ação que manterá desligado o pino respectivo só um instante. Em outras palavras enviará um pulso em sentido contrário a Pulse high. Como já foi percebido na coluna PIN/SFR são selecionados os pinos do PIC que serão estimulados. As colunas Width e units, são usados em caso de que a ação selecionada seja o pulse high ou low, na coluna width (largura) é especificada a largura do pulso, e na coluna units a unidade respectiva. Para que a ação seja executada o usuário deverá clicar o botão da coluna fire. Microcontroladores - PIC

33


MICROCONTROLADORES PIC EM C

As vezes a desorganização faz perder as pessoas um valioso tempo, na programação a organização esta relacionada entre outras coisas com os comentários, A coluna comments serve para escrever comentários ou até para simular entradas de mensagens pela porta serial. Agora o leitor deve estar preparado para simular o seu projeto com estímulos de entrada. Exercícios 5.3: 1) Pressionar o botão Step Over nos botões de controle de simulação e verifique se a linha de comando depois da instrução if é executada. Na seguinte barredura estimule o variável botão e verifique novamente a execução desta linha. Anote suas observações, que esta acontecendo? 2) Incremente na janela de controle de estímulos ações de Set Low e Set high para o botão e visualize este funcionamento.

Microcontroladores - PIC

34


MICROCONTROLADORES PIC EM C

7. O fato de poder estimular as entradas não ajuda muito se não se visualiza com maior clareza a reação das saídas. Existem várias formas de visualizar o comportamento das saídas, mas por enquanto se usará o opção localizada no menu View/Watch.

Ilustração 28: Abrindo um visualizador de registros – watch

Watch, permite você digitar uma variável, ou qualquer expressão importante e visualizar o resultado. Neste caso escolhemos a variável led e clicamos no botão Add Symbol, para poder mudar as características de visualização clicar com o botão direito sobre a variável em questão e selecionar properties e na janela emergente selecione o sistema de numeração binário, feche a janela e simule usando o botão Step Over. O watch Permite visualizar tanto saídas como entradas.

Ilustração 29: Janela da opção Watch

Exercícios 5.4: 1. Inserir na janela watch o byte portb em binário e simular novamente o programa observando detalhadamente os resultados.

Microcontroladores - PIC

35


MICROCONTROLADORES PIC EM C

2. Simular o seguinte programa e descrever o seu funcionamento. Existe um erro neste programa identifique-lo. /******************************************************** * CEFETES * Prof: Marco Antonio * Exemplo 2: Função IF - reforço * Materia: MICROCONTROLADORES * Data: Julho 2006 /Linhares ********************************************************/ #include <16f877A.h> #use delay(clock=4000000, RESTART_WDT) #fuses xt,nowdt,noprotect,put,brownout,nolvp,nocpd,nowrt #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

#bit BotaoLiga = portb.0 #bit BotaoDesliga = portb.1 #bit Motor1 = portb.2 #bit Lampada = portb.3 void main () { set_tris_a(0b11111111); set_tris_b(0b11111011); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00; while(TRUE) { if(!BotaoLiga) { Motor1 = 1; Lampada=1; } if(!BotaoDesliga) { Motor1 = 0; Lampada=0; } } }

Microcontroladores - PIC

36


MICROCONTROLADORES PIC EM C

3. Avalia o circuito seguinte e faz um programa para que apertando o botĂŁo SA14 possa ligar o led 0.

Microcontroladores - PIC

37


MICROCONTROLADORES PIC EM C /******************************************************** * CEFETES * Prof: Marco Antonio * Exemplo 1: Estrutura Básica de um programa em C * Materia: Microcontroladores * Data: Agosto 2006 ********************************************************/ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #fuses

*

*

xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt

// configuração dos fusíveis

#use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #bit BotaoSA14_b1 = portb.1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Microcontroladores - PIC

38


MICROCONTROLADORES PIC EM C #bit HabLed = porta.4 #bit HabBotao = portb.7 #bit

Led0 = portd.0

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

*

void main () { // configura CONFIG setup_counters(RTCC_INTERNAL, WDT_2304MS); // configura os TRIS set_tris_a(0b00100000); set_tris_b(0b00001111); set_tris_c(0b10011001); set_tris_d(0b00000000); set_tris_e(0b00000000); // inicializa os ports porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00;

// limpa porta // limpa portb // limpa portc // limpa portd // limpa porte

HabLed =1; HabBotao=1; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { RESTART_WDT(); if(BotaoSA14_b1) // testa botão Led0 = 1; // Se botão = 0, então led = 1 else Led0=0; // caso contrário, led = 0 } // FIM DO PROGRAMA } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Microcontroladores - PIC

*

39


MICROCONTROLADORES PIC EM C

4. Lembrando do seguinte circuito: Faz um programa para que apertando o botão SA13 mostre no display DS4 o número 7 e com o botão SA14 o número 9. Escolhe outro botão para desligar todos os leds do display.

Microcontroladores - PIC

40


MICROCONTROLADORES PIC EM C /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

*

*

#fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt

// configuração dos fusíveis

#use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. //Este programa não utiliza nenhuma variável de usuário /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #bit Botao7 = portb.1 #bit BotaoDesLiga = portb.2 #bit Botao9 = portb.3 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #bit HabLed = porta.4 #bit HabBotao = portb.6 #bit #byte

Led0 = portd.0 Display = portd

Microcontroladores - PIC

41


MICROCONTROLADORES PIC EM C /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

*

void main () { // configura CONFIG setup_counters(RTCC_INTERNAL, WDT_2304MS); // configura os TRIS set_tris_a(0b00100000); set_tris_b(0b00001111); set_tris_c(0b10011001); set_tris_d(0b00000000); set_tris_e(0b00000000); // inicializa os ports porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00;

// limpa porta // limpa portb // limpa portc // limpa portd // limpa porte

HabLed =1; HabBotao=1;//rb7 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { RESTART_WDT(); if(Botao9) // testa botão portd = 0b01101111; if(Botao7) // testa botão portd = 0b00000111; if(BotaoDesLiga) portd = 0b00000000; // caso contrário, led = 0 } // FIM DO PROGRAMA } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Microcontroladores - PIC

*

42


MICROCONTROLADORES PIC EM C

6. AS VARIÁVEIS NO COMPILADOR CCS

6.1.

O que são Variáveis?

Para você poder manipular dados dos mais diversos tipos, é necessário poder armazená-los na memória e poder referenciá-los quando for preciso. É para isso que existem as variáveis, que nada mais são do que um espaço reservado na memória, e que possuem um nome para facilitar a referência. As variáveis podem ser de qualquer tipo visto nesta aula: int, char, float, double, etc. Como o próprio nome diz, as variáveis podem ter o seu conteúdo alterado durante a execução do programa, ou seja, o programador tem a liberdade de atribuir valores ao decorrer da execução. 6.2.

Tipos de variáveis

O C tem 5 tipos básicos: char, int, float, void, double. Destes não todos os tipos fazem parte do compilador CCS. O double é o ponto flutuante duplo e pode ser visto como um ponto flutuante com muito mais precisão. O void é o tipo vazio, ou um "tipo sem tipo". A aplicação deste "tipo" será vista posteriormente. Na seguinte tabela observaremos os tipos de dados do compilador CCS. Type-Specifier int1 int8 int16 int32 char float short Int long byte bit void

6.3.

Num bits 1 8 16 32 8 32 1 8 16 8 1 0

Coment Define a 1 bit number Defines an 8 bit number Defines a 16 bit number Defines a 32 bit number Defines a 8 bit character Defines a 32 bit floating point number By default the same as int1 By default the same as int8 By default the same as int16

Indicates no specific type

OS MODIFICADORES

Para cada um dos tipos de variáveis existem os modificadores de tipo. Os modificadores de tipo do C são quatro: signed, unsigned, long e short. Ao float não se pode aplicar nenhum. Os quatro modificadores podem ser aplicados a inteiros. A intenção é que short e long devam prover tamanhos diferentes de números inteiros, onde isto for prático. Inteiros menores (short) ou maiores (long). Assim, se especificamos uma variável como sendo do tipo short int, este será uma versão reduzida do tipo int, o

Microcontroladores - PIC

43


MICROCONTROLADORES PIC EM C

que no caso do compilador CCS cria uma variável de apenas um bit. Uma especificação long int criará uma variável de 16 bits O modificador unsigned serve para especificar variáveis sem sinal. Um unsigned int será um inteiro que assumirá apenas valores positivos. A representação de números negativos é feita tomando o bit MSB (Most Significant Bit ou bit mais significativo) da variável para representar o sinal: bit MSB =1, sinal negativo, bit MSB = 0, sinal positivo. Note que devido ao fato de utilizar um bit para representação do sinal, a magnitude absoluta de representação do tipo modificado será metade da magnitude do tipo não modificado. Assim, um tipo de dados signed int pode representar valores entre -128 e +127, em vez de 0 a 255. Todos os tipos, exceto o Float, por defeito são unsigned; porem pode estar precedido por unsigned ou signed. Na seguinte tabela mostramos alguns exemplos de combinações possíveis dos tipos de dados do compilador CCS. Tipo

6.4.

Intervalo

Num de bits Inicio

Fim

char

8

0

255

unsigned char

8

0

255

signed char

8

-128

127

int, int8, byte

8

0

255

unsigned int, unsignet byte

8

0

255

signed int, signed int

8

-128

127

long int

16

0

65.535

signed long int

16

-32.768

32.767

unsigned long int

16

0

65.535

Int32, unsigned int32

32

0

4.294.967.295

Signed int32

32

-2,147.483.648

2,147.483.647

float

32

3,4E-38

3.4E+38

Declaração de Variáveis

Todas as variáveis em C devem ser declaradas antes de serem usadas. A forma geral de declaração de uma variável é a seguinte: tipo nome_da_variavel; Exemplos: Uma variável de cada vez: int id;

Microcontroladores - PIC

44


MICROCONTROLADORES PIC EM C

float aux; unsigned int i; char carac; Ou várias do mesmo tipo em uma única linha: int id, obj, n, t; char c1, c2, c3; Onde tipo pode ser qualquer tipo válido da linguagem C, e nome_da_variavel deve ser um nome dado pelo programador, sendo o primeiro caractere uma letra ou um "_", e os demais, letras, números ou "_". num peso aluno_1

_carac Id_obj AUX

Lembrando que C diferencia maiúsculas de minúsculas. Não são nomes válidos de variáveis: 1num $aux

6.5.

-idade id@al

Inicializando Variáveis

Inicializar significa atribuir um valor inicial a uma variável. Em C, podemos inicializar variáveis na declaração: int n=12; Neste exemplo, estamos declarando a variável inteira n e atribuindo o valor 12 à ela. O sinal de igual (=) em C é o operador de atribuição. Ele serve para colocar o valor (do lado direito) na variável (lado esquerdo). Podemos também inicializar uma variável no corpo do programa, após sua declaração: int n; n=12; Pode-se atribuir também variáveis a variáveis: num=i; Neste caso, a variável num está recebendo o valor da variável i.

Microcontroladores - PIC

45


MICROCONTROLADORES PIC EM C

6.6.

Variáveis Locais e Globais

As variáveis podem ser locais ou globais. As variáveis locais são aquelas declaradas dentro de uma função, sendo somente "vistas" dentro desta função. Se você tentar acessar uma variável local de fora da função onde ela está, acontecerá um erro. Após a execução desta função, as variáveis locais ali contidas são destruídas. Na aula sobre funções estudaremos mais sobre variáveis locais, com exemplos. As variáveis globais são aquelas declaradas fora de qualquer função, até da função main(). São reconhecidas pelo programa inteiro e podem ser usadas em qualquer lugar do código, mesmo dentro de funções. Seus valores ficam guardados durante toda a execução do programa. Veja um exemplo do uso de variáveis globais: #include ***** int num;

/* num é uma variável global */

int main() { int contador=0; //contador é uma variável local num= 10; printf("%d", n); return 0; } Assim como as variáveis locais, veremos as variáveis globais com mais detalhes na aula sobre funções. 6.7.

Constantes

Constantes em C são valores fixos, que não mudam durante a execução. Elas podem ser de qualquer tipo básico: inteiras, ponto flutuante, caractere, string. De maneira geral, qualquer tipo de dado pode ser utilizado para definir uma constante, cabendo apenas ao programador representar o valor dela adequadamente. const valor1 = 10 const valor1 = -3 const valor1 = 13.24 const valor1 = ‘c’ const valor1 = “CEFETES-Linhares” As constantes são também utilizadas para impedir que uma função altere um parâmetro passado a ela. Bem, nesta aula você aprendeu sobre os tipos de dados que a linguagem C pode manipular. Também viu a forma de armazenar temporariamente estes dados, com o Microcontroladores - PIC

46


MICROCONTROLADORES PIC EM C

uso de variáveis, e como expressar constantes de vários tipos em C. Na próxima aula estudaremos os operadores da linguagem C (aritméticos, relacionais, lógicos, etc.). Não percam!

Exercícios 6.1: 1. Qual a faixa numérica de uma variável int? E de um unsigned int? 2. Qual a diferença de um signed int para um int? 3. Por que a declaração de uma variável como unsigned é redundante? 4. O que são variáveis e qual é sua utilidade? 5. Qual a diferença entre as variáveis locais e globais? 8. O que são constantes? Dê exemplos. 9. Assinale a alternativa que possui um nome de variável CORRETO: • • • •

$num -temp _carac_ 3aux

Microcontroladores - PIC

47


MICROCONTROLADORES PIC EM C

7. OPERADORES EM C Já aprendemos sobre a estrutura básica de um programa em C, sobre os tipos de dados que C pode manipular, sobre o que são variáveis e constantes. Na aula de hoje você aprenderá a criar expressões em C com o uso de operadores, sejam eles aritméticos, lógicos, relacionais, etc. Mostraremos vários exemplos e finalizaremos a aula com exercícios. Então, pé na tábua! 7.1.

O Operador de Atribuição

Na aula sobre variáveis já foi falado sobre o operador de atribuição (o símbolo de igual "="). O que ele faz é colocar o valor de uma expressão (do lado direito) em uma variável (do lado esquerdo). Uma expressão neste caso pode ser um valor constante, uma variável ou uma expressão matemática mesmo. É um operador binário, ou seja, trabalha com dois operandos. Exemplos: Atribuição de uma constante a uma variável: n= 10; ch= 'a'; fp= 2.51; Atribuição do valor de uma variável a outra variável: n= num; Atribuição do valor de uma expressão a uma variável: n= (5+2)/4; Atribuições múltiplas: x = y = z = 20; Em uma atribuição, primeiro é processado o lado direito. Depois de processado, então, o valor é atribuído a variável. Como você viu no último exemplo acima, C também permite atribuições múltiplas (como x = y = z = 20;). Neste caso, todas as variáveis da atribuição (x, y e z) recebem o valor mais à direita (20). 7.2.

Os Operadores Aritméticos

Estes são, de longe, os mais usados. Os operadores aritméticos em C trabalham praticamente da mesma forma que em outras linguagens. São os operadores + Microcontroladores - PIC

48


MICROCONTROLADORES PIC EM C

(adição), - (subtração), * (multiplicação), / (divisão) e % (módulo ou resto da divisão inteira), todos estes binários (de dois operandos). Temos também o - unário, que muda o sinal de uma variável ou expressão para negativo. Veja a tabela a seguir: Operador Descrição

Exemplo

- unário

Inverte o sinal de uma expressão -10, -n, -(5*3+8)

*

Multiplicação

3*5, num*i

/

Divisão

2/6, n/(2+5)

%

Módulo da divisão inteira (resto)

5%2, n%k

+

Adição

8+10, exp+num

-

Subtração

3-6, n-p

A precedência dos operadores aritméticos é a seguinte: Mais alta - unário */% +Mais baixa Uma expressão deste tipo: 5+2*3-8/4 É avaliada assim: primeiro a multiplicação (2*3), depois a divisão (8/4). Os resultados obtidos destas duas operações são utilizados para resolver as duas últimas operações: 5+6-2 adição e subtração. Igualzinho à matemática aprendida no primário... Tudo isso porque as operações de multiplicação e divisão têm maior precedência e estas são resolvidas primeiro em uma expressão. Para mudar a ordem de operação, devem-se usar parênteses. Deve-se tomar cuidado ao construir expressões, pois a falta de parênteses pode causar erros no resultado. O Operador % é equivalente ao mod em Pascal, e é útil em várias situações. Ele dá como resultado o resto da divisão inteira de dois operandos. Assim, fica fácil, por exemplo, saber se um número é múltiplo de outro: if ((num%3)==0) /* se o resto da divisão entre num e 3 for igual a 0 ... */ printf("Múltiplo de 3\n");

Microcontroladores - PIC

49


MICROCONTROLADORES PIC EM C

Este é apenas um de vários problemas que podem ser resolvidos com o uso do operador %. 7.3.

Operadores Relacionais e Lógicos

Os operadores relacionais e lógicos são usados em testes e comparações, principalmente nos comandos de controle e nos laços. Para entender melhor esses operadores, temos que entender o conceito de verdadeiro e falso. Em C, verdadeiro é qualquer valor diferente de zero, e falso é zero. As expressões que usam operadores relacionais e lógicos retornam 0 para falso e 1 para verdadeiro. Os operadores relacionais são 6: Operador Ação <

Menor que

<=

Menor que ou igual

>

Maior que

>=

Maior que ou igual

==

Igual

!=

Diferente

Veja um exemplo do uso de operadores relacionais: #include <stdio.h> (necessário para printf e scanf) */ int main() { int n; inteira */

/*

Inclusão

de

stdio.h

/* Declaração de uma variável

printf("Digite um número: "); scanf("%d", &n); /* Lê o número e armazena na variável n */ if (n < 0) /* Se n for MENOR QUE 0... */ printf("Número negativo\n"); /* ... escreve isto. */ else /* Senão... */ printf("Número positivo\n"); /* ... escreve isto. */ return 0; /* Retorna 0 para o sistema (sucesso) */ } Tente fazer alguns testes com os outros operadores relacionais. Sei lá, seja criativo! Você é o programador... :)

Microcontroladores - PIC

50


MICROCONTROLADORES PIC EM C

Os operadores lógicos são 3: Operador Ação

Formato da expressão

&&

and (e lógico)

p && q

||

or (ou lógico)

p || q

!

not (não lógico) !p

Veja um exemplo, só do bloco if: if ((n > 0) && (n < 100)) /* se n for maior que 0 E n for menor que 100... */ printf("Número positivo menor que 100\n"); /* ... imprime isto */ Outro exemplo: if ((n == 0) || (n == 1)) ... */ printf("zero ou um\n");

/* se n for IGUAL a 0 OU n for igual a 1 /* ... imprime isto. */

A tabela seguinte mostra a precedência dos operadores relacionais e lógicos: Maior ! >, >=, <, <= ==, != && || Menor Os parênteses também podem ser usados para mudar a ordem de avaliação das expressões, como no caso das expressões aritméticas. 7.4.

Operadores de Incremento e Decremento

A linguagem C possui dois operadores que geralmente não são encontrados em outras linguagens, mas que facilita bastante a codificação: os operadores de incremento(++) e decremento(--). O operador ++ soma 1 ao seu operando, similar a operação de variavel= variavel+1;, mas muito mais resumido. O operador -- subtrai 1 de seu operando, também similar a variavel= variavel-1;. Estes operadores são unários, e podem ser usados antes da variável: ++n; Microcontroladores - PIC

51


MICROCONTROLADORES PIC EM C

ou depois da variável: n++; A diferença é que, se o operador precede o operando (++n), o incremento ou decremento é realizado antes do valor da variável ser usado. E se o operador vem depois do operando (n++), o valor da variável poderá ser usado antes de acontecer a operação de incremento ou decremento. Veja estes dois exemplos: Exemplo 1: n= 5; p= ++n; printf("%d ",p); /* imprime na tela: 6 */ Exemplo 2: n= 5; p= n++; printf("%d ",p); /* imprime na tela: 5 */ No exemplo 1, a variável n é incrementada de 1 ANTES de seu valor ser atribuído a p. No exemplo 2, o valor de n é atribuído a p antes de acontecer a operação de incremento. Essa é a diferença de se colocar esses operadores antes ou depois da variável. 7.5.

Operadores Aritméticos de Atribuição

Algumas operações de atribuição podem ser feitas de forma resumida. Por exemplo, a atribuição: x= x+10; pode ser escrita: x+=10; A forma geral desse tipo de atribuição é: variável [operador]= [expressão]; que é igual a: variável= variável [operador] [expressão]

Veja essa tabela com exemplos: Microcontroladores - PIC

52


MICROCONTROLADORES PIC EM C

Forma longa Forma resumida x= x+10

x+=10

x= x-10

x-=10

x= x*10

x*=10

x= x/10

x/=10

x= x%10

x%=10

Se familiarize com essa notação, pois é um estilo largamente adotado pelos profissionais que trabalham com C. 7.6.

Operadores Bit a Bit

A linguagem C, ao contrário de outras linguagens, suporta um amplo conjunto de operadores bit a bit. Como C precisava substituir a linguagem Assembly na maioria das tarefas, era de vital importância que pudesse realizar essas operações. As operações bit a bit manipulam diretamente os bits de um byte ou uma palavra, e essas operações só podem ser feitas em variáveis int e char (e suas variantes). Os tipos void, float, double e long double NÃO podem ser usados. Esses operadores são usados com mais freqüência em drivers de dispositivo, como rotinas de impressoras, modems, operações com arquivos em disco, rotinas da porta serial e paralela, etc. Veja os operadores bit a bit: Operador & | ^ ~ >> <<

Ação and ("e" lógico) or ("ou" lógico) exclusive or ("ou exclusivo") complemento de 1 deslocamento à direita deslocamento à esquerda

Obs: Não confunda os operadores bit a bit com os operadores lógicos.

Microcontroladores - PIC

53


MICROCONTROLADORES PIC EM C

Para saber como se comportam os operadores bit a bit, segue abaixo uma tabela verdade dos operadores, com exceção dos operadores de deslocamento: p q p&q p|q p^q ~p 0 0 0

0

0

1

0 1 0

1

1

1

1 0 0

1

1

0

1 1 1

1

0

0

O operador & compara os dois operandos bit a bit e cada bit do resultado é 1 somente quando os dois bits do operando for 1. Caso contrário, 0. O bits do resultado de uma operação | bit a bit só será 1 quando um dos dois bits, ou os dois, forem 1. Na operação ^ só será 1 quando os bits dos operandos forem diferentes. Se forem iguais (0^0 ou 1^1) será 0. O operador de complemento (~) é um operador unário que inverte os bits do operando. 1 vira 0 e 0 vira 1. Vejamos um exemplo mais claro. Digamos que as variáveis inteiras x e y recebem os valores 8 e 9, respectivamente: x= 8; y= 9;

/* 8 em binário é 1000 */ /* 9 em binário é 1001 */

Vamos fazer algumas operações bit a bit nesses números: x & y: 1000 1001 ---1000

=> O resultado desta operação é 8 (1000).

1000 1001 ---1001

=> O resultado desta operação é 9 (1001).

1000 1001 ---0001

=> O resultado desta operação é 1.

x | y:

x ^ y:

~x:

1000 ----

Microcontroladores - PIC

54


MICROCONTROLADORES PIC EM C

~y:

0111

=> O resultado desta operação é 7 (111).

1001 ---0110

=> O resultado desta operação é 6 (110).

Aí você me pergunta: e os operadores de deslocamento? Esses operadores deslocam n bits para a esquerda ou direita: x>>1 x>>2

0100 0010

=> resultado: 4 => resultado: 2

y<<1 x<<1

10010 10000

=> resultado: 18 => resultado: 16

Você deve ter notado que deslocar um bit à direita é o mesmo que dividir o número por 2. Deslocar 2 bits à direita é o mesmo que dividir o número por 4, e assim por diante. Deslocar um bit à esquerda, porém, é o mesmo que multiplicar o número por 2. Deslocar 2 bits à esquerda significa multiplicar por 4, e assim por diante. Em um determinado ponto do curso, criaremos uma calculadora bit a bit, onde vocês poderão estudar melhor essas operações. 7.7.

Interface com os interruptores

Provavelmente este tema foge um pouco ao tema de operadores, mas é importante compreender as formas de poder ligar um interruptor no PIC. Este conteúdo foi localizado nesta parte do texto com fins didáticos para poder complementar os conhecimentos necessários para desenvolver o próximo exemplo. A figura seguinte mostra dois circuitos possíveis para ligar um interruptor de pressão ao microcontrolador. Na figura 1 a) o pino de E/S é ligado a +5V através de uma resistência pull-up de valor elevado, ficando a nível lógico 1. Quando o interruptor é fechado, o pino é ligado à massa através de uma resistência menor, passando a nível lógico 0. O circuito da figura 1 b) tem um princípio de funcionamento simétrico ao que acabamos de descrever. Inicialmente o pino de E/S está ligado à massa através de uma resistência pull-down de valor elevado, ficando a nível lógico 0. Quando o interruptor é fechado, o pino é ligado a +5V através de uma resistência menor, passando a nível lógico 1. Ambos os circuitos funcionam igualmente bem tanto para interruptores normalmente abertos, como para interruptores normalmente fechados. Notar que é indispensável a existência de resistências pull-up e pull-down. Imaginemos o caso da figura 1 (a). Se o interruptor estiver fechado, o pino de E/S é ligado à massa e não é necessário nada mais. Mas quando o interruptor estiver aberto, se não houver resistência pull-up, a entrada digital está “ao ar”, o que para Microcontroladores - PIC

55


MICROCONTROLADORES PIC EM C

portas de alta impedância é especialmente problemático, uma vez que o valor lógico da porta poderá oscilar continuamente entre nível lógico alto e baixo.

Ilustração 30: a)Configuração com resistência pull-up; b) Configuração com resistência pull-down

Estudem bastante e façam os exercícios e exemplos.

Microcontroladores - PIC

56


MICROCONTROLADORES PIC EM C

Exemplos: 1. Resolver o seguinte problema: Fazer o Projeto, para o controle da Bomba B1, sendo que o nível sempre estará entre S1 e S2 (sensores bóia). Quando o nível atinge o motor S2 o seu contato fecha, e quando o nível atinge S1 este também fecha, sendo que S2, já esta fechado porque o nível esta sobre S2.

Para poder ter uma noção, de como poderia ser o circuito eletrônico, é apresentado o esquemático deste. O motor não pode ser ligado diretamente pelo PIC, por enquanto consideraremos que um Led (LMOTOR)representando o Motor.

Ilustração 31: Circuito elétrico do exemplo 7.1

Microcontroladores - PIC

57


MICROCONTROLADORES PIC EM C

Simular o seguinte programa escrito. Depois descrever o seu funcionamento. /******************************************************** * CEFETES * Prof: Marco Antonio * Exemplo 2: Controle de Nível num tanque de água * Materia: MICROCONTROLADORES * Data: Julho 2006 /Linhares ********************************************************/ #include <16f877A.h> #use delay(clock=4000000, RESTART_WDT) #fuses xt,nowdt,noprotect,put,brownout,nolvp,nocpd,nowrt #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

#bit #bit #bit

LMotor = portb.0 S1 = portb.2 S2 = portb.3

void main () { set_tris_a(0b11111111); set_tris_b(0b11110110); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00; while(TRUE) { if((!S1)&&(!S2)) LMotor =1; if((S1)&&(S2)) LMotor = 0; } }

Microcontroladores - PIC

58


MICROCONTROLADORES PIC EM C

Exercícios 7.1: 1) Para que serve o operador de atribuição? 2) Assinale a expressão aritmética com resultado CORRETO: a) 2+3*5 = 30 b) 5*2/2 = 5 c) 4+6-8/2 = 6 d) (-3)*4 = 12 3) As expressões a seguir têm como resultado VERDADEIRO (1) ou FALSO (0)? a) 1 > 2 b) 2 >= 1 c) 3 != 3 d) 'c' == 'c' 4) Fazer um projeto para que a pressão do vapor sempre permaneça entre uma faixa específica (histerese), sabendo que a histerese do pressostato é calibrada no instrumento. Os níveis do tanque sempre devem de estar entre S1 e S2, sabendo que a bomba 1 tem uma partida simples. V2 só abrira quando a pressão esteja entre os níveis de histereses determinado.

. Ilustração 32: Exercício 7.4, controle de pressão

Microcontroladores - PIC

59


MICROCONTROLADORES PIC EM C

5) Um misturador permite a seleção entre 2 materiais através de um seletor S2. Na posição 1 (S2 = 0), o material A passa para o tanque de mistura se o botão S1 esta atuado simultaneamente. Com o seletor S2 em posição 2 (S2=1) e S1 atuado o material B passa para o tanque de mistura. As Válvulas solenóides VA e VB permitem a passagem dos materiais. Faça o projeto e simule.

Ilustração 33: Exercício 7.5, misturador, combinacionais

Microcontroladores - PIC

60


MICROCONTROLADORES PIC EM C

8. TEMPORIZAÇÃO NO PIC Los “temporizadores” los encontramos en muchos lugares de nuestra vida diaria, generalmente integrados en aparatos domésticos. Por ejemplo en los hornos de microondas para controlar el tiempo de calentamiento de nuestros alimentos, o en las lavadoras de ropa para seleccionar el tiempo lavado. También a escala industrial las aplicaciones de los temporizadores son múltiples. Los hay para controlar el tiempo de arranque de algún proceso, se usan en máquinas herramientas, en dosificadores, fotografía, etc. La lista es interminable. Neste capítulo aprenderemos a usar temporizadores, são duas formas básicas: usando a função delay e interrupções. A função delay não permite a execução de outras funções no decorrer do tempo, já usando interrupções isto não acontece. Desta forma, as interrupções têm muitas vantagens sobre a função Delay.

8.1.

A função Delay:

Esta função criará código para executar uma demora do tempo especificado. O tempo é especificado em milisegundos. Esta função trabalha executando um número preciso de instruções para causar a demora pedida. O tempo de demora pode ser mais longo do que o pedido se uma interrupção for chamada durante a espera do tempo. O tempo gastado na interrupção não conta para o tempo de demora. Sintaxes da função: delay_ms(time); Parâmetros: time – se for variável de 0 a 255 se for constante de 0 a 65635. Exemplo 8.1: È conveniente observar que neste exemplo o watch dog timer esta ativado, neste caso será necessário resetar o WDT para que o PIC não seja resetado e comece a ser executada a primeira linha do programa. Para isto é usada a função RESTART_WDT().

Alem da função Delay, existem outras funções que ainda não foram vistas. Trata-se das funções output_high(PIN_B0) e output_low(PIN_B0). A função output_high(PIN_B0), é utilizada para setar (ou seja, colocar em nível lógico ‘1’) um pino do microcontrolador. Isto significa que o pino RB0 (da porta B) será setado. Note que “PIN_B0” é um símbolo predefinido para especificar o pino RB0. Este símbolo esta localizado no arquivo de cabeçalho do processador “16f877A.h”.

Microcontroladores - PIC

61


MICROCONTROLADORES PIC EM C

Da mesma forma a função output_high(PIN_B0), é utilizada para resetar (ou seja, colocar em nível lógico ‘0’) um pino do microcontrolador. Isto significa que o pino RB0 (da porta B) será resetado. /******************************************************** * CEABRA * Prof: Marco Antonio * Exemplo 1: Pisca – Pisca (Estrutura básica de um programa) * Matéria: Microcontroladores * Data: Julho 2006 ********************************************************/ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

*

*

#fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt

// configuração dos fusíve

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definições para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

*

#use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07

Microcontroladores - PIC

62


MICROCONTROLADORES PIC EM C #byte #byte

portd = 0x08 porte = 0x09

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

*

void main () { // configura CONFIG setup_counters(RTCC_INTERNAL, WDT_2304MS); // configura os TRIS set_tris_a(0b11111111); set_tris_b(0b11111000); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); // inicializa os ports porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00;

// configuração dos pinos de I/O

// limpa porta // limpa portb // limpa portc // limpa portd // limpa porte

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { RESTART_WDT(); output_high(PIN_B0); delay_ms(1000); output_low(PIN_B0); delay_ms(1000); output_high(PIN_B1); delay_ms(1000); output_low(PIN_B1); delay_ms(1000); } // FIM DO PROGRAMA } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa *************************************

Microcontroladores - PIC

*

63


MICROCONTROLADORES PIC EM C

Ilustração 34: Circuito para o Exemplo 2

8.2.

Interrupção Temporizador:

As interrupções são mecanismos que o microcontrolador possui e que torna possível responder a alguns acontecimentos no momento em que eles ocorrem, qualquer que seja a tarefa que o microcontrolador esteja a executar no momento. Esta é uma parte muito importante, porque fornece a ligação entre um microcontrolador e o mundo real que nos rodeia. Geralmente, cada interrupção muda a direção de execução do programa, suspendendo a sua execução, enquanto o microcontrolador corre um subprograma que é a rotina de atendimento de interrupção. Depois de este subprograma ter sido executado, o microcontrolador continua com o programa principal, a partir do local em que o tinha abandonado.

8.3.

O temporizador TIMER 0

Os temporizadores são normalmente as partes mais complicadas de um microcontrolador, assim, é necessário gastar mais tempo a explicá-los. Servindonos deles, é possível relacionar uma dimensão real que é o tempo, com uma variável que representa o estado de um temporizador dentro de um microcontrolador. Fisicamente, o temporizador é um registro cujo valor está continuamente a ser incrementado até 255, chegado a este número, ele começa outra vez de novo: 0, 1, 2, 3, 4, ...,255, 0,1, 2, 3,..., etc.

Microcontroladores - PIC

64


MICROCONTROLADORES PIC EM C

Este registro é chamado de TMR0 que é incrementado a cada ciclo de máquina (sem pré-escala: Clock/4). Se ocorrer uma escrita em TMR0, o incremento será inibido pelos dois ciclos de máquina seguintes. A interrupção do Timer 0 é gerada quando o conteúdo do registrador TMR0 passar de FFH para 00H. Exemplo 8.2: Vejamos neste exemplo como configurar o módulo timer 0 para que uma saída pisque a cada segundo. Neste caso o clock é de 4 MHz e é utilizado um prescaler de 32, então teremos uma freqüência de entrada no timer 0 de: Fosc/(4*preEscala) = 4 000 000/(4*32) = 31250 Deste resultado podemos tirar uma conclusão: a cada vez que o registro TMR0 se incrementa em 1, passa na verdade um tempo de 1/31250 seg. Agora a pergunta é a cada quanto tempo é chamada a função de interrupção? A resposta é simples como a função de interrupção é chamada depois do estouro do registrador TMR0 e esta estoura depois de 255 vezes o tempo para cada interrupção será de: 255*1/31250 = 0,00816 seg O tempo desejado é de 1 seg, então: #Interrup*0,00816 seg = 1 seg Î #Interrup = 122,549 Como o número de interrupções é inteiro, temos que encontrar outro médio de ter maior exatidão. Para isto, podemos iniciar o registro TMR0 com 13, de forma que a primeira interrupção aconteça depois de 125 ciclos (256-131) de TMR0, e para fazer isto repetitivo é reiniciado o registro TMR0 com 131 na propria sub-rotina de interrupção. Cada interrupção teria 125 ciclos, como cada ciclo tem um tempo de 1/31250 Î cada interrupção terá um tempo de 125*1/31250 = 0,004 seg. O tempo desejado é de 1 seg, então: #Interrup*0,004 seg = 1 seg Î #Interrup = 250

/******************************************************** * CEFETES * Prof: Marco Antonio * Exemplo 8.2: Pisca - Pisca, usando interrupção Timer 0 * Materia: Eletrônica Digital * Data: Setembro 2005 ********************************************************/ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <16f877A.h> // microcontrolador utilizado /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Microcontroladores - PIC

*

*

65


MICROCONTROLADORES PIC EM C #fuses

xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt // configuração dos fusíveis

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definições para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

*

#use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //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. int conta; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. #bit led = portb.0

// Led correspondente ao botão 0

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #int_timer0 void trata_t0() {

Microcontroladores - PIC

*

66


MICROCONTROLADORES PIC EM C //reinicia o timer 0 em 131 menos a contagem que já passou set_timer0 (131-get_timer0()); conta++; //se já ocorreram 125 interrupções if (conta ==125) { conta=0; led = !led; //inverte o led } } void main () { // configura CONFIG setup_counters(RTCC_INTERNAL, WDT_2304MS); //configura o timer 0 para o clock interno e prescaler dividindo por 32 setup_timer_0 (RTCC_INTERNAL | RTCC_DIV_32 ); SET_TIMER0(131); //INICIA O TIMER 0 EM 131 //HABILITA INTERRUPÇÕES ENABLE_INTERRUPTS (GLOBAL | INT_TIMER0); // configura os TRIS set_tris_a(0b11111111); set_tris_b(0b11111000); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); // inicializa os ports porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00;

// configuração dos pinos de I/O

// limpa porta // limpa portb // limpa portc // limpa portd // limpa porte

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { RESTART_WDT(); } // FIM DO PROGRAMA } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Microcontroladores - PIC

*

67


MICROCONTROLADORES PIC EM C

Exercícios 8.1: 1) Qual é a diferença entre usar a função Delay e a interrupção do TMR0? 2) Fazer um semáforo, primeiro usando a função Delay e depois usando a interrupção TMR0. Simular e testar na bancada. 3) Utilizando seu conhecimento em temporizadores, automatizar o sinal de trânsito. Simular e testar na bancada.

Red = O:2/00 Green = O:2/06

Amber = O:2/05

8 sec.

4 sec.

Green = O:2/02

Amber = O:2/01

R

Red = O:2/04 1s

8 sec.

4 sec.

1s

<-------------------------------- Tempo em segundos ------------------------------>

4) O proprietário de uma casa está cansado porque muitas vezes os ladrões entram no quintal e decidiu pedir ajuda aos alunos do CEFETES-Linhares. Pediu uma forma barata de fazer um alarme. O professor orientou aos alunos da seguinte forma: •

• • •

Como o quintal era grande pediu para usar um diodo lazer para construir um sensor de barreira, só que o lazer não podia estar ligado constantemente, devia ficar ligado o 10% do período a uma freqüência de 1 KHz. Para o receptor oriento trabalhar com uma resistência LDR que tem maior área sensora. O alarme não poderia disparar imediatamente ao ser cortada a barreira, deverá esperar ½ segundo para ter certeza que se trata de um ladrão. Boa sorte galera. Vocês terão que montar o projeto.

Microcontroladores - PIC

68


MICROCONTROLADORES PIC EM C

5) Quando o sensor S5 detecte a presença de uma pessoa a porta abrirá rapidamente até que o sensor S3 seja atingido, onde a velocidade diminui quando chegue a S4 este para, espera 15 segundos e o portão fecha. Chegando a S2 a velocidade diminui e em S1 o portão para. Considera a velocidade lenta como uma saída VL e a rápida como VR. Faz o grafcet e o projeto.

6) Pressionando o botão S1 o guindaste vai para a izquerda até o fim de curso S5 onde para, só o botão S3 faz ao guindaste retornar até a posição S6. O botão S2 envia o guindaste para a direita até S7 e para retornar só o botão S4 faz este retornar até S6. Sem grafcet.

Microcontroladores - PIC

69


MICROCONTROLADORES PIC EM C

9. SINAIS ANALÓGICOS NO PIC Como os sinais dos periféricos são substancialmente diferentes daqueles que o microcontrolador pode entender (zero e um), eles devem ser convertidos num formato que possa ser compreendido pelo microcontrolador.

9.1.

CONCEITOS BÁSICOS DOS CONVERSORES

Uma entrada analógica de tensão para que possa entrar no CLP, PIC ou computador precisa ser amostrada e convertida num valor numérico através de um conversor A/D. A seguinte figura mostra como muda a tensão contínua sobre o tempo. Existem três amostras indicadas na figura. O processo de amostragem dos dados não é instantâneo, existe um tempo inicial e final. O tempo requerido para a amostra é chamado de tempo de amostragem.

Ilustração 35: Amostragem de um sinal analógico

O conversor A/D pode só adquirir um número limitado de amostras por segundo. O tempo entre cada amostra é chamado de período de amostragem T e a inversa desse período é a freqüência de amostragem. A freqüência de amostragem dependerá de alguns fatores como do programa e do Clock. Existem vários ranges de entradas analógicas padronizadas como de 0 a 5V, de 0 a10V, de -5 a 5V, de -10 a 10V, de 0 a 20 mA, de 4 a 20 mA. Quando o tipo do sinal analógico for corrente, é necessário colocar em serie uma resistência de para transformar este sinal em tensão. A resistência recomendada é de 250 ohms, desta forma ranges de 0 a 20ma e de 4 a 20 mA transformam-se em faixas de 0 a 5V e de 1 a 5V respectivamente. Microcontroladores - PIC

70


MICROCONTROLADORES PIC EM C

O número de bits do conversor A/D é o número de bits da palavra resultado. Se o conversor A/D fosse de 8 bits, então o resultado ter 256 níveis. O PIC que estamos usando tem conversores de 10 bits. No exemplo da figura seguinte vemos que se a freqüência de amostragem fosse menor que a freqüência do sinal o instrumento estaria perdendo informação. Para isto é recomendado que a freqüência do CLP deve de ser pelo menos duas vezes a do sinal.

Ilustração 36: Amostragem de um sinal com freqüência muito maior a frequencia de amostragem

Exercícios 9.1: a) Sendo que o range de uma entrada analógica de um CLP é de 0 a10V, e o conversor tivesse uma resolução de 10 bits. Qual seria o valor do número resultante para uma entrada de 5 volts? b) No desenho temos um potenciômetro que atua como sensor do braço Mecânico construído por alunos do CEFETES/AN3 2003, este potenciômetro representa a posição do braço, sendo que a posição do braço é de 0 a 100%. E o potenciômetro na posição 0% tem uma tensão de saída de 1V e na de 100% uma tensão de 4.5 V, e esta tensão representa a entrada analógica do PIC na variável SenAnalog1 (0/4095-10bits e de 0 a 5V), disser qual será a variação de SenAnalog1.

Microcontroladores - PIC

71


MICROCONTROLADORES PIC EM C

9.2.

Tratamento de Entradas Analógicas no PIC

As funções necessárias para poder desenvolver uma aplicação usando sinais analógicos são as seguinte: #device adc=10

Especifica ao compilar o número de bits da conversão analógico digital setup_adc_ports (RA0_RA1_RA3_analog);//Configura Vdd e Vss como Vref

Configura os pinos para serem entradas analógicas, digital ou uma combinação destes. O parâmetro escrito dentro do parênteses é uma constante e são usadas constantes diferentes para cada tipo de PIC. Checar o arquivo de cabeçalho para visualizar a lista completa disponível destas constantes. As constantes ALL_ANALOG e NO_ANALOGS estão disponíveis em todos os PICs. Exemplos: setup_adc_ports (RA0_RA1_RA3_analog); se configuram as entradas RA0, RA1 e RA3 como entradas analógicas e as rederencias de tensão são 5v e 0v. Todos os outros pinos são digitais setup_adc_ports( ALL_ANALOG ); todos os pinos são entradas analógicas setup_adc_ports( RA0_RA1_ANALOGRA3_REF ); RA0 e RA1 são analógicos e RA3 é usado como referencia. Todos os outros pinos são digitais.

No arquivo cabeçalho 16F877A.h encontramos as constantes: // Constants used in SETUP_ADC_PORTS() are: #define NO_ANALOGS 7 // None #define ALL_ANALOG 0 // A0 A1 A2 A3 A5 E0 E1 E2 Ref=Vdd #define AN0_AN1_AN2_AN4_AN5_AN6_AN7_VSS_VREF 1 // A0 A1 A2 A5 E0 E1 E2 Ref=A3 #define AN0_AN1_AN2_AN3_AN4 2 // A0 A1 A2 A3 A5 Ref=Vdd #define AN0_AN1_AN2_AN4_VSS_VREF 3 // A0 A1 A2 A5 Ref=A3 #define AN0_AN1_AN3 4 // A0 A1 A3 Ref=Vdd #define AN0_AN1_VSS_VREF 5 // A0 A1 Ref=A3 #define AN0_AN1_AN4_AN5_AN6_AN7_VREF_VREF 0x08 // A0 A1 A5 E0 E1 E2 Ref=A2,A3 #define AN0_AN1_AN2_AN3_AN4_AN5 0x09 // A0 A1 A2 A3 A5 E0 Ref=Vdd #define AN0_AN1_AN2_AN4_AN5_VSS_VREF 0x0A // A0 A1 A2 A5 E0 Ref=A3 #define AN0_AN1_AN4_AN5_VREF_VREF 0x0B // A0 A1 A5 E0 Ref=A2,A3

Microcontroladores - PIC

72


MICROCONTROLADORES PIC EM C #define AN0_AN1_AN4_VREF_VREF 0x0C // A0 A1 A5 Ref=A2,A3 #define AN0_AN1_VREF_VREF 0x0D // A0 A1 Ref=A2,A3 #define AN0 0x0E // A0 #define AN0_VREF_VREF 0x0F // A0 Ref=A2,A3 #define ANALOG_RA3_REF 0x1 //!old only provided for compatibility #define A_ANALOG 0x2 //!old only provided for compatibility #define A_ANALOG_RA3_REF 0x3 //!old only provided for compatibility #define RA0_RA1_RA3_ANALOG 0x4 //!old only provided for compatibility #define RA0_RA1_ANALOG_RA3_REF 0x5 //!old only provided for compatibility #define ANALOG_RA3_RA2_REF 0x8 //!old only provided for compatibility #define ANALOG_NOT_RE1_RE2 0x9 //!old only provided for compatibility #define ANALOG_NOT_RE1_RE2_REF_RA3 0xA //!old only provided for compatibility #define ANALOG_NOT_RE1_RE2_REF_RA3_RA2 0xB //!old only provided for compatibility #define A_ANALOG_RA3_RA2_REF 0xC //!old only provided for compatibility #define RA0_RA1_ANALOG_RA3_RA2_REF 0xD //!old only provided for compatibility #define RA0_ANALOG 0xE //!old only provided for compatibility #define RA0_ANALOG_RA3_RA2_REF 0xF //!old only provided for compatibility

setup_adc (opções);

Esta função configura o relojo para o conversor A/D. As opções são variáveis ou constantes inteiras de 8 bits. As opções variam de acordo com cada PIC e podem ser encontradas no arquivo de cabeçalho de cada dispositivo. No caso do Pic 16F877A encontramos: • ADC_OFF • ADC_CLOCK_DIV_2 • ADC_CLOCK_DIV_4 • ADC_CLOCK_DIV_8 • ADC_CLOCK_DIV_16 • ADC_CLOCK_DIV_32 • ADC_CLOCK_DIV_64 • ADC_CLOCK_INTERNAL Ejemplo: setup_adc(ADC_CLOCK_INTERNAL); set_adc_channel (1);

Sintaxe: set_adc_channel (canal) Parâmetros: canal é o número do canal selecionado. O número do canal começa com zero referente ao pino AN0. Função: Especifica o canal que será usado para executar o próximo comando READ_ADC. Verifique que passe um pequeno tempo antes de trocar de canal para que possa ter maior exatidão. O tempo varia em função do valor da impedância da fonte de entrada. Em geral 10us são suficientes. Não será necessário trocar de canal antes de cada leitura se o canal não muda. Esta função esta disponível em PICs com conversores A/D. Exemplo: set_adc_channel(2); delay_us(10); value = read_adc(); read_adc(); Sintaxe: value = read_adc ([mode]) Parâmetros: mode é um parâmetro opcional. Se usado estes podem ser: ADC_START_AND_READ (this is the default) ADC_START_ONLY (starts the conversion and returns) ADC_READ_ONLY (reads last conversion result)

Microcontroladores - PIC

73


MICROCONTROLADORES PIC EM C Retorna: o valor da conversão analógica digital para o caso do PIC 16F877A, retorna um valor de 16 bits. Função: Esta função faz a leitura do valor digital do conversor analógico digital.

Examples: setup_adc( ADC_CLOCK_INTERNAL ); setup_adc_ports( ALL_ANALOG ); set_adc_channel(1); value = read_adc();

Exemplo 9.2: Neste exemplo existe um sinal analógico variando de 0 a 5v entrando no pino RA0. Se a tensão for menor que 1v um led deverá indicar que a tensão esta baixa, se a tensão estiver entre 1 e 4 volts um outro led indicará que a tensão esta média, e se a tensão estiver entre 4 e 5v um outro led indicará que a tensão esta alta. Este programa foi feito com a intenção de servir como modelo para o desenvolvimento de outros projetos. Como o PIC16F877A tem uma resolução de 10 bits para os sinais analógicos então na escala da conversão variará de 0 a 1023. Quando se trata de conversão analógico-digital é comum usar escalonamentos, existe uma forma de transformar valores a outras escalas. Relembremos um pouco de instrumentação: EscNova – OffsetEscNova -------------------------------------- = SpanEscNova

EscVelha – OffsetEscVelha --------------------------------------SpanEscVelha

No caso deste exemplo não temos offset. A escala nova vária de 0 a 5 v, a velha de 0 a 1023, para transformar da escala velha à nova: EscNova = 5 * Conversão/1023

/******************************************************** * CEFETES * Prof: Marco Antonio * Exemplo 4: Conversão analógica digital * Materia: Eletrônica Digital * Data: Julho 2006 ********************************************************/ #include <16f877A.h> #device adc=10

Microcontroladores - PIC

// microcontrolador utilizado

74


MICROCONTROLADORES PIC EM C #fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt #use

delay(clock=4000000, RESTART_WDT)

#use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

// configuração dos fusíveis

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ float conversao = 0; // armazena o resultado da conversão AD /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #bit LedTensaoBaixa = portb.0 #bit LedTensaoMedia = portb.1 #bit LedTensaoAlta = portb.2 void main() { // configura microcontrolador setup_adc_ports (RA0_RA1_RA3_analog);//Configura Vdd e Vss como Vref setup_adc (adc_clock_div_32); setup_counters (rtcc_internal, WDT_2304MS); set_adc_channel (1); // configura os tris set_tris_a(0b11011111);

// configuração da direção dos pinos

de I/O set_tris_b(0b00000000); set_tris_c(0b11111101); set_tris_d(0b00000000); set_tris_e(0b00000100); // inicializa os ports porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00; while(TRUE) { RESTART_WDT();

// limpa porta // limpa portb // limpa portc // limpa portd // limpa porte // rotina principal // incia o watch-dog timer

conversao = read_adc(); // inicia conversão AD conversao = (conversao * 5); // faz regra de 3 para converter o valor, conversao = (conversao / 1023); // das unidades de AD em Volts.

Microcontroladores - PIC

75


MICROCONTROLADORES PIC EM C if (conversao<=1) LedTensaoBaixa = 1; else LedTensaoBaixa = 0; if ((conversao<=4)&&(conversao>=1)) LedTensaoMedia = 1; else LedTensaoMedia = 0; if ((conversao<=5)&&(conversao>=4)) LedTensaoAlta = 1; else LedTensaoAlta = 0; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Exercícios: 1. Construir uma rampa de aceleração, para acionamento da bomba do problema 2, mostrada no gráfico abaixo:

Microcontroladores - PIC

76


MICROCONTROLADORES PIC EM C

A cada 2 s o uC deve adicionar à sua saída analógica 1 volt, até alcançar 10 volts. Isto será iniciado quando o operador pressionar o botão start, e quando for pressionado o botão stop a rampa deverá ser decrescente até o motor parar. Para este problema assuma que a saída analógica é a porta B e que através de um DAC é conectada à entrada analógica do inversor. 2. Em uma linha de produção temos 3 produtos. O primeiro produto foi embalado em uma caixa de 10 cm de altura, o segundo com 8 cm de altura e o terceiro com 5 cm de altura. Temos que contar a quantidade de cada produto que passa na esteira pelos sensores infravermelhos. Existe um sensor ultra-som para medir a altura das caixas e um sensor capacitivo para determinar que as caixas estão baixo o sensor Ultra-som. Depois que passem 5, 7 e 8 caixas de cada produto 1,2 e 3 respectivamente as lâmpadas L1, L2 e L3 deverão ligar por um tempo de 5 segundos cada e a contagem deverá ser reiniciada. Quer disser se passam 5 caixas do produto 1 a lâmpada 1 liga e depois de 5 segundos esta desliga. 3. Fazer um programa para representar através da variável NívelT1 o nível do tanque 1 em unidades de engenharia. Sabe-se que o LT usado para medir o nível é um Ultra-som sendo seu range de 0-20 mA na saída e de 0-10 m na entrada. Mostrar em 3 displays de 7 segmentos o valor de 0 a 100% do nível. 4. Fazer um controlador ON-OFF, para a automatização da planta mostrada na seguinte figura.

Microcontroladores - PIC

77


MICROCONTROLADORES PIC EM C

mA

Curva Característica do Sensor

20

4

VARIÁVEL DO PROCESSO 0%

100%

Nível

4-20mA

4-20mA

LT

Tanque

CP Y0

SET - POINT

VARIÁVEL MANIPULADA OU DE CONTROLE

INVERSOR WEG

B1

Assuma que a fonte de corrente variável esta instalada na entrada AN0 através de uma resistência de 250 ohms e que a sinal do PDT esta instalado na entrada AN1 também com uma resistência de 250 ohms. A velocidade da bomba não é variada pelo uC, mas o controle de liga e desliga sim.

Microcontroladores - PIC

78


MICROCONTROLADORES PIC EM C

10.COMUNICAÇÃO SERIAL Em muitas aplicações microcontroladas, pode ser necessário realizar a comunicação entre o microcontrolador e um ou mais dispositivos externos. Esses dispositivos podem estar localizados tanto na mesma placa do circuito, como fora dela, a metros ou mesmo dezenas de quilômetros de distância. A escolha do sistema de comunicação mais adequado para realizar a tarefa depende de diversos fatores, como: velocidade, imunidade a ruídos, custo, etc. As duas formas conhecidas são a comunicações seriais e a paralela. Na comunicação paralela enviamos uma palavra por vez ao longo de um barramento composto por vários sinais. A comunicação com impressoras é tipicamente uma comunicação paralela. A velocidade é alta, porém as distâncias são curtas. Além do envio dos dados deve-se também enviar sinais de controle. Na comunicação serial o dado é enviado bit por bit. O cabo que conecta os dispositivos pode ser mais longo, em virtude de características especiais do sinal que é transmitido. 10.1. Comunicação Serial Síncrona x Comunicação Serial Assíncrona Diversos protocolos de comunicação operam sobre comunicação serial: redes de campo, comunicação com modens, etc... Existem dois modos de comunicação serial: Síncrono e Assíncrona. Comunicação Serial Síncrona Neste modo de comunicação o transmissor e o receptor devem ser sincronizados para a troca de comunicação de dados. Geralmente uma palavra de SINCRONISMO é utilizada para que ambos ajustem o relógio interno. Após a sincronização os bits são enviados seqüencialmente, até uma quantidade pré-combinada entre os dispositivos. Comunicação Serial Assíncrona Esta é a forma mais usual de transmissão de dados. Não existe a necessidade de sincronização entre os dispositivos, uma vez que os caracteres são transmitidos individualmente e não em blocos como na comunicação síncrona. A transmissão de cada caractere é precedida de um bit de start e terminada por 1 (1/2 ou 2) bit(s) de stop. O PIC 16F877A suporta duas formas de comunicação serial : • Comunicação assíncrona universal (formato RS232) SCI ou USART; • Comunicação síncrona entre dispositivos SPI;

Ilustração 37: Composição típica de um frame assíncrono

Microcontroladores - PIC

79


MICROCONTROLADORES PIC EM C

Notem que neste frame existe um bit de start, 8 bits de dados, um bit de paridade e um bit de parada. A paridade pode ser par ou ímpar. Quando a paridade é par o bit de paridade é gerado de modo que o número de 1s resultante na palavra mais o bit de paridade sejam pares. Por exemplo, se a palavra 10001010 está sendo transmitida, ou recebida, o bit de paridade deve ser 1, para que o conjunto palavra + bit de paridade tenha sempre um número par de 1s. Se a paridade usada for ímpar o bit de paridade no exemplo anterior será zero. No processo de transmissão assíncrona, os dispositivos envolvidos no processo de comunicação devem ter a mesma taxa de transmissão e recepção.

10.2. O RS232 no PIC Para realizar a interface de comunicação serial entre o PC e o circuito controlador, utiliza-se o conversor de nível de tensão padrão RS232 para TTL/CMOS (MAX232 – CI2) acrescido de quatro capacitores (1 μF / +50 VCC) em conjunto com o conector DB-9 (X1). O circuito integrado dedicado MAX232 estabelece a conversão dos níveis de tensão do microcontrolador PIC (0 VCC e +5 VCC) para os níveis de tensão da porta serial do computador padrão RS232 (-12 VCC e +12 VCC) e vice-versa.

Ilustração 38: Circuito básico de ligação do RS232 do PIC

Microcontroladores - PIC

80


MICROCONTROLADORES PIC EM C

Ilustração 39: Cabo serial para conectar DB9 com DB9

EXEMPLO: Neste exemplo esta sendo usada uma entrada analógica de 0 a 5V e o seu valor é transferido através do RS232 a um computador. No computador pode-se desenvolver um programa para poder trocar dados com o programa do PIC. Mas também podemos usar o hiperTerminal que é um acessório do Windows para comunicação serial. Basta ir a: Iniciar\Programas\Acessórios\Comunicações\Hiperterminal O programa exige que o operador digite uma letra “d” para que o PIC possa transmitir a informação. /******************************************************** * CEABRA * Prof: Marco Antonio * Exemplo 4: Conversão analógica digital e comunicação via RS232 * Matéria: Eletrônica Digital * Data: Outubro 2005 ********************************************************/ #include <16f877A.h> #device adc=10

// microcontrolador utilizado

#fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt #use #use

// configuração dos fusíveis

delay(clock=4000000, RESTART_WDT) rs232(baud=9600,xmit=pin_c6,rcv=pin_c7)

#define t_filtro 500 float conversao = 0; char Comando; #use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte

porta = 0x05 portb = 0x06

Microcontroladores - PIC

// tamanho do filtro // armazena o resultado da conversão AD

81


MICROCONTROLADORES PIC EM C #byte #byte #byte

portc = 0x07 portd = 0x08 porte = 0x09 void main()

{ // configura microcontrolador setup_adc_ports (RA0_RA1_RA3_analog);//Configura Vdd e Vss como Vref setup_adc (adc_clock_div_32); setup_counters (rtcc_internal, WDT_2304MS); set_adc_channel (1); setup_vref(VREF_LOW|6); // configura os tris set_tris_a(0b11011111);

// configuração da direção dos pinos

de I/O set_tris_b(0b00000011); set_tris_c(0b11111101); set_tris_d(0b00000000); set_tris_e(0b00000100); // inicializa os ports porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00;

// limpa porta // limpa portb // limpa portc // limpa portd // limpa porte

while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog timer Comando=getc(); if (Comando=='d') { conversao = read_adc(); // inicia conversão AD conversao = (conversao * 5); // faz regra de 3 para converter o valor, conversao = (conversao / 1023); // das unidades de AD em Volts. printf("Voltimetro: %f\r\n", conversao); delay_ms(1000); } // printf("Voltimetro: %c\r\n", Comando); // delay_ms(3000); } }

Exercícios: 1) Olhando o help do CCS explicar detalhadamente o programa feito no exemplo. 2) Pesquisar e mostrar a diferencia entre o RS485 e RS232. 3) Montar o circuito do exemplo explicado neste capítulo.

Microcontroladores - PIC

82


MICROCONTROLADORES PIC EM C

/******************************************************** * CEABRA * Prof: Marco Antonio * Exemplo 3: Controle de nível num tanque * Uma bomba é acionada quando o tanque esta vazio * e quando este esteja cheio, a bomba desliga. Dois sensores * são instalados, sensor de tanque cheio e tanque vazio. * Materia: Eletrônica Digital * Data: Outubro 2005 ********************************************************/ #include

<16f877A.h> // microcontrolador utilizado

/*#fuses xt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt dos fusíve*/ #fuses xt,WDT,NOPROTECT,put, NOLVP

// configuração

#use delay(clock=24000000, RESTART_WDT) #use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit

Tanque_Cheio = portb.0 // 1 -> Cheio

#bit

Tanque_Vazio = portb.1

//0 -> Vazio

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE. #bit

Bomba = portb.2

Microcontroladores - PIC

// 1 -> Bomba ligada 83


MICROCONTROLADORES PIC EM C

void main () { // configura CONFIG setup_counters(RTCC_INTERNAL, WDT_2304MS); // configura os TRIS set_tris_a(0b11111111); set_tris_b(0b00000011); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); // inicializa os ports porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00;

// configuração dos pinos de I/O

// limpa porta // limpa portb // limpa portc // limpa portd // limpa porte

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Loop principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { RESTART_WDT(); IF ((Tanque_Vazio==0) && (Tanque_Cheio==0)) Bomba=1; IF ((Tanque_Vazio==1) && (Tanque_Cheio==1)) Bomba=0; } // FIM DO PROGRAMA } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fim do Programa * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Microcontroladores - PIC

*

84


MICROCONTROLADORES PIC EM C

Ilustração 40: Circuito para o Exemplo 3

Exemplo4: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Programação em C - 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: mosaico@mosaico-eng.com.br * ************************************** * VERSÃO : 1.0 * * DATA : 05/06/2003 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

* * *

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Descrição geral * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ Microcontroladores - PIC

85


MICROCONTROLADORES PIC EM C

// Este software está preparado para ler quatro botões e tocar o buzzer com //duração variavel conforme a tecla pressionada, além de acender o led //indicando a última tecla pressionada. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DEFINIÇÃO DAS VARIÁVEIS INTERNAS DO PIC * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include

*

<16f877A.h> // microcontrolador utilizado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configurações para gravação * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

*

#fusesxt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusíveis

// configuração dos

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definições para uso de Rotinas de Delay * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

*

#use delay(clock=4000000, RESTART_WDT) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constantes internas * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de constantes facilita a programação e a manutenção. #define t_filtro 20 // tamanho do filtro /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização das variáveis * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //Neste bloco estão definidas as variáveis globais do programa. int status_botoes = 0; botões int status_leds = 0; pressionado int per = 0; int filtro1 = t_filtro; int filtro2 = t_filtro; int filtro3 = t_filtro; int filtro4 = t_filtro;

// armazena o estado lógico dos // atualiza leds conforme o botão

// inicia filtro do botao1 // inicia filtro do botao2 // inicia filtro do botao3 // inicia filtro do botao4

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Definição e inicialização dos port's * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #use fast_io(a) Microcontroladores - PIC

86


MICROCONTROLADORES PIC EM C

#use #use #use #use

fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Declaração dos flags de software * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //A definição de flags ajuda na programação e economiza memória RAM. #bit #bit #bit #bit

botao1_press = status_leds.0 botao2_press = status_leds.1 botao3_press = status_leds.2 botao4_press = status_leds.3

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ENTRADAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // As entradas devem ser associadas a nomes para facilitar a programação e //futuras alterações do hardware. #bit

botao1 = status_botoes.0 // Estado do botão 1 // 1 -> Liberado // 0 -> Pressionado

#bit

botao2 = status_botoes.1 // Estado do botão 2 // 1 -> Liberado // 0 -> Pressionado

#bit

botao3 = status_botoes.2 // Estado do botão 3 // 1 -> Liberado // 0 -> Pressionado

#bit

botao4 = status_botoes.3 // Estado do botão 4 // 1 -> Liberado // 0 -> Pressionado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // AS SAÍDAS DEVEM SER ASSOCIADAS A NOMES PARA FACILITAR A PROGRAMAÇÃO E //FUTURAS ALTERAÇÕES DO HARDWARE.

Microcontroladores - PIC

87


MICROCONTROLADORES PIC EM C

#bit

buzzer = porta.5

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tabela de Valores * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ byte const tabela[16] = {16,32,32,48,64,80,96,112,128,144,160,176,192,208,224,240}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Configuração do Microcontrolador * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // A rotina principal simplesmente limpa o WDT, pois toda a lógica do // programa é tratada dentro das interrupções. void main() { // configura microcontrolador setup_adc_ports (no_analogs); setup_counters(rtcc_internal , rtcc_div_8); setup_timer_2 (t2_div_by_16,per,1); // configura os tris set_tris_a(0b11011111); set_tris_b(0b11110000); set_tris_c(0b11111111); set_tris_d(0b11111111); set_tris_e(0b00000111); // inicializa os ports porta=(0b00000000); portb=(0b00000000); portc=(0b00000000); portd=(0b00000000); porte=(0b00000000); // habilita a interrupção de TMR0 enable_interrupts(GLOBAL|INT_RTCC); #priority timer0,timer2

// prioridade para a int de trm0

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina principal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ while(TRUE) { RESTART_WDT(); } }

// rotina principal // incia o watch-dog timer

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Microcontroladores - PIC

88


MICROCONTROLADORES PIC EM C

* Rotina de Tratamento de interrupção de TMR0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Esta interrupção ocorrerá a cada 2048us. // O filtro dos botões tem duração de 40ms (2048us x 20) e são decrementados a cada interrupção. // Esta interrupção é responsável por converter os pinos dos botões em entrada, salvar a condição // dos botões em variável temporária e converter os pinos em saída novamente. #int_rtcc void trata_int_tmr0(void) { set_tris_b(0b00001111); // configura os pinos como entrada para testar os botões delay_cycles(4); // aguarda 4 ciclos de máquina para a estabilização do portb status_botoes = portb; // lê o status dos botoes, salva em variável temporária status_botoes = (status_botoes & 0x0f); // zera a parte alta do registrador set_tris_b(0b00000000); // configura os pinos como saída para controle dos leds /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao1) { filtro1--; if (filtro1 == 0) { botao1_press = 1;

// testa botão 1 // botão 1 está pressionado ? // Sim, então decrementa o filtro // acabou o filtro do botão 1 ? // marca que o botão está

pressionado } } else { filtro1 = t_filtro; botao1_press = 0;

// botão 1 liberado // inicia o filtro do botão 1 // marca que o botão foi liberado

} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao2) { filtro2--; Microcontroladores - PIC

// testa botão 2 // botão 2 está pressionado ? // Sim, então decrementa o filtro 89


MICROCONTROLADORES PIC EM C

if (filtro2 == 0) { botao2_press = 1;

// fim do filtro do botão 2 ? // marca que o botão está

pressionado } } else { filtro2 = t_filtro; botao2_press = 0;

// botão 2 liberado // inicia o filtro do botão 2 // marca que o botão foi liberado

} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao3) { filtro3--; if (filtro3 == 0) { botao3_press = 1;

// testa botão 3 // botão 3 está pressionado ? // Sim, então decrementa o filtro // fim do filtro do botão 3 ? // marca que o botão está

pressionado } } else { filtro3 = t_filtro; botao3_press = 0;

// botão 3 liberado // inicia o filtro do botão 3 // marca que o botão foi liberado

} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tratamento do Botão 4 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ if (!botao4) { filtro4--; if (filtro4 == 0) { botao4_press = 1;

// testa botão 4 // botão 4 está pressionado ? // Sim, então decrementa o filtro // fim do filtro do botão 4 ? // marca que o botão está

pressionado } } else { filtro4 = t_filtro; Microcontroladores - PIC

// botão 4 liberado // inicia o filtro do botão 4 90


MICROCONTROLADORES PIC EM C

botao4_press = 0; }

// marca que o botão foi liberado

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Atualiza Leds conforme botões pressionados * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ portb = status_leds; // atualiza os leds

*

if (status_leds == 0) { per = 0xff; setup_timer_2 (t2_div_by_16,per,1); disable_interrupts (INT_TIMER2); buzzer = 0; } else { per = (tabela[status_leds]); // consulta tabela e inicializa timer2. setup_timer_2 (t2_div_by_16,per,1); enable_interrupts (INT_TIMER2);

// habilita interrupção de

timer2. } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina de Tratamento de interrupção de TMR2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Está interrupção só irá ocorrer quando alguma tecla estiver pressionada, // o periodo de ocorrência depende do botão ou da conbinação de botões pressionados, // ela irá inverter o pino de I/O do buzzer a cada interrupção. #int_timer2 void trata_int_tmr2(void) { if (buzzer != 0) { buzzer = 0; } else { buzzer = 1; } }

Microcontroladores - PIC

// o buzzer está ligado ? // sim, então desliga

// não, então liga

91


MICROCONTROLADORES PIC EM C

/******************************************************** * CEABRA * Prof: Marco Antonio * Exemplo 4: Conversaõ analógica digital e comunicação vía RS232 * Materia: Eletrônica Digital * Data: Outubro 2005 ********************************************************/ #include <16f877A.h> // microcontrolador utilizado #device adc=10 #fusesxt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusíveis

// configuração dos

#use delay(clock=4000000, RESTART_WDT) #use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7) #define

t_filtro 500

float conversao = 0; char Comando; #use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

// tamanho do filtro // armazena o resultado da conversão AD

void main() { // configura microcontrolador setup_adc_ports (RA0_RA1_RA3_analog);//Configura Vdd e Vss como Vref setup_adc (adc_clock_div_32); setup_counters (rtcc_internal, WDT_2304MS); set_adc_channel (1); // configura os tris set_tris_a(0b11011111);

// configuração da direção dos

pinos de I/O set_tris_b(0b00000011); set_tris_c(0b11111101); set_tris_d(0b00000000); set_tris_e(0b00000100); Microcontroladores - PIC

92


MICROCONTROLADORES PIC EM C

// inicializa os ports porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00;

// limpa porta // limpa portb // limpa portc // limpa portd // limpa porte

while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog timer Comando=getc(); if (Comando=='d') { conversao = read_adc(); // inicia conversĂŁo AD conversao = (conversao * 5); // faz regra de 3 para converter o valor, conversao = (conversao / 1023); // das unidades de AD em Volts. printf("Voltimetro: %f\r\n", conversao); delay_ms(1000); } // printf("Voltimetro: %c\r\n", Comando); // delay_ms(3000); } }

Microcontroladores - PIC

93


MICROCONTROLADORES PIC EM C

Microcontroladores - PIC

94


MICROCONTROLADORES PIC EM C

/******************************************************** * CEABRA * Prof: Marco Antonio * Exemplo 5: Uso dos LCDs * Materia: Eletrônica Digital * Data: Setembro 2005 ********************************************************/ #include

<16f877A.h> // microcontrolador utilizado

#fusesxt,wdt,noprotect,put,brownout,nolvp,nocpd,nowrt fusíveis

// configuração dos

#use delay(clock=4000000, RESTART_WDT) #zero_ram #use #use #use #use #use

fast_io(a) fast_io(b) fast_io(c) fast_io(d) fast_io(e)

#byte #byte #byte #byte #byte

porta = 0x05 portb = 0x06 portc = 0x07 portd = 0x08 porte = 0x09

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SAÍDAS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #bit rs = porte.0 // via do lcd que sinaliza recepção de dados ou comando #bit enable = porte.1 // enable do lcd /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um COMANDO para o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void comando_lcd(int caracter) { rs = 0; // seleciona o envio de um comando portd = caracter; // carrega o portd com o caracter enable = 1 ; // gera pulso no enable delay_us(1); // espera 3 microsegundos enable = 0; // desce o pino de enable delay_us(40);

Microcontroladores - PIC

// espera mínimo 40 microsegundos

95


MICROCONTROLADORES PIC EM C

return;

// retorna

} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Rotina que envia um DADO a ser escrito no LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void escreve_lcd(int caracter) { rs = 1; // seleciona o envio de um comando portd = caracter; // carrega o portd com o caracter enable = 1; // gera pulso no enable delay_us(1); // espera 3 microsegundos enable = 0; // desce o pino de enable delay_us(40); return;

// espera mínimo 40 microsegundos // retorna

} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Função para limpar o LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void limpa_lcd() { comando_lcd(0x01); // limpa lcd delay_ms (2); return; }

*

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Inicialização do Display de LCD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void inicializa_lcd() { comando_lcd(0x30); display delay_ms(4); comando_lcd(0x30); display delay_us(100);

*

// envia comando para inicializar // espera 4 milisengundos // envia comando para inicializar // espera 100 microsengundos

comando_lcd(0x30); display

// envia comando para inicializar

comando_lcd(0x38); 7x5, 2 linhas

// configura LCD, 8 bits, matriz de

limpa_lcd(); Microcontroladores - PIC

// limpa lcd 96


MICROCONTROLADORES PIC EM C

comando_lcd(0x0c);

// display sem cursor

comando_lcd(0x06);

// desloca cursor para a direita

return;

// retorna

} void main() { // configura microcontrolador setup_adc_ports (no_analogs); setup_counters (rtcc_internal, WDT_2304MS); // configura os tris set_tris_a(0b11011111);

// configuração da direção dos

pinos de I/O set_tris_b(0b00000011); set_tris_c(0b11111101); set_tris_d(0b00000000); set_tris_e(0b00000100); // inicializa os ports porta=0x00; portb=0x00; portc=0x00; portd=0x00; porte=0x00;

// inicializa os ports // limpa porta // limpa portb // limpa portc // limpa portd // limpa porte

inicializa_lcd();

// configura o lcd

while(TRUE) // rotina principal { RESTART_WDT(); // incia o watch-dog timer comando_lcd(0x80); // posiciona o cursor na linha 0, coluna 0 printf (escreve_lcd, " Marco Antonio"); // imprime mensagem no lcd comando_lcd(0xC2); // posiciona o cursor na linha 1, coluna 2 printf (escreve_lcd, " CEFETES "); // imprime mensagem no lcd } }

Microcontroladores - PIC

97

Introdução a programação e microcontroladores pic  
Introdução a programação e microcontroladores pic  
Advertisement