By - - 0 Comments 1.057 visualizações

Olá pessoal. Neste post será tratado com mais detalhes a programação do micro controlador PIC16F628A utilizando a linguagem C, no ambiente da mikroelektronika o mikroC. Existe material farto na internet cobrindo o assunto, exemplos muito bons podem ser encontrados com certa facilidade com esquemas e código fonte completo. Muitas vezes sem documentação adequada, o iniciante acaba se perdendo ao deparar com alguns parâmetros, configurações, etc., isto frustra muito e também é o motivo de desistências no aprendizado. Tentarei neste post da melhor forma possível mostrar o “caminho das pedras”, tenho certeza que se houver empenho e vontade o leitor acabará entrando de vez neste mundo e o embarcando.

pic16f628a

Na programação (em qualquer linguagem) existe a famosa “receita de bolo” e isto vale também para micro controladores, hoje com linguagens muito avançadas (alto nível), muitas vezes o programador se preocupa apenas no que sua lógica deve fazer e não como fazer (as bibliotecas prontas ditam as regras de como será feito). No caso dos micro controladores a tendência é este caminho, sem esquecer a mais poderosa, a linguagem assembly não ficará no passado. Esta sempre terá seus momentos de glória, num mundo onde o software que está rodando, digamos ser a própria mente/inteligência do programador sendo executada linha após linha, tudo feito na “unha”, este não será nosso foco, porém alguns trechos do datasheet onde se mostra o assembly para a configuração, faremos um pequeno comparativo com a linguagem C.

pic16f628

Ao iniciar um projeto, devemos juntar todos os requisitos antes de começar qualquer codificação, isto impede que alguns problemas possam ocorrer por descuido ou mesmo falta de conhecimento no assunto. No último post,  disse que iriamos usar os componentes reaproveitados.  Neste faremos uso somente do cristal. Decidi usar nossa interface com leds e botões, afinal é necessário estreá-la! Neste projeto o requisito é aplicação somente digital. Como o PIC16F628A não possui conversores A/D internamente, não precisamos nos preocupar, porém ainda operando de forma analógica o mesmo possui 2  comparadores internos e multiplexados com os pinos no portA. Na imagem acima, encontra-se as descrições de cada pino. Note que podem possuir 1, 2, 3 ou mesmo 4 funções. Observe também as setas. As setas duplas, indicam que o pino pode trabalhar como entrada ou saída e setas simples apenas como entrada (não existe nenhuma apontando para fora do micro controlador, indicando apenas saída!). Sabendo que nosso projeto trabalhará com 0v ou 5v (bit 0 e bit 1), podemos procurar no datasheet como configurar corretamente nosso hardware interno ao pic. Vamos aos parâmetros:

  • Todos os pinos em modo digital.
  • O oscilador será à cristal com clock em 4Mhz (O clock interno do pic será XT / 4 = 1Mhz, todos dividem por 4 o clock vindo de fonte externa) .
  • Serão usadas entradas e saídas em modo digital.

Basicamente os itens acima satisfazem nosso propósito. Neste ponto, quero deixar claro aos amigos (iniciantes) que a leitura/entendimento do datasheet é tão fundamental (quanto entender um pouco de lógica e programação básica) para que nosso programa funcione. Não adianta questionar, quando adquirir experiência no assunto volte e deixe seu comentário (ou melhor experiência) sobre ler o datasheet do tal!

ScreenHunter_01-Jan.-26-22.56-300x46

