Вы находитесь на странице: 1из 28

EXERCCIOS DE PROGRAMAO

A seguir so apresentados exerccios de programao que podem ser testados nas


placas de laboratrio de processadores que utilizam o MSC1211. So propostos vrios
exerccios. Em alguns, a soluo (em assembly e C) est impressa junto com esta
documentao. Nos demais, voc poder encontrar os respectivos programas, no site desta
disciplina. Junto aos circuitos voc tambm vai encontrar a proposta de novos exerccios.

Exemplo I Semforo
Este exerccio utiliza a porta P1 para controlar as lmpadas de um conjunto de trs
semforos. O semforo S3 do pedestre e s utiliza as lmpadas vermelha e verde. Veja a
descrio do funcionamento dos semforos que encontra-se impressa junto ao esquemtico do
circuito. Por simplicidade o circuito foi simplificado ao mximo. As lmpadas do semforo so
consideradas ideiais, e portanto no consomem corrente da porta lgia. Portanto no h
necessidade de resistores para limitao de corrente. Alm disto, os semforos possuem os
circuitos necessrios para acionar uma lmpada conectada a rede eltrica, atravs de um sinal
lgico do tipo TTL. Na prtica, o projeto deveria contemplar tanto os resistores de limitao de
corrente quanto os circuitos de disparo das lmpadas. Para quem tiver curiosidade, procure a
documentao do circuito MOC3020. Ele um circuito de disparo para tiristores que pode ser
utilizado nesta tarefa.

Soluo em Assembly
Obs.: Este programa foi elaborado sem a adio das bibliotecas disponveis e portanto, a
listagem do programa ficou consideravelmente maior.

;
; **** SEMAF_I.ASM *********************************************************
; **
**
; ********************************************************* by [JCLima ] ***
;
$MOD51
; *** Exemplo de Declarao de Pinos de I/ O *******************************
; **
**
; **************************************************************************
;
VM3
EQU
P1.0
; VM3
equ
90h
AM3
EQU
P1.1
; AM3
equ
91h
VD3
EQU
P1.2
; VD3
equ
92h

; *** Exemplo de Declaraes de Constantes e Variveis *********************


; **
**
; **************************************************************************
;
contador
EQU
7FH
; unsigned char contador
estado1
estado2
estado3
estado4
estado5

EQU
EQU
EQU
EQU
EQU

85h
45h
32h
29h
28h

;
;
;
;
;

S1
S1
S2
S2
S2

Verde
Amarelo
Verde
Amarelo e S3 Vermelho On
Amarelo e S3 Vermelho Off

; *** Vetor de Reset *******************************************************


; **
**
; ****************************************************** Endereco: 0000H ***
;
ORG
0000H
LJMP
START
; *** Vetor da INT0 ********************************************************
; **
**
; ****************************************************** Endereco: 0003H ***
;
ORG
0003H
RETI
; *** Vetor do Timer 0 *****************************************************
; **
**
; ****************************************************** Endereco: 000BH ***
;
ORG
000BH
RETI
; *** Vetor da INT1 ********************************************************
; **
**
; ****************************************************** Endereco: 0013H ***
;
ORG
0013H
RETI
; *** Vetor do Timer 1 *****************************************************
; **
**
; ****************************************************** Endereco: 001BH ***
;
ORG
001BH
RETI
; *** Vetor da Porta Serial ************************************************
; **
**
; ****************************************************** Endereco: 0023H ***
;
ORG
0023H
RETI

; *** PROGRAMA PRINCIPAL ***************************************************


; **
**
; **************************************************************************
;
START:
MOV
SP,#80h
; Move a pilha para a RAM indireta!!!
; *** LOOP Programa Principal...
;
REPETE:
MOV
P1,#estado1
MOV
A,#22
LCALL
DELAYx1000ms

LOOP_REPETE:

delay 22s

MOV
MOV
LCALL

P1,#estado2
A,#3
DELAYx1000ms

; delay 3s

MOV
MOV
LCALL

P1,#estado3
A,#15
DELAYx1000ms

; delay 15s

MOV
MOV
LCALL

contador,#3
P1,#estado4
DELAY500ms

MOV
LCALL
DJNZ

P1,#estado5
DELAY500ms
; delay 0.5s
contador,LOOP_REPETE

LJMP

REPETE

; delay 0.5s

; Obs.: No MSC1211 um ciclo de Mquina = 4 pulsos de clock...


; Obs.: No 8051 um ciclo de Mquina = 12 pulsos de clock...
;
; *** DELAY 1ms ************************************************************
; **
**
; ******************************** [ MSC1211 @ 11.0592MHz = 2757 CICLOS] ***
;
DELAY1ms:
PUSH
07H
MOV
R7,#83
; <-- 250 para um MSC1211 (4 pulsos/ciclo!!!)
_LOOP1ms:

NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ
POP
RET

R7,_LOOP1ms
07H

; *** DELAY 500ms **********************************************************


; ** Baseada na rotina de 1ms!
**
; ********************************************* [ MSC1211 @ 11.0592MHz ] ***
;
DELAY500ms:
PUSH
07H
MOV
R7,#100
_LOOP500ms:

LCALL
LCALL
LCALL
LCALL
LCALL
DJNZ

