1 - Programacion en C - Tema 2 8051

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 13

Programación en C

para 8051
Informática Industrial
Universidad de Jaén
Ángel Gaspar González Rodríguez

1
Especificadores de memoria en C para 8051
 code: la variable se almacena en memoria de programa
 variable de sólo lectura
 no tiene sentido si no está inicializada
 data: se almacena en memoria de datos interna (0 a 0x7F)
 bdata: se almacena en subárea direccionable bit a bit (0x20 a 0x2F)
 xdata: se almacena en memoria externa de datos
 También idata y pdata
 La extensión _at_ (en var. globales) impone la dirección de almacenamiento
 Ejemplos
char code texto[] = “Pulsa 0 para salir”;
int data suma_parcial _at_ 0x40;
int bdata word_flags;
sbit flag1 = word_flags^1;
sbit flag10 = word_flags^10;
int xdata ventas[100];

2
Ejemplos de direccionamiento
// Definiciones de valores constantes. No se almacenan en ningún sitio. Es más bien una herramienta de
edición.
#define CONSTANTE1 300
#define CONSTANTE2 0x40
#define CONSTANTE3 'C'

/* Variables que imponemos que su valor se almacene en una posición RAM determinada (RAM interna <->
data) */
// Han de ser globales (fuera de cualquier función, incluida main()
char data c_variable_de_1_byte _at_ 0x11;
int data i_variable_de_2_bytes _at_ 0x12;

/* La mayoría de variables que vienen a continuación pueden ser definidas como globales o locales. Las
binarias han de ser también globales. */

// Otras variables globales cuya dirección no especificamos. Podemos inicializarlas o no.


char data c_variable_global1 = CONSTANTE3;
char data c_variable_global2 = CONSTANTE1;
// ¡CUIDADO! estamos asignando el valor 300 dentro de un byte, pero no nos avisa de eso
int data i_variable_global;

// Variables intermedias que pueden ser direccionables bit a bit, y que se emplearán a tal fin
int bdata b_word_de_flags; // El compilador le busca una posición en la zona entre 0x20 y 0x2F

3
// Variables binarias
// Si queremos que ocupen un lugar determinado, se declara con sbit. Ha de referirse a un SFR o a una
variable declarada con bdata
sbit P0_6 = P0^6; // Es el bit 6 del puerto P0
sbit flag_alarma1 = b_word_de_flags^1;

// O tal vez no sea preciso imponer que se encuentre en una posición determinada
bit flag_timer0;
bit flag_interrupcion0 = 1;

char data array_global[10] _at_ 0x60;


//Puede ser peligroso si ya se almacenó algo en las posiciones 0x61, 0x62…
int xdata x_array[100] _at_ 0x1D00;

/* En memoria de programa se incluirían datos constantes que no variarán a lo largo de la ejecución del
programa.
No podemos especificar dónde queremos grabar esos datos (durante la programación de la EEPROM). */

int code c_array[4] = {100,200,300,400};


char code c_pulsa[20] = "Pulsa para continuar";
// NO EXISTEN ARRAYS DE BITS

void main(void)
{
char xdata x_array2[100];
char array_local[16];
unsigned char contador;

for (contador = 0; contador < 4; contador ++)


{ // Visualizar el resultado en X:0x1D00
x_array[contador] = c_array[contador] + 1; // simplemente por modificar el dato
}
}

4
Definición de los SFR
/* FILE NAME : C8051F340.h */
 Existe un fichero de
cabecera con la definición /* BYTE Registers */
de los SFR’s sfr P0 = 0x80; /* PORT 0 */
sfr SP = 0x81; /* Stack Pointer */
 Incluye los SFR’s del 8051 sfr DPL= 0x82; /*Data Pointer-low byte*/
genérico y los específicos sfr DPH= 0x83; /*Data Pointer-high byte */
sfr PCON = 0x87; /* Power Control */
del µC empleado …
/* Specific registers */
 El archivo de cabecera sfr DAC0CN = 0xD4; /* DAC 0 Control */
para un 8051 genérico es …
reg51.h /* BIT Registers */
/* TCON 0x88 */
 El de las prácticas es sbit TF1 = TCON^7; /*Timer1 overflow flag */
C8051F340.h sbit TR1 = TCON ^ 6; /* Timer1 On/Off */

5
Ejercicios simples de Bucles III. Factura
 Lista de productos que se van leyendo con un lector de código
de barras conectado a P1.
 Cuando se pulse P0.0, debe proporcionar la suma de precios.
Factura
SumaP ß 0
n_prod ß 0
SumaP ß 0
n_prod ß0
Mientras tecla_fin no pulsada
c_prodß0
Si codigo == 0
Continuar en bucle ¿tecla_fin Sí
Fin Si pulsada?
No ¿c_prod<
codigosn_prod = codigo No
n_prod?
n_prod ++ Sí Sí
Esperar a que P1 sea 0 ¿P1 = 0?
Fin Mientras producto ß codigos[c_prod]
No
codigos[n_prod] ß P1
Para c_prod ß 0 hasta n_prod-1 hacer Sumap += precio[producto]
producto ß codigosc_prod
n_prod++
SumaP += preciosproducto
c_prod++ Fin
Fin Para cont
Esperar a que P1 sea 0

6
Factura. Codigo fuente
#include <reg51.h>

