Eletrônica digital – alias, RS485, interrupções, PIC16F877A


Como prometido no post sobre rs485 com Arduino, agora vamos ver como fazer a comunicação bidirecional, completando assim o post sobre o assunto; mas além disso vamos entrar em detalhes importantes sobre interrupções (introduzido nesse post). Veremos como controlar uma interrupção adequadamente, achar as flags correspondentes e buscar as respostas sobre um determinado PIC no datasheet. Para finalizar, esse post usará como base o PIC16F877A para os exemplos. Iniciaremos pelas ferramentas.


PICmicro Database
Essa ferramenta é essencial para quem trabalha com MCU PIC. Com ela você poderá ver todas as características de uma determinada micro-controladora, filtrar por recursos ou simplesmente descontrair vendo os diversos sabores de PIC que existem. Ela trabalha offline e está disponível para Android no Google Play, no link acima.

ElectroDroid
Essa ferramenta é excepcional; possui diversas calculadoras para calculos específicos de projetos eletrônicos, além de plugins que dão mais poder à ferramenta. Entre os plugins, há um simulador de circuito, mas não deixe de visitar o link do Google Play para confirmar.

Como escolher o PIC

Existem muitos fatores que influenciam na escolha da MCU e, dependendo do tamanho do projeto, centavos podem ser representativos em escala de produção. Tamanho de circuito, número de trilhas, recursos periféricos, saídas PWM, comunicação USB e outros recursos variam de modelo para modelo, então o primeiro passo é amadurecer a idéia do objetivo, posteriormente escolher a MCU. Um detalhe que deve ser levado em consideração é a intensidade de processamento e complexidade do código e da operação. A quantidade dos diversos tipos de memória de cada MCU varia drasticamente e é necessário ter esse recurso de sobra ou muito bem planejado para não ter grandes surpresas durante uma fase mais avançada do desenvolvimento.

Especificamente esse post é baseado no P16F877A porque é a MCU padrão dos exemplos da IDE MikroC e como estou me adaptando à board de desenvolvimento (EasyPIC), preferi utilizar uma MCU que minimizasse possíveis dúvidas.

Comunicação RS485
A comunicação com o CI RS485 é transparente, de forma que a comunicação se dá pela UART, bastando escrever dados seriais. O ‘pulo do gato’ está no chaveamento dos pinos DE e RE do MAX485 e a forma de ligá-los é bastante simples; faz-se um jumping entre eles. O que definirá se os dados sairão ou entrarão é mais do que o TX e RX da UART, fazendo-se fundamental o chaveamento de controle de fluxo, descrito e detalhado no código adiante.

A comunicação RS485 possui duas partes fundamentais – o Master e o Slave. Isto é porque não podem ambos iniciar uma comunicação no barramento, pois não haveria como controlar a leitura e escrita sincronizada. Então, essa rede possui 1 Master e N Slaves.

A tarefa do Master é ser o controlador do barramento, que pode conter até 32 dispositivos em uma distância máxima de 1200 metros! Ou seja, toda a conversa é iniciada pelo Master e todos os Slaves ficam ‘escutando’ o barramento esperando que haja alguma tarefa para si.

A mensagem enviada pelo master é disparada como um broadcast no barramento; todos os dispositivos escutarão as mensagens, mas a resposta deverá partir exclusivamente do dispositivo a qual a mensagem pertença. Isso é possível graças a um identificador, normalmente colocado ao inicio da mensagem. Quando o Slave responde, novamente a mensagem trafega como um broadcast, porém é imediatamente descartado após a leitura do primeiro byte, que identifica a mensagem como uma resposta. Esses detalhes serão descritos no decorrer do código, mais adiante.

Indo mais a fundo, fica claro que o chaveamento do CI RS485 nos slaves está em um modo e no Master está de outro modo. Assim o é. Então, há duas maneiras para o Slave aguardar por uma mensagem.

Polling
Esse é o modo mais simples; em um loop infinito com um delay, o programa tentará validar dados no buffer na UART. Encontrando dados, passa a executar a tarefa de tratamento da mensagem de entrada e saída. Apesar de ser de fácil implementação, possui alguns contras, entre os quais, o consumo de energia certamente será maior, pois a MCU executará uma quantidade X de instruções a cada ciclo. Também nesse modo, é possível que haja pequenos delays na recepção e resposta pois a MCU pode estar executando outras tarefas que precedam a verificação de dados seriais.

Interrupções
A maneira mais clean de lidar com esse tipo de tarefa é com a utilização de interrupções. Ao meu ver, há uma semelhança muito grande com threads em programação desktop. Explico mais detalhadamente.

Quando habilitamos um determinado recurso na MCU, quando esse recurso é utilizado ele gera uma interrupção; um bit é marcado em reação ao evento. As interrupções podem ser desabilitadas ou pode-se habilitar de uma a todas, mas para isso é necessário basicamente ter o datasheet da MCU à mão. A grosso modo, a interrupção é como se fosse uma thread, que reage ao evento assincronamente. Os detalhes serão vistos no código, não se preocupe.

