Está en la página 1de 16

CONTADOR 3 PULSOS.

TIMER0 COMO CONTADOR


#include <pic.h>

// ***************************************************
// Palabra de configuracin (verin compilador < 9.80)
// ***************************************************
#ifdef _16F84A
// FOSC : EXTRCCLK, EXTRCIO, INTOSCCLK, INTOSCIO, EC, HS, XT, LP
// PWRTE : Reset al conectar (PoWeR-up Timer Enable bit):
// WDTE : Perro Guardin (Watchdog Timer Enable bit):
// CP
: Proteccin lectura del cdigo (Code Protection bit)
#pragma config FOSC=XT, PWRTE=OFF, WDTE=OFF, CP=OFF
// Compatibilidad con ciertos bits que cambian de nombre en el 16F88
#define TMR0IF T0IF
#define TMR0IE T0IE
#define INT0IF INTF
#else
// FOSC : EXTRCCLK, EXTRCIO, INTOSCCLK, INTOSCIO, EC, HS, XT, LP
// WDTE : Perro Guardin (Watchdog Timer Enable bit):
// PWRTE : Reset al conectar (PoWeR-up Timer Enable bit):
// CP
: Proteccin lectura del cdigo (Code Protection bit):
// MCLRE : Pin de Reset (Master CLeaR Enable bit):
// BOREN : Corte parcial de alimentacin (BrOwn-out Reset ENable bit):
// LVP
: Programacin con baja tensin (Low-Voltage Programming Enable bit):
// CPD
: Proteccin lectura de la EEPROM (Code Protection Data enable bit):
// WRT
: Proteccin escritura de la EEPROM (WRiTe enable bit):
// DEBUG : Pines para depuracin (In-circuit DEBUGger mode bit
// CCPMX : Pin para el mdulo captura/comparacin/PWM (CCP1 Pin)
// FCMEN : Monitor del reloj (Fail-safe Clock Monitor ENable bit):
// IESO : Arranque con reloj interno y conmutacin al externo (Internal External
SwitchOver bit)
#pragma config FOSC=XT, WDTE=OFF, PWRTE=OFF, CP=OFF, MCLRE=OFF, BOREN=OFF,
LVP=OFF, \
CPD=OFF, WRT=OFF, DEBUG=OFF, CCPMX=RB3, FCMEN=OFF, IESO=OFF

#endif
// *******************************************
// Constantes y definiciones
// *******************************************
#define TMR0_carga -3
// Si quieren contar 3 flancos
#define int8 char
// -128 <= n <= 127
#define uint8 unsigned char // 0 <= n <= 255

#define int16 int


