Sie sind auf Seite 1von 39

Pràctica d’Ordinadors

Hardware 8031

Barcelona a dijous, 30 de maig del 2002

Xavi Gonzalvo (st06375)


Dani Rubio (st06602)
Placa 8031 2

1. Enunciat

En la pràctica de software es va implementar una peixateria industrial amb una


sèrie d’opcions o estadístiques que l’usuari podia consultar. Si recordem, l’usuari
podia seleccionar una persona amb el mouse, i llavors el programa li mostrava les
seves característiques. Aquestes característiques són el numero de persona i la
seva llista de la compra, que estava dividida en dos parts: els productes comprats i
els productes que li quedaven per comprar. En la pràctica de hardware aprofitarem
aquesta funció per implementar una megafonia externa controlada per un
microcontrolador 8031.

1.1. Funcionament de la pràctica.

En la part de hardware tindrem un teclat de matriu per controlar el programa,


un LCD per mostrar resultats i un altaveu que farà la funció de megafonia de
la peixateria.

La placa del 8031 haurà d’estar permanentment connectada al PC, on


tindrem la pràctica de software funcionant. Inicialment hi haurà visualitzat en
l’LCD el missatge “Introdueixi numero de persona:” i el programa esperarà
que introduïm el numero (identificador) corresponent a la persona que volem
consultar. Mentrestant la pràctica de software anirà corrent amb tota
normalitat i nosaltres podem anar afegint persones o consultar el que
vulguem. Un cop introduïm un identificador d’una persona pel teclat de
matriu, el 8031 s’haurà de posar amb contacte amb el PC, i li haurà de
demanar la llista de la compra d’aquella persona (només els productes que li
queden per comprar). Un cop rebi aquestes dades, el 8031 ha de visualitzar
per LCD una informació semblant a aquesta:

Això significa que hem seleccionat la persona 2 i que li falten per comprar 2
unitats del producte 3, 3 del producte 1 i 5 del producte 2. El format per
escriure la informació ho podeu fer com vulgueu, però si no cap tot a la
pantalla haureu de fer lletres amb desplaçament o anar canviant a una
segona pantalla, etc...

A més tota aquesta informació l’haureu de reproduir per l’altaveu, i quedaria


una cosa d’aquest estil:

En aquest format d’exemple només hauríem de gravar les paraules: persona,


falten, unitats, producte, i els números del 0 al 9.

En el cas que la persona seleccionada no existeixi en la peixateria (ja hagi


sortit, o encara no hagi entrat) haurem de treure un missatge d’error per
l’LCD que ho indiqui.
Placa 8031 3

Com podeu observar s’haurà de modificar lleugerament la pràctica de


software i crear un protocol de comunicació entre el PC i la nostra placa per
poder passar la informació de les llistes de la compra.

2. Explicació del diseny

2.1. Hardware

2.1.1. Banc de codi

La pràctica ha d’executar codi des de la EPROM i des de la FLASH. Per


tant des del punt de vista del direccionament de codi hem de veure:

La longitud de la flash ha fet que haguem d’utilitzar paginació. La elecció


ha estat de fer planes de 32Kb. A la primera romandrà el codi a
executar i a les següents les mostres d’àudio.

Per a fer-ho possible s’han utilitzat com a adreces falses de la flash des
de 15...18 gràcies als bits baixos del P1 del 8031 (veure apartat 2.1.4).

2.1.2. Banc de dades

Des de les dades hem de veure tots els perifèrics que utilitzem a més de
la flash ja que en aquesta hi guardem totes les mostres. Per tant el
mapa queda de la següent forma:

A15 A14 A13


CS_LCD

A15 A14 !A13 CS_DAC


A15 !A14 A13 CS_BOTTON
-

!A15 CS_FASH
CS_FASH
CS_FASH
Placa 8031 4

2.1.3. Generació de Chip Selects

Per a generar tots els senyals de control de la pràctica hem usat una
GAL22V10. No és l’ús més recomenat en muntatge de plaques però pel
cas que ens ocupa li hem de veure 3 factors a favor:
1. És la primera pràctica amb un 8031 i per tant els errors són
possibles. La GAL permet regrabar.
2. És una pràctica i per tant el comput de hardware surt clarament
inferior a utilitzar portes lògiques. Menys a soldar, menys temps.
3. Un cop acabada la pràctica, tot es desmunta i cap a la capsa de
nou. No existeix problema de fallida a la GAL

Recomenem el disseny de portes lògiques per a futurs dissenys amb el


microprocessador.

A aquesta GAL hem generat:


• Chip selects
• Output Enable de la FLASH per a fer-la visible des de codi i dades.
• La multiplexació de les adreces falses de la FLASH.

+5

U3
24

2 14
A15 AF18
VCC

3 I1 I/O0 15
A14 I2 I/O1 AF17
4 16
A13 I3 I/O2 AF16
5 17
!RD I4 I/O3 AF15
6 18
!PSEN I5 I/O4 !OE_FLASH
7 19
!WR I6 I/O5 !CS_BOTON
8 20
A15_FALSA I7 I/O6 !CS_DAC
9 21
A16_FALSA I8 I/O7 CS_LCD
10 22
A17_FALSA I9 I/O8 !CS_FLASH
11 23
A18_FALSA I10 I/O9 !CS_ROM
13
I11
GND

1
CLK/I0
12

PALCE22V10

;PALASM Design Description

;---------------------------------- Declaration Segment ------------


TITLE Ordinadors
PATTERN
REVISION 3.0
AUTHOR Jare Crisna
COMPANY Crisna Jare
DATE 04/16/02

CHIP _ord1 PAL22V10

;---------------------------------- PIN Declarations ---------------


PIN 2 A15
PIN 3 A14
PIN 4 A13
PIN 5 NO_RD
PIN 6 NO_PSEN
PIN 7 NO_WR
PIN 8 A15_F
PIN 9 A16_F
PIN 10 A17_F
PIN 11 A18_F

PIN 23 NO_CSROM
PIN 22 NO_CSFLASH
PIN 21 CSLCD
PIN 20 NO_CSDAC
PIN 19 NO_CSBOTON
PIN 18 NO_OEFLASH
PIN 17 A15_FLASH
PIN 16 A16_FLASH
Placa 8031 5

PIN 15 A17_FLASH
PIN 14 A18_FLASH

;----------------------------------- Boolean Equation Segment ------


EQUATIONS

NO_CSROM = A15 + NO_PSEN


NO_CSFLASH = ( NO_RD*NO_WR + /A15 )*( NO_PSEN + /A15 )
CSLCD = /( NO_RD*NO_WR + A15 + A14 + A13)
NO_CSDAC = NO_RD*NO_WR + A15 + A14 + /A13
NO_CSBOTON = NO_RD*NO_WR + A15 + /A14 + A13
NO_OEFLASH = NO_RD*NO_PSEN
A15_FLASH = A15_F*( NO_PSEN + /A15 )
A16_FLASH = A16_F*( NO_PSEN + /A15 )
A17_FLASH = A17_F*( NO_PSEN + /A15 )
A18_FLASH = A18_F*( NO_PSEN + /A15 )

2.1.4. El Microprocessador

Es tracta d’un microprocesador Philips 80C31. S’han utilitzat tots els


ports per adreces i dades, per tant !EA s’ha conectat a massa. No s’han
utilitzats ni interrupcions ni timers externs. El port 1 s’ha utilitzat per
adreces falses de la flash i control de jumpers.

La configuració del jumpers és la següent:


• Jumper 1: Si hi ha jumper fem telecàrrega, sinó saltem
directament a la flash
• Jumper 2: Si hi ha, telecarreguem mostres d’àudio, sinó codi.

El circuit de clock utilitza un cristall de 11.0592 MHz. És un valor útil par


a configurar los timers internos para la transmisión serie.

Per multiplexar la part baixa de les direccions usem un 573 que és més
útil que el 373 per la disposició dels pins.

2.1.5. La memoria

Hem utilitzat 32k de ROM i 512k de flash. El codi de boot resideix a la


ROM i es tracta d’un programa de telecàrrega per a grabar la flash.

L’Output Enable de la flash está format per !PSEN i !RD per a fer
possible que aquesta la veiem tant des del mapa de codi com del de
dades.

Distribució física de la memòria:

0x00000h
Telecàrrega
EPROM (32Kb)
0x08000h
Codi programa
principal
(32Kb)
0x28000h
Mostres àudio
“0”
FLASH

0xCA000h
Mostres àudio
“20”
0x??000h
Placa 8031 6

2.1.6. El port sèrie

La transmissió amb el PC es realitza a 9600 bps. El clock utilizat ens ha


permés configurar el timers corresponents.

S’ha configurat el port sèrie en Mode 1. Amb aquest mode el baud rate
és variable.

Segons la documentació, per configurar el timer 1 podem usar la


següent fòrmula:

K ·Cristall
TH 1 = 256 −
384·Baud Rate

El valor de K está en funció de com configurem el registre SMOD. En


cas que volguem doblar el baud rate només hem de fer SMOD=1, i per
tant, K=2.

Per a adaptar els nivells de tensions del RS232 del PC i la placa hem
utilitzat un MAX232.

2.1.7. Perifèrics

El periférics utilitzats en la práctica están en funció dels requisits de


l’enunciat. Són els següents:

2.1.7.1. Teclat
El teclat consta de 10 tecles (del 0 al 9). Fem ús d’un buffer 244
que ens permetrà, amb un sol batec de clock, posar i llegir files i
columnes.

Per a fer-ho possible conectem les adreces a les files i les dades
a les columnes. Quan llegim d’una columna, els bits d’adreces
corresponents a aquesta columna estaran a “1” i només haurem
de mirar el valor del bus de dades. Òbviament la columna haurà
d’anar rotant. Tota aquesta feina sense inteferir la resta de
programa.

Cal tenir en compte, que aquest teclat produeix rebots, per tal
d’evitar-los, hem fet servir el timer intern per deixar un petit
temps d’espera i així evitar-los.

; Nos da el boton presionado probando una columna cada vez


; Devuelve: tecla_actual