DELAY1ms
DELAY1ms
DELAY1ms
DELAY1ms
DELAY1ms
R7,_LOOP500ms

POP

07H

;
;
;
;
;
;

Aguarda 1ms!!!
Aguarda 1ms!!!
Aguarda 1ms!!!
Aguarda 1ms!!!
Aguarda 1ms!!!
Repete 100x

RET
; *** DELAYx1000ms(A) ******************************************************
; ** Baseada na rotina de 1ms!
**
; ********************************************* [ MSC1211 @ 11.0592MHz ] ***
;
DELAYx1000ms: PUSH
07H
PUSH
06H
MOV
_LOOPxx1000ms: MOV

R7,A
R6,#200

_LOOPx1000ms:

LCALL
LCALL
LCALL
LCALL
LCALL
DJNZ

DELAY1ms
DELAY1ms
DELAY1ms
DELAY1ms
DELAY1ms
R6,_LOOPX1000ms

DJNZ

R7,_LOOPxx1000ms

POP
POP
RET

06H
07H

; Aguarda
; Aguarda
; Aguarda
; Aguarda
; Aguarda
; Repete

1ms!!!
1ms!!!
1ms!!!
1ms!!!
1ms!!!
200x = 1segundo

; Repete A vezes

END

Soluo em Linguagem C (utilizando o SDCC - compilado no modelo small)


#include <8052.h>
#include <stdio.h>
//
// ****************************************************************
// ** Pinos do MICROCONTROLADOR
**
// ****************************************************************
//
sfr at 0x90 semaforo;
// S1,S2,S3 --> P1
//
// ****************************************************************
// ** V A R I V E I S E C O N S T A N T E S
**
// ****************************************************************
//
const unsigned char estado[5] = {0x85, 0x45, 0x32, 0x29, 0x28};
//
// ****************************************************************
// ** P R O T O T Y P E S
**
// ****************************************************************
//
void delay1ms(void) _naked;
void delay(unsigned int tempo);
//
// ****************************************************************
// ** M A I N
**
// ****************************************************************
//
void main(void)
{
unsigned char i;
while(1)
{
semaforo = estado[0];
delay(22000);
semaforo = estado[1];
delay(3000);
semaforo = estado[2];

// aguarda 22s
// aguarda 3s

delay(15000);
// aguarda 15s
for(i=0; i<3;i++)
// Vermelho piscante por 3s
{
semaforo = estado[3];
delay(500);
semaforo = estado[4];
delay(500);
}
}
}
//
// ****************************************************************
// ** D E L A Y D E 1 m s
@11.0592MHz
**
// ****************************************************************
//
// mov r7,#212 ; <-- para um MSC1211 (4 pulsos/ciclo!!!)
// mov r7,#70 ; <-- para um AT89C52 (12 pulsos/ciclo!!!)
//
void delay1ms(void) _naked
{
_asm
push
ar7
mov
r7,#70
DELAY_1ms: nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
djnz
r7,DELAY_1ms
pop
ar7
ret
_endasm;
}
//
// ****************************************************************
// ** D E L A Y P A R A M E T R I Z V E L
@11.0592MHz
**
// ****************************************************************
//
void delay(unsigned int tempo)
{
while (tempo > 0)
{
tempo--;
delay1ms();
}
}

Exerccio I
Modifique o cdigo acima, de modo que o sinal de vermelho piscante do semforo S3
fique neste estado por 5 segundos, mas o estado de ateno do semforo S2 permanea em 3
segundos.

Exerccio II
Escreva o cdigo para fazer o acionamento de um novo conjunto de semforos que
esto representados no circuito dado a seguir. Veja a descrio do funcionamento das lmpadas
que se encontra impresso junto ao circuito eltrico.

Exemplo II Circuito de Display de 7 segmentos


Neste exemplo utiliza-se a porta P1 para controlar um display de 7 segmentos,
implementando um contador de 0 9 que atualizado de segundo em segundo. No circuito, h
um transistor PNP para fazer o acionamento do anodo do display. Em um circuito com apenas
um display este transistor totalmente dispensvel. Ele est neste circuito apenas como
exemplo de um circuito de drive de potncia, para situaes em que o usurio queira, por
exemplo, alterar o brilho do display (atravs de um sinal de pwm) ou queira fazer a multiplexao
de diversos dispositivos para a formao de um display de vrios dgitos.
Os resistores foram acrescentados para limitar a corrente de base do transistor e a
corrente de cada segmento do display.
Note que o circuito foi simplificado ao mximo, no estando representado no esquema
eltrico o cristal oscilador e o circuito de reset. Em uma implementao real, tanto o cristal
oscilador quanto o circuito de reset deveriam estar presentes.

Soluo em Assembly
;
; **** UMDIGITO.ASM ********************************************************
; **
**
; ********************************************************* by [JCLima ] ***
;
;
$MOD51
; *** Declarao de Pinos de I/O *******************************************
; **
**
; **************************************************************************
;
display
EQU
P1
anodo
EQU
P3.2

; *** Vetor de Reset *******************************************************


; **
**
; ****************************************************** Endereco: 0000H ***
;
ORG
0000H
LJMP
START
; *** Vetor da INT0 ********************************************************
; **
**
; ****************************************************** Endereco: 0003H ***
;
ORG
0003H
RETI
; *** Vetor do Timer 0 *****************************************************
; **
**
; ****************************************************** Endereco: 000BH ***