unsigned int code precios[11] = {0, 6, 33, 65, 2, 45, 77 , 22, 500, 123, 245};
// el 1er elemento corresponde al producto de código 0, que no existe
char xdata codigos[100] _at_ 0x100;
sbit tecla_fin = P0^0; // Suponemos un pulsador unido mediante R de pull-down

main()
{
char n_prod = 0; // nº total de productos que han pasado
char c_prod; // contador de productos
char producto; // código del producto
unsigned int sumaparcial = 0;

while ( ! tecla_fin) {
if (P1 == 0)
continue;
codigos[n_prod] = P1;
n_prod ++;
while (P1); // espera a que deje de reconocerse el producto
}
for (c_prod = 0; c_prod < n_prod; c_prod ++)
{
producto = codigos[c_prod];
sumaparcial += precios[producto];
}
}

7
Ejercicio bits. Codificación NRZI
 NRZI (Non Return to Zero Inverted):
 el uno se representa por una transición
 el cero lógico por una no transición. El 1º que se envía
Momentos en que se
Inicios y finales de bit cambia el estado

NRZ 1 0 1 0 0 0 1 0 1 0 1 1 1 0 0 0 0 1 01000101 00011101

NRZI

reloj
externo

Primera consulta del 2º byte leído

 Realizar un codificador y decodificador partiendo de una


señal de reloj externa (en P1.0)
 Transmisor en P1.1 (codif) Receptor en P1.2 (decodif).
8
NRZI. Codificación
procedimiento codif(dato) void codif(char dato)
{
para c ß0 hasta 7 hacer char c;
si (bit c de dato == 1) bit valor_bit;
for (c = 0; c < 8; c++)
canal ß ! canal
{
fin si valor_bit = (dato & 1<<c);
Esperar un_bit if (valor_bit)
fin para canal_out = ! canal_out;
Esperar_un_bit();
procedimiento Espera_un_bit( ) }
}
Si (reloj == 0)
void Espera_un_bit()
Esperar mientras (reloj == 0); {
Esperar mientras (reloj ==1); bit reloj_inicial;
Si no /* Lo indicado en el pseudocódigo
Esperar mientras (reloj == 1); equivale a */
reloj_inicial = reloj;
Esperar mientras (reloj ==0); while (reloj == reloj_inicial);
Fin si while (reloj != reloj_inicial);
}
9
NRZI. Decodificación
funcion decodif( ) void Esperar_medio_bit();
void Esperar_un_bit();
dato ß 0 sbit reloj = P1^0;
valor_anterior ß 0 (sólo 1ª vez) sbit canal_in = P1^2;
// Espera_medio_bit sbit canal_out = P1^1;

para c ß0 hasta 7 hacer char decodif(void)


si (valor_canal <> valor_anterior) {
char dato=0, c;
poner un 1 en bit c de dato // Esperar_medio_bit
fin si static bit valor_anterior = 0;
valor_anterior ß valor_canal for (c = 0; c < 8; c++)
{
Espera_un_bit if (canal_in != valor_anterior)
fin para dato |= 1 << c;
devolver dato valor_anterior = canal_in;
Esperar_un_bit();
}
return dato;
}
10
Señales digitales. Tanque
Salidas Entradas
Fallo Lleno Vacío B2 B1 SB SA

P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0

B1 B2 Fallo Lleno Vacío B2 B1 SB SA Estado


Fallo
0 0 1 1 1 0 0 0
Lleno
SB
0 0 0 0 1 0 1 1
Vacío 1 0 0 0 0 1 0 2
0 1 0 0 0 1 1 3

SA

P1.0 y P1.1 son entradas.


Asignación de salidas No deben asignarse a 0.
Estado Salida
P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
0 0 0 0 1 1 1 1 1 1F
1 0 0 0 0 0 1 1 1 07
2 0 1 0 0 0 0 1 1 43
3 0 0 1 0 0 0 1 1 23
11
Tanque. Solución combinacional
 En cuanto a P1.7: Problema: excesiva
 si fuera entrada  1 conmutación de las bombas
 P1 ß salida | 0x80 entre los estados 1 y 3.
 si fuera salida  no modificar • Al llegar a estado 3,
 P1 ß salida | (P1 & 0x80);
 si no se emplea indistinto B1= B2 = 0.
• Debido al consumo, se pasa al
include "direcciones_SFR.h"
estado 1, donde B1 = 1
char code actuacion[4] = {0x1F, 0x07, 0x43, 0x23}; • Esto vuelve a llenar el depósito
main()
y pasa de nuevo al estado 3
{
char estado, salida;
Es necesaria una solución
do secuencial
{
estado = P1 & 03;
salida = actuacion[estado];
P1 = salida;
} while (1);
}

12
Tanque. Solución secuencial
#include "direcciones_SFR.h"

char code actuacion[4] =


{0x1F, 0x07, 0x43, 0x23};
main()
Tanque
{
char estado, salida;
char estado_anterior = 0;
Obtener estado

do
{
estado No estado No estado = P1 & 03;
=1 =2 if (estado != 1)
Sí estado_ant ß estado {

if (estado != 2) // no hay error
estado_anterior = estado;
estado_ant
=0 Obtener salida
salida = actuacion[estado];
No
Sí }
salida ß 0x07 salida ß 0x03
else
Una bomba Ninguna bomba switch(estado_anterior)
{
case 0: salida = 0x07; break;
case 3: salida = 0x03; break;
}
P1 = salida ;
} while (1);
}

13

También podría gustarte