botonera:
lcall programa_timer_0_botonera
mov dph, #port_boton
mov dpl, columna_actual
movx a, @dptr ; Aixequen les Ai i llegim les Di
anl a, #0Fh
cjne a, #00h, hay_boton
mov flag_boton, #00h
sjmp botonera_fin
Placa 8031 7

hay_boton:
lcall espera_timer_0
lcall espera_timer_0
lcall espera_timer_0
mov fila_actual, a
lcall decodifica_tecla
mov flag_boton, #01h
botonera_fin:
lcall incrementa_columna
ret

2.1.7.2. LCD
Es un display de 16 caracters x 2 files. El controlem com a
qualsevol perifèric mitjançant un Chip Select que funciona per
lògica positiva.

Per a distingir escriptura de lectura i dades de control usem les


adreces baixes als pins 4 i 5. Això ens definirà 3 ports al codi:
• Escriptura de comandes
• Lectura de comandes
• Escriptura de dades

L’accés al LCD l’hem realitzat mitjantçant la definició d’una taula


de valors segons el datasheet i la implementació d’una funció a
la qual li passem cada un d’aquests valors segons el caràcter a
representar:

.org 6C00h
;* Post Pone una letra en el LCD
;* Necesita: letra en registro A
;* Modifica: a,dptr
pon_letra:
mov dptr, #port_lcd_wd
movx @dptr, a
lcall espera_respuesta_display
ret

Més tard, comparant amb exemples d’assembler del 8086, ens


hem adonat que podríem haver realitzat un accés més óptim:

...
mov dptr,#mensaje_lcd
lcall outstr
...
mensaje_lcd: db 'Mensaje en el Lcd\',0
...

;* Post Pone un mensaje en el LCD


;* Necesita: direccion mensaje en dptr
;* Modifica: a,dptr
pon_mensaje_lcd:
clr a
movx a,@dptr
cjne a,#'\', pon_mensaje_lcd_sigue
sjmp pon_mensaje_lcd_fin

pon_mensaje_lcd_sigue:
push dph
push dpl
lcall envia_caracter
lcall espera_respuesta_display
pop dpl
Placa 8031 8

pop dph
inc dptr
sjmp outstr

pon_mensaje_lcd_fin:
ret

2.1.7.3. DAC
Donat que hem de reproduir diferents sons per un altaveu hem
fet ús d’un conversor digital analògic de 8 bits. La seva
freqüència de treball és més que suficient per a aplicacions
d’àudio com la nostra.

Com a amplificador d’audio hem utilitzat el LM386 a la


configuració estándard que ens dóna fins a 20dB de guany
controlat per una resistència que controla el volum.

Mitjançant un timer intern accedirem periòdicament al perifèric


(concretament cada Ts = 1 = 125µseg ) controlant-l’ho per
8kHz
!WR en mode automàtic.

Per aixó hem fet servir el timer 0 (ja que el timer 1 es utilitzat pel
port sèrie), tant per controlar aquest temps com el temps
d’espera del rebots del teclat. Les funcions són:

init_timer_0:
mov tmod, modo_timer
mov th0, espera_timer_0_h
mov tl0, espera_timer_0_l
clr tr0
ret

; Espera para evitar rebotes


espera_timer_0:
setb tr0
jnb tf0, espera_timer_0
clr tr0
clr tf0
ret

; Espera para sacar frecuencia de 8k


freq_t0:
setb tr0
freq_t0_2:
jnb tf0, freq_t0_2
clr tr0
clr tf0
ret
Placa 8031 9

D0
D1
D2
D3
D4
D5
+5
D6
D7
+5

40

20
U1 U2
31 39 2 19
A0

VCC

VCC
EA/VP P0.0 38 3 D1 Q1 18
P0.1 D2 Q2 A1
+5 19 37 4 17
X1 P0.2 D3 Q3 A2
Y 36 5 16
P0.3 D4 Q4 A3
35 6 15
11.05M P0.4 D5 Q5 A4
PUSH1 18 34 7 14
X2 P0.5 D6 Q6 A5
RESET COSC2 33 8 13
P0.6 D7 Q7 A6
COSC1 32 9 12
22p P0.7 D8 Q8 A7
CReset 9
22p RESET 21 11

GND
33n P2.0 A8 ALE C
22 1
P2.1 A9 OC
12 23
INT0 P2.2 A10
13 24 54ABT573
INT1 P2.3 A11

10
14 25
T0 P2.4 A12
R1 +5 15 26
T1 P2.5 A13
27
33k P2.6 A14
1 28
AF15 P1.0 P2.7 A15
2
AF16 P1.1
R2 3 17
AF17 P1.2 RD !RD
4 16
10k AF18 P1.3 WR !WR
5 29
P1.4 PSEN PSEN
6 30
P1.5 ALE/P ALE
2

7 11
P1.6 P1.6 TXD TX

VSS
+5 J2 8 10
P1.7 P1.7 RXD RX
B2S
80C31

20
+9 J1
R3
1

1
10k 2
+5 CON2

U3 +5
24
2

J3 2 14 U4
A15 AF18
VCC
3 I1 I/O0 15 +9 D1 UPC7805 D2
B2S A14 I2 I/O1 AF17
4 16 1 2

GND
A13 I3 I/O2 AF16 IN OUT
5 17 CReg
!RD I4 I/O3 AF15 D1N4001
6 18 RLED
1

!PSEN I5 I/O4 !OE_FLASH 0.1u


7 19 LED
!WR I6 I/O5 !CS_BOTON 330
8 20

3
A15_FALSA I7 I/O6 !CS_DAC
9 21
A16_FALSA I8 I/O7 CS_LCD
10 22
A17_FALSA I9 I/O8 !CS_FLASH
11 23
A18_FALSA I10 I/O9 !CS_ROM
13
I11
GND

1
CLK/I0
12

PALCE22V10
Title
80C31 i Chip Selects

Size Document Number Rev


A 1 2.0

Date: Saturday , May 18, 2002 Sheet 1 of 1


Placa 8031 10

U5
10 11
A0 A0 O0 D0
9 12
A1 A1 O1 D1
8 13
A2 A2 O2 D2
7 15
A3 A3 O3 D3
6 16
A4 A4 O4 D4
5 17
A5 A5 O5 D5
4 18
A6 A6 O6 D6
3 19
A7 A7 O7 D7
25
A8 A8
24
A9 A9
21 +5
A10 A10
23
A11 A11
2 28
A12 A12 VCC
26 14
A13 A13 GND
27
A14 A14
20
!CS_EPROM CE
22
!PSEN OE
1
VPP
27C256

+5

32
U6
12 13
A0

VCC
11 A0 DQ0 14
A1 A1 DQ1
10 15
A2 A2 DQ2
9 17
A3 A3 DQ3
8 18
A4 A4 DQ4
7 19
A5 A5 DQ5
6 20
A6 A6 DQ6
5 21
A7 A7 DQ7
27
A8 A8
26
A9 A9
23
A10 A10
25
A11 A11
4
A12 A12
28
A13 A13
29
A14 A14
3
AF15 A15
2
AF16 A16
30
AF17 A17
1
AF18 A18
24
!OE_FLASH OE
22
!CS_FLASH CE
VSS

31
!WR WE
16

AM29F040/LCC

Title
Memòries

Size Document Number Rev


A 2 1.2

Date: Saturday , May 18, 2002 Sheet 1 of 1


Placa 8031 11

+5

16
U7
13 12
TXD RX

VCC
8 R1IN R1OUT 9
11 R2IN R2OUT 14
TX T1IN T1OUT RXD
10 7
T2IN T2OUT
1u CMax1
1
C+
3
1u CMax2 C1-
4
C2+
+5 5
CMax3 C2-
2
V+
6

GND
CMax5 V-

10u

15
MAX232

P1
1
6
2
RXD
7
3
TXD
8
4
9
5

CONNECTOR DB9

+5

CBy pass_1 CBy pass_2 CBy pass_3 CBy pass_4 CBy pass_5 CBy pass_6 CBy pass_7
22n 22n 22n 22n 22n 22n 22n

Title
RS232

Size Document Number Rev


A 5 1.0

Date: Tuesday , May 28, 2002 Sheet 1 of 1


Placa 8031 12

PUSH PUSH PUSH


U9 BD0 BD0 BD0
2 18
A0 1A1 1Y 1 BA0
4 16
A1 1A2 1Y 2 BA1 PUSH PUSH PUSH
6 14
A2 1A3 1Y 3 BA2
8 12
1A4 1Y 4 BD1 BD1 BD1
11 9
D0 2A1 2Y 1 BD0
13 7
D1 2A2 2Y 2 BD1 PUSH PUSH PUSH
15 5
D2 2A3 2Y 3 BD2
17 3
D3 2A4 2Y 4 BD3 BD2 BD2 BD2
1
!CS_TECLAT 1G PUSH
19
2G
BD3
74LS244

BA0 BA1 BA2

U10
+5 AUDIO
+5 2 18 +5
AUDIO OUTA VDD
RCon J5
+5 1 6 RVOL
1 OUTB DGND
10K 2 U4

6
1
20 3 10K
3 OUTC VSS 3 Calt2
A1 + J1
4 19 5 7 5
A0 5 OUTD AGND 1
+5 2
!CS_LCD 6 - 250u 2
14 4 LM386
D0 7 D0 D0 REF
13 Calt1 CON2
D1 8 D1 D1
12

4
8
D2 9 D2 D2 0.05u
11
D3 10 D3 D3
10 15 Ralt1
D4 11 D4 D4 !WR !CS_DAC
9
D5 12 D5 D5 1k
8
D6 13 D6 D6
7

A0

A1
D7 14 D7 D7
LCD TLC7226 17

16

Title
Perif èrics

Size Document Number Rev


A 3 1.0

Date: Tuesday , May 28, 2002 Sheet 1 of 1


Placa 8031 13

2.2. Software

2.2.1. Telecàrrega de codi i mostres

El programa de telecàrrega es troba a la ROM. Es tracta d’un codi que


es comunica amb un programa de PC el qual transmet el conjunt de
codi que s’anirà gravant a la flash.