;
ORG
RETI

000BH

; *** Vetor da INT1 ********************************************************


; **
**
; ****************************************************** Endereco: 0013H ***
;
ORG
0013H
RETI
; *** Vetor do Timer 1 *****************************************************
; **
**
; ****************************************************** Endereco: 001BH ***
;
ORG
001BH
RETI
; *** Vetor da Porta Serial ************************************************
; **
**
; ****************************************************** Endereco: 0023H ***
;
ORG
0023H
RETI

; *** PROGRAMA PRINCIPAL ***************************************************


; **
**
; **************************************************************************
;
START:
MOV
DPTR,#TABELA
; DPTR aponta para a tabela de 7seg
MOV
R7,#0
; R7 o contador de 0 9...
CLR
anodo
; Liga o anodo para sempre...
; *** LOOP Programa Principal ...
;
REPETE:
MOV
A,R7
MOVC
A,@A+DPTR
MOV
P1,A
LCALL
DELAY1000ms
INC
R7
CJNE
R7,#10,REPETE
MOV
R7,#0
LJMP
REPETE

; A = contador
; Converte para 7 segmentos
; Escreve no display...
; Incrementa o contador
; Testa se contador = 10

; *** ARQUIVOS DE INCLUSAO *************************************************


; **
**
; **************************************************************************
; Exemplos de declarao de Arquivos de Incluso!!!
; OBS.: Descomente as linhas de comando, caso queira utilizar
;
as bibliotecas listadas abaixo.
;
$INCLUDE(DELAY_PR.INC)
; <--- S esta biblioteca foi includa!!!
;$INCLUDE(LCD_PROT.INC)
;$INCLUDE(I2C_PROT.INC)

; *** TABELAS, CONSTANTES, STRINGS *****************************************


; **
**
; **************************************************************************
;
TABELA:
DB
0C0h, 0F9h, 0A4h, 0B0h, 99h, 92h, 82h, 0D8h, 80h, 90h
END

Soluo em Linguagem C
#include <8052.h>
#include <stdio.h>

//
// ****************************************************************
// ** Pinos do MICROCONTROLADOR
**
// ****************************************************************
//
sfr at 0x90 display; // Display na porta P1 (A - P1.0, B - P1.1 ...)
sbit at 0xb2 anodo;
// Controle do anodo (P3.2)
//
// ****************************************************************
// ** V A R I V E I S E C O N S T A N T E S
**
// ****************************************************************
//
const unsigned char Tabela[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99,
0x92, 0x82, 0xd8, 0x80, 0x90};
//
// ****************************************************************
// ** P R O T O T Y P E S
**
// ****************************************************************
//
void delay1ms(void) _naked;
void delay(unsigned int tempo);
//
// ****************************************************************
// ** M A I N
**
// ****************************************************************
//
void main(void)
{
unsigned char i = 0;
anodo = 0; // Liga o anodo...
while(1)
{
display = Tabela[i];
i++;
if(i == 10) i = 0;
delay(1000);
}
}
//
// ****************************************************************
// ** D E L A Y D E 1 m s
@11.0592MHz
**
// ****************************************************************
//
void delay1ms(void) _naked
{
_asm
push
ar7
mov
r7,#70
DELAY_1ms: nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
djnz
pop
ret
_endasm;
}

r7,DELAY_1ms
ar7

//
// ****************************************************************
// ** D E L A Y P A R A M E T R I Z V E L
@11.0592MHz
**
// ****************************************************************
//
void delay(unsigned int tempo)
{
while (tempo > 0)
{
tempo--;
delay1ms();
}
}

Exerccio III
Modifique os programas em C e assembly do exemplo descrito acima (exemplo II), de
modo a que o mesmo possa realizar a contagem em hexadecimal.

Exemplo III Circuito de Display de 7 Segmentos


Neste exemplo mapeia-se o mesmo display de 7 segmentos na memria RAM externa.
A aplicao a mesma, ou seja, implementar um contador de 0 9 que atualizado de segundo
em segundo. A diferena entre o exemplo II e este, est na forma de acessar o display. No
exemplo II, o display estava conectado diretamente a porta P1 e bastava apenas um comando
de MOV para acion-lo. Para este exemplo, necessrio fazer uso da instruo MOVX
@DPTR para acessar o display, pois agora o mesmo est mapeado na RAM. Para simplificar,
foram retirados os resistores de limitao da corrente de cada segmento. Em um circuito real
isto no pode ser feito, sob pena de danificar o display e o latch conectado ao mesmo!

Obs.: Para que se possa acessar o display necessrio saber em que posio da memria o
mesmo foi colocado. O endereo obtido pela anlise do circuito eltrico.
Soluo em Assembly
;
; **** UM_MEM.ASM **********************************************************
; **
**
; ********************************************************* by [JCLima ] ***
;
$MOD51

; *** Definies ***********************************************************


; **
**
; **************************************************************************
;
display
EQU
0EE00h
; Endereo do display na RAM externa

; *** Vetor de Reset *******************************************************


; **
**
; ****************************************************** Endereco: 0000H ***
;
ORG
0000H
LJMP
START

; *** Vetor da INT0 ********************************************************