No capítulo 5, temos os esclarecimentos dos pinos de entradas e saídas (i/o). Os textos que seguem são partes do datasheet, declaro não ser a tradução exata, mas um resumo para entendimento fácil; O PIC16F628A possui duas portas de comunicação com o mundo externo, chamadas de portA e portB. Alguns pinos estão multiplexados com funções dos periféricos presentes no interior do micro controlador. No quadro em destaque a nota 1 diz que quando ligamos a alimentação ou mesmo resetamos o micro controlador, o registrador TRISA é setado inteiramente com bit1 ou seja entradas (se fosse 0 seria saídas), isso é um padrão que a fábrica determina. As entradas digitais estão desabilitadas e as entradas dos comparadores forçadas ao GND para reduzir o consumo de corrente. Podemos concluir que isto é feito somente em função do consumo. A nota 2 diz que os bits RA6 e RA7 do trisA serão sobrescritos dependendo do oscilador, ou seja, se for determinado que todo portA for saída, quando o tipo de oscilador for setado (é claro, tem que ser externo!), os pinos RA6 e RA7 serão sobrescritos. Não é preciso direcionar estes dois bits ao usar o oscilador externo.

ScreenHunter_02-Jan.-26-23.23

A figura acima mostra mais um dado importante. Os comparadores estão ligados no portA, e o registrador responsável é o CMCON (devemos ir ao capítulo dos comparadores e ver o que encontramos por lá!). A nota nos diz que o pino A5 compartilha a entrada com a tensão de programação, ou seja, se aplicado um pulso de aproximadamente 13v neste pino, ele entra no modo de programação e fica a espera de um novo firmware escrito por nós.

ScreenHunter_03-Jan.-26-23.32

Uma espiada no capítulo 9, encontramos a situação da figura acima no reset do micro controlador. Os pinos RA1 e RA2 estão ligados no comparador 2; RA0 e RA3 no comparador 1. Presumimos desta forma que não tem como operar no modo digital sem antes mudar, ou melhor, desativar os comparadores.

ScreenHunter_04-Jan.-26-23.36

Para isto basta setar com bit 1 os bit CM0, CM1 e CM2 (figura acima). Vamos olhar como está distribuído o registrador CMCON na figura abaixo e ver onde estão localizados os bits CM2:CM0.

ScreenHunter_05-Jan.-26-23.37

O quadro vermelho mostra a posição dos bits que necessitamos. Seguindo a faixa de valores em azul, vemos o valor de cada bit no registrador.  Setando em 1 os bits necessários para desativar os comparadores, temos 4+2+1 = 7. Isto nos diz que se escrevermos o valor 7 no registrador CMCON, desativa-se os 2 comparadores. Mas como proceder?

ScreenHunter_06-Jan.-26-23.47

E aí está o assembly! O comando CLRF PORTA, limpa os pinos de saída do portA, isto evita que algum periférico externo seja ativado sem o consentimento de nosso programa (imagine um rele pequeno em algum pino do pic e um motor que seja acionado por este rele, e o mesmo parta antes de acionarmos!). Já o MOVLW (Move a Literal 0×07 para o registrador Work) é o nosso “4+2+1″ que irá desabilitar os comparadores!!! E o MOVWF CMCON é a escrita do valor 7 no registrador. Em C (mikroC) basta: [sourcecode language="c"] CMCON = 7; [/sourcecode] ou mesmo [sourcecode language="c"] CMCON |= 7;  // esta forma não altera o valor dos outros bits. [/sourcecode] Nesta altura, deve estar se perguntando: “e os outros bits do CMCON, como ficaram?”. Isto para nossa aplicação não é relevante, portanto podemos ignorar  os valores contidos nos bits 4:7. Ao usar CMCON = 7; em binário foi escrito 00000111 (repare que os outros bits estão desligados, caso contrario não teria sido escrito o valor 7 e sim algum maior entre 7 e 255). Alguns dos outros comandos (no quadro em assembly) serão visto mais tarde. Apenas por curiosidade, se o leitor ainda perguntar como os bits são acionados, a imagem abaixo responde a pergunta. Imaginemos que os bits dentro de um registrador sejam pequenas chaves. Aberta ela representa bit 0 e fechada bit 1. Assim esclarece um pouco mais a estrutura lógica de como fica a memória do micro controlador. Cada chave responde por uma função. Se acionada o processador irá verificar (quando necessário) a que função ela responde e tratará de atuar conforme programado pelo fabricante ou mesmo parâmetros passados pelo programador.

ScreenHunter_01-Jan.-28-20.09

