Escolar Documentos
Profissional Documentos
Cultura Documentos
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
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
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
}
}
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)
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:
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.
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.