; **
**
; ****************************************************** Endereco: 0003H ***
;
ORG
0003H
RETI
; *** Vetor do Timer 0 *****************************************************
; **
**
; ****************************************************** Endereco: 000BH ***
;
ORG
000BH
RETI
; *** Vetor da INT1 ********************************************************
; **
**
; ****************************************************** Endereco: 0013H ***
;
ORG
0013H
RETI
; *** Vetor do Timer 1 *****************************************************
; **
**
; ****************************************************** Endereco: 001BH ***
;
ORG
001BH
RETI
; *** Vetor da Porta Serial ************************************************
; **
**
; ****************************************************** Endereco: 0023H ***
;
ORG
0023H
RETI

; *** PROGRAMA PRINCIPAL ***************************************************


; **
**
; **************************************************************************
;
START:
MOV
R7,#0
; R7 o contador de 0 9...

; *** LOOP Programa Principal ...


;
REPETE:
MOV
DPTR,#TABELA
MOV
A,R7
MOVC
A,@A+DPTR

; DPTR aponta para a tabela de 7seg


; A = contador...
; Converte para 7 segmentos...

MOV
MOVX

DPTR,#display
@DPTR,A

; DPTR aponta para a RAM externa...


; Escreve na RAM externa...

LCALL
INC
CJNE
MOV
LJMP

DELAY1000ms
R7
R7,#10,REPETE
R7,#0
REPETE

; Delay de 1 segundo...
; contador = contador + 1
; contador = 10?

; *** ARQUIVOS DE INCLUSAO *************************************************


; **
**
; **************************************************************************
; OBS.: Descomente as linhas de comando, caso queira utilizar
;
as bibliotecas listadas abaixo.
;
$INCLUDE(DELAY_PR.INC)
; S esta biblioteca foi includa!!!
;$INCLUDE(LCD_PROT.INC)
;$INCLUDE(I2C_PROT.INC)

; *** TABELAS, CONSTANTES, STRINGS *****************************************


; **
**
; **************************************************************************
;
TABELA:
DB
0C0h, 0F9h, 0A4h, 0B0h, 99h, 92h, 82h, 0D8h, 80h, 90h
END

Soluo em Linguagem C
#include <8052.h>
#include <stdio.h>
//
// ****************************************************************
// ** Pinos do MICROCONTROLADOR
**
// ****************************************************************
//
xdata at 0xee00 unsigned char display; // Endereo da RAM ext.
//
// ****************************************************************
// ** V A R I V E I S E C O N S T A N T E S
**
// ****************************************************************
//
const unsigned char Tabela[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99,
0x92, 0x82, 0xd8, 0x80, 0x90};
//
// ****************************************************************
// ** P R O T O T Y P E S
**
// ****************************************************************
//
void delay1ms(void) _naked;
void delay(unsigned int tempo);

//
// ****************************************************************
// ** M A I N
**
// ****************************************************************
//
void main(void)

{
unsigned char i = 0;
while(1)
{
display = Tabela[i];
if(++i == 10) i = 0;
delay(1000);
}
}
//
// ****************************************************************
// ** D E L A Y D E 1 m s
@11.0592MHz
**
// ****************************************************************
//
void delay1ms(void) _naked
{
_asm
push
ar7
mov
r7,#70
DELAY_1ms: nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
djnz
pop
ret
_endasm;
}

r7,DELAY_1ms
ar7

//
// ****************************************************************
// ** D E L A Y P A R A M E T R I Z V E L
@11.0592MHz
**
// ****************************************************************
//
void delay(unsigned int tempo)
{
while (tempo > 0)
{
tempo--;
delay1ms();
}
}

Exerccio IV
Modifique os programas em C e assembly do exemplo descrito acima (exemplo III), de
modo a que o mesmo possa realizar uma contagem em octal.

Exemplo IV Circuito de Display de 7 Segmentos Multiplexado


Neste exemplo, dois displays de 7 segmentos esto conectados a porta P1. Para que
seja feita a seleo de qual dgito ser acionado, foram utilizadas duas linhas de controle: P3.3
para acionar o dgito da dezena e P3.2 para acionar o dgito da unidade. De modo que o usurio
no perceba que os dgitos esto piscando, sugere-se que cada dgito seja acionado pelo menos
50 vezes por segundo (varredura de 100Hz). O display do tipo anodo comum. Os segmentos

so acionados com nvel lgico 0 e os anodos so acionados com nvel lgico 1. O circuito foi
simplificado ao mximo, tanto com relao ao microcontrolador quanto com relao ao circuito
de multiplexao do display. Desta forma no aparecem as chaves (transistores) responsveis
pelo chaveamento dos displays. Admita que estes circuitos esto embutidos nos prprios
displays. Em um circuito real no possvel conectar o display ao microcontrolador da
forma como est representado no diagrama eltrico. Seria necessrio acrescentar os
resistores para limitao de corrente e os transistores para o chaveamento dos displays.
Para o circuito proposto deseja-se implementar um contador de 0 99 que ser
atualizado a cada segundo. A contagem ser feita empregando apenas um contador, ou seja, o
programa deve tratar de separar a unidade da dezena, utilizando as operaes de diviso inteira
e resto da diviso.

