La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Introducción.

Presentaciones similares


Presentación del tema: "Introducción."— Transcripción de la presentación:

1 Introducción

2 Objetivos Familiarizarse con el manejo de un micro (procesador/controlador) Arquitectura Organización de un SED Entender la documentación Entender la especificación de un SED Desde el punto de vista de la aplicación Desde el punto de vista del propio SED Requisitos de CPU Requisitos de memoria Requisitos de I/O Desarrollar habilidades de diseño y depuración de un SED Parte hardware Parte software (en C y/o Ensamblador)

3 Programa Introducción Arquitectura del microcontrolador SIEMENS 80C167
Registros Lenguaje Ensamblador: Juego de instrucciones Modos de direccionamieno Memoria y mapa de memoria Periféricos Puertos paralelo/serie Timers Otros: Displays, teclados, etc. Interrupciones Programación en alto nivel: Lenguaje C Proyecto Hardware/software

4 Normas y bibliografía Evaluación (consultar información oficial)
Nota = .7 Teoría+ .3 Lab Teoría .3 Pruebas intermedias + .7 Prueba final Habrá varias pruebas intermedias (Evaluación continua) Habrá ejercicios para casa (algunos evaluables) Se pedirá la participación del alumno en clase Incluso se podrán cambiar los porcentajes Fundamental: la asistencia Bibliografía Página WEB: Teoría, calendario, prácticas Manuales Siemens Libro de programación en C

5 Introducción al SIEMENS 80C167

6 SIEMENS 80C167 Microcontrolador (Embedded Processor) de 16 bits
ALU y Registros de 16 bits Diseñado para tareas de control industrial Robusto frente al ruido electromagnético P.e. PLC’s del LAB Rango direccionamiento: 16 Mbytes (memoria) Con memoria RAM interna Ciertas versiones disponen también de ROM interna Con muchos dispositivos integrados en el chip Controladores de comunicaciones serie Puertos paralelo Temporizadores (timers) Convertidor analógico/digital (A/D) Moduladores PWM (electrónica de potencia).

7 “Modelo de programador” del 167
Memoria CPU FF FFFF Registros R7 R15 PC R6 R14 PSW R5 R13 SP R4 R12 (SFR’s) R3 R11 R2 R10 R1 R9 R0 R8 (GPR’s) 00 FE00 00 FE02 I/O (SFR’s) 00 FE0X

8 dato = READ (dirección) WRITE(dato, dirección)
Memoria Organizada en “celdas” de 1 BYTE (8 bits) Cada byte tiene su DIRECCIÓN Dada en 24 bits (16 Mbytes) Se accede a la memoria usando la dirección. Ejemplos Lectura/escritura (datos/direcciones: 1’s y 0’s) Registros (CPU): Posiciones de memoria de acceso rápido I/O. En el 167 el acceso a puertos es similar al acceso a memoria dato = READ (dirección) WRITE(dato, dirección)

9 Primer ejemplo Suma de dos datos en ASS 167 Suma (940)+(942) en (942)
Para llenar R0 hacen falta dos bytes! (2 bytes por dato) En direcciones consecutivas de memoria (940/941) Parte baja del dato (en R0) en dirección par MOV R0,0x ; READ ADD R0,0x942 MOV 0x942,r ;WRITE

10 Más ejemplos: Programas en C y Ensamblador
Primer ejemplo: bucle “for” En lenguaje C En lenguaje ensamblador N = 5; j en 00FA00 H ( j no está inicializada !) for (i=1; i <=N; i++) j += 1; 500 E0 10 MOV R0,#1 ; r0 (i) 502 E0 11 MOV R1,#1 ; auxiliar CMP R0,#5 ; if i>N 506 DD 05 JMPR cc_sgt,512 ; then goto 512H F1 00 FA ADD 0fa00,R1 ; j += 1 50C ADD R0,#1 ; i += 1 50E FA JMPR cc_uc,504 ; salto sin condición 512

11 Notas En Ensamblador más largo que en C
Línea ensamblador = operación elemental “mov” de un dato de memoria-registro (registro-memoria) Suma dos datos Compara dos datos Saltos (con y sin condición) Las instrucciones se almacenan en memoria en formato BINARIO (1’s y 0’s) Las instrucciones ocupan 2 ó 4 bytes Las instrucciones se almacenan en posiciones de memoria CONSECUTIVAS. Se ejecutan en orden Salvo el los saltos La DIRECCIÓN (de memoria) de la próxima instrucción a ejecutar se almacena en el PC (Contador de Programa)

12 Cómo se ejecuta un programa ?
Dos pasos: Captura de la instrucción (Instruction Fetch, usando el PC) Ejecución (usando la ALU) Fetch: Trae la instrucción de memoria, incrementa PC CPU = MEM(PC); PC++; Execute: La ALU realiza la operación (suma, resta, etc.)

13 Programa ensamblador Traduce las instrucciones de “pnemónico” a binario Por ejemplo, la instrucción Se convierte en (Codificación de instrucciones) Nuestra primera instrucción que suponemos cargada en la posición 500 H de memoria Tipos de ensambladores De línea: No soporta etiquetas (reside en el monitor de la tarjeta) De PC: Soporta etiquetas (reside en el PC) MOV R0,#1 E0 10

14 Ejemplo con etiquetas (ensamblador en PC)
Las etiquetas facilitan la programación en ASS Los campos que forman una instrucción en ASS Los campos etiqueta y comentario son opcionales TAB si no se usa el campo de etiqueta MOV R0,#1 ; r0 (i) MOV R1,#1 ; auxiliar bucle: CMP R0,#5 ; if i>N JMPR cc_sgt,fin ; then goto ´fin’ ADD 0fa00H,R1 ; j += 1 ADD R0,#1 ; i += 1 JMPS bucle ; = jmpr cc_uc, fin: etiqueta: operación operandos ;comentario

15 Operaciones y operandos (resumen)
Transferencia: mov Aritméticas: add, sub, cmp, neg, mul, div Lógicas: and, or, cpl Desplazamientos: shr, shl Saltos: jmpr cc_uc (cc_eq, cc_ne, cc_ugt, cc_sgt, cc_ule, ...) Operandos, modos de direccionamiento Inmediato: #1 Directo a registro: R0 Directo a memoria: 0fa00 Indirecto: [R0] Números Decimal 15 Hexadecimal 0fa00 H (0 por delante si empiezan por letra) Binario B

16 Modos de direccionamiento.
Directo a registro mov r0,r1 ; R0 <- R1 Inmediato mov r0,#3 ; R0 <- 3 (no olvidar # !) directo a memoria mov r0,0fa00H ; R0 <- Mem[fa00 H] Indirecto (“normal”, post-incremento, pre-decremento) mov r0,[r1] ; R0 <- Mem[R1] (R1 Puntero) mov r0,[r1+] ; R0 <- Mem[R1], R1 <- R1 + 2 mov r0,[-r1] ; R1 <- R1 - 2, R0 <- Mem[R1] mov r0,[r1+#4] ; R0 <- Mem[R1+#4] A nivel de byte movb rl0,#3 ; R0 <- 3 movb rh0,[r1+] ; R0 <- Mem[R1], R1 <- R1 + 1

17 Tipos de instrucciones
De transferencia de datos Mov mov r0,#5 ; carga el número 5 en R0 Aritméticas Add, Sub, Neg, Cmp, Mul add r0,r1 ; R0 <- R0 + R1 Lógicas And, Or, Xor, Cpl Desplazamientos Shl, Shr, Rol, Ror Saltos JMPR: Con condición, sin condición (unconditional) Jmpr cc_eq, dir Jmpr cc_uc. dir