Basicamente para que o PIC16F628A funcione, este é um dos parâmetros mais comuns a serem observados. Partiremos agora para o tipo de oscilador que usaremos no projeto.

oscilador

Usaremos um cristal de 4MHz e dois capacitores de 22pF como na figura acima. Como a nota de aplicação diz, alguns tipos de cristais poderão requerer o resistor em série. O datasheet do cristal pode fornecer melhor esta informação. Para o nosso projeto ele não é necessário. Outro detalhe que devemos analisar é que perderemos os pinos RA6 e RA7 como I/O, pois o cristal é ligado neles (a figura acima não deixou claro!). Para facilitar a colocação do cristal no protoboard, um pedaço de placa padrão, 3 pinos de uma barra e um pedaço de fio ajudaram muito. Veja o detalhe na foto.

Não é obrigatório, mas isso evita mau contato e falhas no processamento do código. Com este método, 20MHz no protoboard é conseguido sem problemas ;)

cristal

A figura acima mostra como ficou o cristal montado na placa padrão (um pedaço bem pequeno de placa apenas). O pino no fio marrom vai ao GND e os dois na placa vai o mais próximo do pic em OSC1 e OSC2 (RA7 e RA6 respectivamente).

Abaixo temos a famosa Configuration Word, ou Palavra de Configuração.

conf-word

Este registrador de 14 bits indica ao processador alguns periféricos que irão trabalhar em nosso código.

Os bits CP, são relativos a proteção do código gravado nas memórias internas do micro controlador. Por hora, não iremos tratar sobre elas.

O bit LVP ativa o modo de programação em baixa tensão quando setado em 1. Iremos utilizar um gravador que aplica um pulso de ~13v no pino MCLR, portanto este será setado em 0.

Os bits BODEN e WDTE também ficarão desativados. Não iremos precisar do Brown-out Detect e Watchdog Timer para esta aplicação.

O PWRTE fica opcional (1 = desabilitado, 0 = habilitado), o que ele faz é manter um pequeno atraso (72ms) antes de começar a rodar nosso programa, aguardando a estabilização da tensão.

O pino MCLRE ficará habilitado (bit 1), para resetar manualmente o micro controlador, esta opção deverá estar ativada.

Por fim o FOSC0:FOSC2, estes determinam o tipo de oscilador empregado:

fosc

Como escolhemos o cristal como oscilador, a opção nossa é 001 = XT oscillator. Com isso ligamos o cristal em RA6 e RA7 e perdemos estes dois pinos como entradas ou saídas digitais.

Como ficaria isto no mikroC?

Para o Word Config, usaremos o editor próprio pressionando CTRL + SHIFT + E (caso o projeto esteja aberto).

confword

A imagem acima mostra exatamente como deve ficar a palavra de configuração. Até aqui, o caro leitor já aprendeu algumas coisas que serão fundamentais ao funcionamento do código e consecutivamente a aplicação dele. Muitos detalhes poderão ser vistos no datasheet ou mesmo  na mikroelektronika1. É um excelente material para quem está começando.  Com riqueza de detalhes, imagens perfeitamente sugestivas e boa visualização no navegador, ela pode ser útil em qualquer linguagem de programação ou compiladores.

Para ajudar melhor ainda, um engenheiro português António Sérgio Sena2 traduziu o material para aplicar em cursos que o mesmo ministra. Você também pode fazer o Download3.

Falta agora o esquema para nosso projeto e posteriormente a programação aplicada.

Para quem montou nossa placa de interface, já tem-se a praticidade de ligar direto ao pic o canal escolhido nela. Para quem não, o esquemas seguem abaixo:

chave

Já o led é mais simples e também está disponível na placa de interface, segue o esquema:

led

Os pinos do micro controlador utilizado para ligar o led e o botão, farei a escolha durante a programação e será mostrado o esquema completo no final.

Inicio do projeto no ambiente mikroC (v4.15).

Suponho que o leitor já tenha conseguido sua cópia no site do desenvolvedor4. Lembre-se que para compilar até 2k de programa ele é free (O PIC16F628A só tem 2k de memória!).

