MC9S08SH8 GPIO – Registros de dirección y datos

Anuncio
GPIO
MC9S08SH8
d.codevilla – 2016-06 – v1.3
GPIO
MC9S08SH8
Los pines de entrada – salida de los microcontroladores se agrupan en Ports, cada uno
con hasta 8 pines (hay ports de menos de 8 pines)

El SH8 tiene 17 pines de entrada y salida, y uno de salida solamente, organizados en
tres grupos (ports) de 8 pines como máximo.

Cada port se identifica con una letra.

En este microcontrolador tenemos: Port A (6 pines), Port B (8 pines) y Port C (4 pines).

La distribución de estos ports se muestra a continuación:
Solo salida
A5
A0
A4
A1
A2
A3
B7
B0
B6
B1
B5
B2
B4
B3
C3
C0
C2
C1
d.codevilla – 2016-06 – v1.3
GPIO – Diagrama en boques de un pin
MC9S08SH8
d.codevilla – 2016-06 – v1.3
GPIO – Registros de configuración y datos

MC9S08SH8
Cada pin tiene asociado un bit de dirección de datos (PTxDDn) que lo configura como
entrada o como salida.
Ej. el bit 5 del port B → PTBDD5

Además, un bit de datos (PTxDn) permite fijar el estado lógico del pin (si se lo utiliza
como salida), o leer su estado (si se lo utiliza como entrada).
Ej. el bit 2 del port C →

PTCD2
Otros bits asociados a los pines permiten configurar pull-up o pull-down interno,
interrupciones, etc


Estos bits se agrupan en registros de 8 bits (Que desde la perspectiva del programador
son posiciones de memoria “normales” del microcontrolador)
Tenemos por cada Port un registro de dirección de datos, un registro de datos, etc.
d.codevilla – 2016-06 – v1.3
GPIO – Registros de dirección y datos

MC9S08SH8
Para configurar los pines como entrada o salida se escriben los
registros de dirección de datos:
PTADD
PTBDD
PTCDD

Para leer el estado de los pines (si son entrada o salida) y fijar el estado
(si son salidas) se utilizan los registros de datos:
PTAD
PTBD
PTCD
d.codevilla – 2016-06 – v1.3
GPIO – Registros de dirección

MC9S08SH8
Para configurar un pin como:
- Entrada se escribe 0 en el bit correspondiente
- Salida se escribe 1 en el bit correspondiente
Ej.: para configurar el Port B de la siguiente forma:
- 16, 15, 14, 6 y 7 como salidas
- 13, 8, 5 como entradas
Hay que escribir en el PTBDD:
0
1
1
0
0
1
1
1
PTBDD
d.codevilla – 2016-06 – v1.3
GPIO – Registros de datos

MC9S08SH8
Para fijar el estado de un pin configurado como salida:
- Un 0 en el bit correspondiente, fija estado Low
- Un 1 en el bit correspondiente, fija estado High

Estos bits quedan memorizados (“Latcheados”)

Además de fijar el estado de un pin escribiendo el bit que le
corresponde, se puede leer su estado.

Si se escribe en el bit de datos correspondiente a un pin configurado
como entrada, se ignora la operación en ese bit.
d.codevilla – 2016-06 – v1.3
GPIO – Registros de datos
MC9S08SH8
Ej.: para configurar el Port B de la siguiente forma:
- Los pines 16, 14, 6 estado alto
- Los pines 15, 14, 7 estado bajo
En las entradas se escribe 1 o 0;
como son entradas, no se toma en
cuenta la escritura.
H
L
H
H
L
Hay que escribir en el PTBD:
X
1
0
X
X
1
0
1
PTBD
d.codevilla – 2016-06 – v1.3
GPIO – Registros de dirección y datos
MC9S08SH8
Ej.: configurar el Port C y fijar los
niveles como se indica en la figura
H
H
L
1
1
0
1
0
x
1
PTCDD
1
PTCD
d.codevilla – 2016-06 – v1.3
GPIO – Registros de dirección y datos
MC9S08SH8
¿Cómo colocar ceros y unos en estos registros?

Los registros de dirección de datos y de datos son parte de la memoria del
microcontrolador.

Se puede escribir y leer información en ellos conociendo su dirección de memoria.

Para simplificar el proceso, el entorno de desarrollo nos brinda la posibilidad de
referirnos a estos registros (y el resto de los registros del microcontrolador) por su
nombre; de esta manera, para escribir 01010101 en el registro PTBDD utilizando
lenguaje C hacemos:
PTBDD = 0b01010101;