// -32768 <= n <= 32767
#define uint16 unsigned int
// 0 <= n <= 65535
#define nop() asm("nop");
#define false 0
#define true !false
// *******************************************
// Declaracin de rutinas (excepto el main()
// *******************************************
void iniciaRegistros(void);
// *******************************************
// Variables globales
// *******************************************
uint8 cuenta10;
// Nmero que se muestra en el display
uint8 cuenta16;
// Nmero de interrupciones para tener 1 segundo
// *******************************************
// Mdulo principal (bucle infinito)
// *******************************************
void main(void)
{
//-----------------iniciaRegistros();
//-----------------while (true) // bucle infinito
{
nop();
// Deja pasar un ciclo de mquina
}
}
// *******************************************
// Rutinas
// *******************************************
void iniciaRegistros(void){
#ifdef _16F88
ANSEL= 0b000000000; // Los pines mixtos analgico-digitales sern digitales
#endif
cuenta10=0;
cuenta16=16;

// Valor mostrado en el display


// Interrupciones necesarias de T0 para conseguir 1 segundo

TRISA = 0b11111111; // Puerto A de entrada. Solo interesa RA4


TRISB = 0b11110000; // RB0-RB3 de salida para el display
PORTB = 0;
// Inicialmente el display muestra el 0
// Configuracin TMR0
OPTION_REG = 0b10101000;
// 76543210
// ||||||||
// ||||||| - bit0 PS0
// |||||| -- bit1 PS1

// ||||| --- bit2 PS2 [PS2:PS0] no importa lo que valgan. Se ponen a 0


// |||| ---- bit3 PSA El preescaler no se utiliza para el TMR0
// ||| ----- bit4 T0SE El flanco activo de RA4 ser el de subida
// || ------ bit5 T0CS Utiliza RA4 para incrementar TMR0
// | ------- bit6 INTEDG
// --------- bit7 RBPU No Activa los pullups internos de PORTB
TMR0 = TMR0_carga; // Preparamos TMR0= 253. TMR0 no tiene signo y se le mete
// el contenido de TMR0_carga que es -3 -> 253 (sin signo)
TMR0IF = 0;
TMR0IE = 1;
GIE = 1;

// Habilita interrupcion T0I


(Registro INTCON)
// Mscara global de interrupcin activa
(Registro INTCON)

}
// *******************************************
// Interrupcin
// *******************************************
static void interrupt rutinaInterrupcion(void)
{
// Interrupcin debida al desbordamiento de TMR0
if(TMR0IF)
{
if (++cuenta10==10) // cuenta10=cuenta10+1; si (cuenta10 == 10) entonces ...
{
cuenta10=0;
}
PORTB= cuenta10;

// Muestra el valor de cuenta10 en el display conectado a PORTB

TMR0 = TMR0_carga;
// Preparamos TMR0= 253
TMR0IF = 0;
// Bajamos la bandera. Evento: desbordamiento de TMR0
}
else
{
// No debera ocurrir este caso.
RBIF =0;
INT0IF=0;
EEIF =0;
}
}

ROTACIN DISPLAYS CON TIMER0 PERIDICO


#include <pic.h>
// *******************************************
// Libreras (cabeceras)
// *******************************************
#include "DISPLAYS.h"
// *******************************************
// Palabra de configuracin
// *******************************************
#ifdef _16F84A
// FOSC : EXTRCCLK, EXTRCIO, INTOSCCLK, INTOSCIO, EC, HS, XT, LP
// PWRTE : Reset al conectar (PoWeR-up Timer Enable bit):
// WDTE : Perro Guardin (Watchdog Timer Enable bit):
// CP
: Proteccin lectura del cdigo (Code Protection bit)
#pragma config FOSC=XT, PWRTE=OFF, WDTE=OFF, CP=OFF

#define T0IF TMR0IF


#define T0IE TMR0IE
#define INTF INT0IF
#else
// FOSC : EXTRCCLK, EXTRCIO, INTOSCCLK, INTOSCIO, EC, HS, XT, LP
// WDTE : Perro Guardin (Watchdog Timer Enable bit):
// PWRTE : Reset al conectar (PoWeR-up Timer Enable bit):
// CP
: Proteccin lectura del cdigo (Code Protection bit):
// MCLRE : Pin de Reset (Master CLeaR Enable bit):
// BOREN : Corte parcial de alimentacin (BrOwn-out Reset ENable bit):
// LVP
: Programacin con baja tensin (Low-Voltage Programming Enable bit):
// CPD
: Proteccin lectura de la EEPROM (Code Protection Data enable bit):
// WRT
: Proteccin escritura de la EEPROM (WRiTe enable bit):
// DEBUG : Pines para depuracin (In-circuit DEBUGger mode bit
// CCPMX : Pin para el mdulo captura/comparacin/PWM (CCP1 Pin)
// FCMEN : Monitor del reloj (Fail-safe Clock Monitor ENable bit):
// IESO : Arranque con reloj interno y conmutacin al externo (Internal External
SwitchOver bit)
#pragma config FOSC=INTOSCIO, WDTE=OFF, PWRTE=OFF, CP=OFF, MCLRE=OFF,
BOREN=OFF, LVP=OFF, \
CPD=OFF,
WRT=OFF, DEBUG=OFF, CCPMX=RB3, FCMEN=OFF, IESO=OFF
#endif
// *******************************************
// Constantes y definiciones
// *******************************************
#define byte unsigned char

