_______________________________________________________________________
EA869 Introdução aos Sistemas de Computação Digital
Aula Experimental
1° semestre de 2016
Módulo 1 – Parte 1
Compilador CodeWarrior
As instruções a seguir indicam passo a passo e com imagens como abrir o compilador
CodeWarrior e configurá-lo com a placa para executar um programa. Primeiro, abra o software
no computador. Em seguida, execute as instruções abaixo.
1. Criar um novo projeto
2. Dar o nome ao projeto
1
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
Módulo 1 – Parte 2
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, 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/i6m
cg8in2nc/KL25P80M48SF0RM.pdf
 Manual da Placa Freedom
https://d1b10bmlvqabco.cloudfront.net/attach/i406dyu4aw75jl/hzle6mt0zvk237/i6jct
fqx743j/FRDMKL25Z_Users_Manual_Rev_2.pdf
Antes de começarmos 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 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 é uma PORT? Pense que
a interface com circuitos externos é feitas através de pinos que são agrupados em PORTs.
3
Como, por exemplo, o pino 19 da PORT B que liga o led verde ou o pino 1 da PORT D que liga o
led azul.
Além disso, as PORTs são agrupadas em SIMs. Abrindo o Manual do Microcontrolador
e pocurando 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 do das 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 da PORT
B como um sinal de saída ou output. Cada PORT tem um registrador que faz essa configuração;
no caso da 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 na PORT B. E PDDR? Port Data
Direction Register. Basicamente, é o registrador que define a direção do sinal, como dito.
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 um apaga.
ATENÇÃO: o led é ativo em baixo, isso significa que o registrador GPIOB_PCOR (clear) acende
o led 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 seus endereços:
 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