El ejemplo del slide anterior, en C:
PTCDD = 0b00001101;
PTCD = 0b00001001; //O
PTCD = 0b00001011
d.codevilla – 2016-06 – v1.3
GPIO – Registros de dirección y datos
MC9S08SH8
¿Cómo colocar ceros y unos en estos registros?

Para hacer referencia a un bit en particular utilizamos la siguente notación:
nombreDelRegistro_nombreDelBit
Ej.:
PTAD_PTAD0
hace referencia al bit 0 del PTAD
d.codevilla – 2016-06 – v1.3
GPIO – Registros de dirección y datos
MC9S08SH8
Ej.:
Si la llave está cerrada, encender el led D1 y
apagar D2;
Vdd
Si está abierta, apagar D1 y encender y apagar
en forma alternada D2
#include <hidef.h>
#include "derivative.h"
D1
D2
void main(void) {
/* -- estado inicial: D1 y D2 apagados -- */
PTCD = 0b00000000;
/* -- configuro entradas y salidas: C2 y C1 salidas -- */
PTCDD = 0b00000110;
}
for(;;) {
if (PTCD_PTCD3 == 0) { //llave cerrada C3 == 0
PTCD_PTCD2 = 0; //Led D2 apagado
PTCD_PTCD1 = 1; //Led D1 encendido
} else {
PTCD_PTCD1 = 0; //Led D1 apagado
PTCD = PTCD ^ 0b00000100; //hace xor para toggle de C2
}
}
d.codevilla – 2016-06 – v1.3
GPIO – Registros de dirección y datos
MC9S08SH8
Para mejorar la legibilidad, claridad, y facilidad de mantenimiento del código anterior usamos
#define para referirnos a las diferentes patas y valores constantes:
#include <hidef.h>
#include "derivative.h"
#define ENTRADA 0
#define SALIDA 1
#define ENCENDIDO 1
#define APAGADO
0
void main(void) {
/* -- estado inicial: D1 y D2 apagados -- */
LED1 = APAGADO;
LED2 = APAGADO;
/* -- configuro entradas y salidas: C2 y C1 salidas -- */
_LLAVE = ENTRADA;
_LED1 = SALIDA;
_LED2 = SALIDA;
#define ABIERTA 1
#define CERRADA 0
#define
#define
#define
#define
#define
#define
LLAVE PTCD_PTCD3
_LLAVE PTCDD_PTCDD3
LED2 PTCD_PTCD2
_LED2 PTCDD_PTCDD2
LED1 PTCD_PTCD1
_LED1 PTCDD_PTCDD1
}
for(;;) {
if (LLAVE == CERRADA) { //llave cerrada C3 == 0
LED2 = APAGADO; //Led D2 apagado
LED1 = ENCENDIDO; //Led D1 encendido
} else {
LED1 = APAGADO; //Led D1 apagado
LED2 = ~LED2; //invierte estado de LED2
}
}
Si por ejemplo se quiere cambiar la pata donde se conecta el LED2, en este listado solo hay
que cambiar el define correspondiente → UN cambio → Menos posibilidades de error, más
simple, etc.
d.codevilla – 2016-06 – v1.3
GPIO – Otro ejemplo
MC9S08SH8
Se necesita implementar:
LL ab
Vdd
D1 = 0
D2 = 0
LL ab
LL ce
D1
LL ce
D2
LL ce
D1 = 1
D2 = 1
D1 = 0
D2 = 1
LL ab
LL ab
LL ce
D1 = 1
D2 = 0
d.codevilla – 2016-06 – v1.3
GPIO – Otro ejemplo
#include <hidef.h>
#include "derivative.h"
#define ENTRADA 0
#define SALIDA 1
#define ENCENDIDO 1
#define APAGADO
0
#define ABIERTA 1
#define CERRADA 0
#define
#define
#define
#define
#define
#define
LLAVE PTCD_PTCD3
_LLAVE PTCDD_PTCDD3
LED2 PTCD_PTCD2
_LED2 PTCDD_PTCDD2
LED1 PTCD_PTCD1
_LED1 PTCDD_PTCDD1
void main(void) {
unsigned char estado = 0;
/* -- estado inicial: D1 y D2
apagados -- */
LED1 = APAGADO;
LED2 = APAGADO;
/* -- configuro entradas y
salidas: C2 y C1 salidas -- */
_LLAVE = ENTRADA;
_LED1 = SALIDA;
_LED2 = SALIDA;
MC9S08SH8
for(;;) {
switch (estado) {
Case 0:
// estado 0
LED1 = APAGADO;
LED2 = APAGADO;
/* si llave cerrada cambia a estado 1 */
if (LLAVE == CERRADA)
estado++;
break;
Case 1:
// estado 1
LED1 = ENCENDIDO;
LED2 = ENCENDIDO;
/* si llave abierta cambia a estado 2 */
if (LLAVE == ABIERTA)
estado++;
break;
Case 2:
// estado 2
LED1 = ENCENDIDO;
LED2 = APAGADO;
/* si llave cerrada cambia a estado 3 */
if (LLAVE == CERRADA)
estado++;
break;
Case 3:
// estado 3
LED1 = APAGADO;
LED2 = ENCENDIDO;
/* si llave abierta cambia a estado 0 */
if (LLAVE == ABIERTA)
estado = 0;
break;
}
}
d.codevilla – 2016-06 – v1.3
GPIO – Otra forma...
MC9S08SH8
#include <hidef.h>
#include "derivative.h"
for(;;) {
/* bloquea el programa hasta que se cierre llave */
while (LLAVE == ABIERTA);
/* estado 1 */
LED1 = ENCENDIDO;
LED2 = ENCENDIDO;
#define ENTRADA 0
#define SALIDA 1
#define ENCENDIDO 1
#define APAGADO
0
#define ABIERTA 1
#define CERRADA 0
#define
#define
#define
#define
#define
#define
/* bloquea el programa hasta que se abra llave */
while (LLAVE == CERRADA);
/* estado 2 */
LED1 = ENCENDIDO;
LED2 = APAGADO;
LLAVE PTCD_PTCD3
_LLAVE PTCDD_PTCDD3
LED2 PTCD_PTCD2
_LED2 PTCDD_PTCDD2
LED1 PTCD_PTCD1
_LED1 PTCDD_PTCDD1
/* bloquea el programa hasta que se cierre llave */
while (LLAVE == ABIERTA);
/* estado 3 */
LED1 = APAGADO;
LED2 = ENCENDIDO;
void main(void) {
/* -- estado inicial: D1 y D2
apagados -- */
LED1 = APAGADO;
LED2 = APAGADO;
/* -- configuro entradas y
salidas: C2 y C1 salidas -- */
_LLAVE = ENTRADA;
_LED1 = SALIDA;
_LED2 = SALIDA;
}
}
/* bloquea el programa hasta que se abra llave */
while (LLAVE == CERRADA);
/* estado 0 */
LED1 = APAGADO;
LED2 = APAGADO;
Esta solución debería evitarse para tareas más complejas que la desarrollada en este ejemplo ya que los
while( <condición>); bloquean la ejecución de cualquier otra instrucción (salvo interrupciones)
d.codevilla – 2016-06 – v1.3
GPIO – Tercer ejemplo
MC9S08SH8
Hay que comparar dos dígitos BCD:
N1 ingresa por B7..B4
N2 ingresa por B3..B0

Si N1 > N2 enciende D2

Si N1 < N2 enciende D1

Si N1 = N2 encienden ambos LED

Si N1 o N2 > 9 se apagan ambos LED
D1
D2
d.codevilla – 2016-06 – v1.3
GPIO – Tercer ejemplo
MC9S08SH8
#include <hidef.h>
#include "derivative.h"
for(;;) {
aux = N1N2;
n1 = (aux & 0xF0) >> 4;
n2 = (aux & 0x0F);
#define ENTRADA 0
#define ENTRADAS 0x00
#define SALIDA 1
if ((n2 > 9) || (n1 > 9)) {
/* si n1 y/o n2 son incorrectos… */
LED1 = APAGADO;
LED2 = APAGADO;
} else {
/* si n1 y n2 correctos… */
if (n1 > n2) {
LED1 = ENCENDIDO;
LED2 = APAGADO;
}
#define ENCENDIDO 1
#define APAGADO
0
#define
#define
#define
#define
#define
#define
N1N2 PTBD
_N1N2 PTBDD
LED2 PTCD_PTCD2
_LED2 PTCDD_PTCDD2
LED1 PTCD_PTCD1
_LED1 PTCDD_PTCDD1
void main(void) {
unsigned char n1, n2, aux;
/* -- estado inicial: D1 y D2
apagados -- */
LED1 = APAGADO;
LED2 = APAGADO;
if (n1 < n2) {
LED1 = APAGADO;
LED2 = ENCENDIDO;
}
/* -- configuro entradas y
salidas: C2 y C1 salidas -- */
_N1N2 = ENTRADAS;
_LED1 = SALIDA;
_LED2 = SALIDA;
}
}
if (n1 == n2) {
LED1 = ENCENDIDO;
LED2 = ENCENDIDO;
}
d.codevilla – 2016-06 – v1.3
Descargar