Soluo em Assembly
;
; **** DOIS_DGT.ASM ********************************************************
; **
**
; ** Ultima Modificacao em: 05/10/2008
**
; **
**
; ********************************************************* by [JCLima ] ***
;
;
$MOD51

; *** Exemplos de Declarao de Pinos de I/O *******************************


; **
**
; **************************************************************************
;
display
EQU
P1

anodo_u
anodo_d

EQU
EQU

P3.2
P3.3

; *** Vetor de Reset *******************************************************


; **
**
; ****************************************************** Endereco: 0000H ***
;
ORG
0000H
LJMP
START

; *** Vetor da INT0 ********************************************************


; **
**
; ****************************************************** Endereco: 0003H ***
;
ORG
0003H
RETI
; *** Vetor do Timer 0 *****************************************************
; **
**
; ****************************************************** Endereco: 000BH ***
;
ORG
000BH
RETI
; *** Vetor da INT1 ********************************************************
; **
**
; ****************************************************** Endereco: 0013H ***
;
ORG
0013H
RETI
; *** Vetor do Timer 1 *****************************************************
; **
**
; ****************************************************** Endereco: 001BH ***
;
ORG
001BH
RETI
; *** Vetor da Porta Serial ************************************************
; **
**
; ****************************************************** Endereco: 0023H ***
;
ORG
0023H
RETI

; *** PROGRAMA PRINCIPAL ***************************************************


; **
**
; **************************************************************************
;
START:
MOV
DPTR,#TABELA
; DPTR aponta para a tabela de 7seg
MOV
R7,#0
; R7 o contador de 0 99...
CLR
anodo_d
; Desliga o anodo da dezena...
CLR
anodo_u
; Desliga o anodo da unidade...
; *** LOOP Programa Principal ...
;
REPETE:
MOV
R6,#50

; Contador da varredura

LOOP_VAR:

MOV
MOV
DIV
MOVC
MOV
SETB
LCALL
CLR

A,R7
B,#10
AB
A,@A+DPTR
P1,A
ANODO_D
DELAY10ms
ANODO_D

; Carrega Contador...

MOV

A,B

; Liga dgito da unidade por 10ms

; Separa A = Dezena, B = Unidade


; Liga dgito da dezena por 10ms

MOVC
MOV
SETB
LCALL
CLR
DJNZ

A,@A+DPTR
P1,A
ANODO_U
DELAY10ms
ANODO_U
R6,LOOP_VAR

INC
CJNE
MOV
LJMP

R7
R7,#100,REPETE
R7,#0
REPETE

; Repete por 50x


; 50x(10ms+10ms) = 1s --> Delay da varredura
; Incrementa contador...
; Contador = 100?

; *** ARQUIVOS DE INCLUSAO *************************************************


; **
**
; **************************************************************************
;
$INCLUDE(DELAY_PR.INC)

; *** TABELAS, CONSTANTES, STRINGS *****************************************


; **
**
; **************************************************************************
;
TABELA:
DB
0C0h, 0F9h, 0A4h, 0B0h, 99h, 92h, 82h, 0D8h, 80h, 90h
END

Soluo em Linguagem C
#include <8052.h>
#include <stdio.h>
#include <delay.h>
//
// ****************************************************************
// ** Pinos do MICROCONTROLADOR
**
// ****************************************************************
//
sfr at 0x90 display; // Display na porta P1 (A - P1.0, B - P1.1 ...)
sbit at 0xb2 anodou; // Controle da dezena (P3.2)
sbit at 0xb3 anodod; // Controle da unidade (P3.3)
//
// ****************************************************************
// ** V A R I V E I S E C O N S T A N T E S
**
// ****************************************************************
//
const unsigned char Tabela[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99,
0x92, 0x82, 0xd8, 0x80, 0x90};
//
// ****************************************************************
// ** P R O T O T Y P E S
**
// ****************************************************************
//
void delay1ms(void) _naked;
void delay(unsigned int tempo);

//
// ****************************************************************
// ** M A I N
**
// ****************************************************************
//
// Obs:. As rotinas de delay foram includas em uma biblioteca
//
denominada de delay.lib
//
void main(void)

{
unsigned char i, contador = 0;
anodod = 0;
// Desliga Dezena e...
anodou = 0;
// desliga unidade
while(1)
{
for(i=0; i<50; i++)
{
display = Tabela[contador/10];
anodod = 1;
delay(10);
anodod = 0;
display = Tabela[contador%10];
anodou = 1;
delay(10);
anodou = 0;

// Separa a dezena...
// e liga display dezena

// Seapara a Unidade
// e liga display unidade

}
if(++contador == 100) contador = 0;
}
}

Exerccio V
Modifique os programas em C e assembly do exemplo anterior (exemplo IV) de modo
que o mesmo implemente um contador de 0 59, o qual ser atualizado a cada segundo, mas
com numerao em octal e em hexadecimal. A contagem ser feita empregando apenas um
contador, ou seja, o programa deve tratar de separar a unidade da dezena, utilizando as
operaes de diviso inteira e resto da diviso.