ATENÇÃO: 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
#define
#define
#define
#define
SIM_SCGC5 (*(unsigned int volatile *) 0x40048038)
PORTB_PCR18 (*(unsigned int volatile *) 0x4004A048)
GPIOB_PDDR (*(unsigned int volatile *) 0x400FF054)
GPIOB_PSOR (*(unsigned int volatile *) 0x400FF044)
GPIOB_PCOR (*(unsigned int volatile *) 0x400FF048)
4
A seguir definimos uma função delay. Como o programa é executado extremamente
rápido, precisamos de um tempo razoavelmente grande para conseguirmos ver o led acender
e apagar. A função delay basicamente atrasa o programa com um loop de decremento de uma
variável que possui um valor muito grande, esse valor pode ser alterado.
Em código, temos:
void delay(unsigned int i){
while (i)
i--;
}
Para entender as próximas instruções, você deve entender o que o comando a seguir
faz: SIM_SCGC5 = (1<<10);
O comando(1<<10)envia o valor 1 para o bit 10 do registrador, ou seja, ativa o bit 10
do registrador SIM_SCGC5.
Já podemos iniciar a função principal.
int main(void){
A instrução abaixo ativa o bit 10 do SIM_SCGC5 que, olhando o esquemático do
SIM_SCGC5 acima, é a PORT B. O | significa o “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, esse registrador define o pino ativado
como saída, como queremos, já que estamos trabalhando com um led.
GPIOB_PDDR
como saída
= GPIOB_PDDR
| (1<<18); // Seta pino 18 do PORTB
Loop infinito
for(;;) {
A instrução abaixo ativa o bit 18 do registrador GPIOB_PSOR, esse registrador seta a
saída e apaga o led vermelho.
GPIOB_PSOR = (1<<18);
em PTB18 (apaga)
// Set bit 18, LED vermelho
A instrução abaixo faz com que o programa espere um tempo.
delay(500000); // Espera um tempo
A instrução abaixo ativa o bit 18 do registrador GPIOB_PCOR, esse registrador limpa a
saída e acende o led vermelho.
GPIOB_PCOR = (1<<18);
em PTB18 (acende)
// Clear bit 18, LED vermelho
A instrução abaixo faz com que o programa espere um tempo.
delay(500000); // Espera um tempo
Assim, ele retorna para o início do loop, piscando o led vermelho infinitamente.
}
5
}
Código pronto para execução abaixo. 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
Portas do GPIO (Reg. SIM_SCGC5)
#define PORTB_PCR18 (*(unsigned int
(Reg. PORTB_PCR18)
#define GPIOB_PDDR (*(unsigned int
do PORTB (Reg. GPIOB_PDDR)
#define GPIOB_PSOR (*(unsigned int
register do PORTB (Reg. GPIOB_PSOR)
#define GPIOB_PCOR (*(unsigned int
register do PORTB (Reg. GPIOB_PCOR)
volatile *) 0x40048038) // Habilita as
volatile *) 0x4004A048) // MUX de PTB18
volatile *) 0x400FF054) // Data direction
volatile *) 0x400FF044) // Set bit
volatile *) 0x400FF048) // Clear bit
void delay(unsigned int i) {
while (i)
i--;
}
int main( void)
{
SIM_SCGC5
PORTB_PCR18
assim os 3 bits de
GPIOB_PDDR
saída
= SIM_SCGC5 | (1<<10);
= 0x00000100;
MUX serão 001
= GPIOB_PDDR | (1<<18);
for(;;) {
GPIOB_PSOR = (1<<18);
(apaga)
delay(500000);
GPIOB_PCOR = (1<<18);
PTB18 (acende)
delay(500000);
}
}
// Habilita clock GPIO do PORTB
// Seta bit 8 do MUX de PTB18,
// Seta pino 18 do PORTB como
// Set bit 18, LED vermelho em PTB18
// Espera um tempo
// Clear bit 18, LED vermelho em
// 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 no CodeWarrior para que ele pisque o
LED Verde.
a) O LED Verde está no Pino 19 da PORT B. Como ele se encontra em uma PORT já
utilizada, os registradores abaixo continuarão a ser utilizados.
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.
6
a) O LED Azul está no Pino 1 da PORT D, diferente da utilizada. Assim precisaremos de
registradores que atuam na PORT D.
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
#define
#define
#define
#define
#define
#define
#define
#define
#define
SIM_SCGC5
PORTB_PCR18
PORTB_PCR19
PORTD_PCR1
GPIOB_PDDR
GPIOD_PDDR
GPIOB_PSOR
GPIOD_PSOR
GPIOB_PCOR
GPIOD_PCOR
(*(unsigned
(*(unsigned
(*(unsigned
(*(unsigned
(*(unsigned
(*(unsigned
(*(unsigned
(*(unsigned
(*(unsigned
(*(unsigned
int
int
int
int
int
int
int
int
int
int
volatile
volatile
volatile
volatile
volatile
volatile
volatile
volatile
volatile
volatile
*)
*)
*)
*)
*)
*)
*)
*)
*)
*)
0x40048038)
0x4004A048)
0x4004A04C)
0x4004C004)
0x400FF054)
0x400FF0D4)
0x400FF044)
0x400FF0C4)
0x400FF048)
0x400FF0C8)
void delay(unsigned int i) {
while (i)
i--;
}
int main( void)
{
SIM_SCGC5
PORTB_PCR18
PORTB_PCR19
PORTD_PCR1
GPIOB_PDDR
GPIOD_PDDR
=
=
=
=
=
=
SIM_SCGC5 |(1<<10)|(1<<12);
0x00000100;
0x00000100;
0x00000100;
GPIOB_PDDR |(1<<18)|(1<<19);
GPIOB_PDDR |(1<<1);
for(;;) {
GPIOB_PSOR
GPIOB_PSOR
GPIOD_PSOR
delay(5000000);
GPIOB_PCOR
delay(5000000);
GPIOB_PSOR
GPIOB_PCOR
delay(5000000);
GPIOB_PSOR
GPIOD_PCOR
delay(5000000);
GPIOD_PSOR
GPIOB_PCOR
GPIOB_PCOR
delay(5000000);
GPIOB_PSOR
GPIOD_PCOR
delay(5000000);
GPIOB_PSOR
GPIOB_PCOR
delay(5000000);
GPIOB_PCOR
delay(5000000);
}
= (1<<18);
= (1<<19);
= (1<<1);
= (1<<18);
= (1<<18);
= (1<<19);
= (1<<19);
= (1<<1);
= (1<<1);
= (1<<18);
= (1<<19);
= (1<<19);
= (1<<1);
= (1<<18);
= (1<<19);
= (1<<18);
}
7