mkc

Clique em Project > New Project (SHIFT + CTRL + N):

project

Clique em next na tela seguinte:

novo

Escolha o modelo 16F628A:

pic16

Acerte o Clock como segue:

clock

Determine um diretório e um nome para seu projeto:

diretorio

Não precisaremos de arquivos externos em nosso projeto, clique em next:

sem-include

As bibliotecas necessárias faremos manualmente, marque como esta abaixo e clique em Next:

biblioteca

Finalizando o projeto, marque a opção abaixo para abrir o editor da palavra de configuração:

finalizando

Esta  imagem foi mostrada anteriormente:

confwordproj

Clique em OK e teremos o ambiente pronto para iniciar a programação. Porém antes, marquemos as bibliotecas necessárias, clique ou passe o mouse em Library Manager no painel da direita:

libman

Bibliotecas necessárias:

libnec

Agora o ambiente está totalmente pronto para receber nossa codificação. Repare que ele já coloca na tela a função main:

voidmain

Faremos uso de 2 Macros para simplificar o programa:

#define Led PORTB.F0

e

#define Chave PORTA.F0

O que isto faz? R.: O pré-processador do compilador entenderá que onde escrevermos Led ou Chave, ele deverá subsitituir por PORTB.F0 e PORTA.F0 respectivamente.

Neste caso temos definido quais os pinos utilizaremos. Para o Led, RB0 e para a Chave RA0. O Leitor poderá usar o pinos que quiser no PORTB, pois este pode ter qualquer pino como entrada ou saída. Já não é o mesmo para o PORTA. Evite os pinos RA4 e RA5. Embora RA4 possa ser configurado como saída, ele é Dreno Aberto e uma configuração diferente da normal deve ser adotada, um caso para outro post. RA5 pode ser utilizado somente como entrada, porém é necessário desativar o MCLRE na palavra de configuração. RA6 e RA7 estão ocupado pelo cristal.

Seguramente os pinos RA0, RA1, RA2, e RA3 podem ser utilizados como I/O.

A forma de acessar bits individuais no mikroC é PORTx.Fy, onde x = Port ao qual se quer acessar: a, b, c, d, e, etc;  y = pino especifico: 0, 1, 2, 3, 4, 5, 6 ou 7. Existe outro metodo que consta no help do compilador (não utilizaremos neste post).

Até o momento, se o leitor estiver se perguntando mas como o compilador saberá o que é entrada e o que é saída, falta configurar o registrador TRISx para isso, onde x = A para o PORTA e x = B para o PORTB.

TRIS-e-PORT

A imagem acima ilustra como é a configuração do Registrador Tris. Ela fica sempre da seguinte forma:

Bit 7, 6, 5, 4, 3, 2, 1, 0

A configuração da imagem acima ficaria:

0b00110101 // Binário

0×35 //Hexadecimal

53 //Decimal

Exemplo: Aplicar a configuração da imagem acima ao trisB, como fica:

BCF STATUS, RP1

BSF STATUS, RP0 MOVLW 0×35 MOVWF TRISA

Acima o exemplo em assembly. Em C, logo abaixo:

TRISB = 0b00110101;  //Binário ou

TRISB = 0×35; //Hexadecimal ou

TRISB = 53 //Decimal

Bem simples, apenas lembre-se que os bits da direita são menos significativos e os da esquerda, mais significativos sempre!

Neste exemplo, usaremos também a função Button que é uma já pronta do compilador. Analise de como aplicar esta função.