18 Más ejemplos if ( ) Alto nivel Ensamblador if (a == b) a = 0; MOV R0,a
CMP R0,b JMPR cc_ne,next MOV R0,#0 MOV a,R0 next:

19 Otro ejemplo while ( ) Alto nivel Ensamblador i = 0; while (i<10) {
a[i] = i; i += 1; } MOV R0,#0 MOV R1,#1 MOV R2,#0fa00h otro: CMP R0,#10 JMPR cc_sge,next MOV [R2],R0 ADD R0,R1 ADD R2,#2 JMPS otro next:

20 Mapa de memoria del 80C167

21 Mapa de memoria del 80C167 Segmentada, en código. Paginada en datos.
FF FFFF H FFFF H P3 (RAM I.) C000 H 255 Segmentos de 64 kB P2 8000 H P1 (ROM) 4000 H H P0 (ROM) S0 H 0000 H

22 Página 3: RAM interna + SFR’s
Los registros de control de los periféricos están en P3. Reciben el nombre de Special Function Registers. Los GPR’s son los registros R0 a R15 (en esta zona de memoria caben más de 16 registros de 16 bits!). FFFF H SFR’s (bit) SFR’s FF00 H SFR’s FE00 H Bit a bit FD00 H GPR’s FC00 H RAM Stack F600 H

23 SFR’s Son: PSW (Processor Status Word). Contiene los flags, ó códigos de condición (para instrucciones de salto. P.e. “jmpr cc_eq,dir”) N: Negative C: Carry (acarreo) V: Overflow (números con signo) Z: Zero PC (Program Counter) IP: Instruction Pointer (16 bits, apunta dentro del segmento) CSP: Code Segment Pointer (8 bits, apunta al segmento en uso) SP (Stack Pointer) Apunta a la zona de Stack (F600 H a FC00 H, crece hacia abajo). DPP’s (Data Page Pointer Registers) Otros: Control de periféricos (p.e. Las luces en FFC0 H)

24 GPR’s Registros de propósito general (R0 a R15) Son de 16 bits
Los 8 primeros registros (R0 a R7) se pueden acceder a nivel de byte (8 bits). En este caso reciben los nombres: RL0 y RH0 (para R0) Los 4 primeros registros (R0 a R3) pueden almacenar direcciones (punteros) Ubicados en la zona (FC00 H a FD00 H) Se puede “reubicar” el banco de registros (los 16) en esta zona de memoria actuando sobre el registro (SFR): CP (Contex Pointer) CP inicial = FC00 H Más: rendimiento, prestaciones, capacidad, etc. No sólo CPU: sistema completo

25 Puertos de entrada/salida del 80C167

26 Entrada/salida. Puertos paralelo
9 puertos, 111 líneas (144 pin) P0 y P1 (16 bits): Bus de datos y bus de direcciones P2 (16 bits): de propósito general Parte baja: Diodos led (y teclado en tarjeta de ampliación) Parte alta: Interruptores (tarjeta de ampliación) P3 (16 bits): Vía serie con PC (y display en tarjeta de ampliación) (P4, 8 bits: parte alta del bus de direcciones) P5 (16 bits): Entradas A/D. (P6, 8 bits: de “chip select”). (P7, 8 bits: de “PWM”). (P8, 8 bits: de “Capture Compare”)

27 Puerto 2 Dos registros de control de 16 bits: DP2 y P2 DP2 en FFC2 H
DP2 (bits DP2.0 a DP2.15): “Data Direction Register”. Ej: DP2.0 = 1 : Línea de salida DP2.0 = 0 : Línea de entrada P2 en FFC0 H P2 (bits P2.0 a P2.15): “Data Register”. Ej; Si DP2.0 = 1, (P2 como registro de escritura) P2.0 = 1: La Salida P2.0 se pone a 5 V. P2.0 = 0: La Salida P2.0 se pone a 0 V. Si DP2.0 = 0, (P2 como registro de lectura) Si P2.0 = 1: La Entrada P2.0 está a 5 V. Si P2.0 = 0: La Entrada P2.0 está a 0 V.

28 Diodos e interruptores
Tenemos diodos (leds) en parte baja P2 (P2.0 a P2.7) e interruptores en la parte alta (P2.8 a P2.15). ¿Qué nivel lógico tengo que poner en P2.0 para que el diodo se encienda? + 5V + 5V P2.8 P2.0

29 Ejemplo de manejo de P2 en C
Lee entradas, efectúa cierta operación con las mismas, pone el resultado en los diodos. ¿Qué operación se realiza con el dato introducido mediante los interruptores? #include <reg167.h> void main(void){ int lect,temp1,temp2; DP2 = 0x00ff; while (1) { lect = P2; temp1 = lect & 0x0f00; temp1 = temp1 >> 8; temp2 = lect & 0xf000; temp2 = temp2 >> 12; P2 = ~(temp1 + temp2); }

30 Ejemplo de manejo de P2 en C
De una forma más compacta #include <reg167.h> void main(void){ DP2 = 0x00ff; while (1) { P2 = ~(((P2 & 0x0f00) >> 8) + ((P2 & 0xf000) >> 12)); }

31 Programación avanzada en Ensamblador

32 Ejemplo con etiquetas (ensamblador en PC)
Las etiquetas facilitan la programación en ASS Los campos que forman una instrucción en ASS Los campos etiqueta y comentario son opcionales TAB si no se usa el campo de etiqueta MOV R0,#1 ; r0 (i) MOV R1,#1 ; auxiliar bucle: CMP R0,#5 ; if i>N JMPR cc_sge,fin ; then goto ´fin’ ADD 0fa00H,R1 ; j += 1 ADD R0,#1 ; i += 1 JMPS bucle ; = jmpr cc_uc, fin: etiqueta: operación operandos ;comentario

33 Programando en ensamblador con etiquetas
Línea de ensamblador típica etiqueta: operanción operandos ; comentario El primer carácter de la etiqueta en columna 1 Campos separados por “tabs” El campo de “etiqueta” se puede suprimir (poner un “tab”) Usando etiquetas Ini: mov r0, #1 . Jmpr cc_uc, ini

34 Tareas que realiza el programa ensamblador
El programa ensamblador (A166) Traduce el fuente (.a66) a código máquina (.obj) Cada instrucción tiene su código binario. Ejemplos: mov Rx, Ry en código máquina F0xy H donde x e y están codificados en 4 bits cada uno de ellos (los diferentes modos de direccionamiento van en el campo de instrucción) Esta instrucción completa usa 16 bits (2 bytes) mov reg, # dato 16 en código máquina E6reg Dato16 donde reg esta codificado en 8 bits Esta instrucción completa usa 32 bits (4 bytes) Resuelve los valores de las etiquetas Lleva un contador direcciones en memoria de las instrucciones La etiqueta toma el valor de la dirección de memoria de la instrucción asociada