A més de telecarregar el codi a la flash, el codi de la ROM implementa


un seguit de funcions que s’inclouen a la part alta. Aquestes funcions es
poden cridar des del codi de la flash com si es tractessin de rutines
BIOS.

a) Códi:

Hem utilitzat el format INTEL HEX:

:04800000029C373275

• (:) Æ Inici de totes les línies. Si durant la transmissió hi ha


hagut algun error de Checksum, el codi de l’EPROM queda
deturat reinicialitza el programa de telecàrrega.
• (04) Æ El dos següents bytes rebuts són el número de bytes
de codi que s’hauran d’escriure.
• (8000) Æ És la posició a partir de la qual hem d’escriure la
dada. És directament l’adreça de la FLASH si el codi té els
.org a 8000h i següents.
• (00) Æ Són dos bytes de farciment que indiquen l’última línia
i per tant fi de transmissió si valen 01.
• (29 C3 37 32) Æ Bytes d’informació. En total tants com indica
el primer byte de la línia. Són els opcodes de l’assembler.
• (75) Æ És el Checksum de tots els bytes anteriorment rebuts.
Si sumem tots els bytes rebuts i hi afegim el 75 ens ha de
quedar 0x00.

Amb aquest format controlem els possibles errors que puguin


ocòrrer a la transferència sèrie.

La transmissió es realitza caràcter a caràcter en format ASCII.


Les funcions encarregades de rebre, enviar i convertir les dades
a la placa són:

• init_serie: inicialitza el port serie, per tant el timer 1, i


altres registres implicats per aconseguir 9600 bps.
• Inchar: rep un caràcter pel port sèrie.
• Outchar: envia un caràcter pel port sèrie.
• Gethex: dues crides a inchar per agafar dos caràcters i
formar un byte hexadecimal.
• Atoh: conversió ASCII a hexadecimal. Funcionament:

Atoi(‘A’)=65
Atoi(‘B’)=66
Transferència sèrie de ‘65’
Placa 8031 14

Transferència sèrie de ‘66’


Atoh(‘65’ & ‘66’)=0xAB

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PORT SERIE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.org 6400h
;* Post: Inicializa puerto serie a 9600 bps
init_serie:
mov scon, #50h
mov tmod, #20h
mov th1, #fdh
setb tr1
setb ti
ret

.org 6500h
;* Post: Espera hasta que recibe un byte por el puerto serie.
;* Devuelve el valor en A.
inchar:
jnb ri, inchar
clr ri
mov a, sbuf
ret

.org 6600h
;* Post: Tx por el bit serie un byte en ascii
;* Necesita: dada_a_tx_serie
outchar:
jnb ti, outchar
clr ti
mov sbuf, dada_a_tx_serie
ret

.org 6700h
;* Post:Coge dos caracteres del puerto serie y forma un byte hexa
;* Retorna en A
;* Modifica: a,r0
gethex:
push dptr
lcall inchar
lcall outchar
lcall atoh
swap a
mov r0, a
lcall inchar
lcall outchar
lcall atoh
orl a, r0
lcall calcula_checksum
pop dptr
ret

;* Post: Convierte ASCII to HEX


;* Necesita: A
atoh:
clr acc.7
cjne a, #3ah, next
next:
jc atoh2
add a, #9
atoh2:
anl a, #0fh
ret

b) Telecàrrega de mostres:
Placa 8031 15

La telecàrrega de mostres d’audio es realitza també caràcter a


caràcter. Pot fer-se de fitxers wav i fitxers text. El format de
transferència és el següent:

Caràcter
Pasos 1 2 3 4 5
1 1 8 0 0 0
2 0 E C E
3 8 0
... ... ...
5 1 2
6 F 3

• Pas 1: el caràcter 1 és la pàgina de la flash, els caràcters


2 i 3 és la part alta de la direcció de la flash inici on es
grabaran i els caràcters 4 i 5 la part baixa.
• Pas 2: caràcters 1 i 2 la part alta del total de bytes a
enviar i 4 i 5 la part baixa.
• Pasos següents fins final fitxer: caràcter 1 del byte
hexadecimal i caràcter 2 del byte hexadecimal.

2.2.2. Programa ASM

El programa el podríem organitzar en diferents parts:

• Anar llegint el teclat per format el número de persona amb dos


dígits.
• Un cop tenim el número de la persona, el programa es comunica
amb el PC i rep els productes i quantitat de la persona en
qüestió.
• Finalment reproduïm els sons corresponents a la llista de
comprar seleccionada i els mostrem pel LCD.

2.2.3. Modificacions al programa Software de CPP

En la práctica de software s’ha creat un nou mòdul per realitzar la


comunicacions entre la placa hardware i el nostre programa.

Aquest nou mòdul, anomenat PLACA, inclou la inicializatzació i el


tancament del port sèrie. Inclou també un motor cooperatiu amb la resta
del programa, que controla tot el relacionat amb aquesta comunicació.
És a dir:

• La captura del número de persona enviat de la placa.


• El tipus i la quantitat de productes que resten per comprar.
• Control de l’existència de la persona i els productes restants.
Aquests són unicament els que s’enviem pel port sèrie.

L’objectiu primordial era aconseguir el mínim de modificacions a la part


de C. S’ha aconseguit. A part del nou TAD anterior només hem tingut
Placa 8031 16

que modificar una funció per recuperar la llista de compra, la resta de la


pràctica ha quedat intacte.

#include "mercado.h"
#include "graficos.h"
#include "placa.h"
extern "C"{
#include "tadsio.h"
}

int EstadoSerie,valor;
int *Codes;
int persona;
int Producto;

//////////////////////////////////////////////////////////////
// INICIALIRZA EL PORT SERIE //
//////////////////////////////////////////////////////////////

void PL_init(){
if(Si_Init(SI_COM1,b_9600,SI_WORD_8,SI_PAR_NONE)==SI_NO_SIO)
GR_PintaEstatPort(0);
else GR_PintaEstatPort(1);
EstadoSerie=0;
}

////////////////////////////////////////////////////
// MOTOR DE LA SIO //
////////////////////////////////////////////////////

void PL_motor(void){
switch(EstadoSerie){
case 0:{// Miramos si tenemos algun valor por el puerto serie
if (Si_CharAvail()!=0) EstadoSerie=1;
break;}
case 1:{// Cogemos el valor del puerto
valor=Si_GetChar();
if(valor==VALOR_INICIO){
EstadoSerie=2;
Si_PutChar(VALOR_OK);
}
else {
Si_PutChar(VALOR_KO);
EstadoSerie=0;
}
break;}
case 2:{// Esperamos las decenas de la persona
if (Si_CharAvail()!=0){
EstadoSerie=3;
valor=Si_GetChar();
Si_PutChar(VALOR_OK);
persona=valor*10;
}
break;}
case 3:{// Esperamos las unidades de la persona
if (Si_CharAvail()!=0){
valor=Si_GetChar();
persona=persona+valor;
if (ME_ExistePersona(persona)==VALOR_OK){
Si_PutChar(VALOR_OK);
EstadoSerie=4;
}
else{
Si_PutChar(VALOR_KO);
EstadoSerie=0;
}
}
break;}
case 4:{// Buscamos la persona y cogemos sus paquetes
Codes=ME_IluminaPersona(persona);
Producto=0;
EstadoSerie=5;
Placa 8031 17

break;}
case 5:{// Enviamos los productos
if(Producto==8){
EstadoSerie=8;
}
else{
if (Codes[Producto]!=0){
Si_PutChar(Producto+1);
EstadoSerie=6;
}
else{
Producto++;
}
}
break;}
case 6:{//Seguimos enviando los productos
if (Si_CharAvail()!=0){
valor=Si_GetChar();
Si_PutChar(Codes[Producto]);
EstadoSerie=7;
}
break;}
case 7:{//Esto dura demasiado
if (Si_CharAvail()!=0){
valor=Si_GetChar();
Producto++;
EstadoSerie=5;
}
break;}
case 8:{//Envia final de tx
Si_PutChar(0x09);
EstadoSerie=9;
break;}
case 9:{//rRecibe constestacion
if (Si_CharAvail()!=0){
valor=Si_GetChar();
EstadoSerie=0;
}
break;}
}
}

/////////////////////////////////
// Se cierra el tema
/////////////////////////////////

void PL_End(void){
Si_ResetRx();
Si_End();
}
Placa 8031 18

3. Conclusions i problemes observats

Els principals problemes que hem trobat en el desenvolupament de la pràctica han


estat en el hardware. Podríem començar per:

• La primera CPU que vam comprar va ser una INTEL. El resultat va ser que
no donava suficient corrent i les senyals que anaven a parar a la GAL
s’amorraven. La solució va ser incloure pull-ups als bits del P1 i al !RD i
!WR. Les dues últimes setmanes abans de l’entrega la vam cambiar per
una PHILIPS. Tot va començar a funcionar millor, psicològic però part de
raó tenim.
• Hem aprés, després de patir molt, que quan es monta la placa és
indispensable testejar-la amb el Reset soldat, la CPU i la EPROM. Per no
dir alimentació i massa. En cas de que no hi hagi EPROM la CPU salta a
executar “no sabem que” i executa HALT el que fan que pari l’oscil·lació i el
més important, que es pugui confondre amb un problema del circuit de
clock. Ull!
• Muntar una placa des de 0 és un bon camí d’aprenentatge, bravo! Només
dir que les plaques wriwrap són un niu d’errors i els cables només fan que
portar problemes. De totes formes és també una manera de trobar averies.
• Hem de destacar que l’assembler del 8031 és molt agraït. Es nota l’evolució
des del Z80 amb estructures com “cjne” entre d’altres. Hem provat
compiladors de C però per la feina a desenvolupar no ha estat necessari.
• S’ha hagut de fer servir un timer per evitar el rebots que produeix el teclat.
D’aquesta manera s’eviten repeticions inexistents d’una tecla.
• Hem tingut problemes amb el LCD, no pel desconeixement del chip (ja ho
havíem fet servir) sinó perquè en principi no anava bé, i més tard, interferia
en el bus de dades a causa d’un mal contacte causat per col·locar-lo
malament en un zòcal.
Placa 8031 19

