EA869 - Introdução aos Sistemas de Computação Digital
Atividade Experimental – Entrada e Saída
2º Semestre de 2016
1. Introdução
Compilador CodeWarrior
As instruções a seguir indicam passo a passo, com o auxílio de imagens,
como abrir o compilador CodeWarrior e configurá-lo para executar um
programa considerando a placa que temos à disposição. Primeiro, abra o
software no computador. Em seguida, execute as instruções abaixo.
1. Criar um novo projeto
2. Dar o nome ao projeto
3. Selecionar o microcontrolador MKL25Z128
4. Selecionar a interface openSDA
5. Language: C
6. Finish
O compilador está pronto para ser utilizado. O código será alterado na
diretriz main.c, localizada à direita da interface.
2. Trabalhando com Entrada e Saída – LED RGB
Programa em C Pisca Led RGB da placa Freedom
A placa Freedom é a placa menor inferior do acoplamento. Ela possui o
microcontrolador MKL25Z128 da Freescale, que é selecionado pelo
CodeWarrior na parte anterior do roteiro.
Ambos dispositivos – placa e microcontrolador – possuem manuais nos quais
vamos nos basear. Abra os dois para consulta no seu navegador.
 MCU - KL25Z - Manual do Microcontrolador
https://d1b10bmlvqabco.cloudfront.net/attach/i406dyu4aw75jl/hzle6mt0zvk237/i
6mcg8in2nc/KL25P80M48SF0RM.pdf
 Manual da Placa Freedom
https://d1b10bmlvqabco.cloudfront.net/attach/i406dyu4aw75jl/hzle6mt0zvk237/i
6jctfqx743j/FRDMKL25Z_Users_Manual_Rev_2.pdf
Antes de começarmos a apresentar os códigos, precisamos ter em
mente que, mesmo programando em C, estamos lidando com registradores do
microcontrolador. Portanto, os programas seguintes diferem dos programas
que vocês fizeram em MC102 e as instruções e comandos podem parecer
estranhas no início.
A primeira coisa que precisamos fazer é definir quais registradores
vamos utilizar. Escolhendo manipular o led vermelho, precisamos saber onde
ele está ligado. Abrindo o Manual da Placa e procurando por “RGB LED”,
encontramos a tabela abaixo.
Segundo ela, o led vermelho está ligado ao pino PTB18. Isso significa
que ele está ligado ao pino número 18 da PORT B do microcontrolador. Mas o
que é um PORT? Pense que a interface com circuitos externos é feita através
de pinos que são agrupados em PORTs. Por exemplo, o pino 19 da PORT B
liga o led verde ou o pino 1 da PORT D que liga o led azul.
Além disso, os PORTs são agrupados em SIMs. Abrindo o Manual do
Microcontrolador e procurando por “PORT B”, encontramos o esquemático
abaixo. Portanto, sabemos que o SIM que controla o clock da PORT B é o
SIM_SCGC5, assim como ocorre com os PORTs A, C, D e E.
Já temos dois dos registradores que vamos utilizar: SIM_SCGC5 e
PORTB_PCR18.
Bom, como os pinos podem ser input ou output, precisamos definir o
pino 18 do PORT B como um sinal de saída. Cada PORT tem um registrador
que realiza esta configuração. No caso do PORT B, o registrador é
GPIOB_PDDR. Mas o que significa GPIO? General Purpose Input Output. E o
B? Significa que o registrador pertence e atua no PORT B. E PDDR? Port Data
Direction Register. Basicamente, é o registrador que define a direção do sinal.
Além disso, queremos piscar o led, ou seja, acender e apagar. Para isso,
vamos precisar de mais dois registradores: o GPIOB_PCOR e o
GPIOB_PSOR. O que significa PSOR? Port Set Output Register. E PCOR?
Port Clear Output Register. Basicamente, um acende e o outro apaga.
Atenção: o led é ativo baixo, o que significa que o registrador GPIOB_PCOR
(clear) acende o led, já que coloca em nível baixo aquela saída, e o
GPIOB_PSOR (set) apaga o led.
Bom, já temos todos os registradores que precisamos e procurando pelo
nome no Manual do microcontrolador, encontramos os respectivos endereços
(note que temos entrada e saída mapeada em memória):
 SIM_SCGC5 - endereço: 0x40048038
 PORTB_PCR18 - endereço: 0x4004A048
 GPIOB_PDDR - endereço: 0x400FF054
 GPIOB_PSOR - endereço: 0x400FF044
 GPIOB_PCOR - endereço: 0x400FF048
