Você está na página 1de 49

Curso Online de Microcontroladores Pic

Aluno: Kaylens Lee Jhonson Lira de Souza


O curso para microcontroladores PC em linguagem
C tem como base o compilador MikroC da
Mikroelektronika (www.mikroe.com) e nosso kit de
desenvolvimento ACEPC40 (pode ser adquirido em
nossa loja virtual, www.acepiccamp.com.br)....
26 janeiro - 1 fevereiro
UNIDADE 1
ntroduo Recurso
O compilador MikroC Recurso
Criando um projeto Recurso

Nesta primeira parte sero explicados sobre tipos e modificadores de tipos de variveis,
variveis, operadores e tambm alguns comandos bsicos e bastantes utilizados na
programao em linguagem C.
ntroduo linguagem C Recurso
ntroduo linguagem C - Continuao Recurso
Notao Numrica Recurso

Criaremos agora o nosso primeiro projeto, onde o cdigo ser escrito, compilado e gravado
no microcontrolador.
Podemos gravar o microcontrolador seguindo as instrues do arquivo "nstalao da
ACEPC 40.pdf", que se encontra no CD do curso.
Primeiro projeto Recurso
Compilando e gravando o projeto Recurso
Projeto de fixao Recurso

Responda as questes referentes ao assunto da primeira semana seguindo o link abaixo


Este questionrio importante para que sua mdia seja formada e tambm um feedback
para que voc avalie sua participao no curso
Voc pode acompanhar sua nota e as correes clicando no link "Nota" no menu
"Administrao" ao lado direito.
Questes - Semana 1 Tarefa
Linguagem C
uma linguagem de programao de propsito geral, estruturada,
imperativa, procedural de alto e baixo nvel, criada em 1972 por Dennis Ritchie
no AT&T Bell Labs, para desenvolver o sistema operacional UNX (que foi
originalmente escrito em Assembly). Desde ento, espalhou-se por muitos
outros sistemas e tornou-se uma das linguagens de programao mais usadas
influenciando muitas outras linguagens, especialmente o C++, que foi
desenvolvida como uma extenso para C.
Programao de Microcontroladores em linguagem C
Atualmente, a maioria dos microcontroladores existentes nos
mercado, contam com compiladores em C para o desenvolvimento de software,
pois a linguagem C permite a construo de programas e aplicaes muito
mais complexas do que o Assembly.
O compilador C tem a capacidade de "traduzir com alto grau de
inteligncia e velocidade o cdigo em C para o cdigo de mquina, portanto
podemos dizer que a linguagem C possui grande eficincia.
Essa eficincia da linguagem C faz com que o programador preocupe-
se mais com a programao em si e o compilador assume responsabilidades
como localizao da memria, operaes matemticas e lgicas, verificao de
bancos de memrias e outros..
O Compilador MikroC
O compilador MikroC foi desenvolvido pela Mikroelektronika e com ele que
vamos desenvolver nossos projetos. Segue no CD do curso uma cpia de
demonstrao do compilador MikroC e este tambm pode ser baixado no site:
www.mikroe.com.
Todos os exemplos do curso podero ser feitos na cpia de demonstrao,
sendo que esta liberada para programas com tamanho at 2K.
Abaixo est a tela inicial do compilador.
Quando da instalao do compilador, na primeira vez que abrir o programa, a
tela dever estar como a da figura acima.
A Interace do compilador
Ns temos na interface do compilador MikroC o editor de cdigo (Code Editor).
aqui que o cdigo do projeto ser escrito:

possvel modificarmos a cor do fundo do editor de cdigo clicando no menu
em "Tools -> Options ou clicando na figura , localizado acima do editor
de cdigo mais direita.
Escolha a opo "Colors dentro da chave "Editor e altere a mscara em
"Scheme, conforme a figura abaixo:
Do lado esquerdo ao editor de cdigo temos o Code Explorer:
Logo abaixo est o Project Setup com as informaes do microcontrolador
utilizado e algumas configuraes para "Debug:


Abaixo de tudo, temos a Janela de Mensagens (Message Window). Nesta
janela sero mostrados o status de compilao, e informaes de erro e alertas
para o nosso cdigo:

O!"#$ Outras janelas e ferramentas, veremos no decorrer do curso.
Criando um no%o pro&eto
niciaremos um projeto somente para verificarmos o funcionamento do
compilador MikroC.
Clique no Menu em "Project e escola a opo "New Project;

Aparecer a tela abaixo para insero dos dados do projeto:

Siga os passos abaixo:

-Em "Project Name, d o nome do projeto, que neste caso pode ser: nicio;
-Em "Project Path, escolha o caminho da pasta onde sero armazenados os
arquivos do projeto;
-"Description no obrigatrio o preenchimento;
-Em "Device, escolha o microcontrolador a ser utilizado em nosso projeto, no
caso, pode ser o P16F877A;
-Em "Clock, deixe o default mesmo, ou seja, 008.000000 (8MHz);
-Em "Device Flags, deixe o default tambm, por enquanto no faremos
nenhuma alterao;
-Digite, no Editor de cdigo, apenas o bloco principal, conforme abaixo:

%oid main()
{
}

-Aps digitar o cdigo acima, vamos compilar o projeto clicando no menu
"Project e escolhendo a opo "Build:

Podemos tambm compilar a projeto com as teclas "Ctrl + F9.