dir_arch_3 EQU 0200h


dir_arch_4 EQU 0300h
4. Codi Assembler de la telecàrrega dir_arch_5 EQU 0400h
dir_arch_6 EQU 0500h
; Constantes dir_arch_7 EQU 0600h
acc EQU 0e0h dir_arch_8 EQU 0700h
b EQU 0f0h dir_arch_9 EQU 0800h
dph EQU 083h dir_arch_10 EQU 0900h
dpl EQU 082h dir_arch_11 EQU 0A00h
dir_arch_12 EQU 0B00h
PUNTO EQU 00101110b dir_arch_13 EQU 0C00h
ESPACIO EQU 00100000b dir_arch_14 EQU 0D00h
BARRITA EQU 00101111b dir_arch_15 EQU 0E00h
LETRA_PAR_A EQU 00101000b dir_arch_16 EQU 0F00h
LETRA_PAR_C EQU 00101001b dir_arch_17 EQU 1000h
LETRA_0 EQU 00110000b dir_arch_18 EQU 1100h
LETRA_1 EQU 00110001b dir_arch_19 EQU 1200h
LETRA_2 EQU 00110010b dir_arch_20 EQU 1300h
LETRA_3 EQU 00110011b dir_arch_21 EQU 1400h
LETRA_4 EQU 00110100b dir_arch_22 EQU 1500h
LETRA_5 EQU 00110101b
LETRA_6 EQU 00110110b
LETRA_7 EQU 00110111b ; Puertos
LETRA_8 EQU 00111000b port_lcd_wc equ 0000h
LETRA_9 EQU 00111001b port_lcd_rc equ 0001h
LETRA_a EQU 01100001b port_lcd_wd equ 0002h
LETRA_ACAPS EQU 01000001b
LETRA_c EQU 01100011b ; Variables
LETRA_CCAPS EQU 01000011b adreca_escriure_alt equ 30h
LETRA_d EQU 01100100b adreca_escriure_baix equ 31h
LETRA_e EQU 01100101b dada_a_escriure equ 32h
LETRA_g EQU 01100111b sector_a_esborrar equ 33h
LETRA_i EQU 01101001b dada_a_tx_serie equ 34h
LETRA_l EQU 01101100b numero_bytes equ 35h
LETRA_n EQU 01101110b suma_checksum equ 36h
LETRA_o EQU 01101111b final_fichero_alta equ 37h
LETRA_r EQU 01110010b final_fichero_baja equ 38h
LETRA_TCAPS EQU 01010100b pagina_fichero equ 39h
LETRA_u EQU 01110101b fichero_actual equ 40h

NUMERO_FICHEROS_ALTO EQU 00110010b ; Valores flash


NUMERO_FICHEROS_BAJO EQU 00110010b sector_flash_0 equ 00h
numero_de_ficheros EQU 16h sector_flash_1 equ 02h
sector_flash_2 equ 04h
dir_arch_1 EQU 0000h sector_flash_3 equ 06h
dir_arch_2 EQU 0100h sector_flash_4 equ 08h
Placa 8031 20

sector_flash_5 equ 0Ah


sector_flash_6 equ 0Ch lcall init_lcd
sector_flash_7 equ 0Eh ret
valor_ok_transferencia equ 01h
valor_no_ok_transferencia equ 07h ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TELECARGA CODIGO
flash set 8000h ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Post: Realiza toda la telecarga del fichero en la primera página de la flash


; Modifica: a,dptr
.symbols TELECARGA_CODIGO:
.org 0 mov a, #sector_flash_0 ; borramos el sector 0 de la Flash
ljmp MAIN mov sector_a_esborrar, a
lcall esborra_sector_flash
.org 0030h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lcall resetea_lcd
; MAIN de la EPROM lcall MUESTRA_MENU_TELECARGA_CODIGO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Miramos los jumpers: inicio_lee_linea:
; p1.4 -> telecarga/flash mov suma_checksum, #00h
; p1.5 -> codigo/muestras lcall inchar
; lcall outchar
; p1.4 -> 0 (Con jumper): Telecarga cjne a, #':', error
; -> 1 (Sin jumper): Salta a la flash
; p1.5 -> 0 (Con jumper): Telecarga muestras recibe_numero_de_bytes:
; -> 1 (Sin jumper): Telecarga código lcall gethex ; cogemos el valor del numero de bytes
mov numero_bytes, a
MAIN:
lcall programacion_inicial recibe_direcciones:
mov a,P1 lcall gethex ; cogemos primer valor de la direccion
jb acc.4, SALTA_FLASH ;orl a, #80h
mov a,P1 mov adreca_escriure_alt, a
jb acc.5, TELECARGA_CODIGO
ljmp TELECARGA_FICHEROS lcall gethex ; cogemos segundo valor de la direccion
mov adreca_escriure_baix, a
SALTA_FLASH:
ljmp flash recibe_flag_final_fichero:
lcall gethex ; miramos si es final de fichero
cjne a, #00h, final_de_transferencia
;* Post: Programación de perifericos
;* Modifica: P1,a recibe_valores_de_datos:
programacion_inicial: lcall gethex ; cogemos el byte correspondiente
lcall init_serie mov dada_a_escriure, a
setb p1.4
setb p1.5 ; Escribimos en la flash
mov dada_a_tx_serie, #valor_ok_transferencia lcall escriu_dada_flash
Placa 8031 21

lcall incrementa_adreca_flash
; Final Escritura flash
TELECARGA_FICHEROS:
mov a,numero_bytes mov a,#numero_de_ficheros
dec a mov fichero_actual, a
mov numero_bytes,a ;lcall esborra_tots_sectors
cjne a,#0h, recibe_valores_de_datos
bucle_telecarga_audio:
recibe_checksum: lcall resetea_lcd
lcall gethex ; cogemos el valor del checksum lcall MUESTRA_MENU_TELECARGA_AUDIO
mov a, suma_checksum mov a, #valor_ok_transferencia
jz continua ; si la suma no es zero (parte baja) el mov dada_a_tx_serie, a
checksum está mal
ljmp error coge_pagina_fichero:
lcall inchar
continua: lcall outchar
lcall outchar ; paso de línea lcall atoh
ljmp inicio_lee_linea anl a, #0fh
mov pagina_fichero, a
final_de_transferencia: mov p1, a
lcall gethex ; De la ultima linia falta el checksum
lcall outchar coge_direccion_fichero:
ljmp SALTA_FLASH ; Parte alta
lcall gethex
error: mov adreca_escriure_alt, a
mov a, #valor_no_ok_transferencia
mov dada_a_tx_serie, a ; Parte baja
lcall outchar lcall gethex
ljmp MAIN mov adreca_escriure_baix, a

coge_longitud_fichero:
; Parte alta
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lcall gethex
; TELECARGA FICHEROS mov r1, a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Parte baja
;* Post: Realiza toda la telecarga de los ficheros de audio lcall gethex
;* Modifica: a,b,dptr,r0 clr c
; addc a, adreca_escriure_baix
; Formato TEXTO & WAV mov final_fichero_baja, a
;1(0) 8(0) 0(0) 0(0) 0(0)
; 49(0) 56(0) 48(0) 48(0) 48(0) ; Parte alta con el carry de la baja si tiene
;0(0) 0(0) 0(0) A(0) mov a, r1
; 48(0) 48(0) 48(0) 65(0) addc a, adreca_escriure_alt
;55(0) 70(0) mov final_fichero_alta, a
;56(0) 48(0)
Placa 8031 22

mov a, #ESPACIO
coge_bytes: lcall pon_letra
lcall gethex mov a, #ESPACIO
mov dada_a_escriure, a lcall pon_letra
mov a, #LETRA_TCAPS
; Escribimos en la flash lcall pon_letra
lcall escriu_dada_flash mov a, #LETRA_e
lcall incrementa_adreca_flash lcall pon_letra
; Final Escritura flash mov a, #LETRA_l
lcall pon_letra
; Miramos si hemos enviado todos los bytes mov a, #LETRA_e
mov a, adreca_escriure_alt lcall pon_letra
cjne a, final_fichero_alta, coge_bytes mov a, #LETRA_c
mov a, adreca_escriure_baix lcall pon_letra
cjne a, final_fichero_baja, coge_bytes mov a, #LETRA_a
lcall pon_letra
mov dada_a_escriure, #13h mov a, #LETRA_r
lcall escriu_dada_flash lcall pon_letra
lcall incrementa_adreca_flash mov a, #LETRA_g
mov dada_a_escriure, #69h lcall pon_letra
lcall escriu_dada_flash mov a, #LETRA_a
lcall incrementa_adreca_flash lcall pon_letra
mov dada_a_escriure, #ffh mov a, #LETRA_n
lcall escriu_dada_flash lcall pon_letra
lcall incrementa_adreca_flash mov a, #LETRA_d
mov dada_a_escriure, #aah lcall pon_letra
lcall escriu_dada_flash mov a, #LETRA_o
lcall incrementa_adreca_flash lcall pon_letra

lcall pasa_linia
siguiente_archivo:
mov a, fichero_actual mov a, #ESPACIO
dec a lcall pon_letra
mov fichero_actual, a mov a, #ESPACIO
cjne a,#0h, bucle_telecarga_audio lcall pon_letra
ljmp SALTA_FLASH mov a, #ESPACIO
lcall pon_letra
mov a, #LETRA_CCAPS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lcall pon_letra
; RUTINAS LCD mov a, #LETRA_o
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lcall pon_letra
mov a, #LETRA_d
;* Post: Muestra por display que estamos telecargando código lcall pon_letra
;* Pre: Haber reseteado el LCD mov a, #LETRA_i
;* Modifica: a, dptr lcall pon_letra
MUESTRA_MENU_TELECARGA_CODIGO: mov a, #LETRA_g
Placa 8031 23