Prototipo: unsigned short Button(unsigned short *port, unsigned short pino, unsigned short tempo, unsigned short estado_da_tecla); (Button (&PORTx,  pino x, tempo em ms, ligado ou desligado) Em nossa aplicação, a chave estará no pino RA3. if (Button (&PORTA, 3, 10, 0) {  // Se o pino RA3 estiver em 0, aguarde 10ms, se ainda continuar em 0 … // … Executa os códigos inseridos aqui. } Deve ter ficado claro como utilizar esta função. Algumas formas de aplicar a lógica de controle do botão e do led ainda serão apresentadas. Caberá ao leitor copiar e colar na IDE, no local indicado pelo arquivo do projeto (disponível para download mais abaixo).

esquema

A imagem acima mostra o esquema completo utilizado em nosso experimento. Devemos lembrar que os pinos de alimentação não apareceram neste esquema. O pino 5 vai ao GND (terra) e o pino 14 vai à VDD (+5v).

Download para o arquivo: Arquivos .Hex (238)

Alguns possíveis códigos, teste-os um de cada vez e veja o efeito. Tente manter o botão pressionado, ou pressione e solte para ver como se comporta os micro controlador.

[sourcecode language="c"] if(Button(&PORTA, 3, 10, 0)){ /* Verifica se a chave está pressionada, aguarda 10ms e verifica novamente. Caso ainda esteja executa os comandos: */ Led = !Led; // Inverte o estado do Led. delay_ms(500); // Aguarda 1/2s. } [/sourcecode] [sourcecode language="c"] // Executando a função Button através software implementado por nós mesmos. if(!Chave){ // Verificamos se a chave está pressionada. delay_ms(10); // Fazemos o debouce da chave por software em 10ms! if(!Chave){ // Caso continue pressionada, executa o código abaixo: Led = !Led; // Led = Led (invertido) delay_ms(500); } } [/sourcecode] [sourcecode language="c"] if(Button(&PORTA, 3, 10, 0)) int i = 0; for(i; i <= 9; i++){ Led = !Led; delay_ms(500); } } [/sourcecode] [sourcecode language="c"] // Executa o mesmo acima, só com debounce através de software. if(!Chave){ delay_ms(10); if(!Chave){ int i = 0; for(i; i <= 9; i++){ Led = !Led; delay_ms(500); } } } [/sourcecode] [sourcecode language="c"] if(!Chave){ delay_ms(10); if(!Chave){ int x = 0; for(x; x <= 4; x++){ int i = 0; for(i; i <= 9; i++){ Led = !Led; delay_ms(50); } delay_ms(1000); } } } [/sourcecode] [sourcecode language="c"] if(!Chave){ aux1 = 1; do { Led = !Led; delay_ms(1000); if(!Chave){ while(!Chave){ aux1 = 0; if(Led) Led = 0; } } } while(aux1); } [/sourcecode]

Os parâmetros de i, x e delay_ms podem ser alterados para novos valores, obtendo tempos menores/maiores, número de piscadas do led. Os arquivos gerados pelo compilador são os mostrados na imagem abaixo:

saida_compiler

O arquivo destacado em preto é o que gravaremos no micro controlador. Já o destacado em azul é o arquivo do projeto. É este que devemos abrir para colocar os códigos já mencionados.

Todos os 6 exemplos de código acima foram devidamente testados. Abaixo um único arquivo com cada .HEX está disponível para download, facilitando para quem não quiser instalar o IDE e somente testar o projeto.

Download: Projeto_PiscaLed (247)

Algumas variáveis auxiliares foram criadas para ajudar nas estruturas de repetição, mas nem todas usadas. Podem ser excluídas. Outro fato importante é que não há muitos comentários nos códigos. Isto obriga nosso iniciante à pensar no que ele faz, alterar à seu modo, ou mesmo estudar lógica de programação, que é essencial nestas aplicações.

Imagem do protoboard de testes:

Proto

No momento em que efetuei os testes, não dispunha do resistor de 3K3, então foi utilizado um de 4K7. Valores entre 3K3 e 10K podem ser utilizados sem problemas.

Para o exemplo n°6 apresento um vídeo logo abaixo:

Concluindo este post, tenho certeza de que os experientes no assunto também concordam no fato de qualquer curso ensinar apenas o básico e nenhum deles fará de você um projetista/programador profissional. Projetos complexos são criados depois de adquirir experiência em programação, lógica e muita leitura do datasheet.

Grande abraço à todos os apreciadores deste post e seguidores do blog. Até a próxima!