Download Programación en XC8

Document related concepts
no text concepts found
Transcript
MODULO II
Memoria EEPROM interna del PIC.
La EEPROM es una matriz de memoria permanente, separada de la RAM de datos y de la FLASH,
se utiliza para almacenar variables que se desean conservar cuando el controlador se desconecte o
quede sin energía. No está mapeada directamente dentro de los registros o en la memoria de
programa, sino que se trata indirectamente a través de registros especiales.
La EEPROM se puede leer y escribir durante la ejecución del programa.
Cuatro registros se utilizan para leer y para escribir los datos en la EEPROM.
•
•
•
•
EECON1
EECON2
EEDATA
EEADR
En la EEPROM se permite la lectura y escritura de bytes. El registro EEDATA es el encargado de
manejar los datos ya sea tanto cuando se leer o se escribe y el registro EEADR lleva a cabo el
direccionamiento de la localización en la EEPROM.
La EEPROM es muy resistente a los ciclos de escritura/borrado. Cuando se escribe un byte
automáticamente se sobreescribe el byte anterior. El tiempo de escritura se controla con un
temporizador integrado en el chip, variará con la tensión y la temperatura así como de chip a chip.
Como se comentó el acceso a los datos se controla con dos registros: EECON1 y EECON2.
Éstos son iguales que los del acceso de control a la memoria del programa (FLASH) y se utilizan de
una manera similar para los datos en la EEPROM.
El registro EECON1 es el registro de control para el acceso a memoria de datos y de programa.
Controlando el bit, EEPGD, se determina si el acceso es a la memoria de programa o a la memoria
de datos EEPROM. Cuando está borrado, las operaciones se hacen a la memoria EERPOM. Cuando
está activado, se dirige a la memoria FLASH.
Controlando el bit, CFGS se determina si el acceso es a los registros de configuración o a la
memoria del FLASH/EEPROM. Cuando está activado, las operaciones siguientes tienen acceso a
los registros de configuración. Cuando CFGS está borrado, el bit EEPGD selecciona la FLASH o
la memoria EEPROM.
El bit WREN, cuando está activado, permitirá una operación de escritura.
Por defecto este bit esta en cero.
El bit WRERR se activa por hardware y el bit WREN se borra cuando finaliza el timer interno y se
completa la operación de escritura.
Durante la operación normal, el WRERR se lee como ‘1’. Esto puede indicar que ha
finalizado una operación de escritura prematuramente cerca de un reset o una
operación de escritura finaliza incorrectamente!!!!!.
El bit de control WR inicia operaciones de escritura. Este bit no se puede borrar, sólo está activar
por software y se borra por hardware al terminar la operación de escritura.
Programación en XC8
Pagina 55 de 174
Se activa el flag de la interrupción EEIF (PIR2<4>) cuando la escritura se completa.
Debe desactivarse por software!!!.
Controlando los bits, RD y WR, comienzan las operaciones lectura y escritura,
respectivamente. Estos bits se activa por software y se desactiva por hardware al
terminar la operación.
El bit RD no se puede activar al tener acceso a la memoria de programa (EEPGD=1).
El registro EECON2 no es un registro físico. Se utiliza exclusivamente en las secuencias de escribir
y borrar en la memoria. La lectura EECON2 leerá todo ceros.
Un ejemplo de manejo de la EEPROM interna.
/* *****************************************************************************
** Nombre
: main.c
** Descripcion : Uso de la memoria EEPROM interna del PIC
** Autor
: Firtec - www.firtec.com.ar
** IDE
: Microchip MPLAB-X
** Compilador
: XC8
** XTAL
: 20MHZ
** ****************************************************************************/
#include <xc.h>
#define _XTAL_FREQ 20000000UL
#pragma config OSC=HS,PWRT=ON,MCLRE=ON,LVP=OFF,WDT=OFF
#include <plib/eep.h>
#include <stdio.h>
#include <stdlib.h>
#include "C:\ELECTRÓNICA\EJERCICIOS_XC8\lcd_xc8.c"
#include "C:\ELECTRONICA\EJERCICIOS_XC8\lcd_xc8.h"
unsigned int direccion; // 1024 Vectores disponibles
unsigned char dato;
char str_int[16];
__EEPROM_DATA(1,2,3,4,5,6,7,8); //
//
void main(void){
lcd_init();
lcd_gotoxy(4,1);
lcd_putrs("EEPROM PIC\n");
direccion = 12;
dato = 12;
Programación en XC8
Macro para colocar valores por defecto si
fuera necesario. (No es este el caso)
// La dirección sera cero (0)
// El dato a guardar 25
Pagina 56 de 174
eeprom_write (direccion, dato); // Escribe el dato en la dirección indicada
Busy_eep ();
// Espera que termine de escribir
dato=0;
sprintf(str_int,"Dato memoria:%03d ",eeprom_read(direccion));
lcd_puts(str_int);
// Lee la dirección indicada
while(1); // Bucle infinito
}
XC8 tiene dos funciones para el manejo de la EEPROM interna.
•
eeprom_write (unsigned char, unsigned int) Escribe un byte en una posición de memoria.
•
eeprom_read(unsigned int) Lee un byte desde una posición de memoria.
Trabajo practico
Se pide que realice un programa para el control de acceso de una puerta que
cumpla con las siguientes consignas:
•
La apertura de la puerta se hará efectiva cuando se ingrese una clave
numérica de cuatro cifras que será comparada con un número almacenado en
EEPROM.
•
Los números de la clave serán generados con un potenciómetro colocado en
un canal A/D que irán desfilando en una pantalla de uno en uno mientras el
usuario mueve el potenciómetro, los números mostrados solo pueden ir de 1
a 9.
•
Cada vez que un número que forma la clave de cuatro cifras se hace visible
en la pantalla se lo valida con el botón de usuario que oficiará como botón de
“Enter”.
•
Para indicar que la acción ha sido válida utilizar un LED.
Programación en XC8
Pagina 57 de 174
Funcionamiento de la USART
En la actualidad y ante la ausencia de puertos
RS232 en las computadoras, acostumbramos a
trabajar con puentes USB-RS232 que solucionan
muchos o todos los problemas a la hora de
vincularnos con computadoras a través del viejo
protocolo 232.
Es interesante comentar que debido a la
desaparición de estos puertos en arquitecturas de computadoras uno tiende a pensar que el puerto
RS-232 está extinguido, nada mas alejado de la realidad ya que arquitecturas en 16 y 32 bits no solo
incorporan uno de estos puestos sino varios.
El controlador no resuelve la capa física, es decir que para
implementar las comunicaciones deberemos utilizar ya sea el
clásico MAX232 o los modernos puentes USB-232.
Esto es particularmente interesante porque con esta
tecnología podemos reutilizar los viejos programas en
puertos COM que por cuestiones de licencias o complejidad
son mas simples de implementar que las aplicaciones USB
nativas.
El ejemplo que vamos a ver recibe los datos enviados desde el teclado de una PC y los re-transmite
como un eco por el mismo puerto serial.
/* *****************************************************************************
** Nombre
: main.c
** Descripcion : Uso de la memoria EEPROM interna del PIC
** Autor
: Firtec - www.firtec.com.ar
** IDE
: Microchip MPLAB-X
** Compilador
: XC8
** XTAL
: 20MHZ
** ****************************************************************************/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <plib/usart.h>
#pragma config OSC=HS,PWRT=ON,MCLRE=OFF,LVP=OFF,WDT=OFF
#define _XTAL_FREQ 20000000
#include "C:\ELECTRÓNICA\EJERCICIOS_XC8\USART.X\lcd_xc8.c"
#include "C:\ELECTRONICA\EJERCICIOS_XC8\USART .X\lcd_xc8.h"
volatile char Data, Kbhit=0;
Se discrimina el origen de la interrupción
void interrupt high_isr (void)
{
if (PIR1bits.RCIF==1){ // Discrimina la interrupción
Data=getcUSART();
// Se lee dato recibido
Kbhit=1;
// Indica que se ha recibido un dato
PIR1bits.RCIF=0; // Borra bandera de interrupción
}
}
Programación en XC8
Pagina 58 de 174
Función Principal
void main(void){
unsigned char base =1;
// Inicializa el USART y lo configura a 8N1, 9600 baud
OpenUSART (USART_TX_INT_OFF &
// TX sin interrupción
USART_RX_INT_ON &
// RX con interrupciónes
USART_ASYNCH_MODE &
// Modo asincrónico
USART_EIGHT_BIT &
// Modo alta velocidad
USART_CONT_RX &
// Recepción continua
USART_BRGH_HIGH,129);
// 9600 baudios a 20Mhz
Para configurar los baudios podemos usar la herramienta Pic Baud Rate
RCONbits.IPEN = 0; // Deshabilitamos prioridades
INTCONbits.PEIE=1; // Habilitamos la interrupcion de perifericos
lcd_init();
//Delay1KTCYx(25);
lcd_putrs("USART PIC18F4620"); // Cartel inicial
INTCONbits.GIE=1; //Habilita interrupción global
while(1){
if(Kbhit !=0){ // Indica que hay nueos datos recibidos
Kbhit = 0;
// Borra la marca de ISR
if(Data!=0x00){ // El dato es distinto de 0?
if(Data==0x08 & base > 0){ // Backspace & base son verdaderos?
base--;
lcd_gotoxy(base,2);
lcd_putc(" ");
}
else{
lcd_gotoxy(base,2);
lcd_putc(Data);// Muestra el dato en pantalla
putcUSART (Data);
base++;
}
}
}
}
}
Programación en XC8
Pagina 59 de 174
Para visualizar los datos recibidos vamos a usar la aplicación terminal.exe que se encuentra entre
las herramientas del curso.
Se recibe el mismo dato enviado por la USART.
Programación en XC8
Pagina 60 de 174
Trabajo practico
Se pide que escriba un programa que envíe por el puerto serial RS-232 los datos
obtenidos de un canal analógico donde se ha conectado un potenciómetro.
El resultado deberá ser como el que se observa en la imagen.
Programación en XC8
Pagina 61 de 174
El protocolo I2C.
Diseñado por Philips, este sistema de intercambio de información a través de tan solo dos cables
permite a circuitos integrados y módulos OEM interactuar entre sí a velocidades relativamente
lentas. Emplea comunicación serie, utilizando un conductor para manejar el reloj y otro para
intercambiar datos.
Este bus se basa en tres señales:
• SDA (System Data) por la cual viajan los datos entre los dispositivos.
•
SCL (System Clock) por la cual transitan los pulsos de reloj que sincronizan el sistema.
•
GND (Masa) Interconectada entre todos los dispositivos "enganchados" al bus.
Las líneas SDA y SCL son del tipo drenador abierto, similares a las de colector abierto pero
asociadas a un transistor de efecto de campo (ó FET). Se deben poner en estado alto (conectar a la
alimentación por medio de resistores Pull-Up) para construir una estructura de bus tal que se
permita conectar en paralelo múltiples entradas y salidas.
En el diagrama se observa la configuración eléctrica básica del bus. Las dos líneas de comunicación
disponen de niveles lógicos altos cuando están inactivas. Inicialmente el número de dispositivos que
se puede conectar al bus es ilimitado, pero observe que que las líneas tienen una especificación
máxima de 400pF en lo que respecta a capacidad de carga. La máxima velocidad de transmisión de
datos que se puede obtener es de aproximadamente 100Kbits por segundo.
Las definiciones o términos utilizados en relación con las funciones del bus I2C son las siguientes:
•
Maestro (Master): Dispositivo que determina la temporización y la dirección del tráfico de
datos en el bus. Es el único que aplica los pulsos de reloj en la línea SCL. Cuando se
conectan varios dispositivos maestros a un mismo bus la configuración obtenida se
denomina "multi-maestro".
•
Esclavo (Slave): Cualquier dispositivo conectado al bus incapaz de generar pulsos de reloj.
Programación en XC8
Pagina 62 de 174
Reciben señales de comando y de reloj proveniente del dispositivo maestro.
•
Bus Desocupado (Bus Free): Estado en el cual ambas líneas (SDA y SCL) están inactivas,
presentando un estado lógico alto. Unicamente en este momento es cuando un dispositivo
maestro puede comenzar a hacer uso del bus.
•
Comienzo (Start): Sucede cuando un dispositivo maestro hace ocupación del bus,
generando esta condición. La línea de datos (SDA) toma un estado bajo mientras que la línea
de reloj (SCL) permanece alta.
•
Parada (Stop): Un dispositivo maestro puede generar esta condición dejando libre el bus.
La línea de datos toma un estado lógico alto mientras que la de reloj permanece también en
ese estado.
•
Dato Válido (Valid Data): Sucede cuando un dato presente en la línea SDA es estable
mientras la línea SCL está a nivel lógico alto.
•
Formato de Datos (Data Format): La transmisión de datos a través de este bus consta de 8
bits de datos (ó 1 byte). A cada byte le sigue un noveno pulso de reloj durante el cual el
dispositivo receptor del byte debe generar un pulso de reconocimiento, conocido como ACK
(del inglés Acknowledge). Esto se logra situando la línea de datos a un nivel lógico bajo
mientras transcurre el noveno pulso de reloj.
•
Dirección (Address): Cada dispositivo diseñado para funcionar en este bus dispone de su
propia y única dirección de acceso, que viene pre-establecida por el fabricante. Hay
dispositivos que permiten establecer externamente parte de la dirección de acceso. Esto
permite que una serie del mismo tipo de dispositivos se puedan conectar en un mismo bus
sin problemas de identificación. La dirección 00 es la denominada "de acceso general", por
la cual responden todos los dispositivos conectados al bus.
•
Lectura/Escritura (Bit R/W): Cada dispositivo dispone de una dirección de 7 bits. El
octavo bit (el menos significativo ó LSB) enviado durante la operación de direccionamiento
corresponde al bit que indica el tipo de operación a realizar. Si este bit es alto el dispositivo
maestro lee información proveniente de un dispositivo esclavo. En cambio, si este bit fuese
bajo el dispositivo maestro escribe información en un dispositivo esclavo.
Funcionamiento del protocolo I2C.
Como es lógico, para iniciar una comunicación entre dispositivos conectados al bus I2C se debe
respetar un protocolo. Tan pronto como el bus esté libre, un dispositivo maestro puede ocuparlo
generando una condición de inicio. El primer byte transmitido después de la condición de inicio
contiene los siete bits que componen la dirección del dispositivo de destino seleccionado y un
octavo bit correspondiente a la operación deseada (lectura o escritura). Si el dispositivo cuya
dirección se apuntó en los siete bits está presente en el bus éste responde enviando el pulso de
reconocimiento ó ACK. Seguidamente puede comenzar el intercambio de información entre los
dispositivos.
Cuando la señal R/W está previamente a nivel lógico bajo, el dispositivo maestro envía datos al
dispositivo esclavo hasta que deja de recibir los pulsos de reconocimiento, o hasta que se hayan
transmitido todos los datos.
En el caso contrario, es decir cuando la señal R/W estaba a nivel lógico alto, el dispositivo maestro
genera pulsos de reloj durante los cuales el dispositivo esclavo puede enviar datos. Luego de cada
byte recibido el dispositivo maestro (que en este momento está recibiendo datos) genera un pulso de
reconocimiento.
Programación en XC8
Pagina 63 de 174
El dispositivo maestro puede dejar libre el bus generando una condición de parada (Stop). Si se
desea seguir transmitiendo, el dispositivo maestro puede generar otra condición de inicio el lugar de
una condición de parada. Esta nueva condición de inicio se denomina "inicio repetitivo" y se puede
emplear para direccionar un dispositivo esclavo diferente ó para alterar el estado del bit de
lectura/escritura (R/W).
Memoria 24LC256.
La memoria 24LC256 fabricada por Microchip tiene una capacidad de almacenamiento de 256Kbits
(32 Kbytes). Sobre el mismo bus pueden conectarse hasta ocho memorias 24LC256, permitiendo
alcanzar una capacidad de almacenamiento máxima de 256 Kbytes.
Como en todas las memorias de la familia 24XXXXX, la dirección de identificación o byte de
control comienza con 1010. Seguidamente, tres bits llamados A2, A1 y A0 permiten seleccionar
una de las ocho posibles memorias conectadas en el bus.
La memoria se compone de 512 páginas de 64 bytes cada una.
Cuando se requiere transferir volúmenes considerables de información, la escritura de bytes resulta
ser bastante ineficiente, pero la escritura por páginas mejora notablemente el rendimiento. Para
Programación en XC8
Pagina 64 de 174
Memoria 24LC256 con XC8.
/* ***************************************************************************
** File Name
: 24LC256.c
** Version
: 1.0
** Description : Control de una memoria 24LC256
**
Memoria de 32Kx8=256Kbit 64Bytes x Paginas
** Target
: 40PIN PIC18F4620
** Compiler
: Microchip XC8
** IDE
: Microchip MPLAB IDE v8.50
** XTAL
: 20MHZ
** ****************************************************/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <plib/i2c.h>
#include "24LC256.h"
#pragma config OSC=HS,PWRT=ON,MCLRE=OFF,LVP=OFF,WDT=OFF
#define _XTAL_FREQ 20000000
#include "C:\ELECTRÓNICA\Programas PIC\2014\EJERCICIOS_XC8\24LC256.X\lcd_xc8.c"
#include "C:\ELECTRÓNICA\Programas PIC\2014\EJERCICIOS_XC8\24LC256.X\lcd_xc8.h"
FUNCIÓN PRINCIPAL DEL PROGRAMA
void main(void){
unsigned char dir_hi =0, dir_low= 500;
unsigned char Dato=54;
// Dato cualquiera a guardar en Memoria
char str_int[14];
lcd_init();
OpenI2C(MASTER,SLEW_OFF);
// Modo Master
SSPADD = 49;
// 100KHz para 20MHz
Escribe_Byte(0xA0,dir_hi,dir_low,Dato); // Escribe la memoria
lcd_putrs(" Memoria 24C256");
lcd_gotoxy(1,2);
sprintf(str_int,"Dato memoria:%02d ",Lee_Byte(0xA0,dir_hi,dir_low));
lcd_puts(str_int);
while(1);
}
Para el funcionamiento de este ejemplo
necesitamos de dos archivos encargados de
lidiar con las funciones relativas a la
memoria I2C.
•
•
24LC256 Contiene las funciones de
control de la memoria.
24LC256.H Contiene las
declaraciones de estas funciones.
Todo lo referente al propio bus I2C esta
contenido en el archivo de cabecera i2c.h
provisto por el compilador.
Programación en XC8
Pagina 65 de 174
El programa ejemplo solo escribe un byte en la posición 500 y lo recupera para hacerlo visible en el
LCD.
Trabajo practico
Escriba un código utilizando I2C2 cambiando lo pines dedicados que complete 500
vectores de la memoria con los datos de un contador.
Programación en XC8
Pagina 66 de 174
RTC DS1307 (Real Time Clock).
Siguiendo con los dispositivos I2C el DS1307 de Dallas Semiconductor (Maxim) es una solución
muy interesante cuando necesitamos trabajar con eventos que requieren puntualidad y exactitud a lo
largo del tiempo. Este pequeño circuito integrado es uno de los más populares relojes RTC del
mercado por su sencillez de uso y por su confiabilidad a largo plazo. Preparado para ofrecerte la
hora hasta el año 2100 con ajuste de años bisiestos.
/* *****************************************************************************
** Nombre
: main_1307.c
** Descripción : Control de un DS1307 & LCD 16x2 & INT
** Target
: PIC18F4620
** Compilador
: XC8
** IDE
: MPLAB
** XTAL
: 20MHZ
** Autor
: Firtec - www.firtec.com.ar
** ****************************************************************************/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <plib/i2c.h>
#include <plib/portb.h>
#include "DS1307.h"
#pragma config OSC=HS,PWRT=ON,MCLRE=OFF,LVP=OFF,WDT=OFF
#define _XTAL_FREQ 20000000
#include "C:\ELECTRÓNICA\Programas PIC\2014\EJERCICIOS_XC8\DS1307.X\lcd_xc8.c"
#include "C:\ELECTRÓNICA\Programas PIC\2014\EJERCICIOS_XC8\DS1307.X\lcd_xc8.h"
void Ajustar_Dato(unsigned char dato);
void Un_Segundo(void);
// Ajusta datos del DS1307
// Prototipo de la Interrupción
volatile unsigned char bandera =0; // Variable usada en la Interrupción
unsigned char Unidad, Decena; // Variables del Programa
#define chip
0xD0 // ID I2C de Chip para el DS1307
Rutina de Interrupción
void interrupt high_isr (void)
{
if(INTCON3bits.INT2IF)
// Pregunta por bandera de INT2
{
bandera =1;
// Marca para actualizar el calendario
INTCON3bits.INT2IF = 0; // Limpia bandera
}
}
FUNCIÓN PRINCIPAL DEL PROGRAMA
void main(void){
PORTB=0;
TRISBbits.TRISB5=0;
ADCON1=0x0F;
// No hay canales analógicos
lcd_init();
OpenI2C(MASTER,SLEW_OFF);
SSPADD = 49;
Programación en XC8
// Master, 100KHz
// 100KHz para 20MHz
Pagina 67 de 174
__delay_us(500);
ByteWriteI2C(chip,0,128);
Se definen valores por defecto para el Reloj
ByteWriteI2C(chip,1,0x59);
// Ajusta Minutos
ByteWriteI2C(chip,2,0x23);
// Ajusta Hora
ByteWriteI2C(chip,4,0x31);
// Ajusta el Día
ByteWriteI2C(chip,5,0x12);
// Ajusta Mes
ByteWriteI2C(chip,6,0x14);
// Ajusta Año
ByteWriteI2C(chip,0x07,0X90);
// Registro de Control (1Hz pin 7)
ByteWriteI2C(chip,0,0x50);
// Ajusta Segundos
OpenRB2INT(PORTB_CHANGE_INT_ON & FALLING_EDGE_INT & PORTB_PULLUPS_ON);
RCONbits.IPEN=0;
// No hay prioridades de interrupciones
INTCONbits.GIEH = 1; // Habilitador general de interrupciones activo
WriteTimer0(100);
lcd_putrs("Fecha ??|??|??");
lcd_gotoxy(1,2);
lcd_putrs("Hora ??|??|?? ");
Bucle Infinito
while(1){
if(bandera){
// Bandera puesta en la interrupción
PORTBbits.RB5 = ~PORTBbits.RB5;
// Cambia el estado del pin RB5
lcd_gotoxy(7,1);
// Coloca el cursor en la primera línea
Ajustar_Dato(ByteReadI2C(chip,4)); // Lee el Día
lcd_putrs("/"); // Barra separadora xx/xx/xx
Ajustar_Dato(ByteReadI2C(chip,5)); // Lee el Mes
lcd_putrs("/");
lcd_putrs("20");
// Imprime 20 para leer 20xx
Ajustar_Dato(ByteReadI2C(chip,6)); // Lee el Año
lcd_gotoxy(6,2);
// Cambia la línea en el LCD
Ajustar_Dato(ByteReadI2C(chip,2)); // Lee Hora
lcd_putrs(":");
// Puntos separadores xx:xx:xx
Ajustar_Dato(ByteReadI2C(chip,1)); // Lee Minutos
lcd_putrs(":");
Ajustar_Dato(ByteReadI2C(chip,0)); // Lee Segundos
bandera =0;
// Borra la bandera para el próximo segundo
}
Sleep();
// Espera en bajo consumo
}
}
Ajusta los datos del RTC
void Ajustar_Dato(unsigned char dato){
char cadena[4];
Unidad = (dato & 0x0F);
// Mascara y prepara dato para el LCD.
Decena = ((dato/16) & 0x0F);
// Intercambia nibles.
sprintf(cadena,"%u", Decena);
lcd_puts(cadena);
sprintf(cadena,"%u", Unidad);
lcd_puts(cadena);
}
Programación en XC8
Pagina 68 de 174
Registros Internos
NOTA:
El DS1307 solo manejas datos BCD por lo que es
necesario ajustar los binarios.
Mapa de memoria
Programación en XC8
Pagina 69 de 174
Circuito de la Aplicación
El pin siete del DS1307 ha sido configurado a través del registro de control para genera un pulso
cada segundo, este pulso se conecta al pin 35 (INT2) del controlador generando una interrupción
cada segundo. Esta interrupción cambia el estado de una bandera que se utiliza como indicativo que
hay valores del reloj a actualizar en pantalla. Cada vez que se actualizan los datos en pantalla se
cambia de estado el LED colocado en el pin 38 para tener una indicación visual que la interrupción
esta funcionado al ritmo de un segundo.
Han sido necesario varios archivos de cabecera para esta aplicación.
•
•
•
plib/i2c.h
plib/portb.h
DS1307.h
Contiene las funciones para el manejo del bus I2C
Contiene las funciones para el manejo de las interrupciones INTx.
Contiene las funciones para el control del RTC.
La línea que configura la interrupción por el pin 35 dice lo siguiente:
•
•
•
PORTB_CHANGE_INT_ON
FALLING_EDGE_INT
PORTB_PULLUPS_ON)
Programación en XC8
Máscara de interrupción activada.
Interrupción por flanco de bajada.
Las resistencias del puerto B están activadas.
Pagina 70 de 174
PCF 8591.
Otro dispositivo I2C interesante es el PCF 8591, un
conversor analógico digital y digital analógico de 8
bits, que se conecta directamente al bus I2C del
microcontrolador. En el trabajo propuesto
controlaremos el PCF8591 en sus dos modos, primero
lo pondremos en modo conversor analógico digital leyendo la tensión de dos potenciómetros
asociados al canal 0 y 1, que estará conectado entre VCC y GND (5V y 0V).
En la segunda parte del programa cambiaremos el modo de funcionamiento del PCF8591, y lo
utilizamos digital analógico (DAC) sacando por el pin de salida analógica un voltaje que se
corresponde con el dato enviado, por ejemplo en ese modo si enviamos el número 128 por el pin
analógico leemos 2,5V aproximados al 50% de Vdd.
Las dos partes del programa ejemplo son controladas por un botón colocado en RA0 (pin2).
La dirección del dispositivo.
Esta tiene 3 bits, con lo que podremos tener asta 8
dispositivos iguales en el bus I2C, la dirección sera la
siguiente “1001xxxy” donde los 4 bits de mayor peso
son fijos (0x90 es el identificador I2C para este chip), los
tres siguientes bits son definidos por el programador y
hacen referencia a su dirección en el bus, el bit de menor peso se utiliza para decir si el PCF8591 va
a estar en modo lectura o en su defecto modo escritura, siendo el ’1′ para la lectura y el ’0′ para la
escritura. El mecanismo es casi el mismo que para el acceso de una memoria I2C solo que aquí
leemos en la dir 0,1,2, 3 o 4 dependiendo del canal apuntado desde el PIC.
Otro punto importante que debemos conocer es la manera de configurar el byte de control del
dispositivo, podemos elegir las entradas analógicas para la lectura con respecto a masa o en modos
diferenciales, también podemos activar la salida analógica, en nuestro caso, utilizaremos una
configuración en la cual la salida analógica está deshabilitada, y las lecturas de las entradas
analógicas están tomadas respecto a masa. (Consultar la hoja de datos del dispositivo).
/* ****************************************************************************
** Nombre
: PCF8591.c
** Descripcion : Midiendo en dos canales del ADC y funcionamiento del DAC
** Target
: PIC18F4620
** Compilador
: Microchip XC8
** XTAL
: 20MHZ
** *****************************************************************************
El pulsador colocado en RA0 controla el flujo del programa.
*******************************************************************************/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <plib/i2c.h>
#pragma config OSC=HS,PWRT=ON,MCLRE=OFF,LVP=OFF,WDT=OFF
#include "C:\ELECTRÓNICA\Programas PIC\2014\EJERCICIOS_XC8\PCF8591.X\lcd_xc8.c"
#include "C:\ELECTRÓNICA\Programas PIC\2014\EJERCICIOS_XC8\PCF8591.X\lcd_xc8.h"
#define _XTAL_FREQ 20000000
static bit bandera1 = 0;
// Bandera para cambiar el canal.
unsigned char bandera2 = 0;
Programación en XC8
Pagina 71 de 174
char Str_float[5];
float voltaje = 0.00;
// Cadena para convertir el float en ASCII.
// Contenedor para guardar la medición.
unsigned char Lee_Byte( unsigned char ByteControl, unsigned char Direccion){
unsigned char Valor;
IdleI2C();
// El modulo esta activo?
StartI2C();
// Condición de START
while ( SSPCON2bits.SEN ); // Espera a que la condición de inicio termine
WriteI2C( ByteControl );
WriteI2C( Direccion );
RestartI2C();
// Envía ReStart
while ( SSPCON2bits.RSEN ); // Si se ha recibido el byte sigue
WriteI2C( ByteControl | 0x01 ); // Cambia bit 0 de ByteControl para leer.
Valor=ReadI2C();
// Realiza lectura.
NotAckI2C();
// Envía NACK
while ( SSPCON2bits.ACKEN );
// Espera a que de ASK termine
StopI2C();
// Condición de STOP
while ( SSPCON2bits.PEN );
// Espera fin de condición de stop
return ( Valor );
// Retorna Lectura
}
FUNCIÓN PARA EL CONTROL DEL ADC
void ADC(void){
switch(bandera1){
// Se discrimina en cual canal se medirá.
case 0:{
// Si es "0" se lee en el canal cero.
voltaje =Lee_Byte(0x90,0); // En voltaje se guarda el dato desde el A/D.
__delay_ms(10);
bandera1 =1;
// Se cambia bandera para el siguiente
canal.
break;
}
case 1:{
voltaje =Lee_Byte(0x90,1);
__delay_ms(10);
bandera1 =0;
break;
}
}
voltaje = (voltaje*5.0)/256; // Se escala el valor para medir entre 0 y 5V
sprintf(Str_float,"%1.2f ",voltaje); // El float es convertido a ASCII
if(bandera1 ==0)
// Si bandera es cero se coloca el cursor en el lugar
lcd_gotoxy(4,2);
// indicado junto al cartel que le corresponde.
else
lcd_gotoxy(13,2);
// Si bandera es uno se coloca el cursor en el lugar
lcd_puts(Str_float); // indicado junto al cartel que le corresponde.
}
FUNCIÓN VERIFICA LA PRESENCIA DEL PCF8591
void check_PCF8591(unsigned short dir){
StartI2C();
// Condición de inicio en el bus.
if (WriteI2C(dir)){
// Escribe la dirección del chip en el bus.
lcd_gotoxy(2,2);
// Si retorna "1" no hay sensor en el bus.
lcd_putrs("PCF8591 ERROR!!"); // Aviso de que no hay sensor en el BUS.
while(1);
// Programa termina.
}
else {
lcd_gotoxy(3,1);
lcd_putrs("Chip PCF8591"); // Cartel incial para indicar la presencia
}
// del chip en el bus I2C.
StopI2C();
}
Programación en XC8
Pagina 72 de 174
FUNCIÓN PRINCIPAL DEL PROGRAMA
void main() {
TRISA=0X01;
ADCON1 = 0X0F;
// Configura el pin 2 como entrada digital
// Configura los pines del PORT A como I/O Digitales
OpenI2C(MASTER,SLEW_OFF);
SSPADD = 49;
lcd_init();
check_PCF8591(0x90);
//
//
//
//
Modo Master.
100KHz para 20MHz.
Configura el LCD a valores por defecto.
Verifica la presencia del chip en el BUS.
While(1){
// El boton en RA0 es el encargado de cambiar al DAC o al ADC
if(PORTAbits.RA0!=1 && bandera2== 1){
while(!PORTAbits.RA0);
// Espera a que el botón se suelte
lcd_gotoxy(1,2);
lcd_putrs("
"); // Limpia la línea inferior para el ADC
bandera2=0;
// Coloca la bandera para que el ADC sea el modo por defecto
}
if(PORTAbits.RA0!=1 && bandera2== 0){ // Pasa al modo DAC
while(!PORTAbits.RA0); // Espera a que el botón se suelte
bandera2++;
lcd_gotoxy(1,2);
lcd_putrs(" Conversor DAC ");
StartI2C();
WriteI2C(0x90);
__delay_ms(2);
WriteI2C(0x40);
__delay_ms(2);
WriteI2C(128);
// Saca por el pin analógico 2.5V aprox. (256/2=128)
StopI2C();
// Condición de STOP
while ( SSPCON2bits.PEN ); // Espera que termine la condición de STOP
}
if(bandera2==0){ // Si bandera es 0 se activa el modo por defecto (ADC)
lcd_gotoxy(1,2);
// Coloca los carteles para los canales analógicos
lcd_putrs("A0:");
lcd_gotoxy(10,2);
lcd_putrs("A1:");
ADC();
// LLama a la función del conversor analógico
}
}
}
Programación en XC8
Pagina 73 de 174
Sensor de temperatura I2C TC4A3.
El chip TC74 es un sensor de temperatura
serie accesible a través del bus I2C fabricado
por Microchip Technology que mide con una
resolución de 1°C.
La temperatura está disponible en un byte que
es almacenado en un registro interno.
El dato de temperatura es almacenado en
formato binario con complemento a 2 y el bit
más significativo es el bit de signo, que se
establece en 1 para temperaturas negativas por
lo tanto, la temperatura máxima positiva es de
+ 127 ° C (0111 1111). También existe otro
registro de configuración (RWCR) que se
utiliza para poner el dispositivo en bajo
consumo (5µA), en este modo se detiene el
convertidor A / D.
/* *****************************************************************************
** Nombre
: TC74A3.c
** Descripcion : Sensor de Microchip I2C de 8 bits. (-40 a +125 grados)
** Target
: PIC18F4620
** Compilador
: Microchip XC8
** XTAL
: 20MHZ
** ****************************************************************************/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <plib/i2c.h>
#pragma config OSC=HS,PWRT=ON,MCLRE=OFF,LVP=OFF,WDT=OFF
#include "C:\ELECTRÓNICA\Programas PIC\2014\EJERCICIOS_XC8\TC74.X\lcd_xc8.c"
#include "C:\ELECTRÓNICA\Programas PIC\2014\EJERCICIOS_XC8\TC74.X\lcd_xc8.h"
#define _XTAL_FREQ 20000000
void delay(unsigned int t){
while(--t)
__delay_ms(1);
}
unsigned short num=0;
const int TC74A3 = 0x96; // Dirección I2C del sensor
FUNCIÓN PARA VERIFICAR EL SENSOR
void check_sensor(unsigned short dir){
StartI2C();
if (WriteI2C(dir)){
lcd_gotoxy(1,2);
lcd_putrs("Sensor ERROR!!"); // Aviso de que no hay sensor en el BUS.
while(1);
}
else {
lcd_gotoxy(2,1);
lcd_putrs("Sensor TC74A3"); // Cartel inicial.
}
StopI2C();
Programación en XC8
Pagina 74 de 174
}
FUNCIÓN PARA LEER LA TEMPERTAURA
unsigned short Leer_Temp(){
unsigned short dato;
IdleI2C();
// Pregunta si el bus está libre.
StartI2C();
// Pone la condición de inicio.
IdleI2C();
// Espera que termine.
WriteI2C(TC74A3);
// Direcciona el sensor
while(SSPCON2bits.ACKSTAT);
// Espera el ACK
IdleI2C();
// Espera por el bus libre.
WriteI2C(0x00);
// Escribe la dir 0 (registro de la temp)
while(SSPCON2bits.ACKSTAT);
// Espera el ACK
IdleI2C();
// Espera a que el bus esté libre
RestartI2C();
// Re-inicio del bus
IdleI2C();
// Espera que termine
WriteI2C(TC74A3+1);
// Envía órden de lectura en la dir. 0
while(SSPCON2bits.ACKSTAT); // Espera por ACK
dato = ReadI2C();
// Lee el registro y lo guarda en dato
IdleI2C();
// Espera que termine
NotAckI2C();
// No hay ACK
IdleI2C();
// Espera que termine
StopI2C();
// Condición de fin de transacción.
return dato;
// Retorna la temperatura
}
FUNCION PRINCIPAL DEL PROGRAMA
void main() {
char temperatura[] = "000";
OpenI2C(MASTER,SLEW_OFF);
SSPADD = 49;
// Modo Master
// 100KHz para 20MHz
lcd_init();
// Configura el LCD a valores por defecto.
lcd_gotoxy(1,2);
lcd_putrs("Grados:");
// Cartel inicial II.
check_sensor(TC74A3);
// Verifica la presencia del sensor en el BUS.
while(1) {
num = Leer_Temp();
// Lee la temperatura desde el sensor.
if (num > 127) {
// Verifica si la temperatura es negativa.
num = ~num +1;
// Ajusta la temperatura si es negativa
sprintf(temperatura,"-%d ",num); // Completa el string para el LCD
}
else{
sprintf(temperatura,"+%d ",num);
// Temperatura positiva.
}
lcd_gotoxy(8,2);
lcd_puts(temperatura);
// Muestra la temperatura.
delay(500);
}
}
Programación en XC8
Pagina 75 de 174
PCF8574.
Es un expansor de puertos compatible con la mayoría de
microcontroladores, permite una comunicación bidireccional, necesitando
solo dos líneas a través del bus I2C.
Características del módulo
• Tensión de alimentación de 2.5 a 6 V CC.
• Bajo consumo en standby (máximo 10 microamperios).
• Conversión de datos de I2C a paralelo y viceversa.
• Un Pin de interrupción de salida a drenador abierto (necesita resistencia pul-up).
• Un puerto cuasi-bidireccional de ocho bits (necesitan resistencias pul-up).
• Tres pines disponible para configurar por hardware la dirección del dispositivo.
• Disponible en encapsulados DIP y SMD.
Este módulo dispone de dos modelos (PCF8574 y PCF8574A) cuya única diferencia es su
dirección.
Los primeros cuatro bits vienen configurados de fábrica y los tres últimos son configurables por
hardware, por lo que podemos tener 8 módulos conectados al mismo bus I2C (y si combinamos
ambas versiones hasta 16).
Una trama de datos en una transmisión consta de:
•
•
•
•
Un bit de inicio de la comunicación.
Un byte formado por siete bits que identifican la dirección del esclavo + un bit para indicar
si se va hacer una lectura (R/W=1) o escritura (R/W=0) en el módulo.
Los datos en sí (de transmisión o recepción); el número de bytes de datos a transmitir o
recibir entre el comienzo de la comunicación y la condición de fin de transmisión (bit de
parada) no está limitada.
Un ACK de reconocimiento. A cada byte transmitido le sigue un bit de reconocimiento,
Programación en XC8
Pagina 76 de 174
•
cuando el esclavo recibe un byte este envía el ACK para indicarle al maestro que lo ha
recibido correctamente, cuando la petición del maestro al esclavo es de lectura este debe de
enviar un ACK al esclavo para indicarle que ha recibido el byte correctamente.
Un bit de parada. La condición de parada (P) ocurre cuando la línea SDA cambia de nivel
alto a bajo mientras la línea de reloj se encuentra a nivel alto y es controlada por el
dispositivo maestro (en nuestro caso el microcontrolador).
/*******************************************************************************
* File:
PCF8574.c
* Author: Firtec
* www.firtec.com.ar - [email protected]
* Created on 24 de mayo de 2014
******************************************************/
#include
#include
#include
#include
<xc.h>
<stdio.h>
<stdlib.h>
<plib/i2c.h>
#include "PCF8574.h"
#pragma config OSC=HS,PWRT=ON,MCLRE=OFF,LVP=OFF,WDT=OFF
#define _XTAL_FREQ 20000000
#define chip
0x40
// Valor de Chip para el PCF8574
FUNCIÓN PRINCIPAL DEL PROGRAMA
void main(void){
unsigned char byte =0;
PORTB=0;
TRISCbits.TRISC4=1;
TRISB = 0;
ADCON1=0x0F;
// No hay canales analógicos
OpenI2C(MASTER,SLEW_OFF);
// Master, 100KHz
SSPADD = 49;
(Fos/Fck*4)-1 donde Fos 20Mhz (20000Kc) y Fck 100Kz
(20000Kc/400kc)-1 = 49 para 20Mhz y Ck I2c 100K
BUCLE INFINITO
while(1){
byte = ByteReadI2C(chip);
// Lee el puerto del PCF8574
byte = ((byte >> 4) & 0x0f) | ((byte << 4) & 0xf0); // Swap nibles
__delay_us(3000);
ByteWriteI2C(chip,byte);
// Escribe el puerto del PCF8574
}
}
Este simple programa lee cuatro bits del puerto del PCF8574 intercambia los 4 bits de menor peso
con los de mayor peso y los envía nuevamente al puerto.
Programación en XC8
Pagina 77 de 174
Protocolo 1-wire.
Es un protocolo de comunicaciones en serie diseñado por Dallas. Está basado en un bus, un maestro
y varios esclavos en una sola línea de datos en la que también se alimentan. Por supuesto, necesita
una referencia a tierra común a todos los dispositivos.
El bus tiene un funcionamiento bastante particular, se mantiene la señal de datos a 0 voltios durante
480 microsegundos. Se reinician todos los dispositivos conectados al bus (les retira la
alimentación). Los dispositivos reiniciados indican su presencia manteniendo la señal de datos a 0
voltios durante 60 microsegundos. En la actualidad los microcontroladores PIC no tienen un puerto
nativo para este protocolo de comunicaciones.
Señales del Bus.
Programación en XC8
Pagina 78 de 174
Envío y recepción de datos por 1-Wire.
Para enviar un bit a 1 el maestro se lleva a 0 voltios la línea de datos durante 1-15 microsegundos.
Para enviar un bit a 0 el maestro se lleva a 0 voltios la línea de datos durante 60 microsegundos.
Los dispositivos esclavos leen el bit aproximadamente a los 30 microsegundos después del flanco
de bajada de cada bit.
Cuando el maestro lee los datos del dispositivo esclavo el pone 0 voltios durante 1-15
microsegundos en la línea de datos y a partir de ese momento el esclavo no hace nada (la señal pasa
a vale 5 voltios) si quiere mandar un 1 lógico o mantiene la señal en 0 voltios hasta los 60
microsegundos si quiere mandar un 0 lógico.
Los datos se envían o reciben en grupos de 8 bits.
Para iniciar una comunicación se reinicia el bus. El protocolo puede incluir detección de errores
transmitiendo códigos de detección de errores (CRC).
Como en el bus puede haber muchos dispositivos el protocolo incluye el direccionamiento de los
mismos empleando un código único de 64 bits de los cuales el byte más significativo indica el tipo
de dispositivo, y el último es un código de detección de errores (CRC) de 8 bits.
Los comandos que pueden interpretar los dispositivos esclavos dependerán de estos.
Para encontrar los dispositivos presentes en el bus el maestro puede enviar un comando de
enumeración que responderán todos los dispositivos.
Sensor de temperatura 1-wire DS18B20.
Veamos un ejemplo con un sensor de temperatura muy interesante que muestra el funcionamiento
de este protocolo de comunicaciones.
/* *****************************************************************************
** File Name
: DS1820.c
** Version
: 1.0
** Description : Dallas/Maxim Sensores Temp. DS1820, DS18S20 o DS18B20
**
conectado al pin 6 (RA4) (Sin Rom Code).
** Author
: www.firtec.com.ar
** Target
: 40PIN PIC18F4620
** Compiler
: Microchip XC8
** IDE
: Microchip MPLAB-X
** XTAL
: 20MHZ
** ****************************************************************************/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#pragma config OSC=HS,PWRT=ON,MCLRE=OFF,LVP=OFF,WDT=OFF
#define _XTAL_FREQ 20000000
#include "C:\ELECTRÓNICA\DS1820.X\lcd_xc8.c"
#include "C:\ELECTRÓNICA\DS1820.X\lcd_xc8.h"
#include "1wire.h"
FUNCIÓN PRINCIPAL
void main(void){
float Grados;
// Variable para contener el dato temperatura
char TempStr[5];
lcd_init();
lcd_gotoxy(2,1);
lcd_putrs("SENSOR DS18B20"); // Cartel inicial
lcd_gotoxy(1,2);
lcd_putrs("Temperatura:
");
Programación en XC8
Pagina 79 de 174
while(1){
Medir_Temperatura();
// Inicia la conversion
Grados = Leer_DS18B20();
// DS18B20 12 BITS
//Grados = Leer_DS18S20(); // DS1820 10 BITS
sprintf(TempStr,"%2.1f", Grados);
lcd_gotoxy(13,2);
// Coloca el cursor en posición
lcd_puts(TempStr);
}
}
Como se comentó anteriormente, estos microcontroladores no tienen puerto nativo para esta
comunicación por lo que es necesaria construirlo por software.
El archivo que contiene todo el saber de esta comunicación es 1wire.c donde encontramos
funciones para leer temperatura tanto con el DS18B20 o con el veterano DS1820 a 10 bits de
resolución.
El contenido del archivo 1wire.c contiene la librería para el manejo de este dispositivo en XC8.
///////////////////////////////////////////////////////////////////////
//// Driver para el manejo de las comunicaciones entre un pic y un ////
//// dispositivo Dallas/Maxim 1-wire
////
//// Los tiempos han sido calculados para un cristal de 20Mhz
////
//// El pin de datos se ha dispuesto por RA4
////
//// WEB: www.firtec.com.ar
////
//// mail: [email protected]
////
///////////////////////////////////////////////////////////////////////
// NOTA: No olvidar la resistencia de 4,7K entre el pin RA4 y Vdd.
///////////////////////////////////////////////////////////////////////
Programación en XC8
Pagina 80 de 174
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "1wire.h"
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 20000000
#endif
#define Pin_BAJO PORTAbits.RA4=0; TRISA = 0b00000000;
#define Pin_Entrada
TRISA = 0b00010001;
#define Pin_Lee
PORTAbits.RA4;
/***************************** Reset_1Wire *****************************/
/*Esta función inicializa el buz 1wire */
/*Argumentos: ninguno */
/*Retorna: 0 si todo OK */
/***********************************************************************/
int Reset_1wire(void)
{
int result=1;
Pin_BAJO
__delay_us(500);
Pin_Entrada;
__delay_us(60);
result = (int)Pin_Lee;
__delay_us(240);
return (result);
}
/*********************** Escribir_Bit() ******************************/
/* Esta función escribe un bit en el sensor. */
/* Argumentos: Un bit (El bit a escribir en el bus 1-wire) */
/* Retorna: nada */
/*********************************************************************/
void Escribir_Bit(int _bit)
{
if (_bit)
{
Pin_BAJO;
__delay_us(6);
Pin_Entrada;
__delay_us(60);
}
else
{
Pin_BAJO
__delay_us(60);
Pin_Entrada;
}
__delay_us(10);
}
/*********************** Leer_Bit() ******************************/
/* Esta función lee un bit desde el sensor. */
/* Argumentos: ninguno */
/* Retorna: El estado del bit en el pin DQ del sensor */
/***********************************************************************/
int Leer_Bit(void)
{
int result=0;
Pin_BAJO;
__delay_us(6);
Programación en XC8
Pagina 81 de 174
Pin_Entrada;
__delay_us(6);
result = (int)Pin_Lee;
__delay_us(60);
return (result);
}
/*********************** Escribir_Byte() ******************************/
/* Esta función escribe un byte en el sensor. */
/* Argumentos: byte (El byte a escribir en el bus 1-wire) */
/* Retorna: nada */
/***********************************************************************/
void Escribir_Byte(int data)
{
int loop;
for (loop = 0; loop < 8; loop++)
{
Escribir_Bit(data & 0x01);
data >>= 1;
}
}
/*********************** leer_Byte() **********************************/
/* Esta función lee 8 bit´s desde el sensor 1-wire.
*/
/* Argumentos: ninguno */
/* Retorna: 8 bit´s (1-byte) los datos desde el sensor */
/***********************************************************************/
int Leer_Byte(void)
{
int loop, result=0;
for (loop = 0; loop < 8; loop++)
{
result >>= 1;
if (Leer_Bit())
result |= 0x80;
}
return result;
}
/*********************** Medir_Temperatura() ***************************/
/* Esta función inicia la conversión para medir la temperatura. */
/* Argumentos: ninguno */
/* Retorna: nada */
/***********************************************************************/
void Medir_Temperatura(void)
{
Reset_1wire();
Escribir_Byte(0xCC);
Escribir_Byte(0x44);
while(Leer_Bit() == 0);
Reset_1wire();
}
/*********************** Leer_DS18S20() ***************************/
/* Esta función lee la temperatura de un sensor DS1820. */
/* Argumentos: ninguno */
/* Retorna: La temperatura con signo */
/******************************************************************/
float Leer_DS18S20(void)
{
unsigned char get[10];
Programación en XC8
Pagina 82 de 174
int k, temp;
float ftemp;
Escribir_Byte(0xCC);
Escribir_Byte(0xBE);
for (k=0; k<8; k++)
get[k]=Leer_Byte();
temp = get[0];
if (get[1] > 0x80)
temp = temp * -1;
ftemp = temp;
return (ftemp/2);
}
/*********************** Leer_DS18B20() ***************************/
/* Esta función lee la temperatura de un sensor DS18B20. */
/* Argumentos: ninguno */
/* Retorna: La temperatura con signo */
/******************************************************************/
float Leer_DS18B20(void)
{
unsigned char temp1, temp2;
int temp3;
float result;
Reset_1wire();
Escribir_Byte(0xCC);
Escribir_Byte(0x44);
Reset_1wire();
Escribir_Byte(0xCC);
Escribir_Byte(0xBE);
temp1 = Leer_Byte();
temp2 = Leer_Byte();
temp3 = (( int) (((( int )( temp2 )) << 8 ) + ((int )( temp1 )))) ;
result = (float) temp3 / 16.0;
return(result);
}
Programa en ejecución.
Programación en XC8
Pagina 83 de 174
En ocasiones puede ser necesario necesitar leer el código ROM de los sensores.
En el ejemplo siguiente vemos la forma de leer este código y mostrarlo en un LCD. Este número de
64 bits puede sernos útil para realizar una red de sensores e interrogarlos por su número ROM.
Podríamos tener varios sensores y tratarlos por su número de “RED”. A continuación el ejemplo
para leer el número de serie de casa sensor.
/* *****************************************************************************
** File Name
: RomCode.c
** Author
: www.firtec.com.ar
** Target
: 40PIN PIC18F4620
** Compiler
: Microchip XC8
** IDE
: Microchip MPLAB-X
** XTAL
: 20MHZ
** *****************************************************/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <plib/usart.h>
#include "1wire.h"
#include "RomCode.h"
#pragma config OSC=HS,PWRT=ON,MCLRE=OFF,LVP=OFF,WDT=OFF
#define _XTAL_FREQ 20000000
#include "C:\ELECTRÓNICA\Programas PIC\DS1820_ROM.X\lcd_xc8.c"
#include "C:\ELECTRÓNICA\Programas PIC\DS1820_ROM.X\lcd_xc8.h"
unsigned char ROM_DATA [8]; // Array donde se guardará el codigo ROM
unsigned char puntero_array = 0;
void main (void)
{
unsigned char b;
// Variable de uso multiple
char a[2];
lcd_init();
// Inicializa el LCD
lcd_gotoxy(1,1);
lcd_putrs("CODIGO ROM 64bit"); // Cartel inicial
while(OWReset()){
Programación en XC8
// Si no es cero SENSOR ERROR
Pagina 84 de 174
lcd_gotoxy(1,2);
lcd_putrs(" SENSOR ERROR!!");
}
lcd_gotoxy(1,2);
lcd_putrs("
"); // Limpia pantalla
LEER_ROM();
// Se leen los 64 bit's del sensor
lcd_gotoxy(1,2);
for(puntero_array=0;puntero_array<8;puntero_array++){
sprintf(a,"%02X",ROM_DATA[puntero_array]);
lcd_puts(a);
}
while(1);
}
Programa en ejecución.
Trabajo practico
En base a lo aprendido escriba un programa que envíe por el puerto USART la
temperatura de un sensor DS18B20 y visualizar los datos en una la computadora.
Programación en XC8
Pagina 85 de 174