lcall pon_letra
mov a, #LETRA_o lcall pasa_linia
lcall pon_letra
mov a, #ESPACIO mov a, #ESPACIO
lcall pon_letra lcall pon_letra
mov a, #PUNTO mov a, #ESPACIO
lcall pon_letra lcall pon_letra
mov a, #PUNTO mov a, #LETRA_ACAPS
lcall pon_letra lcall pon_letra
mov a, #PUNTO mov a, #LETRA_u
lcall pon_letra lcall pon_letra
ret mov a, #LETRA_d
lcall pon_letra
;* Post: Muestra por display que estamos telecargando audio mov a, #LETRA_i
;* Pre: Haber reseteado el LCD lcall pon_letra
;* Necesita: en B el valor actual del fichero telecargado mov a, #LETRA_o
;* Modifica: a, dptr lcall pon_letra
MUESTRA_MENU_TELECARGA_AUDIO: mov a, #ESPACIO
mov a, #ESPACIO lcall pon_letra
lcall pon_letra mov a, #LETRA_PAR_A
mov a, #ESPACIO lcall pon_letra
lcall pon_letra mov a, #numero_de_ficheros
mov a, #LETRA_TCAPS mov b, fichero_actual
lcall pon_letra subb a, b
mov a, #LETRA_e inc a
lcall pon_letra mov r0,a
mov a, #LETRA_l anl a,#11110000b
lcall pon_letra swap a
mov a, #LETRA_e orl a, #30h
lcall pon_letra lcall pon_letra
mov a, #LETRA_c
lcall pon_letra mov a, r0
mov a, #LETRA_a anl a,#00001111b
lcall pon_letra orl a, #30h
mov a, #LETRA_r lcall pon_letra
lcall pon_letra
mov a, #LETRA_g mov a, #BARRITA
lcall pon_letra lcall pon_letra
mov a, #LETRA_a mov a, #NUMERO_FICHEROS_ALTO
lcall pon_letra lcall pon_letra
mov a, #LETRA_n mov a, #NUMERO_FICHEROS_BAJO
lcall pon_letra lcall pon_letra
mov a, #LETRA_d
lcall pon_letra mov a, #LETRA_PAR_C
mov a, #LETRA_o lcall pon_letra
lcall pon_letra ret
Placa 8031 24

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov dph, adreca_escriure_alt


; RUTINAS BIOS by mov dpl, adreca_escriure_baix
; Lagartos: Dani & Xavi mov a, dada_a_escriure
; Barcelona a 7 marzo de 2002 movx @dptr, a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Guía para no iniciados... lcall espera_final_escriptura_flash
; - Hay que incluir las variables en la misma direccion que
; este fichero pop a
; - Hay que incluir un equ al valor del .org en cuestión pop dptr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;* Post: Prepara la flash para ser borrada


; FLASH ;* Modifica; dptr,a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; prepara_escriptura_flash:
MOV DPTR,#8555H
; Incrementa: MOV A,#0aaH
; adreca_escriure_alt MOVX @DPTR,A
; adreca_escriure_baix
.org 5500h MOV DPTR,#82aaH
incrementa_adreca_flash: MOV A,#55H
push a MOVX @DPTR,A

mov a, adreca_escriure_baix MOV DPTR,#8555H


cjne a, #FFh, incrementa_flash_nada MOV A,#0a0H
mov adreca_escriure_baix, #00h MOVX @DPTR,A
inc adreca_escriure_alt ret
sjmp incrementa_flash_fin
incrementa_flash_nada:
inc adreca_escriure_baix ;* Post: Bucle de espera hasta el final de la escritura
;* Modifica: dptr,a,r0
incrementa_flash_fin: espera_final_escriptura_flash
pop a mov dph, adreca_escriure_alt
ret mov dpl, adreca_escriure_baix

MOVX A,@DPTR
.org 6000h
;* Post: ESCRIPTURA BYTE A LA FLASH bucle_espera_escriptura:
;* Necesita: dada_a_escriure, adreca_escriure_alt, adreca_escriure_baix MOV R0,A
;* Modifica: a,dptr, r0 MOVX A, @DPTR
escriu_dada_flash: ANL A, #44h
push dptr CJNE A, 0,bucle_espera_escriptura
push a
ret
lcall prepara_escriptura_flash
.org 6200h
Placa 8031 25

;* Post: ESBORRA SECTOR FLASH movx a, @dptr


;* Necesita: sector_a_esborrar anl a,#44h
;* Modifica: dptr,a,r0 bucle_espera_esborra_sector_flash:
esborra_sector_flash: mov r0,a
mov P1, sector_a_esborrar MOVX A, @DPTR
anl a,#44h
lcall prepara_esborra_sector_flash CJNE A, 0, bucle_espera_esborra_sector_flash
lcall espera_esborra_sector_flash
ret
ret
.org 6300h
;* Post: Esborra el sector seleccionat de la flash esborra_tots_sectors:
;* Pre: Haver carregar el sector a esborrar al P1 mov a,#sector_flash_1
;* Modifica; a,dptr mov sector_a_esborrar, a
prepara_esborra_sector_flash: lcall esborra_sector_flash
MOV DPTR,#8555H mov a,#sector_flash_2
MOV A,#0aaH mov sector_a_esborrar, a
MOVX @DPTR,A lcall esborra_sector_flash
mov a,#sector_flash_3
MOV DPTR,#82AAH mov sector_a_esborrar, a
MOV A,#55H lcall esborra_sector_flash
MOVX @DPTR,A mov a,#sector_flash_4
mov sector_a_esborrar, a
MOV DPTR,#8555H lcall esborra_sector_flash
MOV A,#80H mov a,#sector_flash_5
MOVX @DPTR,A mov sector_a_esborrar, a
lcall esborra_sector_flash
MOV DPTR,#8555H mov a,#sector_flash_6
MOV A,#0aaH mov sector_a_esborrar, a
MOVX @DPTR,A lcall esborra_sector_flash
mov a,#sector_flash_7
MOV DPTR,#82AAH mov sector_a_esborrar, a
MOV A,#55H lcall esborra_sector_flash
MOVX @DPTR,A ret

MOV DPTR,#8000H ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


MOV A,#30H ; PORT SERIE
MOVX @DPTR,A ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ret .org 6400h


;* Post: Inicializa puerto serie a 9600 bps
init_serie:
;* Post: Bucle d'espera fins esborrar un sector de la flash. mov scon, #50h
;* Modifica: a,dptr,r0 mov tmod, #20h
espera_esborra_sector_flash: mov th1, #fdh
MOV DPTR,#8000H setb tr1
Placa 8031 26

setb ti clr c
ret mov suma_checksum, a
pop a
.org 6500h ret
;* Post: Espera hasta que recibe un byte por el puerto serie.
;* Devuelve el valor en A. ;* Post: Convierte ASCII to HEX
inchar: ;* Necesita: A
jnb ri, inchar atoh:
clr ri clr acc.7
mov a, sbuf cjne a, #3ah, next
ret next:
jc atoh2
.org 6600h add a, #9
;* Post: Tx por el bit serie un byte en ascii atoh2:
;* Necesita: dada_a_tx_serie anl a, #0fh
outchar: ret
jnb ti, outchar
clr ti ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov sbuf, dada_a_tx_serie ; LCD
ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.org 6700h .org 6A00h


;* Post:Coge dos caracteres del puerto serie y forma un byte hexa ;* Post: Inicialitza LCD
;* Retorna en A ;* Modifica: a, dptr
;* Modifica: a,r0 init_lcd:
gethex: mov a, #00111000b ;Function set amb 5x7
push dptr mov dptr, #port_lcd_wc
lcall inchar movx @dptr, a
lcall outchar lcall espera_respuesta_display
lcall atoh
swap a mov a, #00001110b ;Display on/off control
mov r0, a mov dptr, #port_lcd_wc
lcall inchar movx @dptr, a
lcall outchar aCALL espera_respuesta_display
lcall atoh
orl a, r0 mov a, #01h ;Clear Display
lcall calcula_checksum mov dptr, #port_lcd_wc
pop dptr movx @dptr, a
ret aCALL espera_respuesta_display

;* Post: Calculamos la suma total del checksum lcall resetea_lcd


; suma_checksum ret
calcula_checksum:
push a .org 6B00h
clr c ;* Post: Borra el LCD
add a, suma_checksum ;* Modifica: a, dptr
Placa 8031 27

resetea_lcd:
mov a, #01h ; Carguem dades "RESET DISPLAY"
mov dptr, #port_lcd_wc
movx @dptr, a
lcall espera_respuesta_display
ret

.org 6C00h
;* Post Pone una letra en el LCD
;* Necesita: letra en registro A
;* Modifica: a,dptr
pon_letra:
mov dptr, #port_lcd_wd
movx @dptr, a
lcall espera_respuesta_display
ret

.org 6D00h
;* Post:Salta linia en el display
;* Modifica: a, dptr
pasa_linia:
mov a, #11000000b ; Cambia de línea
mov dptr, #port_lcd_wc
movx @dptr, a
lcall espera_respuesta_display
ret

.org 6E00h
;* Post: Espera a que LCD acabi d'escriure les dades
;* Modifica: a,dptr
espera_respuesta_display:
mov dptr, #port_lcd_rc
movx a, @dptr
jb acc.7, espera_respuesta_display
ret

.END
Placa 8031 28

cantidad_paquete_8 equ 52h