Exemplo V
Neste exemplo, quatro displays de 7 segmentos esto conectados a porta P1. Para que
seja feita a seleo de qual dgito ser acionado, foram utilizadas quatro linhas de controle: P3.2
P3.5, para o acionamento do dgito da unidade (P3.5) at o dgito do milhar (P3.2). De modo
que o usurio no perceba que os dgitos esto piscando, sugere-se que cada dgito seja
acionado pelo menos 50 vezes por segundo (varredura de 200Hz). O display do tipo anodo
comum. Os segmentos so acionados com nvel lgico 0 e os anodos so acionados com nvel
lgico 1. O circuito foi simplificado ao mximo, tanto com relao ao microcontrolador quanto
com relao ao circuito de multiplexao do display. Desta forma no aparecem as chaves
(transistores) responsveis pelo chaveamento dos displays. Admita que estes circuitos esto
embutidos nos prprios displays. Em um circuito real no possvel conectar o display ao
microcontrolador da forma como est representado no diagrama eltrico. Seria necessrio
acrescentar os resistores para limitao de corrente e os transistores para o chaveamento dos
displays.
Para o circuito proposto deseja-se implementar um contador de 0 9999 que ser
atualizado a cada dcimo de segundo. A contagem ser feita empregando vrios contadores,
cada um responsvel pelo valor do dgito correspondente, ou seja, sero utilizados quatro
contadores.

Soluo em Assembly
;
; **** DOIS_DGT.ASM ********************************************************
; **
**
; ** Ultima Modificacao em: 05/10/2008
**
; **
**
; ********************************************************* by [JCLima ] ***
;
;
$MOD51

; *** Declaraes de Variveis *********************************************


; **
**
; **************************************************************************
;
MILHAR
EQU
7FH
CENTENA
EQU
7EH
DEZENA
EQU
7DH
UNIDADE
EQU
7CH

; *** Declarao de Pinos de I/O *******************************************


; **
**
; **************************************************************************
;
display
EQU
P1
anodo_m
EQU
P3.2
anodo_c
EQU
P3.3
anodo_d
EQU
P3.4
anodo_u
EQU
P3.5

; *** Vetor de Reset *******************************************************

; **
**
; ****************************************************** Endereco: 0000H ***
;
ORG
0000H
LJMP
START

; *** Vetor da INT0 ********************************************************


; **
**
; ****************************************************** Endereco: 0003H ***
;
ORG
0003H
RETI
; *** Vetor do Timer 0 *****************************************************
; **
**
; ****************************************************** Endereco: 000BH ***
;
ORG
000BH
RETI
; *** Vetor da INT1 ********************************************************
; **
**
; ****************************************************** Endereco: 0013H ***
;
ORG
0013H
RETI
; *** Vetor do Timer 1 *****************************************************
; **
**
; ****************************************************** Endereco: 001BH ***
;
ORG
001BH
RETI
; *** Vetor da Porta Serial ************************************************
; **
**
; ****************************************************** Endereco: 0023H ***
;
ORG
0023H
RETI

; *** PROGRAMA PRINCIPAL ***************************************************


; **
**
; **************************************************************************
;
START:
MOV
DPTR,#TABELA
; DPTR aponta para a tabela de 7seg
MOV
MOV
MOV
MOV

MILHAR,#0
CENTENA,#0
DEZENA,#0
UNIDADE,#0

CLR
CLR
CLR
CLR

ANODO_M
ANODO_C
ANODO_D
ANODO_U

; *** LOOP Programa Principal ...


;
REPETE:
MOV
R6,#5
LOOP_VAR:

;
;
;
;

Desliga
Desliga
Desliga
Desliga

o
o
o
o

anodo
anodo
anodo
anodo

do
da
da
da

milhar...
centena...
dezena...
unidade...

; Contador da varredura

MOV
MOVC
MOV
SETB
LCALL
CLR

A,MILHAR
A,@A+DPTR
P1,A
ANODO_M
DELAY5ms
ANODO_M

; Carrega Contador do milhar...


; Liga dgito do milhar por 5ms

MOV

A,CENTENA

; Carrega Contador da centena...

MOVC
MOV
SETB
LCALL
CLR

A,@A+DPTR
P1,A
ANODO_C
DELAY5ms
ANODO_C

; Liga dgito da centena por 5ms

MOV
MOVC
MOV
SETB
LCALL
CLR

A,DEZENA
A,@A+DPTR
P1,A
ANODO_D
DELAY5ms
ANODO_D

; Carrega Contador da dezena...


; Liga dgito da dezena por 5ms

MOV
MOVC
MOV
SETB
LCALL
CLR

A,UNIDADE
A,@A+DPTR
P1,A
ANODO_U
DELAY5ms
ANODO_U

; Carrega Contador da unidade...


; Liga dgito da unidade por 5ms

DJNZ

R6,LOOP_VAR

; Repete por 5x
; 50x(5ms+5ms+5ms+5ms)=100ms-->Delay da varredura

MOV
INC
CJNE
MOV

A,#10
UNIDADE
A,UNIDADE,REPETE
UNIDADE,#0

INC
CJNE
MOV

DEZENA
A,DEZENA,REPETE
DEZENA,#0

; Incrementa dezena...
; dezena = 10?

INC
CJNE
MOV

CENTENA
A,CENTENA,REPETE
CENTENA,#0

; Incrementa centena...
; centena = 10?

INC
CJNE
MOV

MILHAR
A,MILHAR,REPETE
MILHAR,#0

; Incrementa milhar...
; milhar = 10?

LJMP

REPETE