-Se tudo estiver correto, ser mostrado o resultado da compilao na Janela de
Mensagens, conforme abaixo:
Introduo Linguagem C
'ipos de dados
Os tipos de dados suportados pela linguagem C e utilizados no compilador
MikroC so identificados pela palavras reservadas
*
: c(ar) int) loat) dou*le e
%oid#
'ipo de dado 'aman(o Inter%alo
char 8 bits 0 a 255
int 16 bits 0 a 65536
float e double 32 bits 3.4 x 10
-38
a 3.4 x 10
38
void 0 0
O tipo c(ar representa caracteres ASC de 8 bits, sendo que cada varivel do
tipo c(ar pode representar somente um caracter ASC.
O tipo int representa nmeros inteiro de 16 bits.
O tipo loat e dou*le representam nmeros fracionrios de 32 bits, sendo que
este tipo de dado deve ser evitado tendo em vista o seu tamanho.
O tipo %oid normalmente utilizado em funes para declarar que ela no
deve retornar nenhum valor.
+
palavra reservada = palavra utilizada pelo compilador e que no deve ser
utilizada pelo usurio.
Modiicadores de 'ipo
Alm dos tipos de dados acima, podemos utilizar comandos especiais para
modific-los e so chamados de modificadores de tipo, sendo eles: signed)
unsigned) s(ort e long#
O modificador de tipo signed pode ser utilizado para representar um nmero
positivo ou negativo, assim um tipo de dados signed int pode representar
valores de -32768 a 32767.
O modificador unsigned define um tipo de dado sem sinal, ou seja, somente a
parte positiva de uma varivel, ento o tipo de dados unsigned int representa
valores de 0 65536.
O modificador s(ort utilizada para definir um valor menor do que o tipo
modificado, ou seja, ao declaramos uma varivel com o tipo s(ort) a varivel
tem seu tamanho reduzido para 8 bits.
O modificador long o contrrio, ou seja, amplia o tamanho de uma varivel,
ento uma varivel declarada com o tipo de dado long int passa a ter o
tamanho de 32 bits.
Temos abaixo, uma tabela com todos os tipos de dados e seus modificadores
disponveis para o compilador MikroC:
'ipo 'aman(o ,alores
signed char 8 bits -128 127
(unsigned) char 8 bits 0 255
(signed) short (int) 8 bits -128 127
unsigned short (int) 8 bits 0 255
(signed) int 16 bits -32768 32767
unsigned int 16 bits 0 65535
(signed) long (int) 32 bits -2147483648 2147483647
unsigned long (int) 32 bits 0 4294967295
float 32 bits (+-) 1,17549435082e
-38
(+-) 6,80564774407e
38
double 32 bits (+-) 1,17549435082e
-38
(+-) 6,80564774407e
38
long double 32 bits (+-) 1,17549435082e
-38
(+-) 6,80564774407e
38
void 0 0
* Palavras entre parnteses so opcionais.
,ari-%eis
As variveis so uma representao simblica onde so armazenados dados
do programa ou dados externos como uma tecla pressionada ou uma tenso
lida, etc. As variveis podem conter letras e nmeros, sempre comeando com
letras e no devem ter nome de palavras reservadas pelo compilador como,
por exemplo, for, do, int, etc.
Declarao de ,ari-%eis
Declarar uma varivel simplesmente informar ao compilador que uma varivel
chamada "X do tipo "Y e declarada da seguinte forma:
<tipo> + <nome da varivel>;
Podemos tambm declarar e inicializar uma varivel da seguinte forma:
<tipo> + <nome da varivel> = <valor da varivel>;
Exemplos: unsigned int x = 12345;
int conta;
short x1;
,ari-%eis .lo*ais -> So declaradas no incio de nosso cdigo e que podem
ser acessadas em qualquer ponto do programa:
Ex.:
int conta;
unsigned int c;
void main()
{
conta = 10;
c = c + 1;
while (1);
}

,ari-%eis Locais -> So declaradas dentro de uma funo e somente existe
durante a execuo da funo. Elas so descartadas depois de executada a
funo:
void main()
{
int conta
conta = conta++;
while(1);
}
Operadores
Temos, na linguagem C, vrios operadores e podemos verific-los abaixo:
Operadores de Atri*uio
So utilizados para atribuir valores s variveis:
Operador Descrio E/emplo
= Associa um valor varivel a = 2
Aritm0ticos$
Operador Descrio E/emplo
+ Soma dos argumentos a + b
- Subtrao dos argumentos a - b
* Multiplicao dos argumentos a * b
/ Diviso dos argumentos a / b
% Resto da diviso (s pode ser utilizado com valores
inteiros)
a % b
++ Soma 1 ao argumento a++
-- Subtrai 1 ao argumento a--
1elacionais$
So utilizados para comparao entre argumentos e retornam uma resposta
verdadeira ou falsa. Como em linguagem C no existe uma varivel booleana
para um resultado verdadeiro ou falso, todo valor igual a 0 ser considerado
falso e todo valor diferente de 0 (qualquer valor) ser considerado verdadeiro.
Operador Descrio E/emplo
==
Compara se igual a a == 5
!= Compara se diferente de a != 5
> Compara se maior que a > 5
< Compara se menor que a < 5
>= Compara se maior ou igual a a >= 5
<= Compara se menor ou igual a a <= 5
Operadores l2gicos *it3a3*it$
Operador Descrio
& E (AND)
| OU (OR)
^ OU EXCLUSVO (XOR)
~ Complemento (NOT)
>> Deslocamento direita
<< Deslocamento esquerda
Operadores l2gicos relacionais$
Operador Descrio
&& Comparao lgica E (AND)
|| Comparao lgica OU (OR)
! Comparao lgica Complemento (NOT)
Introduo 4 Linguagem C
Declara5es de controle$
Comando i 6se7$
O comando F uma comando de deciso e utilizado para avaliar uma
determinada condio e determinar se ela verdadeira, caso seja, executa o
bloco contido dentro desta condio. Sua forma geral :
i 6e/p7 comando;
Se o resultado da condio referente a expresso (exp) for verdadeiro, o
comando ser executado, caso contrrio, o programa segue sem executar o
comando.
i 6e/p7
8
comando19
comando:9
;
Para o caso acima, a mesma explicao anterior se encaixa, sendo que agora,
se a condio da expresso for verdadeira, sero executados comando1 e
comando2.
Exemplos:
i 6conta<=>7 conta ? >9
Neste caso, se a varivel conta atingir um valor maior que 50, o comando
conta = 0 ser executado e a varivel conta ser zerada.
i 6conta<=>7
8
conta ? >9
conta1@@9
;
Neste caso, se a varivel conta atingir um valor maior que 50, os comandos
conta = 0 e conta1++ sero executados e assim a varivel conta ser zerada e
a varivel conta1 ser incrementada em 1, respectivamente.
Comando IA3EL"E$
Neste caso, a condio F utilizada da mesma forma anterior, sendo que
agora, se a condio da expresso for falsa a condio ELSE ser executada,
ou seja, neste caso existe a possibilidade de escolha de uma entre duas
opes. Sua forma :
i 6e/p7 comando19
else comando:9
Caso a expresso seja verdadeira, o comando1 ser executado, caso seja
falsa, o comando2 ser executado.
Exemplo:
i 6conta<>7
8
conta ? >9
conta1@@9
;
else conta@@9
Para o exemplo, se o valor da varivel conta for maior que 0, ento os
comandos conta = 0 e conta1++ sero executados, porm caso o valor da
varivel conta seja 0 ou menor que 0, ento o comando conta++ ser
executado.
Comando "BI'CC3CA"E$
Quando existem muitos valores para testar de uma s varivel, o comando F
pode ficar meio confuso ou sem muita eficincia, para isso podemos utilizar o
SWTCH-CASE. Segue sua forma:
sDitc(6%ari-%el7
8
case %alor1$ comando19
####
*reak9
case %alor:$ comando:9
####
*reak9
####
####
deault$ comandoN9
####
####
;
Neste caso, a varivel ser testada e se o valor dela for igual a valor1, o
comando1 ser executado, se for igual ao valor2, o comando2 ser executado
e assim por diante, agora se o valor for diferente de qualquer caso (case), o
comandoN ser executado.
Exemplo:
sDitc(6conta7
8
case 1> $ conta1@@9
*reak9
case 1=$ conta:@@9
*reak9
case :>$ 8
conta1@@9
conta:@@9
;
*reak9
deault$ contaE@@9
;
Neste caso, se o valor da varivel conta for igual a 10, a varivel conta1 ser
incrementado, se o valor da varivel conta for igual a 15, o valor da varivel
conta2 ser incrementado, caso o valor de conta seja igual a 20, tanto os
valores de conta1 quanto de conta2 sero incrementados, para todos outros
valores diferentes para a varivel conta, o valor de conta3 ser incrementado.
Note que aps cada comando, temos a clusula break, cuja funo encerrar
o teste da varivel tendo em vista j ter sido satisfeita a condio, assim, por
exemplo:
sDitc(6conta7
8
case 1> $ conta1@@9
*reak9
#
#
#
Se a varivel conta tem seu valor igual a 10, o comando de incremento da
varivel conta1 ser executado, ou seja, a condio j foi atendida e no
preciso testar mais vezes a varivel conta. Ento, a clusula break, encerra os
teste feitos por case e, assim, o programa continua na prxima instruo aps
a estrutura switch.
Lao AO1$
Este um dos comandos de lao (loop ou repetio) disponveis na linguagem
C, a sua forma :
or6inicialiFao9condio6t0rmino79incremento7 comando:
ou,
or6inicialiFao9condio6t0rmino79incremento7
8
comando19
comando:9
;
onde:
inicialiFao$ essa seo conter uma inicializao para a varivel;
condio$ responsvel por contar a condio de finalizao do lao;
incremento$ aqui pode conter uma ou mais variveis para incremento da
varivel.
Exemplo:
int conta9
int a ? >9
or 6conta?>9contaG1>9conta@@7 a ? conta9
Neste exemplo, a varivel conta ser iniciada com o valor 0, a expresso a =
conta ser executada e aps isso a varivel conta ser incrementada
novamente. Essa repetio ou lao se encerrar quando a condio conta < 10
for satisfeita, ou seja quando a varivel conta for igual a 9.
Lao BCILE$
Neste lao, os comandos sero repetidos enquanto a expresso for verdadeira,
sua forma :
D(ile 6e/p7
8
comando9
;
Exemplo:
int /9
/ ? >9
D(ile6/G1>7 /@@9
A programa ficar no lao de repetio whil, enquanto a varivel x for menor
que 10 e o programa s continuar quando o valor de x for maior ou igual a 10.

Lao DO3BCILE$
Este lao uma variao do comando WHLE, sendo que neste caso o
comando ser executado antes de testar se a condio verdadeira. Sua
forma :
do
8
comando9
;
D(ile6e/p79
O comando ser executado pelo menos uma vez antes de verificar a condio
da expresso.
Exemplo:
int /9
int H9
do
8
/@@9
; D(ile6HI?179
Introduo 4 Linguagem C
Notao num0rica
Em linguagem C, podemos usar as 4 formas de representao numrica,
decimal, binria, hexadecimal e octal, sendo as mais comuns somente as 3
primeiras.
Notao decimal: a representao desta notao direta, ou seja, como
estamos acostumados a escrever:
Ex.: PO1'! ? 1>9
Notao binria: esta representao vem precedida de "0b ou "0B, indicando
a notao:
Ex.: PO1'! ? >*>>>>>>1>9
ou
PO1'! ? >!>>>>>>1>9
Notao Hexadecimal: esta representao vem precedida de "0x ou "0X, ex:
Ex.: PO1'! ? >/>A9
ou
PO1'! ? >J>A9
Primeiro Pro&eto
Primeiramente, sugiro que se abra uma pasta no seu HD com o nome
CURSO_PC, para armazenarmos os nossos projetos criados durante o curso.
Dentro da pasta CURSO_PC, podemos criar outras pastas referentes ao
projetos.
Vamos abrir um novo projeto, conforme explicado anteriormente, com as
definies abaixo
Deinindo o pro&eto$
-Project Name : PiscaLed
-Project Path : C:\CURSO_PC\PSCA LED\
-Description : ....
-Device : P16F877A
-Clock : 008.000000
-Device Flags : Clique no boto Default no lado direito dos "Device Flags
Os bits de configurao (fuses) podem ser configurados, selecionando ou no
os mesmos em "Device Flags e quando utilizamos a opo "Default os fuses
sero configurados da seguinte forma:
_LVP_OFF;
_WDT_OFF
_HS_OSC

Circuito$
O circuito que utilizaremos neste primeiro exemplo est logo abaixo:


Escre%endo o c2digo$
Em linguagem C, os programas podem ter uma ou mais funes, isso faz com
que tenhamos uma estrutura modular, ou seja, tenhamos blocos que podem
ser acessados em qualquer parte do programa facilitando a visualizao e o
entendimento do programa.
Todo programa C tem uma uno principal 6main7 e a partir dela nosso
programa ser inicializado.
Estrutura bsica de um programa em C utilizando o compilador mikroC:
%oid main67
8 KKInicia a uno#
KKEste 0 o *loco principal do programa e 0 o Lnico Mue a linguagem C
precisa para uncionar#
; KKAinaliFa a uno#
Este, como vimos anteriormente, o menor programa escrito em linguagem C
no compilador MikroC. Note a funo principal void main() e logo aps,
abrimos a inicializao da funo com uma chave, logo aps vem o corpo do
programa (onde ele ser escrito) e em seguida fechamos o programa com
outra chave.
Note tambm as duas barras (//) antes das explicaes. Essas barras iniciam
um comentrio e tudo que vier aps estas barras no ser 'entendido' pelo
programa, ou seja, no ser compilado.
Podemos tambm fazer comentrios de outra maneira, veja a seguir:
/*Temos aqui uma outra forma de comentar num programa. Esta maneira
indicada quando precisamos escrever algum comentrio grande como este ou
maior*/
Neste caso, o comentrio tem seu incio com '/*' e finalizado com '*/'.
C2digo do Pro&eto$
%oid main()
{ //nicia a funo main (principal)
PORTD = 0;
TRSD = 0; //Configura todos os pinos da porta D como sada.
D(ile(1) //Comeo do loop (infinito)
{
PORTD = ~PORTD; //Troca situao dos pinos na porta D.
delay_ms(1000); //Tempo de atraso de 1 segundo.
}
} //Finaliza a funo main
Compilando o Pro&eto
Depois de escrevermos o cdigo, devemos compilar o projeto para que
possamos gravar no microcontrolador. A compilao se d pressionando-se
"ctrl + F9 ou clicando no menu Project e escolher a opo Build, conforme
abaixo.


Estando o projeto sem erros, as informaes abaixo devem ser mostradas na
parte de baixo do programa.


.ra%ando o c2digo
Utilizaremos, para gravar o programa no microcontrolador, o programa
WinPic800 como segue a figura abaixo:
Siga os procedimentos de instalao e gravao do microcontrolador no
WinPic800 conforme manual "nstalao da ACEPC 40.pdf que segue no CD
do curso.

Pro&eto de Ai/ao
Pro&etos de i/ao$
-Este projeto faz piscar o led conectado ao pino 0 da porta D
void main()
{
TRISD.F0 = 0; //Configura o pino 0 a porta D como !a"a.
while (1)
{
#$RTD.F0 = 0; //Co%oca pino 0 a porta D &m n"'&% %(gico 0
&%a)*m!(+00); //T&mpo & atra!o & +00m!
#$RTD.F0 = 1; //Co%oca pino 1 a porta D &m n"'&% %(gico 1
&%a)*m!(+00); //T&mpo & atra!o & +00m!
}
}
obs.: Os registradores especiais, TRSD, PORTD, PORTA, TRSA, NTCON,
TMR0 e outros so tratados, pelo compilador, como variveis, portanto,
podemos atribuir valor e trat-los exatamente como uma varivel qualquer.
UNIDADE :

Nesta segunda semana, veremos como fazer a leitura de uma tecla pressionada atravs
da leitura direta do bit e da funo do prprio compilador, trataremos do acionamento de
bits individualmente e tambm das funes e prottipos de funes da linguagem C.
Verificaremos tambm a utilizao do Timer 0 como contador e temporizador, assim como
faremos alguns projetos para entendimento dos assuntos da semana.
Leitura das teclas Recurso
Controle individual de bits Recurso
Funo Button Recurso
Funes em Linguagem C Recurso

Abaixo veremos a utilizao do timer 0 como contador e temporizador.


Seguem tambm exemplos de utilizao e nas pximas aulas veremos os outros dois
timers 1 e 2 para o PC 16F877A.
Contador/Temporizador Timer 0 Recurso
Clculo / Contando um tempo de 1 segundo Recurso
Timer 0 com sinal externo Recurso

Responda as questes referentes aos assuntos da segunda semana seguindo o link


abaixo
Este questionrio importante para que sua mdia seja formada e tambm um feedback
para que voc avalie sua participao no curso
Voc pode acompanhar sua nota e as correes clicando no link "Nota" no menu
"Administrao" ao lado direito.
Questes - Semana 2 Tarefa

Acionamento de !ot5es
Pro&eto
-Fazer um programa que, se o usurio pressionar um dos botes "1,
"4, "7 e "*, um dos Led's D1, D2, D3 e D4,respectivamente, dever
acender.
Deinindo o pro&eto$
-Project Name : Botao
-Project Path : \ CURSO_PC\Botoes\
-Description : ....
-Device : P16F877A
-Clock : 008.000000
-Device Flags: Default

Escre%endo o programa
Note que os botes tem suas ligaes em toda PORTA B e que os
botes "1, "2, "3 e "A tem uma de sua conexes no PNO RB0,
sendo assim, quando pressionarmos um desses botes, o LED D1
acender e se pressionarmos um dos botes "4, "5, "6 ou "B, o LED
D2 acender e assim tambm para o restante dos botes.
Como sabemos, os microcontroladores PC tem resistores de PULL UP
internos conectados na porta B (verificar Datasheet) e para o nosso
programa deveremos habilitar estes resistores. A habilitao dos
resistores de PULL UP se d atravs do registrador OPTON_REG,
atravs do Bit 7 (RBPU) e este deve estar em 0 para que os resistores
sejam habilitados.


Ligao dos resistores de Pull Up interna

%oid main()
{
OPTON_REG.F7 = 0; //Habilita resistores de PULL UP da porta B

TRSB = 0X0F; //Configura os 4 bits menos significativos
como entrada
//... e os 4 bits mais significativos como sada
para a porta B
TRSD = 0X00; //Configura toda a porta D como sada
PORTB = 0X00; //Limpa porta B
PORTD = 0X00; //Limpa portaD -> apaga os Led's

D(ile(1)
{
i (PORTB.F0 == 0) //Se o bit 0 da porta B for igual a zero
PORTD.F1 = 1; //Aciona o bit 1 da porta D -> acende o LED 1

i (PORTB.F1 == 0) //Se o bit 1 da porta B for igual a zero
PORTD.F2 = 1; //Aciona o bit 2 da porta D -> acende o LED 2
i (PORTB.F2 == 0) //Se o bit 2 da porta B for igual a zero
PORTD.F2 = 1; //Aciona o bit 2 da porta D -> acende o LED 3

i (PORTB.F3 == 0) //Se o bit 3 da porta B for igual a zero
PORTD.F3 = 1; //Aciona o bit 3 da porta D -> acende o LED 4
}
}

Controle de !its de registradores 3 Acionamento de um


Lnico *it
No nosso programa, precisamos acionar somente o bit 7 (RBPU) do
registrador OPTON_REG, ento utilizamos a seguinte forma:
OP'IONN1E.#AO ? >9
sso faz com que somente o bit 7 do registrador OPTON_REG seja
afetado, ou seja, somente ele passar a ter o valor 0 e o restante dos
bits permanecem em seu estado anterior que, neste caso, esto em
"default. Podemos tambm atribuir das seguintes maneiras:
OPTON_REG = 0, OPTON_REG = 0x00 ou ainda OPTON_REG =
0b00000000.
Utilizamos este modo de acionamento tambm para verificao dos
botes e para o acionamento dos LED's, conforme abaixo:
i 6PO1'!#A> ?? >7
Nesta condio, verificaremos somente se o bit 0 da porta B est em
nvel lgico 0.
Logo aps temos:
PO1'D#A> ? 19
Com este comando, somente o LED conectado ao pino RD0, ou seja,
bit 0 da porta D ser acionado. Podemos tambm atribuir das seguintes
maneiras: PORTD = 1, PORTD = 0x01 ou ainda, PORTD =
0b00000001.
Este modo de atribuio de bits interessante quando necessitamos
modificar somente um bit sem nos preocupar com os outros. Por
exemplo: na porta, os LED's 1, 2, 3 e 4, esto acionados, portanto
PORTD = 15 ou PORTD = 0x0F ou ainda PORTD = 0b00001111.
Queremos acionar o LED 8 que est conectado no pino RD7 e
mantermos os outros como esto... ento podemos simplesmente
atribuir PORTD.F7 = 1.

Como foi dito anteriormente, todos os registradores so tratados como variveis e tem
seu tipo como unsigned s(ort) ou seja, tm tamanho de 8 bits. Sendo assim,
podemos acionar os bits da mesma maneira para outras variveis do tipo unsigned
s(ort#
E/#1$
unsigned s(ort cmd = 0; //Aqui declaramos a varivel cmd e
atribumos a ela o valor zero.
cmd.F0 = 1; //Aqui, somente o bit 0 desta varivel ter seu valor em 1,
ento a varivel passa a ter
//...o valor de 1, ou seja, cmd = 1. Podemos tambm
atribuir assim: cmd = 0b00000001;
E/#:$
unsigned s(ort cmd = 0; //Aqui declaramos a varivel cmd e
atribumos a ela o valor zero.
cmd.F1 = 1 //Aqui, somente o bit1 desta varivel ter seu valor em 1,
ento a varivel passa a ter
//...o valor de 2, ou seja, cmd = 2. Podemos tambm
atribuir assim: cmd = 0b00000010;

Auno !utton
O compilador MikroC disponibiliza uma biblioteca para verificao do
acionamento de botes e esta pode ser acessada atravs do comando:
!utton6PPO1'/) pino) tempo) estado de ati%ao7
Onde:
PPO1'/ = Porta onde est conectado o boto, Exemplo: PORTB;
Pino = Pino da porta onde est conectado o boto, exemplo pino 0 da
porta B;
'empo = Perodo de debounce em milisegundos;
Estado de ati%ao = Pode ser 0 ou 1 e determina se o boto
acionado pelo nvel lgico 1 ou nvel lgico 0.
Sintaxe da funo:
unsigned s(ort Button(unsigned s(ort *port, unsigned s(ort pin, unsigned s(ort time,
unsigned s(ort active_state);
Exemplo de uso:
i (Button(&PORTB,0,20,1)); //verifica se o pino 0 da porta B est em
nvel lgico 1, sendo que
//...estando em 1, faz um delay de 20ms
(debounce)

Exemplo utilizando a biblioteca Button no projeto no projeto


ciona!ento de Bot"es.
-Project Name : Button_test
-Project Path : \ CURSO_PC\Botoes\
-Description : ....
-Device : P16F877A
-Clock : 008.000000
-Device Flags: Default
%oid main()
{
OPTON_REG.F7 = 0; //Habilita resistores de PULL UP da
porta B

TRSB = 0X0F; //Configura os 4 bits menos
significativos como entrada
//... e os 4 bits mais significativos
como sada para a porta B
TRSD = 0X00; //Configura toda a porta D como
sada
PORTB = 0X00; //Limpa porta B
PORTD = 0X00; //Limpa portaD -> apaga os Led's

D(ile(1)
{
i (Button(&PORTB,0,20,0) //Se o bit 0 da porta B for igual a
zero
PORTD.F1 = 1; //Aciona o bit 1 da porta D -> acende
o LED 1
i (Button(&PORTB,1,20,0) //Se o bit 1 da porta B for igual a
zero
PORTD.F2 = 1; //Aciona o bit 2 da porta D -> acende
o LED 2
i (Button(&PORTB,2,20,0) //Se o bit 2 da porta B for igual a
zero
PORTD.F2 = 1; //Aciona o bit 2 da porta D -> acende
o LED 3
i (Button(&PORTB,3,20,0) //Se o bit 3 da porta B for igual a
zero
PORTD.F3 = 1; //Aciona o bit 3 da porta D -> acende
o LED 4
}
}
Note que no nosso caso, quando o boto for acionado, ele levar o pino
de entrada para o nvel lgico 0, portanto, na biblioteca Button, o estado
de ativao do boto ser 0.

Obs.: Podemos atibuir um outro nome a uma constante ou a um


registrador atravs da diretiva define conforme segue abaixo:
Definies do Projeto acima:
-Project Name : Button_def
-Project Path : \ CURSO_PC\Botoes\
-Description : ....
-Device : P16F877A
-Clock : 008.000000
-Device Flags: Default
#de$ine %&D1 P'R(D.)0 //Atribui o nome LED1 ao bit 0 da porta D
#de$ine %&D2 P'R(D.)1 //Atribui o nome LED2 ao bit 1 da porta D
#de$ine %&D3 P'R(D.)3 //Atribui o nome LED3 ao bit 2 da porta D
#de$ine %&D* P'R(D.)* //Atribui o nome LED4 ao bit 3 da porta D

%oid main()
{
OPTON_REG.F7 = 0; //Habilita resistores de PULL UP da porta B
TRSB = 0X0F; //Configura os 4 bits menos significativos
como entrada
//... e os 4 bits mais significativos como
sada para a porta B
TRSD = 0X00; //Configura toda a porta D como sada
PORTB = 0X00; //Limpa porta B
PORTD = 0X00; //Limpa portaD -> apaga os Led's

D(ile(1)
{
i (Button(&PORTB,0,20,0) //Se o bit 0 da porta B for igual a zero
LED1 = 1; //Aciona o bit 1 da porta D -> acende
o LED 1
i (Button(&PORTB,1,20,0) //Se o bit 1 da porta B for igual a
zero
LED2 = 1; //Aciona o bit 2 da porta D ->
acende o LED 2
i (Button(&PORTB,2,20,0) //Se o bit 2 da porta B for igual a
zero
LED3 = 1; //Aciona o bit 2 da porta D ->
acende o LED 3
i (Button(&PORTB,3,20,0) //Se o bit 3 da porta B for igual a
zero
LED4 = 1; //Aciona o bit 3 da porta D ->
acende o LED 4
}
}

Aun5es
As funes em linguagem C so muito parecidas com as sub-rotinas da
linguagem assembly. O seu uso permite executar uma sequncia de
comandos sempre que necessitarmos, sem a necessidade de repet-
los.
O formato geral de uma funo :
8tipo; nomeNdaNuno 68parQmetros;7
8
ComandoN19
ComandoN:9
####
;
Onde:
tipo: Especifica o tipo de dado que a funo retornar para onde ela foi
chamada.
nomeNdaNuno: dentifica a funo, ou seja, como ela ser chamada
pelo programa. Este nome no pode ter o mesmo nome utilizado por
funes prprias do MikroC.
parQmetros: Utilizados para enviar valores para a funo de modo que
estes sejam utilizados pela funo para clculos, atribuies, controle,
etc.
Esses valores consistem em tipos de variveis separados por vrgulas e
so opcionais, portanto, podemos escrever funes sem qualquer
parmetro.
Mesmo sem a existncia dos valores, os parnteses devem ser
utilizados.
Exemplo:
s(ort soma (s(ort a, s(ort b)
{
return a + b;
}

%oid main ()
{
s(ort c;
c = soma (2,3);
D(ile(1);
}

Neste programa, definimos uma funo soma que retornar o resultado
da operao dos parmetros "a + o parmetro "b. Note que o a
funo do tipo s(ort, isso ento especifica que a funo retornar um
valor do tipo short de 8 bits.
No corpo da funo, encontramos somente o cdigo return a @ *, onde
o comando "return utilizado para retornar o valor da operao dos
parmetros "a + b.
No bloco principal, encontramos a chamada da funo atravs de c ?
soma 6:)E7) onde a varivel "c receber o valor do retorno da funo
(note que a varivel tambm foi declarada com o mesmo tipo da
funo) e os parmetros so os valores "2 e "3, separados pela vrgula
e dentro dos parnteses.
Ento neste caso, a funo soma recebe os valores "2 e "3 e estes
sero atribudos s variveis "a e "b, respectivamente e a funo
retornar o valor da soma entre eles, portanto o valor "5 que ser
repassado para a varivel "c no corpo principal do programa.

Prot2tipo de uno
Um programa em linguagem C pode ficar muito grande e muito
complexo e, s vezes, uma funo pode ser chamada antes desta ter
sido definida. Neste caso, o compilador gera um erro, veja o exemplo
abaixo:
%oid main ()
{
s(ort c;
c = soma (2,3);
D(ile(1);
}
s(ort soma (s(ort a, s(ort b)
{
return a + b;
}



Veja que a funo soma est definida aps a funo principal (main).
Neste caso, como a funo soma foi definida aps a sua chamada, o
compilador retornar um erro dizendo que o identificador soma no foi
declarado, veja a mensagens de erro na prxima figura:

Podemos solucionar este tipo de problema se declararmos previamente


a funo, ou seja, informaremos ao compilador que existe uma funo
com aquele "nome que estamos "chamando. sto conhecido como
prototipagem de funo.
O prottipo de funo deve ser declarado obedecendo os mesmos tipos
e parmetros da funo seguido do ponto e vrgula (;) e, normalmente,
so declarados logo no incio do programa.
Exemplo:
s(ort soma6s(ort a) s(ort b79

%oid main ()
{
s(ort c;
c = soma (2,3);
D(ile(1);
}

s(ort soma (s(ort a, s(ort b)
{
return a + b;
}

ContadorK'emporiFador 'imer >


O Timer 0 um contador/ temporizado binrio e pode ser utilizado para
contagem de eventos externos por meio do pino RA4/T0CK ou como
temporizao quando a entrada do clock tida do clock interno.
O Timer 0 possui um +rescaler de at 256 e tem 8 bits, ou seja, se
configurarmos o +rescaler para 1, ento haver um o,er$low (estouro da
contagem) a cada 256 contagens (0 255). Para a configurao do
Timer 0, utilizam-se os registros especiais OPTON_REG e NTCON.
1egistrador OP'IONN1E. R Endereo$ S1( E 1S1(
!it Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Nome /RBPU NTEDG T0CS T0SE PSA PS2 PS1 PS0
O*s#$ Somente os pinos marcados com fundo cinza sero utilizados
para a configurao do Timer 0#

Conigurao dos *its de controle do 'imer >$



'>C" ? 1$ ncremento a cada transio no pino RA4/T0CK.
'>C" ? >$ ncremento a cada ciclo de mquina (Fosc/4).

'>"E ? 1$ ncremento na borda de descida.
'>"E ? >$ ncremento na borda de subida.

P"A ? 1$ Prescale aplicado ao WDT.
P"A ? >$ Prescale aplicado ao TMR0.

P":) P"1 e P"> - Configurao do Prescale.
P": P"1 P"> 'M1> BD'
0 0 0 1:2 1:1
0 0 1 1:4 1:2
0 1 0 1:8 1:4
0 1 1 1:16 1:8
1 0 0 1:32 1:16
1 0 1 1:64 1:32
1 1 0 1:128 1:64
1 1 1 1:256 1:128

Interrupo do 'imer >


Para se utilizar a interrupo do Timer 0 (TMR0), devemos setar
(colocar em nvel lgico 1) os bits do registrador NTCON, conforme a
tabela abaixo.
O Registrador NTCON o responsvel pelo controle das interrupes
no PC.
1egistrador IN'CON R Endereo$ >!() S!() 1>!( E 1S!(
!it Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Nome GE PEE T0E NTE RBE T0F NTF RBF

.IE ? 1$ Habilita a interrupo global.
.IE ? >$ Desabilita a interrupo global.

'>IE ? 1$ Habilita a interrupo do TMER 0.
'>IE ? >$ Desabilita a interrupo do TMER 0.

'>IA Flag de sinalizao da ocorrncia de overflow no TMER0, este
Flag dever ser limpo (levado 0) quando do tratamento da
interrupo.
'>IA ? 1$ Houve overflow no Timer 0.
'>IA ? >$ No houve overflow no Timer 0.
Trataremos da interrupo do Timer 0 mais adiante no curso.

Contanto um tempo com o 'imer >


Primeiramente, precisamos entender a funo do prescale para que
possamos iniciar a contagem de um tempo com o Timer 0.
O Prescale um divisor programvel utilizado para reduzir a freqncia
do clock no Timer 0, ento, como dito antes, se programarmos o
prescale para 1:1, estamos dizendo que o Timer 0 ter seu valor
incrementado a cada ciclo de mquina, ou seja, se tivermos um ciclo de
mquina de 1us, o Timer 0 ter um incremento a cada 1us.
Programando o prescale para 1:2, o incremento do Timer 0 se dar a
cada 2 ciclos de mquina, ou seja a cada 2us e assim por diante at o
prescale de 1:256, onde o Timer 0 incrementar somente com 256
ciclos de mquina, em 256us.
O valor da contagem do Timer 0 acessado atravs do registrador
TMR0 e, como dito anteriormente, este registrador tem 8 bits, ento ele
pode contar de 0 255, portanto, mais uma contagem (256), ele retorna
para 0, fazendo com que o bit TOF (bit 2 do registrador NTCON) seja
ativado sinalizando o trasbordo da contagem (overflow).

Contanto um tempo de 1>>us


Primeiramente verifica-se que este tempo se encaixa na diviso do
prescaler 1:1, onde o tempo total com este prescaler de 256us, ento
o valor que precisamos para iniciar o Timer 0 ser:
:=T R 1>> ? 1=T#
O Valor 1=T dever ser escrito no registrador 'M1> e devemos
selecionar o prescale de 1:1 ativando a contagem pelo WatchDog.
Para o exemplo utilizaremos o circuito abaixo:

Definies do Projeto:
-Project Name : Timer0
-Project Path : \ CURSO_PC\Timer0\
-Description : ....
-Device : P16F877A
-Clock : 008.000000
-Device Flags: Default
Faamos, ento um programa onde a contagem do tempo ser de
100us:
%oid main()
{
TRSD = 0; //Direciona toda a porta D como sada
PORTD = 0; //Limpa a porta D apagando os LED's

OPTON_REG = 0X80; /*Configura o Registrador OPTON_REG
RBPU = 1 -> PULL UP's porta B
desligados
NTEDG = 0 nterrupo na borda de
descida do sinal
...no pino RB0 (no utilizado neste
exemplo).
T0CS = 0 -> ncremento pelo ciclo de
mquina
...0,5us para o cristal de 8MHz.
T0SE = 0 -> ncremento na orda de
subida.
PSA = 0 -> Prescale aplicado ao Timer 0
PS2, PS1 e PS0 = 0 -> Prescale = 1:2*/
TMR0 = 156; //Valor nicial para o timer 0

D(ile(1)
{
i (NTCON.T0F == 1) //Se ocorrer um overflow no timer 0
{
NTCON.T0F = 0; //Limpa o Flag sinalizador de overflow
TMR0 = 156; //Retoma o valor inicial para o Timer 0
PORTD = ~PORTD; //nverte os Bits da porta D, acendendo
ou apagando
//...os LED's
}
}
}
Ao gravarmos este programa no microcontrolador, verificaremos que os
LED's permanecero todos acesos, mas na realidade, todos esto
piscando numa freqncia muito alta 10KHz (100us) para o olho
humano e que para verificarmos o acionamento ou no dos LED's ser
necessrios verificarmos com um osciloscpio conectado a qualquer
um dos pinos da porta D.

Calculando o tempo 'otal com o 'imer >


Podemos calcular o tempo total para a contagem do Timer 0 seguindo a
seguinte frmula:
Tempo = 256 x prescaler x ( 1 / (FOSC / 4))

Ento, se tivermos um cristal de 8MHz, teremos ento em ( 1 / (FOSC /
4)) = 0,5 us e se formos utilizar o prescaler de 1:2 aplicado ao TMR0,
teremos:
Tempo = 256 x 2 x 0,5u;
Tempo = 256 us.

Para um prescaler de 256, teremos:
Tempo = 256 x 256 x 0,5u;
Tempo = 32768 us ou 32,768ms

Contando um tempo de 1 segundo


Como sabemos, 1 segundo o equivalente a 1000ms e o tempo
mximo que conseguimos chegar com o Timer 0 de 32,768ms. Sendo
assim, precisamos ento dividir estes 1000ms para que possamos
adequar realidade do nosso PC.
Bem, a diviso de 1000ms por 32,768ms resulta em 30,5175.... Este
resultado, por ser um valor "quebrado no nos ajudar muito, ento
vamos dividir o tempo de 1000ms por 25ms. O resultado agora ser
40. ...Guardaremos este resultado para ser usado posteriormente.
Ento, precisamos que o overflow do Timer 0 ocorra a cada 25ms...
Verificamos tambm que este tempo se "encaixa no prescaler 1:256.
Basta-nos encontrar o valor de incio para o Timer 0 a fim de que o
overflow ocorra conforme a nossa necessidade.
Podemos lanar mo da frmula abaixo para definirmos este valor de
incio para o Timer 0:


Atribuindo os valores na frmula temos:
TMR0 = 256 (25 ms / (0,5us x 256))
TMR0 = 60,69

O resultado um valor fracionrio, mas podemos aproxim-lo para 61.
Ento o valor a ser atribudo ao registrador TMR0 a fim de inici-lo ser
61.
De posse dos dados acima, podemos iniciar a escrita do cdigo para
programao do microcontrolador. O circuito ser o mesmo utilizado no
exemplo anterior.

Definies do Projeto:
-Project Name : Timer0_1s
-Project Path : \ CURSO_PC\Timer0_1s\
-Description : ....
-Device : P16F877A
-Clock : 008.000000
-Device Flags: Default
%oid main()
{
s(ort conta = 0; //Varivel de controle para a contagem

TRSD = 0; //Direciona toda a porta D como sada
PORTD = 0; //Limpa a porta D apagando os LED's

OPTON_REG = 0X87; /*Configura o Registrador OPTON_REG
RBPU = 1 -> PULL UP's porta B
desligados
NTEDG = 0 nterrupo na borda de
descida do sinal
...no pino RB0 (no utilizado neste
exemplo).
T0CS = 0 -> ncremento pelo ciclo de
mquina
...0,5us para o cristal de 8MHz.
T0SE = 0 -> ncremento na orda de
subida.
PSA = 0 -> Prescale aplicado ao Timer 0
PS2, PS1 e PS0 = 1 -> Prescale = 1:256*/
TMR0 = 61; //Valor nicial para o timer 0

D(ile(1)
{
i (NTCON.T0F == 1) //Se ocorrer um overflow no timer 0
{
NTCON.T0F = 0; //Limpa o Flag sinalizador de
overflow
TMR0 = 61; //Retoma o valor inicial para o
Timer 0
i (conta >= 40) //Se a varivel conta for maior ou
igual a 40
{
PORTD = ~PORTD; //nverte os Bits da porta D,
acendendo ou apagando os LED's
conta = 0; //...e zera novamente a varivel
para a prxima contagem
}
conta++; //incrementa a varivel conta++
}
}
}

Um dos erros bastante comuns a falta das chaves que abrem e
fecham as declaraes de controle, conforme abaixo:

D(ile(1)
{ KKA*re o lao D(ile
i (NTCON.T0F == 1) //Se ocorrer um overflow no timer 0
{ KKA*re o primeiro comando i
NTCON.T0F = 0; //Limpa o Flag sinalizador de overflow
TMR0 = 61; //Retoma o valor inicial para o Timer 0
i (conta >= 40) //Se a varivel conta for maior ou igual a
40
{ KKA*re o segundo comando i
PORTD = ~PORTD; //nverte os Bits da porta D, acendendo ou
apagando os LED's
conta = 0; //...e zera novamente a varivel para a
prxima contagem
} KKAec(a o segundo comando i
conta++; //incrementa a varivel conta++
} KKAec(a o primeiro comando i
} KKAec(a o lao D(ile

Perceba tambm que temos, para o exemplo acima um comando if
dentro de outro comando if. sso bastante comum na linguagem C.

i (NTCON.T0F == 1) //Se ocorrer um overflow no timer 0
{ KKA*re o primeiro comando i
NTCON.T0F = 0; //Limpa o Flag sinalizador de overflow
TMR0 = 61; //Retoma o valor inicial para o Timer 0
i (conta >= 40) //Se a varivel conta for maior ou igual
a 40
{ KKA*re o segundo comando
i
PORTD = ~PORTD; //nverte os Bits da porta D, acendendo
ou apagando os LED's
conta = 0; //...e zera novamente a varivel para a
prxima contagem
} KKAec(a o segundo comando i
conta++; //incrementa a varivel conta++
} KKAec(a o primeiro comando i

Veja tambm onde foi utilizado o valor U> que havamos guardado
anteriormente. U> o nmero de vezes que ocorrer o estouro da
contagem do Timer 0 para que possamos apagar ou acender os LED's.
Ento temos que haver um estouro da contagem do timer 0 a cada
:=ms e multiplicando este valor por 40, temos 1000ms ou ainda 1
segundo de atraso que ser o tempo de permanncia dos LED's
apagados ou acesos.
Note tambm que logo quando condio i (conta >= 40) satisfeita,
depois de inverter o sinal dos LED's, temos o comando conta = 0 que
faz com que a varivel conta volte a sua condio inicial e recomece a
contagem para a prxima condio de temporizao.

UtiliFando o 'imer > com um sinal e/terno


Para utilizarmos a contagem do Timer 0 por um sinal externo, devemos
configurar o registrador OPTON_REG de modo que o incremento do
contador Timer 0 dever ser pela transio do sinal aplicado ao pino
RA4/T0CK e para o nosso circuito, o incremento se dar na borda de
descida do sinal, tendo em vista que o sinal aplicado ao pino RA4 est
conectado diretamente aos 5V.
Sendo assim, os bits T0CS e T0SE sero colocados em 1.

-Project Name : T0_Ext


-Project Path : \ CURSO_PC\Timer0_Ext\
-Description : ....
-Device : P16F877A
-Clock : 008.000000
-Device Flags: Default
%oid main()
{
TRSD = 0; //Direciona toda a porta D como
sada
PORTD = 0; //Limpa a porta D apagando os
LED's

OPTON_REG = 0b10110000; /*Configura o Registrador
OPTON_REG
RBPU = 1 -> PULL UP's porta B
desligados
NTEDG = 0 nterrupo na borda
de descida do sinal
...no pino RB0 (no utilizado neste
exemplo).
T0CS = 1 -> ncremento na
transio do pino RA4/T0CK
T0SE = 1 -> ncremento na borda
de subida.
PSA = 0 -> Prescale aplicado ao
Timer 0
PS2, PS1 e PS0 = 0 -> Prescale =
1:2*/
TMR0 = 250; //Valor nicial para o timer 0

D(ile(1)
{
i (NTCON.T0F == 1) //Se ocorrer um overflow no timer 0
{
NTCON.T0F = 0; //Limpa o Flag sinalizador de
overflow
TMR0 = 250; //Retoma o valor inicial para o
Timer 0
PORTD = ~PORTD; //nverte os Bits da porta D,
acendendo ou apagando
//...os LED's
}
}
}

Auncionamento do pro&eto$
Se pressionarmos uma vez o boto conectado ao pino RA4/T0CK,
veremos que nada acontece, portanto, se pressionarmos 12 vezes este
boto, os LED's acendero e depois mais 12 vezes, os LED's apagaro
e assim sucessivamente.
Analisando o cdigo temos que definimos o prescale com 1:2, portanto
a cada 2 transies no pino RA4/T0CK acontecer 1 incremento no
contador do timer 0 e tambm definimos que o timer 0 (registrador
TMR0) ir contar partir de 250.
Ento 256 250 = 6 e, sendo 1 incremento cada2 transies, temos
6 X 2 = 12.

Você também pode gostar