numero_productos equ 53h
5. Codi Assembler del programa principal espera_timer_0_h equ 54h
espera_timer_0_l equ 55h
dada_a_reproduir equ 58h
; Puertos direccion_a_reproducir_alta equ 59h
port_lcd_wc equ 0000h direccion_a_reproducir_baja equ 60h
port_lcd_rc equ 0001h pagina_a_reproducir equ 61h
port_lcd_wd equ 0002h producto1 equ 62h
port_dac equ 20h cantidad_paquete_1 equ 63h
port_boton equ 40h numero_a_reproducir equ 64h
modo_timer equ 65h
;Especiales rutinas BIOS persona_alta_reproducir equ 66h
inchar equ 6500h persona_baja_reproducir equ 67h
outchar equ 6600h cantidad_reproducir equ 68h
gethex equ 6700h
init_lcd equ 6A00h
resetea_lcd equ 6B00h
pon_letra equ 6C00h ; Valores flash
pasa_linia equ 6D00h sector_flash_0 equ 00h
espera_respuesta_display equ 6E00h sector_flash_1 equ 02h
incrementa_adreca_flash equ 5500h sector_flash_2 equ 04h
sector_flash_3 equ 06h
; Variables sector_flash_4 equ 08h
adreca_a_escriure_alt equ 30h sector_flash_5 equ 0Ah
adreca_a_escriure_baix equ 31h sector_flash_6 equ 0Ch
dada_a_escriure equ 32h sector_flash_7 equ 0Eh
sector_a_esborrar equ 33h
dada_a_tx_serie equ 34h ;Constantes
columna_actual equ 35h valor_transferencia_ok equ 01h
fila_actual equ 36h valor_transferencia_error equ 02h
tecla_actual equ 37h columna_1 equ 01h
flag_boton equ 38h columna_2 equ 02h
persona_alta equ 39h columna_3 equ 04h
persona_baja equ 3Ah fila_1 equ 01h
contador_codigo_persona equ 3Bh fila_2 equ 02h
contador_inchar equ 3Ch fila_3 equ 04h
fila_4 equ 08h
producto equ 3Dh constante_espera_timer_0_h equ ffh
cantidad_producto equ 45h constante_espera_timer_0_l equ ffh
cantidad_paquete_2 equ 46h retries_inchar equ 03h
cantidad_paquete_3 equ 47h final_transferencia_paquetes equ 09h
cantidad_paquete_4 equ 48h freq_audio equ dfh
cantidad_paquete_5 equ 49h direccion_sonido_0 equ 80h
cantidad_paquete_6 equ 50h direccion_sonido_1 equ A0h
cantidad_paquete_7 equ 51h direccion_sonido_2 equ 80h
Placa 8031 29

direccion_sonido_3 equ A0h POR equ 00101010b


direccion_sonido_4 equ 80h ESPACIO equ 00100000b
direccion_sonido_5 equ A0h BARRITA equ 00101111b
direccion_sonido_6 equ 80h DOS_PUNTOS equ 00111010b
direccion_sonido_7 equ A0h LETRA_PAR_A equ 00101000b
direccion_sonido_8 equ 80h LETRA_PAR_C equ 00101001b
direccion_sonido_9 equ A0h LETRA_MICRO equ 11100100b
direccion_sonido_lubina equ 80h LETRA_0 equ 00110000b
direccion_sonido_caviar equ C0h LETRA_1 equ 00110001b
direccion_sonido_gambas equ 80h LETRA_2 equ 00110010b
direccion_sonido_rape equ C0h LETRA_3 equ 00110011b
direccion_sonido_sardinas equ 80h LETRA_4 equ 00110100b
direccion_sonido_almejas equ C0h LETRA_5 equ 00110101b
direccion_sonido_bacalao equ 80h LETRA_6 equ 00110110b
direccion_sonido_pulpo equ C0h LETRA_7 equ 00110111b
direccion_sonido_persona equ 80h LETRA_8 equ 00111000b
direccion_sonido_unidad equ 80h LETRA_9 equ 00111001b
direccion_sonido_unidades equ A0h LETRA_a equ 01100001b
pagina_sonido_0 equ 02h LETRA_ACAPS equ 01000001b
pagina_sonido_1 equ 02h LETRA_BCAPS equ 01000010b
pagina_sonido_2 equ 03h LETRA_c equ 01100011b
pagina_sonido_3 equ 03h LETRA_CCAPS equ 01000011b
pagina_sonido_4 equ 04h LETRA_d equ 01100100b
pagina_sonido_5 equ 04h LETRA_DCAPS equ 01000100b
pagina_sonido_6 equ 05h LETRA_e equ 01100101b
pagina_sonido_7 equ 05h LETRA_FCAPS equ 01000110b
pagina_sonido_8 equ 06h LETRA_g equ 01100111b
pagina_sonido_9 equ 06h LETRA_HCAPS equ 01001000b
pagina_sonido_lubina equ 07h LETRA_i equ 01101001b
pagina_sonido_caviar equ 07h LETRA_ICAPS equ 01001001b
pagina_sonido_gambas equ 08h LETRA_k equ 01101011b
pagina_sonido_rape equ 08h LETRA_l equ 01101100b
pagina_sonido_sardinas equ 09h LETRA_LCAPS equ 01001100b
pagina_sonido_almejas equ 09h LETRA_m equ 01101101b
pagina_sonido_bacalao equ 0Ah LETRA_n equ 01101110b
pagina_sonido_pulpo equ 0Ah LETRA_NCAPS equ 01001110b
pagina_sonido_persona equ 0Bh LETRA_ny equ 11101110b
pagina_sonido_unidad equ 0Ch LETRA_o equ 01101111b
pagina_sonido_unidades equ 0Ch LETRA_OCAPS equ 4fh
modo_timer_boton equ 21h LETRA_p equ 01110000b
modo_timer_audio equ 22h LETRA_PCAPS equ 01010000b
LETRA_r equ 01110010b
; Valores LCD LETRA_RCAPS equ 01010010b
PUNTO equ 00101110b LETRA_s equ 01110011b
MENOS equ 10110000b LETRA_SCAPS equ 01010011b
MAS equ 00101011b LETRA_t equ 01110100b
Placa 8031 30

LETRA_u equ 01110101b mov contador_codigo_persona, #00h


LETRA_v equ 01110110b lcall resetea_lcd
LETRA_VCAPS equ 01010110b lcall muestra_menu_persona
LETRA_x equ 01111000b sjmp principio
LETRA_y equ 01111001b
LETRA_z equ 01111010b main_continua:
lcall escribe_tecla_lcd
mov tecla_actual, #00h
.symbols mov flag_boton, #00h
sjmp main
.org 8000h

principio: ; Inicializamos variables


lcall init_variables init_variables:
lcall init_lcd mov a, #01h
lcall init_rs232 mov columna_actual, a
lcall muestra_menu_persona mov a, #00h
sjmp main mov p1, a
mov contador_codigo_persona, a
.org 8035h mov contador_inchar, a
ret
main:
lcall botonera
lcall compon_codigo_persona
mov a, contador_codigo_persona ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cjne a, #02h, main_continua ; SACA MUESTRAS DAC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
main_codigo_persona_correcto:
lcall escribe_tecla_lcd
; Reproduce sonidos de personas con su lista de compra
; Inicio transferencia con el PC reproduce_sonidos_personas:
lcall envia_codigo_persona lcall reproduce_numero_persona
cjne a, #valor_transferencia_ok, main_codigo_persona_no_existe lcall reproduce_paquetes
lcall recibe_paquetes ret
lcall reproduce_sonidos_personas
sjmp main_codigo_persona_correcto_sigue ; Reproduce código persona
; Fin transferencia Pc ; persona_alta
; persona_baja
main_codigo_persona_no_existe: reproduce_numero_persona:
lcall resetea_lcd mov direccion_a_reproducir_baja, #00h
lcall pinta_menu_no_hay_persona
lcall presiona_para_continuar ; Reproduce palabra PERSONA
mov direccion_a_reproducir_alta, #direccion_sonido_persona
main_codigo_persona_correcto_sigue: mov pagina_a_reproducir, #pagina_sonido_persona
mov tecla_actual, #00h lcall reproduce_sonido
mov flag_boton, #00h
Placa 8031 31

; Reproduce numero alto sjmp direccion_from_numero_fin


mov numero_a_reproducir, persona_alta direccion_from_numero_5:
lcall direccion_from_numero cjne a, #05h, direccion_from_numero_6
lcall reproduce_sonido mov direccion_a_reproducir_alta, #direccion_sonido_5
mov pagina_a_reproducir, #pagina_sonido_5
; Reproduce numero bajo sjmp direccion_from_numero_fin
mov numero_a_reproducir, persona_baja direccion_from_numero_6:
lcall direccion_from_numero cjne a, #06h, direccion_from_numero_7
lcall reproduce_sonido mov direccion_a_reproducir_alta, #direccion_sonido_6
ret mov pagina_a_reproducir, #pagina_sonido_6
sjmp direccion_from_numero_fin
direccion_from_numero_7:
; Pone direcciones segun numero a reproducir cjne a, #07h, direccion_from_numero_8
; numero_a_reproducir mov direccion_a_reproducir_alta, #direccion_sonido_7
; mov pagina_a_reproducir, #pagina_sonido_7
; direccion_a_reproduir_baja sjmp direccion_from_numero_fin
; direccion_a_reproduir_alta direccion_from_numero_8:
; pagina_a_reproducir cjne a, #08h, direccion_from_numero_9
direccion_from_numero: mov direccion_a_reproducir_alta, #direccion_sonido_8
mov direccion_a_reproducir_baja, #00h mov pagina_a_reproducir, #pagina_sonido_8
sjmp direccion_from_numero_fin
mov a, numero_a_reproducir direccion_from_numero_9:
cjne a, #09h, direccion_from_numero_fin
cjne a, #00h, direccion_from_numero_1 mov direccion_a_reproducir_alta, #direccion_sonido_9
mov direccion_a_reproducir_alta, #direccion_sonido_0 mov pagina_a_reproducir, #pagina_sonido_9
mov pagina_a_reproducir, #pagina_sonido_0
sjmp direccion_from_numero_fin direccion_from_numero_fin:
direccion_from_numero_1: ret
cjne a, #01h, direccion_from_numero_2
mov direccion_a_reproducir_alta, #direccion_sonido_1
mov pagina_a_reproducir, #pagina_sonido_1 ; Configura variables para unidad/es segun la cantidad sea singular o plural
sjmp direccion_from_numero_fin ; cantidad_reproducir
direccion_from_numero_2: ;
cjne a, #02h, direccion_from_numero_3 ; direccion_a_reproducir_alta
mov direccion_a_reproducir_alta, #direccion_sonido_2 ; direccion_a_reproducir_baja
mov pagina_a_reproducir, #pagina_sonido_2 ; pagina_a_reproducir
sjmp direccion_from_numero_fin reproduce_unidad:
direccion_from_numero_3: mov a, cantidad_reproducir
cjne a, #03h, direccion_from_numero_4
mov direccion_a_reproducir_alta, #direccion_sonido_3 cjne a, #01h, reproduce_unidad_plural
mov pagina_a_reproducir, #pagina_sonido_3 mov direccion_a_reproducir_alta, #direccion_sonido_unidad
sjmp direccion_from_numero_fin mov pagina_a_reproducir, #pagina_sonido_unidad
direccion_from_numero_4: sjmp reproduce_unidad_fin
cjne a, #04h, direccion_from_numero_5 reproduce_unidad_plural:
mov direccion_a_reproducir_alta, #direccion_sonido_4 mov direccion_a_reproducir_alta, #direccion_sonido_unidades
mov pagina_a_reproducir, #pagina_sonido_4 mov pagina_a_reproducir, #pagina_sonido_unidades
Placa 8031 32