; Incrementa unidade...
; unidade = 10?

; *** ARQUIVOS DE INCLUSAO *************************************************


; **
**
; **************************************************************************
;
$INCLUDE(DELAY_PR.INC)

; *** TABELAS, CONSTANTES, STRINGS *****************************************


; **
**
; **************************************************************************
;
TABELA:
DB
0C0h, 0F9h, 0A4h, 0B0h, 99h, 92h, 82h, 0D8h, 80h, 90h
END

Soluo em Linguagem C
#include <8052.h>
#include <stdio.h>
#include <delay.h>
//
// ****************************************************************
// ** Pinos do MICROCONTROLADOR
**
// ****************************************************************
//
sfr at 0x90 display; // Display na porta P1 (A - P1.0, B - P1.1 ...)

sbit
sbit
sbit
sbit

at
at
at
at

0xb2
0xb3
0xb4
0xb5

dig1;
dig2;
dig3;
dig4;

//
//
//
//

Controle
Controle
Controle
Controle

do
do
do
do

digito
digito
digito
digito

1
1
1
1

(P3.2)
(P3.3)
(P3.4)
(P3.5)

//
// ****************************************************************
// ** V A R I V E I S E C O N S T A N T E S
**
// ****************************************************************
//
const unsigned char Tabela[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99,
0x92, 0x82, 0xd8, 0x80, 0x90};
//
// ****************************************************************
// ** P R O T O T Y P E S
**
// ****************************************************************
//
void delay1ms(void) _naked;
void delay(unsigned int tempo);

//
// ****************************************************************
// ** M A I N
**
// ****************************************************************
//
// Obs:. As rotinas de delay foram includas em uma biblioteca
//
denominada de delay.lib
//
void main(void)
{
unsigned char i, unidade, dezena, centena, milhar;
dig1
dig2
dig3
dig4

=
=
=
=

0;
0;
0;
0;

unidade = 0;
dezena = 0;
centena = 0;
milhar = 0;
while(1)
{
for(i=0; i<50; i++)
{
display = Tabela[milhar];
dig1 = 1;
delay(5);
dig1 = 0;
display = Tabela[centena];
dig2 = 1;
delay(5);
dig2 = 0;
display = Tabela[dezena];
dig3 = 1;
delay(5);
dig3 = 0;
display = Tabela[unidade];
dig4 = 1;
delay(5);
dig4 = 0;
}
if(++unidade == 10)
{

unidade = 0;
if(++dezena == 10)
{
dezena = 0;
if(++centena == 10)
{
centena = 0;
if(++milhar == 10) milhar = 0;
}
}
}
}
}

Outra Soluo em Linguagem C


Outra forma de implementar o programa seria utilizando um nico contador (inteiro de
16bits) e separando atravs de divises inteiras os dgitos do milhar at a unidade. Esta
abordagem fcil de ser feita em C mas no to simples de se implementar em assembly
pois divises de nmeros de 16 bits no so nativas do processador e portanto o programador
deve implementar os algoritmos de diviso com base na diviso de 8 bits.
#include <8052.h>
#include <stdio.h>
#include <delay.h>
//
// ****************************************************************
// ** Pinos do MICROCONTROLADOR
**
// ****************************************************************
//
sfr at 0x90 display; // Display na porta P1 (A - P1.0, B - P1.1 ...)
sbit at 0xb2 dig1;
// Controle do digito 1 (P3.2)
sbit at 0xb3 dig2;
// Controle do digito 1 (P3.3)
sbit at 0xb4 dig3;
// Controle do digito 1 (P3.4)
sbit at 0xb5 dig4;
// Controle do digito 1 (P3.5)

//
// ****************************************************************
// ** V A R I V E I S E C O N S T A N T E S
**
// ****************************************************************
//
const unsigned char Tabela[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99,
0x92, 0x82, 0xd8, 0x80, 0x90};
//
// ****************************************************************
// ** P R O T O T Y P E S
**
// ****************************************************************
//
void delay1ms(void) _naked;
void delay(unsigned int tempo);

//
// ****************************************************************
// ** M A I N
**
// ****************************************************************
//
// Obs:. As rotinas de delay foram includas em uma biblioteca
//
denominada de delay.lib
//
void main(void)
{
unsigned char i, unidade, dezena, milhar;
unsigned int centena, contador;
dig1 = 0;

dig2 = 0;
dig3 = 0;
dig4 = 0;
contador = 0;
unidade = 0;
dezena = 0;
centena = 0;
milhar = 0;
while(1)
{
for(i=0; i<5; i++)
{
display = Tabela[milhar];
dig1 = 1;
delay(5);
dig1 = 0;
display = Tabela[centena];
dig2 = 1;
delay(5);
dig2 = 0;
display = Tabela[dezena];
dig3 = 1;
delay(5);
dig3 = 0;
display = Tabela[unidade];
dig4 = 1;
delay(5);
dig4 = 0;
}
if(++contador == 10000) contador = 0;
milhar = contador/1000;
centena = contador%1000;
dezena = centena%100;
centena = centena/100;
unidade = dezena%10;
dezena = dezena/10;
}
}

Exerccio VI
Modifique os programas em C e assembly do exemplo anterior (exemplo V) de modo
que o mesmo implemente um cronmetro centesimal de 00.00 59.99, o qual ser atualizado a
cada centsimo de segundo.