Ainda mais sobre as interrupções, elas são controladas por estágio; um conjunto de chaves que se ligam. O desenho do início deste post descreve com clareza uma interrupção; é como o chaveamento de um interruptor de luz. Para conhecer as chaves, deve-se procurar no datasheet por Interrupts. No datasheet do PIC16F877A, a tabela de interrupções é a seguinte:

Os circulos são as chaves necessárias para ligar as interrupções até o RCIF, marcado com um quadrado. Então, para saber quais chaves ligar, siga o esquema do datasheet e anote as chaves necessárias.

A vantagem de utilizar interrupção é que o processador não precisará fazer nada, ficará dormindo até que seja ‘despertado’ por um evento – quando o master disparar uma mensagem no barramento e essa mensagem chegar ao Slave, um bit é levantado e a implementação da função de interrupções começa a executar seu código, normalmente analisando qual interrupção aconteceu.

Falando diretamente da família F16, o conjunto de chaves necessários para habilitar a interrupção na recepção serial é inicialmente o GIE, ou Global Interrupt Enable. O GIE é a chave geral à qual todos os demais conjuntos de chaves se ligam, como se pode ver na tabela anterior. Se esta chave estiver desligada, nenhuma interrupção específica será utilizada.

Ligando o GIE, o próximo a habilitar é o PEIE ou, Peripheral Interrupt Enable. Essa chave controla as interrupções periféricas. Enfim, para habilitar a interrupção no RX do UART, deve-se habilitar o RCIE. E como saber essas relações sem ter que decorar nada? – resposta simples! RTFM (Read The Fine Manual).

No exemplo de interrupção utilizado nesse post, deve ser habilitada a interrupção de recepção serial, descrito no datasheet como RCIF (Receive Interrupt Flag). Um Ctrl+F no datasheet e encontrei o registrador responsável por essa flag, o PIR1:

Então para habilitá-lo há diversas maneiras, mas preferi utilizar a IDE MikroC, segurando a tecla Ctrl e clicando sobre uma variável qualquer do PIC padrão (escreva por exemplo, PORTC), abre-se a página de constantes, que foi o que utilizei para definir as minhas variáveis da maneira mais clara no código adiante.

Controle da interrupção
Quando uma interrupção acontece, a primeira tarefa é desligar a chave geral; não é prudente manipular interrupções com interrupções acontencendo a todo o tempo. Depois, analisa-se qual interrupção aconteceu e executa-se o bloco de códigos designado para tratar aquele tipo de evento. Ao termino, o bit da interrupção deve ser limpo e posteriormente a chave geral deve ser religada.

No decorrer do código pode ser bastante cansativo lembrar o nome de todos o bits de cabeça. Criar uma variável para cada também não é uma boa providência, pois isso consome preciosos recursos. Então para solucionar esse problema, utiliza-se o alias. Assim posso chamar o bit PIR1.RCIE de INTERRUPT_RX, o que parece bem auto-explicativo.

Agora vamos ver detalhes de todos os recursos citados até esse momento.

Código de exemplo RS485
Esse é o código do Slave:

As conexões físicas devem ser feitas assim no MAX485:

Laranja e Marrom são TX e RX ligados à MCU. O branco é controle de fluxo. A ligação com pilha AA foi apenas para saber onde é ground e onde é VCC, alimentados diretamente pelo PIC. No exemplo da IDE utiliza-se os pinos RC6 e RC7 que são TX e RX e o pino de controle RC2, porém na board de desenvolvimento o pino utilizado é RC0.

Os resistores das extremidades são 56R, os outros dois são 4K7.

No video, estou rodando direto da placa de desenvolvimento da LightComm, conversando diretamente com um terminal (GtkTerm) utilizando um conversor RS232 para RS485, também da lightcomm:

Nem todos os passos de um um produto que estamos desenvolvendo podem ser exibidos, mas quando o produto estiver disponível para o mercado, farei uma avaliação e indicarei onde comprar, pois com certeza será útil a muitas pessoas.

Se gostou, não deixe de compartilhar; dê seu like no video e inscreva-se no nosso canal Do bit Ao Byte Brasil no YouTube.

Prefere seguir-nos pelo facebook? Basta curtir aqui.

Prefere twitter? @DobitAoByte.

Próximo post a caminho!


Comments

comments

Djames Suhanko

Djames Suhanko é Perito Forense Digital. Já atuou com deployer em sistemas de missão critica em diversos países pelo mundão. Programador Shell, Python, C, C++ e Qt, tendo contato com embarcados ( ora profissionalmente, ora por lazer ) desde 2009.

Um comentário em “Eletrônica digital – alias, RS485, interrupções, PIC16F877A

Deixe uma resposta