RobotyPic son proyectos básicos de electrónica con microcontroladores PIC, de aplicación en el mundo de la robótica didáctica, con archivos fuente creados mediante el compilador CCS PIC C COMPILER en lenguajeC.
Este proyecto es un ejemplo de lectura-escritura en una memoria eeprom a través de un pic por bus I2C. En este ejemplo concreto se permite la lectura o escritura de las 10000 primeras posiciones de la eeprom. Al tratarse de un teclado numérico decimal, las direcciones se enviarán en su valor decimal y los datos introducidos serán del 0 al 9, pero podrían tratarse perfectamente de datos hexadecimales ( de 0 a F) si procediesen de otro medio.
Para que el PIC comunique con la memoria eeprom, éste debe “conocer” su dirección ( de la memoria) en el bus I2C. En concreto, para la eeprom empleada en este ejemplo, una M24512, el byte alto de su dirección está fijado por el fabricante como Ah, mientras que el byte bajo se establece por el usuario según la combinación de los niveles lógicos de tensiónen las patillas E0, E1 y E2 además del bit de lectura-escritura que es el de menor peso. Como aquí todas las patillas se han llevado a 0V, (combinación lógica: 0 : 0 : 0 : W=0/R =1) el byte bajo será 0 más el valor del bit de lectura o escritura. Es decir, la dirección I2C de la eeprom será A0h para escribir en ella y A1h para leer.
En los comentarios del programa se puede intuir su funcionamiento.
#use fast_io(B)
#define use_portb_lcd TRUE //Configuración puerto b control lcd
#define use_portb_kbd TRUE //Configuración puerto b control teclado
#include <lcd.c> //archivo para control del lcd
#include <kbd.c> //archivo para control del teclado
#define EEPROM_ADDRESS long int
char tecla; //Valor de la tecla pulsada
int8 dato=0; //Dato a enviar o leer de memoria
int16 address; //Dirección de memoria
/******************************************************************************/
/*********************** FUNCIÓN ESCRITURA EN EEPROM *************************/
void escribir_en_eeprom(long int address, BYTE dato){
short int status;
i2c_start(); //Inicio de la transmisión...
i2c_write(0xA0); //... con la dirección I2C correspondiente a la eeprom en modo escritura
i2c_write(address>>8); //Envío parte alta dirección
i2c_write(address); //Envío parte baja direción
i2c_write(dato); //Envío del dato
i2c_stop(); //Finalización de la transmisión
i2c_start(); //Reinicio de la comunicación...
status=i2c_write(0xa0); //... para lectura de bit ACK (escritura correcta)
while(status==1){ //Si es 1 esperar a que responda eeprom
i2c_start();
status=i2c_write(0xa0);
}
printf(lcd_putc,"\fDato guardado %d\n",dato);
printf(lcd_putc,"Pos%ld Dir%lx", address, address);
}
/*****************************************************************************/ /*********************** FUNCIÓN LECTURA DE EEPROM ***************************/
BYTE lectura_de_eeprom(long int address){
BYTE dato;
i2c_start(); //Inicio de la transmisión...
i2c_write(0xA0); //...con la dirección correspondiente a la eeprom en modo escritura
i2c_write(address>>8); //Envío parte alta dirección
i2c_write(address); //Envío parte baja dirección
i2c_start(); //Reinicio...
i2c_write(0xA1); //...con eeprom en modo lectura
dato=i2c_read(0); //Lectura del dato de la dirección enviada
i2c_stop(); //Fin de la transmisión
return(dato); //La función devuelve el dato leído
}
lcd_putc("\fIntroduce \n");
lcd_putc("posicion en memo");
}
/******************************************************************************/
/******************** FUNCIÓN PRINCIPAL ***************************************/
void main(){
int unidades=0; //Unidades posición de memoria
int decenas=0; //Decenas posición de memoria
int16 centenas=0; //Centenas posición de memoria
int16 millares=0; //Millares posición de memoria
int x; //Valor ASCII de la tecla pulsada
lcd_init(); //Inicialización del lcd
kbd_init(); //Inicialización del teclado
port_b_pullups(TRUE); //Habilitación resistencias pull ups puerto b
presentacion (); //Muestra mensaje de inicio en lcd
while (true){
x=kbd_getc(); //En "x" valor ASCII de la tecla pulsada
tecla=x-48; //Valor ASCII se pasa a su valor numérico
if(x!=0) { //Si se ha pulsado tecla...
if(x=='*'){ //... si es '*' pide dato a guardar
address=(millares*1000)+(centenas*100)+(decenas*10)+unidades;
lcd_putc("\fEscribe dato\n");
x=0; //Inicializa para leer nueva tecla
while(x!='*'){ //Espera a pulsar '*' para guardar dato
x=kbd_getc(); //En "x" valor ASCII de la tecla pulsada
tecla=x-48; //Valor ASCII se pasa a su valor numérico
if (x!=0&&x!='*'){ //Si se pulsa tecla pero no es '*'...
printf(lcd_putc,"\fDato = %d\n", tecla); //...muestra el valor pulsado
printf(lcd_putc,"* para guardarlo");
dato=tecla; //El valor pulsado será el dato a enviar
}
}
escribir_en_eeprom(address, dato); //Pulsado '*' envia envia el dato
delay_ms(3000); //Mantiene mensaje durante 3 segundos...
presentacion (); //...luego muestra mensaje presentación
unidades=0;decenas=0;centenas=0;millares=0;
}
else if (x=='#'){ //Si tecla es '#' lee dato de la dirección especificada
address=(millares*1000)+(centenas*100)+(decenas*10)+unidades;
printf(lcd_putc,"\fPos%ld Dir%lx\n", address, address);
dato=lectura_de_eeprom(address); //En dato el valor leido de eeprom
printf(lcd_putc,"Dato = %x", dato);
delay_ms(3000);
presentacion();
unidades=0;decenas=0;centenas=0;millares=0;
}
else{ //lee valores pulsados para direccion eeprom
lcd_putc(tecla); //Muestra tecla pulsada por display
//Cada valor pulsado desplaza al anterior para obtener dirección...
millares=centenas;
centenas=decenas;
decenas=unidades;
unidades=tecla;
//... y los va mostrando en lcd
printf(lcd_putc,"\f%ld%ld%d%d\n", millares, centenas, decenas, unidades);
lcd_putc("# leer * guardar");
}
}
}
}
Para verificar que el funcionamiento es correcto, tal como se muestra en esta simulación bajo proteus, primeramente se lee el valor de una posición de memoria. Después se escribe un dato diferente en dicha posición. Y finalmente se vuelve a leer para verificar que realmente leemos el dato introducido.
Todos los archivos; archivo fuente, hex para el pic, esquema para proteus y una animación de la simulación se pueden descargar en este enlace (contraseña robotypic):
El proyecto contenido en el artículo ha sido diseñado y probado con éxito utilizando las siguientes versiones de software: - Windows xp y windows 7 - Proteus V7.7 SP2 - CCS PIC C COMPILER v4.084
Las variables deben
declararse antes de ser usadas para que el procesador sepa que cantidad de
memoria reservar para su uso.
Se declaran según el
siguiente formato:
TIPO_DATO
NOMBRE_VARIABLE [=VALOR_INICIAL];
Ejemplos:
int entrada = 5; //Declara
la variable “entrada” como entero (8 bits)y valor inicial 5
float
resultado; //Declara “resultado” como
flotante (32 bits) y valor inicial 0
En esta tabla se pueden ver
todos los tipos de variables que pueden ser empleadas
Tipo de variable
Tamaño
Rango
Descripción
int1
short
1
bit
0,
1
Entero
de 1 bit
int8
int
8
bits
-128 a 127
Entero
de 8 bits
int16
long
int
long
16
bits
0 a 65535 bits
Entero
de 16 bits
int32
32
bits
0 a 4294967295
Entero
de 32 bits
float
32
bits
Coma
flotante
char
8
bits
0 a 255
Carácter
signed
int8
8
bits
-128 a 127
Entero
con signo
signed
int16
16
bits
-32768 a 32767
Entero
largo con signo
signed
int32
32
bits
Entero
32 bits con signo
Además de los tipos
definidos por defecto por el compilador CCS, también se pueden definir tipos
estandarizados mediante la directiva #Type:
#Typeshort=8
#Typeint=16
#Typelong=32
Serán variables de ámbito LOCAL cuando se emplean sólo en la función en la que son
declaradas. De ámbito GLOBAL cuando
se emplean en cualquier función del programa, declaradas antes y fuera de
cualquier función.
Ejemplo:
#include<16f876a.h>
#use delay (clock=4000000)
intinicio = 7;//Variable
GLOBAL tipo entero llamada 'inicio'e inicializada a 7
void funcion () { //Función
secundaria
int temporal; //Variable LOCAL tipo entero llamada 'temporal' e inicializada a 0
}
void main() {
//Función principal
float resultado; //Variable tipo flotante llamada
'resultado' e inicializada a 0
char dato; //Variable tipo carácter llamada
'dato' e inicializada a 0
No hay comentarios:
Publicar un comentario