Exerccio VII
No exemplo de hardware apresentado a seguir, so utilizados seis displays de 7
segmentos, os quais esto conectados a porta P1, e duas chaves do tipo Push Button nas portas
P3.0 e P3.1. Para que seja feita a seleo de qual dgito ser acionado, foram utilizadas seis
linhas de controle: P3.2 P3.7. De modo que o usurio no perceba que os dgitos esto
piscando, sugere-se que cada dgito seja acionado pelo menos 50 vezes por segundo (varredura
de 300Hz). O display do tipo anodo comum. Os segmentos so acionados com nvel lgico 0
e os anodos so acionados com nvel lgico 1. O circuito foi simplificado ao mximo, tanto com
relao ao microcontrolador quanto com relao ao circuito de multiplexao do display. Desta
forma no aparecem as chaves (transistores) responsveis pelo chaveamento dos displays.
Admita que estes circuitos esto embutidos nos prprios displays. Em um circuito real no
possvel conectar o display ao microcontrolador da forma como est representado no

diagrama eltrico. Seria necessrio acrescentar os resistores para limitao de corrente e os


transistores para o chaveamento dos displays.
Para o circuito proposto escreva um programa para implementar um relgio com
indicao de hora, minuto e segundo. O ajuste da hora inicial dever ser feito por meio das duas
chaves disponibilizadas no circuito. Suponha que o ajuste da hora s pode ser feito ao iniciar o
programa, ou seja, aps o reset. Depois de ajustada a hora, o relgio s poder ter sua hora
novamente ajustada ao se dar um reset no microcontrolador.

Exerccio VIII
No circuito apresentado a seguir, quatro displays de 7 segmentos multiplexados esto
conectados a memria RAM externa, atravs de dois latchs. Um dos latchs (U4), controla o valor
dos dgitos, enquanto que o outro latch (U5) controla qual dgito ser acionado naquele
momento. De modo a que o usurio no perceba que os dgitos esto piscando, sugere-se que
cada dgito seja acionado pelo menos 50 vezes por segundo (varredura de 200Hz). O display
do tipo anodo comum. Os segmentos so acionados com nvel lgico 0 e os anodos so
acionados com nvel lgico 1. O circuito foi simplificado ao mximo, tanto com relao ao
microcontrolador quanto com relao ao circuito de multiplexao do display. Desta forma no
aparecem as chaves (transistores) responsveis pelo chaveamento dos displays. Admita que
estes circuitos esto embutidos nos prprios displays. Em um circuito real no possvel
conectar o display ao microcontrolador da forma como est representado no diagrama
eltrico. Seria necessrio acrescentar os resistores para limitao de corrente e os transistores
para o chaveamento dos displays.
Para o circuito proposto implemente, um contador de 0 9999 que indique o valor da
contagem em dcimos de segundo. Implemente tambm com este circuito, um cronmetro

centesimal, de 00.00 59.99, com indicao em centsimos de segundo. Neste exemplo, faa
uso do ponto decimal para separa os segundos dos centsimos de segundo.

Exerccio IX
No circuito apresentado a seguir, quatro displays de 7 segmentos multiplexados esto
conectados a memria RAM externa, atravs de dois latchs. Um dos latchs (U4), controla o valor
dos dgitos, enquanto que o outro latch (U5) controla qual dgito ser acionado naquele
momento. Ao circuito foi foi acrescentado um conversor A/D do tipo ADC0831 (protocolo serial) e
um potencimetro, de modo a variar o sinal na entrada do A/D de 0 1Volts.
Para o circuito proposto, implemente um termmetro digital com a utilizao do
conversor A/D e do potencimetro, o qual vai simular um sensor de temperatura, que varia de 0
a 100C gerando um sinal de 10mV/ C (LM35). A indicao no display ser feita da seguinte
forma

Exerccio X
No circuito apresentado a seguir, um display LCD 20x4 est conectado diretamente as
portas P1 (dados do LCD) e P3 (controle do LCD sinais RS e E do LCD). Ao circuito foi foi
acrescentado um conversor A/D do tipo ADC0831 (protocolo serial) e um potencimetro, de
modo a variar o sinal na entrada do A/D de 0 1Volts. O conversor A/D controlado pela porta
P3.
Para o circuito proposto, implemente um termmetro digital com a utilizao do
conversor A/D e do potencimetro, o qual vai simular um sensor de temperatura, que varia de 0
a 100C gerando um sinal de 10mV/ C (LM35).

Exerccio XI
No circuito apresentado a seguir, um display LCD 20x4 est conectado a memria RAM
externa, atravs de dois latchs. Um dos latchs (U4), controla o valor do barramento de dados,
enquanto que o outro latch (U5) controla os sinais de controle RS e E. Ao circuito foi foi
acrescentado um conversor A/D do tipo ADC0831 (protocolo serial) e um potencimetro, de
modo a variar o sinal na entrada do A/D de 0 1Volts. O Conversor A/D controlado por meio
da porta P1.
Para o circuito proposto, implemente um termmetro digital com a utilizao do
conversor A/D e do potencimetro, o qual vai simular um sensor de temperatura, que varia de 0
a 100C gerando um sinal de 10mV/ C (LM35).

Вам также может понравиться