35 Instrucción MOV. Directo a registro Inmediato directo a memoria
mov r0,r1 ; R0 <- R1 Inmediato mov r0,#3 ; R0 <- 3 (no olvidar # !) directo a memoria mov r0,0fa00H ; R0 <- Mem[fa00 H] Indirecto (“normal”, post-incremento, pre-decremento) mov r0,[r1] ; R0 <- Mem[R1] (R1 Puntero) mov r0,[r1+] ; R0 <- Mem[R1], R1 <- R1 + 2 mov r0,[-r1] ; R1 <- R1 - 2, R0 <- Mem[R1] mov r0,[r1+#4] ; R0 <- Mem[R1+#4] A nivel de byte movb rl0,#3 ; R0 <- 3 movb rh0,[r1+] ; R0 <- Mem[R1], R1 <- R1 + 1

36 Mov: Flags. Extensión de signo.
Mov actualiza N y Z p.e. se puede usar “jmpr cc_eq,dir” después del Mov. Extensión de signo Movbz Carga el byte en parte baja, extiende (a los 16 bits) con ceros Movbs Carga el byte en parte baja, extiende (a los 16 bits) con bit de signo

37 Little/Big Endian En la operación (16 bits)
mov r0,0fa00H ; R0 <- Mem[fa00 H] El byte (8 bits) almacenado en la posición 0fa00H Va a la PARTE BAJA del REGISTRO (a RL0) El byte almacenado en fa01 va a la PARTE ALTA (RH0) El C167 es un Little-Endian En los procesadores MOTOROLA Al revés En ambos casos NO se permite extraer un word (16 bits) de una dirección impar de memoria.

38 Programando con etiquetas (para datos)
La pseudoinstrucción EQU permite dar nombres a los distintos datos de programa Variables (posiciones de memoria, ej 0fa00h) Constantes var1 equ 0fa00h var2 equ 0fa01h MOVB RL0,var1 MOVB RL1,var2 MOVB var2,RL0 MOVB var1,RL1

39 Instrucciones aritméticas
Aritmética en “Coma fija complemento a 2” Números positivos: bit más significativo (bit 15) a 0. Números negativos: bit más significativo (bit 15) a 1. -1 -> FFFF H, -2 -> FFFE H, ...., - 2^15 -> 8000 H Sumando dos positivos “nos vamos a los negativos” 7FFF H + 1 = 8000 H ! (“Overflow”) Instrucción Add Add Rx,op ; op: cualquier modo direccionamiento Add op,Rx ; menos “ortogonal” (que Mov) Flags V = 1 si “Overflow” (cambio de signo) C = 1 si “Carry” (acarreo, no cabe el resultado en 16 bits)

40 Otras instrucciones aritméticas
ADDB. Suma a nivel de byte SUB. Resta SUBB. Resta a nivel de byte NEG. Complemento a 2 de un número (número “negado”). MUL. Multiplica números con signo. MULU. Multiplica números sin signo. DIV/DIVU. Divide (con y sin signo). MUL Rx,Ry ; Dos GPR’s Resultado en 32 bits en registro MD MDL: Parte baja de MD (16 bits). MDH: Parte alta de MD (16 bits).

41 Instrucciones lógicas y desplazamientos.
Lógicas. AND, OR, XOR, CPL And Rx,op ; op: cualquier modo direccionamiento And op,Rx ; menos “ortogonal” (que Mov) Mismos modos direccionamiento de ADD Actualiza flags Z y N (C y V quedan a 0) Desplazamientos y “rotates” Shl op1,op2 Desplaza a la izquierda op1, el número de posiciones indicadas en op2 Introduce ceros por la derecha Rol op1,op2 El bit que sale por la izquierda se introduce por la derecha

42 Control de flujo de programa. Saltos.
Sin condición Jmpr cc_uc, dir ; “dir” dirección de memoria Con condición. Ej: cmp op1,op2 ; Instrucción que actualiza el flag Z jmpr cc_eq, dir ; si Z = 1 Ejemplos de condición cc_eq ; Z=1 (operandos iguales) cc_ ne ; Z=0 (operandos distintos) cc_ sgt ; op1 > op2 con signo cc_sge ; op1 >= op2 con signo cc_ugt ; op1 > op2 sin signo cc_sle ; op1 < = op2 con signo etc: todas las combinaciones

43 Saltos “a nivel de bit” Salto si el bit está a 1
jb bit, dir Salto si el bit está a 0 jnb bit, dir Sólo en zonas bit a bit Otros (Tiempo Real) jbc (jump if bit set and clear) jnbs (jump if bit clear and set) FFFF H SFR’s (bit) SFR’s FF00 H SFR’s FE00 H Bit a bit FD00 H GPR’s FC00 H RAM Stack F600 H

44 “move” a nivel de bit Poner un bit a 1 Poner un bit a 0 Mover un bit
bset bit Poner un bit a 0 bclr bit Mover un bit bmov bitd, bits Lógicas (a nivel de bit) band bor bxor

45 C y Ensamblador if ( ) Alto nivel Ensamblador if (a == b) a = 0;
MOV R0,a CMP R0,b JMPR cc_ne,next MOV R0,#0 MOV a,R0 next:

46 Bucles for ( ) Alto nivel Ensamblador
for (i=START; i <= STOP; i++){ a = STOP - i; MOV R0,#START ; r0 (i) MOV R1,#STOP SUB R1,R0 ; r1 (STOP-START) JMPR cc_uc,test for: MOV a,R1 SUB R1,#1 ADD R0,#1 ; i += 1 test: CMP R0,#STOP JMPR cc_sle,for ; i <= STOP next:

47 Bucles II for ( ) Alto nivel Ensamblador
for (i=START; i <= STOP; i++){ a = STOP - i; MOV R0,#START ; r0 (i) MOV R1,#STOP SUB R1,R0 ; r1 (STOP-START) for: MOV a,R1 CMPD1 R1,#0 ; hasta r1 = -1 JMPR cc_sge,for ; i <= STOP next:

48 Otro ejemplo while ( ) Alto nivel Ensamblador i = 0; while (i<10) {
a[i] = i; i += 1; } MOV R0,#0 MOV R1,#1 MOV R2,#0fa00h otro: CMP R0,#10 JMPR cc_sge,next MOV [R2],R0 ADD R0,R1 ADD R2,#2 JMS otro next:

49 Directivas. “Pseudoinstrucciones”
El ensamblador de Keil (Siemens) no tiene ORG ! Section: Comienzo de una sección De código (programa) ó datos, a partir de una POS de memoria Ends: Cierra la sección Proc : Comienzo de un procedimiento (subrutina/función) Endp: Cierra el procedimiento dsw: Reserva espacio para un word (dsb: para un byte) equ: Fuera de las secciones Define una constante/variable (para esto último se prefiere dsw)

50 Ejemplo completo Las directivas a usar en el ”for” anterior :
$nonsegmented D100 section data at 200H j dsw ; datos D100 ends ej section code at 300H ej1 proc NEAR MOV R0,#START ; código .... fin: nop ; código (final) ej1 endp ej ends end

51 Subrutinas (funciones)
f(x), ejemplo pow2(x) Alto nivel Ensamblador pot = pow2(n); MOV R1,#n ; main call pow2 ; llamada (pow2) . Pow2: MOV R0,#1 ; 2^n SHL R0,R1 RET ; Vuelta a main

52 Stack ¿Cómo se encuentra la dirección de vuelta? CALL RET
Está almacenada en el STACK CALL SP <- SP - 2 (SP) <- IP ; almacena la dirección de vuelta en el stack IP <- d_pow2 ; IP apunta a la dirección de pow2 (primera instrucción) RET IP <- (SP) SP <- SP + 2 ;Todo queda como estaba antes de llamar a pow2

53 Push y Pop PUSH R0 SP <- SP - 2 (SP) <- R0 ; guarda R0 en el stack POP R0 R0 <- (SP) SP <- SP + 2 ; recupera R0 (vacía stack) Push y Pop sirven para poder “reutilizar” los GPR’s en las funciones llamadas (dentro de la función se comportan como las variables locales de C)

54 Ejemplo: atoi Alto nivel. “Prototipo”: int atoi(char s[ ] ) ;
int i,n; n = 0; for(i=0; s[i] >= ’0’ && s[i] <= ’9’; i++) n = 10 * n + (s[i] - ’0’); return n; }

55 pop r10 ; r10 no cambia (r5,mdl y mdh si)
atoi en ensamblador atoi: push r1 ; r1: puntero al string, r4: resultado push r ; r10 : variable “local” mov r4,#0 mov r10,#10 for: mov r5,#0 movb rl5,[r1+] cmp r5,#'0' jmpr cc_slt,fin ; salto si carácter < '0' cmp r5,#'9' jmpr cc_sgt,fin ; salto si carácter > '9' mul r4,r ; n = 10 * n mov r4,mdl sub r5,#'0' ; s[i] - '0' add r4,r ; s10 * n + [i] - '0' jmpr cc_uc,for fin: pop r ; r10 no cambia (r5,mdl y mdh si) pop r ; r1 apunta a la base del string ret

56 Ejemplo: itoa Alto nivel. “Prototipo”: int itoa(int n, char s[ ] ) ;
#define SMAX 6 int itoa(int n, char s[]) { int i = SMAX; for(s[--i] = ’\0’; n/10 > 0; n /= 10) s[--i] = n % 10 + ’0’; }

57 itoa en ensamblador MAXS equ 6
; r1: puntero al string, r8: número a convertir itoa: push r1 push mdl push mdh push r10 add r1,#MAXS movb [-r1],#0 mov r10,#10 ;divisor mov mdl,r8 ;dividendo for: div r10 mov r4,mdh ;mdl:cociente, mdh:resto add r4,#'0' movb [-r1],rl4 cmp mdl,#0 jmpr cc_ne,for fin: pop r10 pop mdh pop mdl pop r1 ret

58 Periféricos: Timer’s y Vía Serie

59 Timer’s Ligados a la CAPCOM Registros de programación (SFR’s) T01CON
Los usamos como timer’s de propósito general Registros de programación (SFR’s) Registro de control: T01CON Registro de datos (contador): T0 Registro de recarga: T0REL T01CON T0I: Pre-escalado T0M: Modo (timer/counter) T0R: Bit Start/Stop 7 6 5 4 3 2 --- T0R --- T0M T0I

60 Funcionamiento Cuenta hacia arriba Rebose (bit T0IR)
Desde el valor inicial de T0, hasta FFFF H Rebose (bit T0IR) En el paso de FFFF H a 0000 H T0 se carga con el valor almacenado en T0REL Primera cuenta de T0 a FFFF H Las siguientes cuenta va de T0REL a FFFF H El rebose queda registrado en el bit T0IR del registro T0IC T0REL clk T0I T0 T0IR

61 Dos niveles de ajuste Ajuste “Grueso”: Pre-escalado (T0I)
000 8 001 16 010 32 .... Ajuste “Fino” Valor en T0 (T0REL para ondas periódicas)

62 Ejemplo de timer “leds a ritmo de reloj” #include <reg167.h>
#define PERIOD -2500 main() { T01CON = 0x00; // timer a 2.5 MHz T0REL = PERIOD; T0 = PERIOD; T01CON |= 0x40; // Start DP2 = 0x00FF; P2 = 0; while (1) { while(!T0IR) ; // bucle de espera P2 ^= 0xFFFF; T0IR = 0; // flag rebose = 0 }

63 Comunicación serie asíncrona
Convierte datos serie en paralelo y viceversa Nivel alto en descanso (sin tráfico) Datos encapsulados entre bits de arranque y parada. Comenzando por el Least Singnificant Bit (LSB) First (primero) Rx 1 . (LSB) 1 1 1 8 bits Paralelo Start Stop Tx S0TBUF / S0RBUF

64 Vía serie S0 del 80C167 Dos registros de datos: S0TBUF/S0RBUF
Tx y Rx son los pines P3.10 y P3.11, respectivamente (DP3.10 = 1 y DP3.11 = 0). El registro de control S0CON (16 bits) contiene: Número de bits/carácter Bits de control de errores (paridad, frame, etc) Bits de estado de errores. Modo loop-back Control de baud-rate. Ejemplo S0CON = 0x8011; //Baud rate E, Recep. E., 8 bit/c Baud Rate Generator Controla la velocidad de transmisión (en base al clk de muP). S0BG = 0x40 // 9600 baud (S0BG=0x10; )

65 Programa hello.c Cabecera de los programas que usan la vía serie
Se compila con la etiqueta MCB167 definida cuando no se quiere que se (re)inicialice la vía serie C166 HELLO.C CODE DEBUG MOD167 DF(MCB167) (S0RIC/S0TIC control de interrupciones de vs) #ifndef MCB /* do not initialize if you use Monitor */ P3 |= 0x0400; /* SET PORT 3.10 OUTPUT LATCH (TXD) */ DP3 |= 0x0400; /* SET PORT 3.10 DIRECTION CONTROL (TXD OUTPUT) */ DP3 &= 0xF7FF; /* RESET PORT 3.11 DIRECTION CONTROL (RXD INPUT) */ S0TIC = 0x80; /* SET TRANSMIT INTERRUPT FLAG */ S0RIC = 0x00; /* DELETE RECEIVE INTERRUPT FLAG */ S0BG = 0x40; /* SET BAUDRATE TO 9600 BAUD */ S0CON = 0x8011; /* SET SERIAL MODE */ #endif

66 Polling Timer Vía serie (transmisión)
T0IR y S0IR en registros de control de interrupciones void espera(int tiempo) { // inicializa timer (tiempo) while(!T0IR) ; // bucle de espera (polling) T0R = 0; // para el timer T0IR = 0; // bandera de rebose a 0 } void puts(char *ps) { while (*ps) { while(!S0TIR) ; // espera S0TBUF vacío (polling) S0TBUF = *ps++; // pone carácter a enviar (S0TBUF) // S0TIR se pone automáticamente a 0 }

67 Interrupciones (Introducción)

68 Interrupciones Creadas para evitar los tiempos de espera de polling (desperdicio de ciclos de CPU). Mecanismo básico (inicialización del periférico) Durante el “trabajo normal” el periférico solicita atención. El procesador suspende el “trabajo normal” Atiende al periférico Continúa con el “trabajo normal” (en el lugar interrumpido). Programa principal Interrupción

69 Interrupciones II (en más detalle)
El periférico solicita interrupción (línea IRQ bus control) Ej: T0IR, S0TIR, etc (hasta 56 flags de interrupt request) El muP completa la instrucción actual (código máquina). El muP guarda PSW y PC (CSP+IP) en el Stack (de CPU). El muP lanza un ciclo de reconocimiento de interrupt. Determina qué periférico ha solicitado la interrupción De entre todos ellos (56) el de mayor prioridad (16 niveles de prioridad. La prioridad se indica en el registro de control de la Interrupc.). Salta a la función de tratamiento de la interrupción Tabla de “vectores de interrupción” . Vector: dirección de comienzo de la subrutina de tratamiento de la interrupción. Durante el tratamiento en PSW se pone el nivel de la interrupción.

70 Recursos 167 para tratamiento interrupciones
Por cada fuente interrupción (56) tenemos: Un vector de interrupción Tabla de vectores en RAM desde 0000H a 0100H (un salto a una subrutina de tratamiento para cada interrupción) Un registro de control Registro de control ILVL: Nivel de la interrupción (0 a 15. Nivel 15 nivel más alto) xxIE: Bit de habilitación de la interrupción (I Enable) xxIR: Bit de petición de interrupción (I Request, ej T0IR) xxIC 8 7 6 5 2 1 15 xxIR xxIE ILVL GLVL

71 Y además ... Registro de estado del procesador (PSW)
Bit 11, IEN : Bit de habilitación global de interrupciones Prioridad del programa en curso en PSW (bits 12 a 15, ILVL) = Prioridad de la interrupción en curso Bits de ILVL del xxIC de la interrupción en curso (todos a 0 cuando se ejecuta main) ¿Por qué se salva en el stack no solo el PC sino que se salva también el PSW? 15 12 11 7 ILVL IEN - Flags

72 Ejemplo Interrupción de timer 0 (main).
Variable global: flag (enlace con la f. Interrupción). void main(void) { T01CON = 0x06; T0REL = PERIOD; /* set reload value */ T0 = PERIOD; T0IC = 0x44; /* set T0IE and ILVL = 1 */ IEN = 1; /* set global interrupt enable flag */ T0R = 1; /* start timer 0 */ while(1) { while(!flag) ; P2 ^= 0xffff ; flag = 0; }

73 Ejemplo Interrupción de timer 0 (subrutina de trat. de interrupt)
Las funciones de tratamiento de interrupción son: De tipo void xx(void) interrupt num_vect;. La comunicación con main: con variables globales. #include <reg167.h> #include <stdio.h> #define PERIOD 0 int flag; void timer0(void) interrupt 0x20 { flag = 1; }

74 Tratamiento interrupts
Reglas para escribir una función de tratamiento de interrupción CORRECTA: Escribir funciones cortas A mayor prioridad, menos líneas de código (es tiempo de CPU que se “roba” a otras interrupciones de menor nivel, y a la propia interrupción con lo que se pueden “perder” interrupciones). No usar printf (incluye la librería matemática). En Ass además Inicializar el vector de interrupción (“a mano”). Salvar todos los registros que se usan en la f. Trat. Interr. (cambio de contexto) en el Stack! (para recuperalos a la salida). ¿Que puede suceder si no se hace así?. Comprobar (si es posible) a la entrada de la función de tratamiento el xxIR (flag de petición de interrupción). Retorno de interrupción RETI (RET retorno de función “normal”)

75 Ejemplo: Reloj/Calendario
Programa principal #include <reg167.h> #include <stdio.h> #define PERIOD -2500 int ticks, sec, min, hour; void main(void) { ticks = sec = min = hour = 0; T01CON = 0x00; T0REL = PERIOD; /* set reload value */ T0 = PERIOD; T0IC = 0x44; /* set T0IE and ILVL = 1 */ IEN = 1; /* set global interrupt enable flag */ T0R = 1; /* start timer 0 */ while(1) ; }

76 Interrupción Los contadores se llevan en la interrupción
Main se encargará de utilizar estos contadores void timer0(void) interrupt 0x20 { ticks++; if (ticks == 1000) { ticks = 0; sec++; if (sec == 60) { sec = 0; min++; if (min == 60) { min = 0; hour++; if (hour == 24) hour = 0; }

77 Un ejemplo más Supuesto que la vía serie está inicializada
char buffer[MAXB], *ps; int bandera; void main(void) { S0TIC = 0x48; /* set S0TIE and ILVL = 2 */ IEN = 1; /* set global interrupt enable flag */ bandera = 0; while(1) if (!bandera){ strcpy(buffer,”mensaje”); bandera = 1; ps=buffer; S0TIC |= 0x80; }

78 Interrupción La interrupción “salta” cuando acaba de salir un carácter de S0TBUF Si en la subrutina de tratamiento No se pone carácter en S0TBUF No “salta” una nueva interrupción !! ¿Para qué sirve la bandera? main no se pelea con main MUTEX: Mutua Exclusión en el acceso a buffer void vs(void) interrupt 0x2A { if (*ps) S0TBUF = *ps++; else bandera = 0; }

79 Lenguaje C para Microprocesadores

80 C para muP Tipos básicos Control/Operadores/Expresiones lógicas
Enteros Flotantes Variables lógicas Caracteres (char’s) Control/Operadores/Expresiones lógicas Cadenas de caracteres/Vectores Punteros Funciones (variables locales/globales) Entrada/Salida (I/O, en ”bajo nivel”)

81 Enteros Números en coma fija, complemento 2 (-2^n-1 a 2^n-1 -1)
int (16 bits) : a 32767 char (8 bits): a 127 long (32 bits): -2^31 a 2^31-1 Enteros en distintas bases int i = 0xff; // Hexadecimal (-1) int i = 0377; // Octal (-1) int i = -1; // Decimal Enteros sin signo unsigned char c = 0xff; // de 0 a 2^n -1 Operadores Unitarios: -, ++, -- Binarios: *, /, % // 2/5 ? Binarios: +, -

82 Enteros II Printf Promoción de enteros
printf(“El valor es %6d”, i); // qué es el 6? scanf(“%d”, &i); printf(“El valor es %x”, i); // en hexadecimal Promoción de enteros unsigned int i; unsigned char c = 0xff; i = c; ¿Cuanto vale i? int i; char c = 0xff; En ensamblador hay instrucciones específicas (promoc.)

83 Flotantes Distintas precisiones printf Conversión de tipos
float // Simple precisión double // Doble precisión long double printf printf(“El valor es %6.2f”, 5.0/9); // No olvidar .0 ! Conversión de tipos int -> float // Promoción automática float -> int // Trunca

84 Variables lógicas En C no hay variables lógicas !
Cualquier variable entera (char, int, long) Si == 0 // Falso Si != 0 // Verdadero Ejemplo Operadores lógicos y de comparación Lógicos: && (AND lógico), || (OR lógico), ! (NOT lógico) !=, ==, <, >, <=, >= // No olvidar == en: if, while, for, ... int i = 5; while (i) { printf(“%d \n”, i); -- i; }

85 Instrucciones de control
If if (e) { } // e: variable/expresión lógica if “encadenados” y “anidados” ¿ Con quien va el else? (Cuidado con la indentación !) Con 1 instrucción (en el bloque), se pueden omitir las llaves if(e1) { } else if (e2) { else { if(e1) { if (e2) { } else { if(e1) { if (e2) { } else printf (” ”);

86 Operadores bit a bit y desplazamientos
& (AND bit a bit) | (OR bit a bit) ^ (XOR bit a bit) ~ (Unitario: Complemento a 1) Desplazamientos: >> (Desplazamiento a derecha, divide potencia de 2) << (Desplazamiento a izquierda , multiplica potencia de 2) Ejemplo: a = P2; a &= 0x000F; // ¿Cuanto vale a? a = P2; a |= 0x000F; // ¿Cuanto vale a? a = P2; a >>= 4; // ¿Cuanto vale a? a = P2; a <<= 4; // ¿Cuanto vale a?

87 Expresiones lógicas. Ejemplos.
Asignación vs. Igualdad. And lógico vs. Bit a bit Otros ejemplos if(a == b) { } if(a = b) { } if(a && b) { } if(a & b) { } if(a & 0x0f) { } if(a = getchar()) { }

88 Precedencia de operadores
En orden de mayor a menor [ ] // Vectores (por índice) ! ~ & * // not lógico y bit a bit, puntero / * % // Aritméticos + - >> << // Desplazamientos < > >= <= // Relacionales == != & // Bit a bit ^ | && // Lógicos || = += *= (etc) // Asignaciones

89 Cadenas de caracteres Vector de char’s (8 bits/char). Acaban con un ’\0’ (8 bits a 0) Se escriben con: printf(”%s”,s); Otra forma (programado “a mano”) main ( ) { char s[] = ”Hola”; // El compilador pone el 0 del final printf(“%s \n”, s); } main ( ) { char s[25]; // espacio suficiente s[0]=’H’; s[1]=’o’; s[2]=’l’; s[3]=’a’; s[4]=’\0’; // MUY IMPORTANTE }

90 scanf(”%d”, &numero); ” en bajo nivel”
La siguiente función (getentero) hace el trabajo La función gets Prototipo: char *gets(char s[ ]); Deja los caracteres (tecleados) en la cadena apuntada por s (pone el ’\0’ del final) Devuelve un ”puntero” a la base de s (puntero NULL si error) int getentero (void ) { char s[MAXINT]; if(gets(s)) return atoi(s); else return 0; }

91 Punteros El puntero es una VARIABLE (en memoria) que almacena la DIRECCIÓN de otra VARIABLE (apunta a ...) Todos los punteros ocupan lo mismo en memoria ¿Cuantos bits se necesitan para almacenar una dirección/puntero en el 167? Puntero Apuntado Char * char int * int long * long

92 Punteros en Ass y C En Ass En C *pi=7; // ¿i1?, ¿i2? ++*pi; // ¿i1?
MOV R0,#5 MOV 200H,R0 MOV R1,#200H ; R1 puntero MOV R2,[R1] ; ¿R2? main() { int i1,i2; int *pi; i1 = 5; pi = &i1; i2 = *pi; // ¿i2? }

93 Cadenas y punteros Versión con índices
Los índices válidos de la cadena van de 0 a n-1. void strcpy(char cadd[],char cads[] ) { int i=0; while (cads[i]) { cadd[i] = cads[i]; i++; } cadd[i] = cads[i]; // 0 del final main ( ) { char s1[] = ”Hola”; char s2[25]; // espacio suficiente strcpy(s2,s1);

94 Cadenas y punteros II Versión con punteros ¿Copia el 0 del final?
void strcpy(char *pd,char *ps) { // PUNTEROS while (*pd++ = *ps++) ; } main ( ) { char s1[] = ”Hola”; // CADENAS char s2[25]; strcpy(s2,s1);

95 Cadenas y punteros III Ambas declaraciones de punteros son equivalentes char s[ ] y char *ps Lo que se pasa a la función cuando hacemos strcpy(s2,s1); Son las DIRECCIONES de s2 y s1 strcpy carga ambas direcciones en sendos punteros RESERVAR siempre suficiente ESPACIO en la CADENA DESTINO !!!!! El puntero no es más que “un mecanismo alternativo” de acceso a la cadena. pd[25] está fuera de la cadena (escribe en una variable DISTINTA de la cadena apuntada por pd !)

96 Otra forma (equivalente):
Cadenas y punteros IV Otra forma (equivalente): Pero esto último es demasiado redundante No usar ! . void strcpy(char *pd,char *ps) { while (*pd++ = *ps++) ; } main ( ) { char s1[] = ”Hola”; // cadena char s2[25]; // cadena char *ps, *pd; // punteros ps = &s1[0];; pd = &s2[0]; strcpy(pd,ps);

97 Vectores Los vectores pueden ser de cuaquier tipo básico (o incluso de tipos propios: estructuras). El 0 es un elemento más (no acaban en 0). Declaración int vec[25]; // Reserva espacio para 25 int’s Indices válidos de 0 a 24 Inicialización vec [0] = 57; vec [1] = 34; etc. Declaración e inicialización int vec[ ] = {57, 455, ....}; // No aportar dimensión El nombre del vector es una constante No puede aparecer a la izquierda del signo = !!! Un puntero es una variable

98 Ejercicio: “Volcado” de memoria
Cambiando el tipo de lo apuntado Puntero Dirección de memoria Tipo de lo apuntado main ( ) { unsigned char mc[] ={1, 2, ’1’, ’2’}; unsigned char *pc, c; unsigned int *pi,i; pc = mc; c = *pc++; // Cuanto vale c c = *pc; // Cuanto vale c pi = (unsigned int *)mc; i = *pi++; // Cuanto vale i (INTEL/MOTOROLA) i = *pi; // Cuanto vale i }

99 Tamaños Tipos (revisados)
Comentar el cast Procesos de pérdida de información No llevan cast Ej: puntero int -> puntero void Procesos de ganar información (necesitan el cast) Dar tipo al contenido de una dirección Ej: puntero void -> puntero int Tipos: con y sin signo El dato sacado de la memoria se asigna a una variable sin signo (si se quiere imprimir en valor absoluto) Para que de esta forma si se pasa a un itoa, el char no promocione a int con signo (acaban saliendo números negativos!) Los programas para micros llevan muchos unsigned !

100 Aritmética de punteros
El puntero “avanza” según el tamaño de lo apuntado p++; - -p; // una posición si apuntan a char p++; - -p; // dos posiciones si apuntan a int p++; - -p; // cuatro posiciones si apuntan a long int, etc. Acceso a la i-ésima posición del vector *(p+i) p[i] Los punteros se pueden restar (resultado: desplazamiento) Los punteros no se suman ! A un puntero se le puede sumar un desplazamiento Este desplazamiento no es el número de bytes Es el número de elementos del tipo apuntado

101 Funciones Las funciones son un elemento básico para la estructuración de los programas Hacer funciones cortas y que hagan una sola cosa ! (fáciles de desarrollar y de depurar, reutilizables) Las funciones deben ser declaradas y definidas Declaración (prototipo) Definición (código) int power(int base, int n); int power(int base, int n) { int i, p; p = 1; for (i=1; i<=n; i++) p = p * base; return p; }

102 Prototipo A incluir en la cabecera de programa cuando las funciones se definen en el fichero de entrada DESPUES de main. El prototipo indica Número y tipo de argumentos (de la función) Tipo de resultado int power(int base, int n); main () { printf(”%d %d \n”, 10, power(2,10)); } int power(int base, int n) { int i, p; p = 1; for (i=1; i<=n; i++) p = p * base; return p;

103 Variables locales/globales
Argumentos y Variables definidas dentro del cuerpo de la función Las variables locales se crean en el Stack! La variable i de una función es DISTINTA de la i de otra (función)!. Variables globales Definidas fuera de las funciones (incluida main) Las variables globales se crean en el heap “Alcance” (scope) de las variables Las locales son solo accesibles dentro de la función Las globales son comunes a todas las funciones (incluida main)

104 Con variables globales
Las variables globales son comunes (a main y funciones) Las variables globales son peligrosas! Darles nombres largos (evitan que se puedan actualizar de forma no intencionada). void power(void); int base=2, exponente = 10, potencia; main () { power(); printf(”%d %d \n”, exponente,potencia); } void power(void) { int i; potencia = 1; for (i=1; i<=exponente; i++) potencia *= base;

105 Paso de parámetros Los parámetros se puede pasar por
Valor: Tipos básicos (atómicos: char, int, long, etc.). Referencia: Tipos compuestos (vectores, cadenas). Paso por referencia para tipos atómicos. Ejemplo: Por Valor Por Referencia void swap(int x, int y) { int temp; temp = x; x = y; y = temp; } main () { int a=5, b=6; swap(a,b); void swap(int *px, int *py) { int temp; temp = *px; *px = *py; *py = temp; } main () { int a=5, b=6; swap(&a,&b);

106 Variables en el Stack Mediante paso por valor se actúa sobre variables de la función No hay forma de actuar sobre las variables de main Mediante paso por referencia se actúa sobre la variable de main. Ej: prinf(”%d”, i); scanf(”%d”, &i); a a b b main main dir_v dir_v x px swap y swap py temp temp

107 ¿Cómo se devuelve una cadena?
Una cadena no se puede devolver vía “return” La cadena se crea (define) en main La función actualiza la cadena de main vía puntero La función puede devolver un puntero Ejemplo: gets char *gets (char *ps ) { while ((*ps++=getchar()) != ’\n’) ; *ps = 0; // 0 del final return ps; // falta control ERR } main ( ) { char s[80], *ps; ps = gets(s); // cuanto vale ps-s ? printf(“%s \n”, s);

108 gets para 167 (por vía serie)
puts por “polling (recordamos ...) Gets por polling (por interrupción funciona mejor) void puts(char *ps) { while (*ps) { while(!S0TIR) ; // espera S0TBUF vacío (polling) S0TBUF = *ps++; // pone carácter a enviar (S0TBUF) // S0TIR se pone automáticamente a 0 } char *gets(char *ps) { while (1) { while(!S0RIR) ; // espera S0RBUF lleno (polling) S0RIR = 0; if ((*ps++ = S0RBUF) == ’\r’) break; } *ps = 0; return ps;

109 Control de errores Las funciones deben devolver código de error
Caso de que algo vaya mal (no hacen printf por pantalla !!) La función gets(s) de librería Devuelve un puntero a la base de s (lo mismo que recibe). Devuelve el puntero NULL en caso de error Forma de controlarlo (pe. en getentero) int getentero (void ) { char s[MAXINT]; if(gets(s)!= NULL) //control de errores return atoi(s); else return 0; }

110 Proyectos en C 1) Dividir el programa en funciones
Diseñar/documentar las funciones haciendo uso de PSEUDOCÓDIGO 2) Agrupar las funciones en distintos ficheros Cada fichero contiene un cierto “grupo de funciones” Los grupos de funciones son reutilizables (librerías) Cada módulo de librería contiene: Un fichero con el código fuente (.c) Un fichero de declaraciones (.h) a incluir por los usuarios de la lib: Prototipos de las funciones Declaraciones de constantes (“define’s”) Declaraciones de variables externas (“extern’s”)

111 Ejemplo sencillo Ejemplo basado en el “filtrado rebotes”
Típico programa de micros (pseudocode cercano a C) con un “while (1)” en main con “actual” y “anterior” main ( ) contador = 0 anterior = P2 while (1) { actual = P2 if (anterior != actual) retraso (tiempo) if (anterior != actual && actual == 1) contador++ P2 = contador anterior = actual }

112 Funciones/librerías Dos funciones: main y retraso
main: “no sabe nada del retraso (timer) retraso: sólo sabe del timer Módulo de librería (time), formado por: time.h : Prototipos de funciones (y “defines”) time.c :Fuentes C de nuestra librería (pseudocode) void retraso (int tiempo); void retraso (int tiempo) ini_timer(tiempo) espera_rebose //polling o interrupción return

113 Proyecto Ejemplo de creación/utilización de librerías
Los módulos se COMPILAN POR SEPARADO ! Se “linkan” para obtener el ejecutable time.h io.h void puts(char *); char* gets(char *); void retraso (int tie); #include <reg167.h> #include ”time.h” #include ”io.h” main (){ inicializaciones while (1) { } } #include ”time.h” void retraso (int tie) ini_timer espera_rebose return #include ”io.h” void puts(char *ps) while (*ps) { while(!S0TIR) .... io.c time.c main.c

114 Variables locales/globales
Alcance Locales: En la función en que se definen Globales: En el fichero Para usar una global definida en otro fichero: extern La declaración No genera código Se puede incluir en fichero .h (para usar varias veces) NO incluir DEFINICIONES en los .h !!! Fich1.c Fich2.c int i; int val[MAX]; extern int i; extern int val[MAX]; Definición Declaración

115 Librerías típicas Todas las distribuciones suelen contener
stdio: Entrada salida estándar (stdio.h) string: Manejo de strings (string.h) char * strcpy(char *to, char *from); char * strcmp(char *to, char *from); char * strcat(char *to, char *from); etc , stdlib: Librería estandar (stdlib.h) int atoi(char *s); char *itoa(int i, char *s); // No viene en la dist, del 167 ! float atof(char *s); math: Librería matemática (math.h) sin cos abs, etc

116 Errores de programación C típicos
Variables sin inicializar Tamaños y tipos Promoción: char -> int, unsigned char -> unsigned int Los tipos unsigned se utilizan muy frecuentemente en micros (ej:Representación de números en hexadecimal) Punteros que no apuntan a nada (sin inicializar) Acceso fuera del espacio reservado para una cadena Típicamente usando un puntero Ej: strcat(cadena_d,cadena_s); // Espacio en cadena_d Olvidar el control de errores Se debe recoger el valor devuelto por la función No hacer printf en la función La función se convierte en “no reutilizable” “Reportar” el error hacia arriba (main)

117 Teclado y buses externos (hardware)

118 Teclado El teclado está conectado a la parte baja de P2 + 5 V P2.0 1 1
1 1 1 1 1 1

119 Configuración del teclado
Filas: Conectadas a las líneas P2.0 a P2.3 (Salidas) Columnas: Conectadas a líneas P2.4 a P2.7 (Entradas) El otro extremo de las líneas forzado a alimentación Energización de salidas/Estado de entradas Con todas las salidas (filas) a 1, entradas (columnas) a 1 Con Primera salida a 0 (resto de salidas a 1), una tecla de la primera fila pulsada => Columna correspondiente a 0 (resto de columnas a 1) Mismo para el resto de filas Nota. El teclado es simétrico ! (Se pueden intercambiar filas por columnas en el texto anterior)

120 Barrido de teclado Energizando por filas
Comprobando el estado de las columnas Nota: Completar siempre el barrido ! int barrido ( ) { for (i=0; i < 4; i++) { P2 = energiza_fila(i); for (j=0; j < 4; j++) if (energizada_columna(j)) tecla = i*4+j; } return tecla;

121 Validación de las teclas pulsadas (polling)
Se compara la tecla pulsada en el barrido anterior con la tecla pulsada en el barrido actual Se valida la tecla UNA VEZ en el momento que se pulsa! tecla es el vector de carátulas del teclado char teclas = ” ” main ( ) tant = barrido(); while (1) { tact = barrido(); if (tant != tac) putchar(teclas[tact]); tant = tact; retraso(tiempo); /* filtrado rebotes */ }

122 Filtrado de rebotes + 5V + 5V + 5V t tri tra ta

123 Buses Tres buses básicos
Bus de Direcciones: del micro a la memoria (y al I/O) Bus de Datos: Bidireccional Bus Control (distintas líneas en ambos sentidos) ADDRESS CPU MEM I/O RD RD Control WR WR DATA

124 Ciclo de acceso a memoria
Ejemplo: ciclo de lectura de memoria Lectura de la posición de memoria: mov R0, fa00 Secuencia: fa00 -> RADD -> ADD(RD) -> DATA -> R0 ADDRESS CPU MEM RADD RD MRADD R1 MRDD RI R0 DATA

125 Un micro de 8 bits Tiene 8 bits en el BUS de DATOS Sistema digital
Y típicamente 16 líneas en el de direcciones: 64 Kbyte Sistema digital ROM: para almacenar el programa RAM: para datos e instrucciones en fase de depuración I/O: para comunicación con el exterior ¿En qué direcciones situamos cada una de estas cosas? !Decodificación del mapa de memoria!

126 Decodificación del mapa de memoria
Por ejemplo: Queremos RAM en la zona baja del mapa de memoria, direcciones FFF ROM en direcciones más altas EFFF I/O en direcciones muy altas F000 - FFFF Truco Fijarse en las líneas altas del bus de direcciones Para la RAM: A15 = 0 Para el I/O; A15 =1, A14 =1, A13 =1, A12 =1 Para la ROM: A15 = 1, y A14 ó A13 ó A12 en 0

127 RAM 0000 a 7FFF 15 líneas directas (las bajas: A0-A14) ¿Tamaño?
Línea A15 al Chip Select de la RAM ¿En qué rango está activa? Las 8 líneas del bus de datos se conectan directamente ADDRESS (A0 - A14) CPU RAM A15 CS RD WR DATA (8 bits)

128 I/O F000 a FFFF 4 líneas altas a 1
Líneas bajas de acuerdo con el número de registros del periférico (log2 n) ADDRESS (A0 - AX) A15 CPU I/O A14 CS A13 A12 RD/WR DATA (8 bits)

129 ROM 8000 a EFFF: En el segmento alto (A15=1) excluyendo el (sub)segmento del I/O Líneas bajas A0 a A14 directas Tamaño de la ROM? Tamaño útil ? A15 A14 CS (ROM) A13 A12

130 Buses del 167 Los tres buses básicos
Direcciones (P1/P4, unidireccional: De la CPU a la memoria e I/O) Datos (P0, bidireccional) Control (distintas líneas en ambos sentidos) ADDRESS (24 bits) CPU MEM I/O RD RD Control WR WR DATA (16 bits)

131 Ciclo de acceso: Diagrama temporal
Ciclo de lectura de memoria 1 2 3 4 1 CLK P1/P4 ADDRESS ALE RD# P0 DATA

132 Organización de la memoria del 167
Bus de datos del 167 (P0): 16 bits Bus de datos de las memorias comerciales: 8 bits Al 167 la memoria se le conecta en DOS BANCOS ADDRESS (23 bits) A1-23 A1-23 A1-23 CPU P1/P4 PAR IMPAR RD/WR P0 CS CS D0-15 D0-7 A0# D8-15 BHE# DATA (16 bits) CONTROL

133 Little Endian/Big Endian
El 167 es un “Little-Endian” (al igual que los INTEL x86) El Banco PAR está conectado a la PARTE BAJA del bus de datos El byte BAJO de un registro va a la dirección PAR de memoria (parte baja registro => parte baja bus de datos) Al contrario que en los micros de MOTOROLA ¿Y en los accesos a nivel de byte? movb RL0,0fa001H H L Registro: R0 YY XX Memoria: FA00 XX YY FA01

134 Decodificación del mapa de memoria
Selección de distintos bancos de memoria usando los CS’s de las memorias ROM (solo lectura) RAM (lectura/escritura) I/O (entrada/salida, se accede como si fuera memoria) Los chips de memoria disponen de 8 líneas de datos XX líneas de direcciones (de acuerdo con el tamaño) Líneas de control: CS, OE, RD, WR (de acuerdo con el modelo) La decodificación del mapa de memoria se encarga de GENERAR los CS’s de los distintos bancos de memoria (ROM, RAM, etc.) De acuerdo con el mapa de memoria especificado (rangos de direcciones de la ROM, RAM, etc.).

135 Decodificación sencilla
Situar ROM en direcciones de a 1F FFFF (2 Mbyte) RAM en direcciones de a 3F FFFF(2 Mbyte) Un I/O en direcciones de E a FF FFFF(2 Mbyte) Esto se consigue con un simple decodificador de 3 a 8 En el primer segmento A21/A22/A23 = 0 CS (ROM) A23 CS (RAM) A22 A21 E0 0000 CS (PER)

136 Más de un periférico Para ubicar 8 periféricos en el segmento más alto
256 Kbyte para cada periférico (un periférico no necesita tanto, ya que se maneja con un par de registros de datos y uno de control). CS (PER) CS (PER1) E0 0000 E A20 E4 0000 CS (PER2) A19 A18 FC 0000 CS (PER7)

137 Decodificación realista
Los rangos (del mapa de memoria) anteriores son muy grandes Un caso más realista. Situar RAM. Dos chips de 32 Kbyte cada uno en a 03 FFFF ROM. Dos chips de 64 Kbyte cada uno en F a FD FFFF 8 periféricos (iguales) en FE 0000 FF FFFF Regla general: Llevar las líneas bajas del bus de direcciones directamente a la memoria (de acuerdo con el tamaño de la misma. A0 excluida) Llevar las líneas altas del bus de direcciones que definen el segmento (líneas constantes en el segmento) a una (varias) puerta(s) de generación de CS. El resto de las líneas (del bus de direcciones) “no importa”. Cuidado con dar CS a más de un chip ! Cortocircuito en el bus de datos

138 RAM Para la RAM Líneas de A1 a A15 directamente a ambos bancos de memoria (PAR e IMPAR). A0 (junto con BHE) selecciona banco PAR/IMPAR Líneas A23 a A18 (a 0 en todo el segmento) a lógica de selección Líneas A17 y A16 “no importa” ¿Que posición de la RAM se accede en la dirección ? A0 CS (PAR) A23 CS (RAM) A18 CS (IMPAR) BHE

139 ROM Para la ROM (y periféricos)
Líneas de A1 a A16 directamente a ambos bancos de memoria (PAR e IMPAR). A0 (junto con BHE) selecciona banco PAR/IMPAR Líneas A23 a A20 (a 1 en todo el segmento) a lógica de selección Líneas A19, A18 y A17 pueden tomar cualquier combinación salvo la (rango reservado a los periféricos) A23 CS (ROM) A20 CS (PER) A19 A18 (a decoder 3/8) A17

140 Ejercicio Diseñar el decodificador
RAM. Dos chips de 64 Kbyte cada uno en a 7F FFFF ROM. Dos chips de 128 Kbyte cada uno en a EF FFFF 8 periféricos (iguales) en F FF FFFF

141 Decodificador programable
El 167 tiene hasta 4 decodificadores (de mapa de memoria) internos y programables (genera 5 CS’s en P6.0 a P6.4) Los decodificadores son muy rápidos (1 clk de reloj, no introducen retrasos en el acceso a la memoria externa). Registros de programación ADDRSEL (1 a 4): Definición de una “ventana” de direcciones BUSCON (0 a 4): Manejo líneas de bus de control en la ventana RGSZ: Tamaño de la ventana RGSAD: Dirección base de la ventana 15 4 3 RGSAD RGSZ ADDRSEL


Descargar ppt "Introducción."

Presentaciones similares


Anuncios Google