// *******************************************
// Variables globales
// *******************************************
byte TMR0_carga;
// *******************************************
// Declaracin de rutinas (excepto el main()
// *******************************************
void iniciaRegistros(void);
// *******************************************
// Mdulo principal (bucle infinito)
// *******************************************
void main(void)
{
//-----------------iniciaRegistros();
//-----------------for(;;)
// bucle infinito que no hace nada
{
// --------------------------------------------------------------// Configuracin TMR0
// --------------------------------------------------------------// Si Tosc=1us (Fosc=1Mhz), TMR0_carga, y Preescalador ->
// Tiempo= 4*1us*(256-TMR0) * Preescalador
// --------------------------------------------------------------if (RA0==1) {
// Periodo rotacin= 100ms
TMR0_carga=61;
// T= 4us*(256-61)*128= 99840us= 100ms
PS2=1; PS1=1; PS0=0; // Preescalador 1:128, [PS2,PS1,PS0]=110
TMR0IE=1;
// -------------------------------------}
else if (RA1==1) {
// Periodo rotacin= 50ms
TMR0_carga=61;
// T= 4us*(256-61)*64= 49920us= 50ms
PS2=1; PS1=0; PS0=1; // Preescalador 1:64, [PS2,PS1,PS0]=101
TMR0IE=1;
// -------------------------------------}
else if (RA2==1) {
// Periodo rotacin= 25ms
TMR0_carga=61;
// T= 4us*(256-61)*32= 24960us= 25ms
PS2=1; PS1=0; PS0=0; // Preescalador 1:32, [PS2,PS1,PS0]=100
TMR0IE=1;
// -------------------------------------}
else if (RA3==1) {
// Periodo rotacin= 8ms
TMR0_carga=6;
// T= 4us*(256-6)*8= 8000us= 8ms
PS2=0; PS1=1; PS0=0; // Preescalador 1:8, [PS2,PS1,PS0]=010
TMR0IE=1;
// -------------------------------------}
else if (RA4==1) {
// Periodo rotacin= 4ms
TMR0_carga=6;
// T= 4us*(256-6)*4= 4000us= 4ms
PS2=0; PS1=0; PS0=1; // Preescalador 1:4, [PS2,PS1,PS0]=001
TMR0IE=1;
// -------------------------------------}

else {
PORTB =0;
TMR0IE=0;
}

// Apaga los displays


// Bloquea la interrupcin peridica del timer 0

}
}
// *******************************************
// Rutinas
// *******************************************
void iniciaRegistros(void)
{
#ifdef _16F88
ANSEL= 0b000000000; // Los pines mixtos analgico-digitales sern digitales

// -----------------------------------------------// Configuracin del cristal interno a 4 Mhz


// -----------------------------------------------OSCCON= 0b01000110; // Configura a 4 Mhz
+-------------+--------+
// 76543210
| IRCF2:IRCF0 | Frec |
// ||| |||
+-------------+--------+
// ||| ||+- OSCCON<0> : SCS0=0 // [SCS1:SCS0]= reloj interno | 000 | 31Khz |
// ||| |+-- OSCCON<1> : SCS1=1 //
| 001 | 125Khz |
// ||| +--- OSCCON<2> : IOFS // Se pone a 1 cuando el
| 010 | 250Khz |
// |||
// reloj se ha estabilizado | 011 | 500Khz |
// ||+----- OSCCON<4> : IRCF0=0
+->| 100 | 1Mhz |
// |+------ OSCCON<5> : IRCF1=1
| | 101 | 2Mhz |
// +------- OSCCON<6> : IRCF2=1 // [IRCF2:IRCF0]=100--> 1Mhz -+ | 110 | 4Mhz
|
//
| 111 | 8Mhz |
while (IOFS==0) { } // Mientras no se estabilice el
+-------------+--------+
// reloj interno -> esperar aqu.
// -----------------------------------------------#endif
//----------------------------------------------------------// Control: <RB3:RB0>, Datos: <RB7:RB5>
DISPLAYS_ini((DAT_EN_PORTB+DAT_4PINES_ALTOS) +
(CTRL_EN_PORTB+CTRL_4PINES_BAJOS));
//----------------------------------------------------------DISPLAYS_anadirDigito(1); // Unidades de millar
DISPLAYS_anadirDigito(9); // Centenas
DISPLAYS_anadirDigito(9); // Decenas
DISPLAYS_anadirDigito(4); // Unidades
-- 6759
//----------------------------------------------------------PSA=0;
T0CS=0;

// PSA= '0'. El Divisor de frecuencia se asigna al TMR0


// T0CS='0'. Utiliza Fosc/4 para temporizar

TMR0_carga= 0;
TMR0IE = 0;
// Habilita interrupcion TMR0I
GIE
= 1;
// Mscara global de interrupcin activa

(Registro INTCON)
(Registro INTCON)

}
// *******************************************
// Interrupcin
// *******************************************
static void interrupt rutinaInterrupcion(void)
{
// ------------------------------------------------------------------// Temporizacin cada 8ms (Fosc=4Mhz)
//
// Tiempo= 4.Tosc.(256-TMR0_carga).Preescalador -- Tosc=0.25us (Fosc=4Mhz)
// ------------------------------------------------------------------// Interrupcin debida al desbordamiento de TMR0
if(TMR0IF)
{
TMR0 = TMR0_carga; // Preparamos TMR0=6 (TMR0_carga=6)
TMR0IF = 0;
// Bajamos la bandera que origin la interrupcin (flanco bajada en
TMR0IF)
//--------------DISPLAYS_rotar();
//--------------}
else
{
GIE=0; // bloquea todas las interrupciones si ocurre una no programada
}
}

// *******************************************
// Libreras (cdigo C)
// *******************************************
#include "DISPLAYS.c"

PWM POR SOFTWARE (TIMER0)

#include <pic.h>
// ***************************************************
// Palabra de configuracin
// ***************************************************
#ifdef _16F84A
#pragma config FOSC=XT, PWRTE=OFF, WDTE=OFF, CP=OFF
// Compatibilidad con ciertos bits que cambian de nombre en el 16F88
#define TMR0IF T0IF
#define TMR0IE T0IE
#define INT0IE INTE
#else
#pragma config FOSC=INTOSCIO, WDTE=OFF, PWRTE=OFF, CP=OFF, MCLRE=ON,
BOREN=OFF, LVP=OFF, \
CPD=OFF,
WRT=OFF, DEBUG=OFF, CCPMX=RB3, FCMEN=OFF, IESO=OFF
#endif
// *******************************************
// Constantes y definiciones
// *******************************************
#define nop() asm("nop");
#define false 0
#define true !false
// *******************************************
// Definicin de tipos
// *******************************************
typedef
char
int8;
// -128 <= n <= 127
typedef unsigned char
uint8;
// 0 <= n <= 255

typedef
int
int16;
// -32768 <= n <= 32767 -- short?
typedef unsigned int
uint16;
// 0 <= n <= 65535
// *******************************************
// Libreras (cabeceras)
// *******************************************
#include "REBOTES.h"
// *******************************************
// Declaracin de rutinas (excepto el main()
// *******************************************
void iniciaRegistros(void);
// *******************************************
// Variables globales
// *******************************************
uint8 cuentaPWM;
// Cuenta de 0 a 9 en cada interrupcin a 10khz
uint8 Ton[4]= {2, 4, 6, 8}; // Valores iniciales de los motores: 20%, 40%, 60%, 80%
uint16 lectura;
// Para leer con control de rebotes
// *******************************************
// Mdulo principal (bucle infinito)
// *******************************************
void main(void)
{
uint8 motor, potencia;
//-----------------iniciaRegistros();
//-----------------while (true)
// bucle infinito
{
// Se lee con control de rebotes el pin 4 del puerto A (RA4)
lectura= REBOTES_leerPuertoA( 0b00010000);
if (lectura!=REBOTES_ERROR)
{
// Si est a 0 el pin RA4
if ((lectura & 0b00010000)==0)
{
motor = PORTB & 0b00000011;
// El puerto B se desplazar 4 posiciones a la derecha
potencia= (PORTB >> 4) & 0b00001111;
// Se actualiza la potencia para que se tenga en cuenta en la interrupcin
Ton[ motor ] = potencia;
}
}
}
}
// *******************************************
// Rutinas

// *******************************************
void iniciaRegistros(void)
{
#ifdef _16F88
ANSEL= 0b000000000; // Los pines mixtos analgico-digitales sern digitales
// -----------------------------------------------// Configuracin del cristal interno a 4 Mhz
// -----------------------------------------------OSCCON= 0b01100110; // Configura a 4 Mhz
+-------------+--------+
// 76543210
| IRCF2:IRCF0 | Frec |
// ||| |||
+-------------+--------+
// ||| ||+- OSCCON<0> : SCS0=0 // [SCS1:SCS0]= reloj interno | 000 | 31Khz |
// ||| |+-- OSCCON<1> : SCS1=1 //
| 001 | 125Khz |
// ||| +--- OSCCON<2> : IOFS // Se pone a 1 cuando el
| 010 | 250Khz |
// |||
// reloj se ha estabilizado | 011 | 500Khz |
// ||+----- OSCCON<4> : IRCF0=0
| 100 | 1Mhz |
// |+------ OSCCON<5> : IRCF1=1
| 101 | 2Mhz |
// +------- OSCCON<6> : IRCF2=1 // [IRCF2:IRCF0]=110 --> 4Mhz -->| 110 | 4Mhz
|
//
| 111 | 8Mhz |
while (IOFS==0) { } // Mientras no se estabilice el
+-------------+--------+
// reloj interno -> esperar aqu.
// -----------------------------------------------#endif

PORTA = 0;
TRISA= 0b00010000;
TRISB= 0b11111111;

// PORTA de salida (tiene 5 pines)


//

// * ************************************************************************
*
// * Configuracin Timer 0: temporizacin a 1ms (Fosc=4Mhz)
// *
// * Tiempo= 4.Tosc.(256-TMR0).Preescalador
// * Si Tosc=0.25us (Fosc=4Mhz), TMR0=206 y Preescalador= 1:2 ([PS2:PS0]=000)->
// * Tiempo= 4.(0.25us).(256-206).2= 0.1ms (10khz)
// * ************************************************************************
*
OPTION_REG = 0b00000000;
// 76543210
// ||||||||
// |||||||+- bit0 PS0 1:2 Predivisor
// ||||||+-- bit1 PS1
// |||||+--- bit2 PS2
// ||||+---- bit3 PSA El Divisor de frecuencia se asigna al TMR0
// |||+----- bit4 T0SE
// ||+------ bit5 T0CS Utiliza Fosc/4 para temporizar
// |+------- bit6 INTEDG
// +-------- bit7 nRBPU Activa los pullups internos de PORTB

10

TMR0IF = 0;
TMR0IE = 1; // Habilita interrupcion T0I
(Registro INTCON)
GIE = 1; // Mscara global de interrupcin activa
(Registro INTCON)
}
// *******************************************
// Interrupcin
// *******************************************
static void interrupt rutinaInterrupcion(void)
{
// Interrupcin debida al desbordamiento de TMR0
if(TMR0IF)
{
TMR0IF = 0;
// Bajamos la bandera. Evento: desbordamiento de TMR0
TMR0 = 206 + 11;
// Preparamos TMR0 con 206 pero hay que sumar 11 para
// ajustar el PUSH y PULL que hace el compilador sin
// que nos demos cuenta.
if (++cuentaPWM == 10)
{
cuentaPWM= 0;
PORTA=0b00001111; // Los 4 motores en marcha. Comienza el Ton
}
else
{
if (Ton[0]==cuentaPWM) { RA0=0; }
if (Ton[1]==cuentaPWM) { RA1=0; }
if (Ton[2]==cuentaPWM) { RA2=0; }
if (Ton[3]==cuentaPWM) { RA3=0; }
}
return;
}
// Este caso no debera ocurrir nunca
RBIF=0;
INTF=0;
EEIF=0;
}

// *******************************************
// Libreras (cdigo C)
// *******************************************
#include "REBOTES.c"

11

I2C AMPLIACIN DE ENTRADAS/SALIDAS CON PFC8574

#include <pic.h>
#define _XTAL_FREQ 4000000
// Reloj a 4Mhz. Definir antes de las cabeceras
// *******************************************
// Cabeceras
// *******************************************
#include "I2C.h"
// Prametros del compilador "%1 --CHIP=16F84A" y OBJ=COF
// *******************************************
// Palabra de configuracin
// *******************************************
#ifdef _16F84A
// FOSC : EXTRCCLK, EXTRCIO, INTOSCCLK, INTOSCIO, EC, HS, XT, LP
// PWRTE : Reset al conectar (PoWeR-up Timer Enable bit):
// WDTE : Perro Guardin (Watchdog Timer Enable bit):
// CP
: Proteccin lectura del cdigo (Code Protection bit)
#pragma config FOSC=XT, PWRTE=OFF, WDTE=OFF, CP=OFF
#else
// FOSC : EXTRCCLK, EXTRCIO, INTOSCCLK, INTOSCIO, EC, HS, XT, LP
// WDTE : Perro Guardin (Watchdog Timer Enable bit):
// PWRTE : Reset al conectar (PoWeR-up Timer Enable bit):
// CP
: Proteccin lectura del cdigo (Code Protection bit):
// MCLRE : Pin de Reset (Master CLeaR Enable bit):
// BOREN : Corte parcial de alimentacin (BrOwn-out Reset ENable bit):
// LVP
: Programacin con baja tensin (Low-Voltage Programming Enable bit):
// CPD
: Proteccin lectura de la EEPROM (Code Protection Data enable bit):
// WRT
: Proteccin escritura de la EEPROM (WRiTe enable bit):
// DEBUG : Pines para depuracin (In-circuit DEBUGger mode bit
// CCPMX : Pin para el mdulo captura/comparacin/PWM (CCP1 Pin)
// FCMEN : Monitor del reloj (Fail-safe Clock Monitor ENable bit):

12

// IESO : Arranque con reloj interno y conmutacin al externo (Internal External


SwitchOver bit)
#pragma config FOSC=INTOSCIO, WDTE=OFF, PWRTE=OFF, CP=OFF, MCLRE=OFF,
BOREN=OFF, LVP=OFF, \
CPD=OFF,
WRT=OFF, DEBUG=OFF, CCPMX=RB3, FCMEN=OFF, IESO=OFF
#endif
// *******************************************
// Constantes
// *******************************************
#define PCF8574_DireccionLectura 0b01000001
#define PCF8574_DireccionEscritura 0b01000010
// *******************************************
// Declaracin de rutinas (excepto el main()
// *******************************************
void iniciaRegistros(void);
byte PCF8574_Lee(void);
void PCF8574_Escribe(byte dato);
void leeEscribe(void);
// *******************************************
// Mdulo principal (bucle infinito)
// *******************************************
void main(void)
{
//-----------------iniciaRegistros();
//------------------

// bucle infinito. En cada iteracin se ejecuta un estado


while (1)
{
}
}
// *******************************************
// Rutinas
// *******************************************
// ==================================
// iniciaRegistros
// ==================================
void iniciaRegistros(void)
{
#ifdef _16F88
ANSEL= 0b000000000; // Los pines mixtos analgico-digitales sern digitales

// -----------------------------------------------// Configuracin del cristal interno a 4 Mhz

13

// -----------------------------------------------OSCCON= 0b01100110; // Configura a 4 Mhz


+-------------+--------+
// 76543210
| IRCF2:IRCF0 | Frec |
// ||| |||
+-------------+--------+
// ||| ||+- OSCCON<0> : SCS0=0 // [SCS1:SCS0]= reloj interno | 000 | 31Khz |
// ||| |+-- OSCCON<1> : SCS1=1 //
| 001 | 125Khz |
// ||| +--- OSCCON<2> : IOFS // Se pone a 1 cuando el
| 010 | 250Khz |
// |||
// reloj se ha estabilizado | 011 | 500Khz |
// ||+----- OSCCON<4> : IRCF0=0
| 100 | 1Mhz |
// |+------ OSCCON<5> : IRCF1=1
| 101 | 2Mhz |
// +------- OSCCON<6> : IRCF2=1 // [IRCF2:IRCF0]=110 --> 4Mhz -->| 110 | 4Mhz
|
//
| 111 | 8Mhz |
while (IOFS==0) { } // Mientras no se estabilice el
+-------------+--------+
// reloj interno -> esperar aqu.
// -----------------------------------------------#endif
byte dato;
TRISA = 0b11111111;
TRISB = 0b11111111;
INTEDG= 0;
OPTION_REG)

// Puerto A de entrada
// Puerto B de entrada
// Interrupcin INT activa por flanco de bajada (Registro

//---------------------------------------------------------// SCL: RB4 -> PORTB + BIT4


// SDA: RB1 -> PORTB + BIT1
//---------------------------------------------------------I2C_iniMaestro(SCL_EN_PORTB + SDA_EN_PORTB, SCL_PIN_4, SDA_PIN_1);
//----------------------------------------------------------

INTE = 1;
GIE = 1;

// Habilita interrupcin INT por pin RB0


// Mscara global de interrupcin activa

(Registro INTCON)
(Registro INTCON)

// Primer refresco de los dispositivos I2C:


//
// Las rutinas PCF8574_Lee() y PCF8574_Escribe(dato) se llaman desde la rutina de
interrupcin.
// "Tambin" se llaman desde aqu por lo que podra haber un efecto colateral -> Mientras
se ejecuta
// una de ellas desde aqu pudiera ocurrir que la interrupcin entre. Esta interrupcin la
// vuelve a llamar. Por tanto si mientras se estaba ejecutando la rutina le asigna un valor a
// una variable local (al no haber pila la variable se almacena en la memoria como si fuera
global)
// y ocurre la interrupcin (que la vuelve a llamar y le asigna otro valor a esa misma variable
// local entonces puede ocurrir que al terminar la interrupcin el programa retorna a la
rutina inicial y
// se encuentra que esa variable no tiene el valor que dicha rutina le haba asignado antes de
la interrupcin.
// La versin xc8 del compilador resuelven este problema ya que se dan cuenta y duplican

14

// internamente el cdigo de la rutina (como si fueran dos rutinas con distinto nombre;
duplicando las
// variables locales que internamente se almacenan en memoria como globales).
leeEscribe();
}
// ==================================
// PCF8574_Lee
// ==================================
byte PCF8574_Lee(void)
{
byte dato;
I2C_start();
// Enva la condicin de Start.
I2C_enviaByte(PCF8574_DireccionLectura);
// Apunta al expansor de lectura.
I2C_MASTER_PARAR=1;
byte
dato= I2C_recibeByte();
I2C_stop();

// Activa esta bandera antes de recibir el siguiente

// Lee el puerto.
// Acaba de leer.

return dato;
}
// ==================================
// PCF8574_Escribe
// ==================================
void PCF8574_Escribe(byte dato)
{
I2C_start();
// Enva la condicin de Start.
I2C_enviaByte(PCF8574_DireccionEscritura); // Apunta al expansor de escritura.
I2C_enviaByte(dato);
// Escribe el puerto.
I2C_stop();
// Acaba de escribir.
}
// ==================================
// leeEscribe(void)
// ==================================
void leeEscribe(void)
{
byte dato;
// Interrupcin debida a flanco activo en INTF
dato= PCF8574_Lee();
// lee la entrada.
dato= dato ^ 0b11111111;
// Complementa el dato ledo porque los diodos (XOR)
// se activan con nivel bajo, (ver esquema).
PCF8574_Escribe(dato);
// Lo visualiza en los diodos LEDs.
}

15

// *******************************************
// Interrupcin
// *******************************************
static void interrupt rutinaInterrupcion(void)
{
if(INTF)
{
INTF = 0; // Bajamos la bandera que origin la interrupcin (flanco bajada en RB0)
leeEscribe();
}
}
#include "I2C.c"

16

También podría gustarte