reproduce_unidad_fin: ; Reproduce nombre producto


mov direccion_a_reproducir_baja, #00h mov direccion_a_reproducir_alta, #direccion_sonido_gambas
ret mov pagina_a_reproducir, #pagina_sonido_gambas
lcall reproduce_sonido
; Reproduce cantidad
mov numero_a_reproducir, cantidad_paquete_3
; Reproduce el tipo de paquete y la cantidad lcall direccion_from_numero
reproduce_paquetes: lcall reproduce_sonido
mov a, cantidad_paquete_1 ; Reproduce UNIDAD/ES
cjne a, #00h, reproduce_paquetes_1_sigue mov cantidad_reproducir, cantidad_paquete_3
sjmp reproduce_paquetes_2 lcall reproduce_unidad
reproduce_paquetes_1_sigue: lcall reproduce_sonido
; Reproduce nombre producto reproduce_paquetes_4:
mov direccion_a_reproducir_alta, #direccion_sonido_lubina mov a, cantidad_paquete_4
mov pagina_a_reproducir, #pagina_sonido_lubina cjne a, #00h, reproduce_paquetes_4_sigue
lcall reproduce_sonido sjmp reproduce_paquetes_5
; Reproduce cantidad reproduce_paquetes_4_sigue:
mov numero_a_reproducir, cantidad_paquete_1 ; Reproduce nombre producto
lcall direccion_from_numero mov direccion_a_reproducir_alta, #direccion_sonido_rape
lcall reproduce_sonido mov pagina_a_reproducir, #pagina_sonido_rape
; Reproduce UNIDAD/ES lcall reproduce_sonido
mov cantidad_reproducir, cantidad_paquete_1 ; Reproduce cantidad
lcall reproduce_unidad mov numero_a_reproducir, cantidad_paquete_4
lcall reproduce_sonido lcall direccion_from_numero
reproduce_paquetes_2: lcall reproduce_sonido
mov a, cantidad_paquete_2 ; Reproduce UNIDAD/ES
cjne a, #00h, reproduce_paquetes_2_sigue mov cantidad_reproducir, cantidad_paquete_4
sjmp reproduce_paquetes_3 lcall reproduce_unidad
reproduce_paquetes_2_sigue: lcall reproduce_sonido
; Reproduce nombre producto reproduce_paquetes_5:
mov direccion_a_reproducir_alta, #direccion_sonido_caviar mov a, cantidad_paquete_5
mov pagina_a_reproducir, #pagina_sonido_caviar cjne a, #00h, reproduce_paquetes_5_sigue
lcall reproduce_sonido sjmp reproduce_paquetes_6
; Reproduce cantidad reproduce_paquetes_5_sigue:
mov numero_a_reproducir, cantidad_paquete_2 ; Reproduce nombre producto
lcall direccion_from_numero mov direccion_a_reproducir_alta, #direccion_sonido_sardinas
lcall reproduce_sonido mov pagina_a_reproducir, #pagina_sonido_sardinas
; Reproduce UNIDAD/ES lcall reproduce_sonido
mov cantidad_reproducir, cantidad_paquete_2 ; Reproduce cantidad
lcall reproduce_unidad mov numero_a_reproducir, cantidad_paquete_5
lcall reproduce_sonido lcall direccion_from_numero
reproduce_paquetes_3: lcall reproduce_sonido
mov a, cantidad_paquete_3 ; Reproduce UNIDAD/ES
cjne a, #00h, reproduce_paquetes_3_sigue mov cantidad_reproducir, cantidad_paquete_5
sjmp reproduce_paquetes_4 lcall reproduce_unidad
reproduce_paquetes_3_sigue: lcall reproduce_sonido
Placa 8031 33

reproduce_paquetes_6: lcall reproduce_sonido


mov a, cantidad_paquete_6 ; Reproduce UNIDAD/ES
cjne a, #00h, reproduce_paquetes_6_sigue mov cantidad_reproducir, cantidad_paquete_8
sjmp reproduce_paquetes_7 lcall reproduce_unidad
reproduce_paquetes_6_sigue: lcall reproduce_sonido
; Reproduce nombre producto
mov direccion_a_reproducir_alta, #direccion_sonido_almejas reproduce_paquetes_fin:
mov pagina_a_reproducir, #pagina_sonido_almejas ret
lcall reproduce_sonido
; Reproduce cantidad
mov numero_a_reproducir, cantidad_paquete_6
lcall direccion_from_numero ; Reproduce un sonido de la flash
lcall reproduce_sonido ; direccion_a_reproducir_alta
; Reproduce UNIDAD/ES ; direccion_a_reproducir_baja
mov cantidad_reproducir, cantidad_paquete_6 ; pagina_a_reproducir
lcall reproduce_unidad reproduce_sonido:
lcall reproduce_sonido lcall programa_timer_0_audio
reproduce_paquetes_7: mov p1, pagina_a_reproducir
mov a, cantidad_paquete_7 mov adreca_a_escriure_alt, direccion_a_reproducir_alta
cjne a, #00h, reproduce_paquetes_7_sigue mov adreca_a_escriure_baix, direccion_a_reproducir_baja
sjmp reproduce_paquetes_8 bucle_reproduce_sonido:
reproduce_paquetes_7_sigue: lcall coge_muestra
; Reproduce nombre producto lcall saca_muestra_DAC
mov direccion_a_reproducir_alta, #direccion_sonido_bacalao cjne a,#13h,bucle_reproduce_sonido
mov pagina_a_reproducir, #pagina_sonido_bacalao lcall coge_muestra
lcall reproduce_sonido lcall saca_muestra_DAC
; Reproduce cantidad cjne a,#69h,bucle_reproduce_sonido
mov numero_a_reproducir, cantidad_paquete_7 lcall coge_muestra
lcall direccion_from_numero lcall saca_muestra_DAC
lcall reproduce_sonido cjne a,#FFh,bucle_reproduce_sonido
; Reproduce UNIDAD/ES lcall coge_muestra
mov cantidad_reproducir, cantidad_paquete_7 lcall saca_muestra_DAC
lcall reproduce_unidad cjne a,#AAh,bucle_reproduce_sonido
lcall reproduce_sonido ret
reproduce_paquetes_8:
mov a, cantidad_paquete_8 ; Programacion timer 0 para freq
cjne a, #00h, reproduce_paquetes_8_sigue programa_timer_0_audio:
sjmp reproduce_paquetes_fin mov modo_timer, #modo_timer_audio
reproduce_paquetes_8_sigue: mov espera_timer_0_h, #freq_audio
; Reproduce nombre producto mov espera_timer_0_l, #00h
mov direccion_a_reproducir_alta, #direccion_sonido_pulpo lcall init_timer_0
mov pagina_a_reproducir, #pagina_sonido_pulpo ret
lcall reproduce_sonido
; Reproduce cantidad ; Coge la muestra de la flash
mov numero_a_reproducir, cantidad_paquete_8 ; dada_a_reproduir
lcall direccion_from_numero ; adreca_a_escriure_alt
Placa 8031 34

; adreca_a_escriure_baix mov a, numero_productos


coge_muestra: inc a
mov dph, adreca_a_escriure_alt mov numero_productos, a
mov dpl, adreca_a_escriure_baix
movx a, @dptr ; Pintamos los productos en el lcd
mov dada_a_reproduir,a lcall pinta_productos_lcd
lcall incrementa_adreca_flash
ret ; componemos la lista de la compra
lcall asigna_producto_lista
; Saca la muestra por el DAC sjmp recibe_paquetes_bucle
; dada_a_reproduir
saca_muestra_DAC: recibe_paquetes_fin:
lcall freq_t0 mov a, numero_productos
mov dph, #port_dac cjne a, #00h, recibe_paquetes_parate
mov dpl, #00h ret
mov a, dada_a_reproduir recibe_paquetes_parate:
movx @dptr, a lcall presiona_para_continuar
lcall freq_t0 ret
ret

; Inicializa lista de la compra para cantidades=0


inicializa_lista_compra:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov cantidad_paquete_1, #00h
; SERIE + CODIGO PERSONA mov cantidad_paquete_2, #00h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov cantidad_paquete_3, #00h
mov cantidad_paquete_4, #00h
; Recibe el producto y la cantidad del programa C mov cantidad_paquete_5, #00h
recibe_paquetes: mov cantidad_paquete_6, #00h
lcall resetea_lcd mov cantidad_paquete_7, #00h
mov a, #valor_transferencia_ok mov cantidad_paquete_8, #00h
mov dada_a_tx_serie, a ret
lcall inicializa_lista_compra
mov a, #00h ; Compone la lista de compra de la persona X
mov numero_productos, a ; producto
; cantidad_producto
recibe_paquetes_bucle: ; cantidad_paquete(i)
lcall inchar asigna_producto_lista:
lcall outchar mov a, producto
cjne a, #final_transferencia_paquetes, recibe_paquetes_inicio
sjmp recibe_paquetes_fin cjne a, #01h, asigna_producto_lista_2
mov cantidad_paquete_1, cantidad_producto
recibe_paquetes_inicio: sjmp asigna_producto_lista_fin
mov producto, a asigna_producto_lista_2:
lcall inchar cjne a, #02h, asigna_producto_lista_3
lcall outchar mov cantidad_paquete_2, cantidad_producto
mov cantidad_producto, a sjmp asigna_producto_lista_fin
Placa 8031 35