Cada registrador do microcontrolador tem um nome e um endereço.
Isso significa que eles não podem ser escritos de maneira incorreta de forma
alguma, por isso, atenção ao programar.
As primeiras instruções do programa são, então, as definições desses
registradores e endereços. A instrução básica é:
#define NOME_DO_REGISTRADOR(*(unsigned int volatile *) 0xENDEREÇO)
Em código, temos:
#define SIM_SCGC5 (*(unsigned int volatile *) 0x40048038)
#define PORTB_PCR18 (*(unsigned int volatile *) 0x4004A048)
#define GPIOB_PDDR (*(unsigned int volatile *) 0x400FF054)
#define GPIOB_PSOR (*(unsigned int volatile *) 0x400FF044)
#define GPIOB_PCOR (*(unsigned int volatile *) 0x400FF048)
A seguir, vamos criar uma função delay. Como o programa é executado
de maneira bastante rápida, precisamos de um tempo razoavelmente grande
para conseguir enxergar o led ora aceso, ora apagado. A função delay
basicamente atrasa o programa com um loop de decremento de uma variável
que possui um valor relativamente grande (e definido pelo programador).
Em código, temos:
void delay(unsigned int i){
while (i)
i--;
}
Podemos, então, avançar para a preparação da função principal.
int main(void){
A instrução a seguir ativa o bit 10 do registrador SIM_SCGC5, o qual
está associado ao PORT B. O caractere | identifica a operação de “ou” lógico e
é utilizado para que não se perca informação que já existia anteriormente no
registrador.
SIM_SCGC5 = SIM_SCGC5 | (1<<10); // Habilita clock do PORTB
A instrução abaixo seleciona o LED vermelho para ser ligado ao Pino 18.
Na Tabela 10.3.1 - Manual do microcontrolador, ele diz para enviar esse valor
para o pino.
PORTB_PCR18 = 0x00000100; // Seta bit 8 do MUX de PTB18, assim os 3 bits de
MUX serão 001
A instrução abaixo ativa o bit 18 do registrador, definindo o sentido da
informação ligada ao pino como de saída.
GPIOB_PDDR = GPIOB_PDDR | (1<<18); // pino 18 do PORTB é para saída
O programa principal ficará em um laço infinito:
for(;;) {
A instrução abaixo ativa o bit 18 do registrador GPIOB_PSOR, o qual
acaba por apagar o led vermelho.
GPIOB_PSOR = (1<<18);
// Set bit 18 – LED vermelho (apaga)
A instrução abaixo faz com que o programa espere um tempo.
delay(500000); // Espera um tempo
Em seguida, ativamos o bit 18 do registrador GPIOB_PCOR, o qual fixa
a saída em nível baixo e, portanto, acende o led vermelho.
GPIOB_PCOR = (1<<18);
// Clear bit 18, LED vermelho em PTB18 (acende)
Após isto, acrescentamos mais um período de espera por meio da rotina
delay.
delay(500000); // Espera um tempo
Finalmente, retornamos para o início do loop, o qual fará com que o led
vermelho pisque indefinidamente.
}
}
Código pronto para execução. Execute na diretriz main.c.
// Pisca LED Vermelho do LED RGB placa Freedom
// LED Vermelho com catodo ligado em PTB18
#define SIM_SCGC5 (*(unsigned int volatile *) 0x40048038) // Habilita as
Portas do GPIO (Reg. SIM_SCGC5)
#define PORTB_PCR18 (*(unsigned int volatile *) 0x4004A048) // MUX de PTB18
(Reg. PORTB_PCR18)
#define GPIOB_PDDR (*(unsigned int volatile *) 0x400FF054) // Data direction
do PORTB (Reg. GPIOB_PDDR)
#define GPIOB_PSOR (*(unsigned int volatile *) 0x400FF044) // Set bit
register do PORTB (Reg. GPIOB_PSOR)
#define GPIOB_PCOR (*(unsigned int volatile *) 0x400FF048) // Clear bit
register do PORTB (Reg. GPIOB_PCOR)
void delay(unsigned int i) {
while (i)
i--;
}
int main( void)
{
SIM_SCGC5 = SIM_SCGC5 | (1<<10); // Habilita clock GPIO do PORTB
PORTB_PCR18 = 0x00000100;
// Seta bit 8 do MUX de PTB18,
assim os 3 bits de MUX serão 001
GPIOB_PDDR = GPIOB_PDDR | (1<<18); // Seta pino 18 do PORTB como
saída
for(;;) {
GPIOB_PSOR = (1<<18);
// Set bit 18, LED vermelho em PTB18
(apaga)
delay(500000);
// Espera um tempo
GPIOB_PCOR = (1<<18);
// Clear bit 18, LED vermelho em
PTB18 (acende)
delay(500000);
// Espera um tempo
}
}
Atividades
1) Altere o valor do parâmetro da função delay e perceba a mudança de
velocidade com que o LED vermelho pisca.
2) Faça as alterações necessárias no programa acima para que ele
pisque, agora, o LED verde.
a) O LED verde está conectado ao Pino 19 do PORT B. Como ele se
encontra em um PORT já utilizado, os registradores abaixo são os
que precisamos para manipular o led.
SIM_SCGC5 - endereço: 0x40048038
GPIOB_PDDR - endereço: 0x400FF054
GPIOB_PSOR - endereço: 0x400FF044
GPIOB_PCOR - endereço: 0x400FF048
b) Além disso, precisamos do registrador referente ao pino 19:
PORTB_PCR18 - endereço: 0x4004A04C
c) Mude todas as referências ao pino 18 para o pino 19.
3) Faça as alterações necessárias no programa acima no CodeWarrior
para que ele pisque o LED azul.
a) O LED azul está conectado ao Pino 1 do PORT D. Por isso,
precisaremos acessar um grupo diferente de registradores.
SIM_SCGC5 - endereço: 0x40048038
PORTD_PCR1 - endereço: 0x4004C004
GPIOD_PDDR - endereço: 0x400FF0D4
GPIOD_PSOR - endereço: 0x400FF0C4
GPIOD_PCOR - endereço: 0x400FF0C8
4) Faça um programa que pisque duas cores de leds ao mesmo tempo
5) Execute o programa abaixo:
// Pisca LED RGB
#define SIM_SCGC5 (*(unsigned int volatile *) 0x40048038)
#define PORTB_PCR18 (*(unsigned int volatile *) 0x4004A048)
#define PORTB_PCR19 (*(unsigned int volatile *) 0x4004A04C)
#define PORTD_PCR1 (*(unsigned int volatile *) 0x4004C004)
#define GPIOB_PDDR (*(unsigned int volatile *) 0x400FF054)
#define GPIOD_PDDR (*(unsigned int volatile *) 0x400FF0D4)
#define GPIOB_PSOR (*(unsigned int volatile *) 0x400FF044)
#define GPIOD_PSOR (*(unsigned int volatile *) 0x400FF0C4)
#define GPIOB_PCOR (*(unsigned int volatile *) 0x400FF048)
#define GPIOD_PCOR (*(unsigned int volatile *) 0x400FF0C8)
void delay(unsigned int i) {
while (i) {
i--;
}
}
int main( void)
{
SIM_SCGC5 = SIM_SCGC5 |(1<<10)|(1<<12);
PORTB_PCR18 = 0x00000100;
PORTB_PCR19 = 0x00000100;
PORTD_PCR1 = 0x00000100;
GPIOB_PDDR = GPIOB_PDDR |(1<<18)|(1<<19);
GPIOD_PDDR = GPIOB_PDDR |(1<<1);
for(;;) {
GPIOB_PSOR = (1<<18);
GPIOB_PSOR = (1<<19);
GPIOD_PSOR = (1<<1);
delay(5000000);
GPIOB_PCOR = (1<<18);
delay(5000000);
GPIOB_PSOR = (1<<18);
GPIOB_PCOR = (1<<19);
delay(5000000);
GPIOB_PSOR = (1<<19);
GPIOD_PCOR = (1<<1);
delay(5000000);
GPIOD_PSOR = (1<<1);
GPIOB_PCOR = (1<<18);
GPIOB_PCOR = (1<<19);
delay(5000000);
GPIOB_PSOR = (1<<19);
GPIOD_PCOR = (1<<1);
delay(5000000);
GPIOB_PSOR = (1<<18);
GPIOB_PCOR = (1<<19);
delay(5000000);
GPIOB_PCOR = (1<<18);
delay(5000000);
}
}
Agradecimentos
Este roteiro foi elaborado com o auxílio do aluno Octávio Salim Moreira
([email protected]).