asigna_producto_lista_3: mov a, cantidad_producto


cjne a, #03h, asigna_producto_lista_4 orl a, #30h
mov cantidad_paquete_3, cantidad_producto lcall pon_letra
sjmp asigna_producto_lista_fin
asigna_producto_lista_4: mov a, #ESPACIO
cjne a, #04h, asigna_producto_lista_5 lcall pon_letra
mov cantidad_paquete_4, cantidad_producto ret
sjmp asigna_producto_lista_fin
asigna_producto_lista_5:
cjne a, #05h, asigna_producto_lista_6 ; Envia el código de persona
mov cantidad_paquete_5, cantidad_producto ; persona_baja
sjmp asigna_producto_lista_fin ; persona_alta
asigna_producto_lista_6: envia_codigo_persona:
cjne a, #06h, asigna_producto_lista_7 mov dada_a_tx_serie, #07h
mov cantidad_paquete_6, cantidad_producto lcall outchar
sjmp asigna_producto_lista_fin lcall inchar
asigna_producto_lista_7:
cjne a, #07h, asigna_producto_lista_8 ; Parte alta
mov cantidad_paquete_7, cantidad_producto mov a, persona_alta
sjmp asigna_producto_lista_fin mov persona_alta_reproducir, a
asigna_producto_lista_8: mov dada_a_tx_serie, a
cjne a, #08h, asigna_producto_lista_fin lcall outchar
mov cantidad_paquete_8, cantidad_producto lcall inchar

asigna_producto_lista_fin: ; Parte baja


ret mov a, persona_baja
mov persona_baja_reproducir, a
mov dada_a_tx_serie, a
; Pinta los productos y la cantidad en el lcd lcall outchar
; producto lcall inchar
; cantidad_producto ret
pinta_productos_lcd:
mov a, numero_productos
cjne a, #05h, pinta_productos_lcd_sin_salto
lcall pasa_linia ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; BOTONERA + PERSONA
pinta_productos_lcd_sin_salto: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Numero Producto
mov a, producto ; Compone el código de la persona en
orl a, #30h ; persona_baja
lcall pon_letra ; persona_alta
;
mov a, #MENOS ; contador_codigo_persona = 0 (parte alta)
lcall pon_letra ; = 1 (parte baja)
; = 2 ok para transferir
; Cantidad del producto compon_codigo_persona:
Placa 8031 36

mov a, flag_boton ; Devuelve: tecla_actual


cjne a,#01h,compon_codigo_persona_final
botonera:
compon_codigo_persona_inicio: lcall programa_timer_0_botonera
mov a, contador_codigo_persona mov dph, #port_boton
jz compon_codigo_persona_alta mov dpl, columna_actual
movx a, @dptr
compon_codigo_persona_baja: anl a, #0Fh
mov a, tecla_actual cjne a, #00h, hay_boton
anl a, #0fh mov flag_boton, #00h
mov persona_baja, a sjmp botonera_fin
mov contador_codigo_persona, #2h
sjmp compon_codigo_persona_final hay_boton:
lcall espera_timer_0
compon_codigo_persona_alta: lcall espera_timer_0
mov a, tecla_actual lcall espera_timer_0
anl a, #0fh mov fila_actual, a
mov persona_alta, a lcall decodifica_tecla
mov contador_codigo_persona, #1h mov flag_boton, #01h
botonera_fin:
compon_codigo_persona_final: lcall incrementa_columna
ret ret

; Programa timer0 para botonera


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; programa_timer_0_botonera:
; BOTONERA + LCD mov modo_timer, #modo_timer_boton
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov espera_timer_0_h, #constante_espera_timer_0_h
mov espera_timer_0_l, #constante_espera_timer_0_l
; Escribe "tecla_actual" como siguiente caracter en lcd lcall init_timer_0
; tecla_actual ret
escribe_tecla_lcd:
mov a, flag_boton ; Nos da el codigo de la tecla con
cjne a,#01h,escribe_final_tecla_lcd ; columna_actual
; fila_actual
escribe_pon_letra:
mov a,tecla_actual decodifica_tecla:
lcall pon_letra mov a, columna_actual
escribe_final_tecla_lcd:
ret jb acc.0, decodifica_boton_columna_1
jb acc.1, decodifica_boton_columna_2
jb acc.2, decodifica_boton_columna_3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sjmp decodifica_tecla_fin
; BOTONERA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; decodifica_boton_columna_1:
mov a, fila_actual
; Nos da el boton presionado probando una columna cada vez jb acc.0, decodifica_boton_1
Placa 8031 37

jb acc.1, decodifica_boton_4 decodifica_tecla_fin:


jb acc.2, decodifica_boton_7 ret

decodifica_boton_columna_2: ; Rotamos la columna


mov a, fila_actual ; Devuelve: columna_actual
jb acc.0, decodifica_boton_2 incrementa_columna:
jb acc.1, decodifica_boton_5 mov a, columna_actual
jb acc.2, decodifica_boton_8 cjne a, #columna_3, botonera_rotes
jb acc.3, decodifica_boton_0 mov a, #columna_1
sjmp botonera_fin_incrementa_columna
decodifica_boton_columna_3: botonera_rotes:
mov a, fila_actual rl a
jb acc.0, decodifica_boton_3 botonera_fin_incrementa_columna:
jb acc.1, decodifica_boton_6 mov columna_actual, a
jb acc.2, decodifica_boton_9 ret

decodifica_boton_0:
mov tecla_actual, #LETRA_0 ; Esperamos a que se presione una tecla
sjmp decodifica_tecla_fin presiona_para_continuar:
decodifica_boton_1: mov tecla_actual, #00h
mov tecla_actual, #LETRA_1 mov flag_boton, #00h
sjmp decodifica_tecla_fin lcall botonera
decodifica_boton_2: mov a, flag_boton
mov tecla_actual, #LETRA_2 jz presiona_para_continuar
sjmp decodifica_tecla_fin mov tecla_actual, #00h
decodifica_boton_3: mov flag_boton, #00h
mov tecla_actual, #LETRA_3 ret
sjmp decodifica_tecla_fin
decodifica_boton_4:
mov tecla_actual, #LETRA_4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sjmp decodifica_tecla_fin ; TIMER
decodifica_boton_5: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov tecla_actual, #LETRA_5
sjmp decodifica_tecla_fin ; modo_timer
decodifica_boton_6: ; espera_timer_0_h
mov tecla_actual, #LETRA_6 ; espera_timer_0_l
sjmp decodifica_tecla_fin init_timer_0:
decodifica_boton_7: mov tmod, modo_timer
mov tecla_actual, #LETRA_7 mov th0, espera_timer_0_h
sjmp decodifica_tecla_fin mov tl0, espera_timer_0_l
decodifica_boton_8: clr tr0
mov tecla_actual, #LETRA_8 ret
sjmp decodifica_tecla_fin
decodifica_boton_9: espera_timer_0:
mov tecla_actual, #LETRA_9 setb tr0
jnb tf0, espera_timer_0
Placa 8031 38

clr tr0 lcall pon_letra


clr tf0 mov a, #LETRA_r
ret lcall pon_letra
mov a, #LETRA_o
; Espera para sacar frecuencia de 8k lcall pon_letra
freq_t0: mov a, #LETRA_d
setb tr0 lcall pon_letra
freq_t0_2: mov a, #LETRA_u
jnb tf0, freq_t0_2 lcall pon_letra
clr tr0 mov a, #LETRA_c
clr tf0 lcall pon_letra
ret mov a, #LETRA_e
lcall pon_letra

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lcall pasa_linia


; PORT SERIE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov a, #ESPACIO
lcall pon_letra
init_rs232: mov a, #ESPACIO
mov scon, #50h lcall pon_letra
mov tmod, #22h ;#21h mov a, #LETRA_PCAPS
mov th1, #fdh lcall pon_letra
setb tr1 mov a, #LETRA_e
setb ti lcall pon_letra
ret mov a, #LETRA_r
lcall pon_letra
mov a, #LETRA_s
lcall pon_letra
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov a, #LETRA_o
; RUTINAS LCD lcall pon_letra
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov a, #LETRA_n
lcall pon_letra
mov a, #LETRA_a
;* Post: Muestra por display que estamos telecargando código lcall pon_letra
;* Pre: Haber reseteado el LCD mov a, #DOS_PUNTOS
;* Modifica: a, dptr lcall pon_letra
muestra_menu_persona: mov a, #ESPACIO
mov a, #ESPACIO lcall pon_letra
lcall pon_letra ret
mov a, #ESPACIO
lcall pon_letra pinta_menu_no_hay_persona:
mov a, #LETRA_ICAPS mov a, #ESPACIO
lcall pon_letra lcall pon_letra
mov a, #LETRA_n mov a, #ESPACIO
lcall pon_letra lcall pon_letra
mov a, #LETRA_t mov a, #LETRA_PCAPS
Placa 8031 39

lcall pon_letra
mov a, #LETRA_e
lcall pon_letra
mov a, #LETRA_r
lcall pon_letra
mov a, #LETRA_s
lcall pon_letra
mov a, #LETRA_o
lcall pon_letra
mov a, #LETRA_n
lcall pon_letra
mov a, #LETRA_a
lcall pon_letra

lcall pasa_linia

mov a, #ESPACIO
lcall pon_letra
mov a, #ESPACIO
lcall pon_letra
mov a, #LETRA_n
lcall pon_letra
mov a, #LETRA_o
lcall pon_letra
mov a, #ESPACIO
lcall pon_letra
mov a, #LETRA_e
lcall pon_letra
mov a, #LETRA_x
lcall pon_letra
mov a, #LETRA_i
lcall pon_letra
mov a, #LETRA_s
lcall pon_letra
mov a, #LETRA_t
lcall pon_letra
mov a, #LETRA_e
lcall pon_letra
ret

.END

Das könnte Ihnen auch gefallen