#include "main_877.h"
#include "comunicacion_877.h"
//------------------------------------------------------------------------------
//#### inicializacion del pic ##################################################
//------------------------------------------------------------------------------
void inicializar_valores(void)
{
contador_interrupciones_timer1 = 0;
}
void activar_interrupciones_PORTB_TIMER(void)
{
INTCONbits.RBIF = 1;
INTCONbits.INTF = 1;
/**** INTERRUPCIONES ****/
INTCONbits.PEIE = 1; // Enables all unmasked peripheral interrupts
INTCONbits.RBIE = 1; // Enables the RB port change interrupt
// PORTB pull-ups are enabled by individual port latch values
OPTION_REGbits.nRBPU = 1;
// Interrupt on rising (creciente) edge of RB0/INT pin
OPTION_REGbits.INTEDG = 1;
INTCONbits.RBIF = 0;
INTCONbits.INTF = 0;
INTCONbits.GIE = 1; // Enables all unmasked interrupts
T1CONbits.TMR1ON = 1; // Timer1 On bit
}
//------------------------------------------------------------------------------
void configurar_pic(void)
{
/*****************************
******** T I M E R 1 ********
*****************************/
T1CONbits.TMR1CS = 0; // Timer1 Clock Source - 0 Internal clock (FOSC/4)
T1CONbits.T1CKPS1 = 1; // prescaler
T1CONbits.T1CKPS0 = 1; // 1:8
TMR1H = VALOR_TMR1H; // 3036
TMR1L = VALOR_TMR1L; // 500 ms
T1CONbits.TMR1ON = 0; // Timer1 On bit
PIE1bits.TMR1IE = 1; // TMR1 Overflow Interrupt Enable bit
/*********************
*** P U E R T O S ***
*********************/
/**** PORTD I/O ****/
TRISEbits.PSPMODE = 0; // PORTD functions in general purpose I/O mode
/**** PORTE I/O ****/
TRISEbits.TRISE2 = 0; // Output
TRISEbits.TRISE1 = 0; // Output
TRISEbits.TRISE0 = 0; // Output
/**** PORTA / PORTE I/O ****/
ADCON1bits.PCFG3 = 0; // RA5:RA0 y RE2:RE0 Digital
ADCON1bits.PCFG2 = 1; // RA5:RA0 y RE2:RE0 Digital
ADCON1bits.PCFG1 = 1; // RA5:RA0 y RE2:RE0 Digital
ADCON1bits.PCFG0 = 1; // RA5:RA0 y RE2:RE0 Digital
/*
* RA0 Clock salida
* RA1 Data salida
* RA2 Listo para escucha ( 1 ) entrada
*/
TRISA = 0b00100100;
TRISB = 0b11110010;
TRISC = 0b00000000; // Salida
TRISD = 0b00000000; // Salida
TRISE = 0b00000000; // Salida
}
//------------------------------------------------------------------------------
/*
* M A I N
*/
int main(void)
{
configurar_pic();
activar_interrupciones_PORTB_TIMER();
PORTA = 0b00000000;
PORTB = 0b00000000;
PORTC = 0b00000000;
PORTD = 0b00000000;
PORTE = 0b00000000;
t_byte comando;
t_int dato;
comando.variable = 23;
dato.variable = 54;
enviar_datos( comando, dato );
while ( true ) ;
}
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <pic16f877a.h>
#include <stdbool.h>
#include "interrupciones_877.h"
//------------------------------------------------------------------------------
//######## configuracion del pic ###############################################
//------------------------------------------------------------------------------
#define _XTAL_FREQ 4000000 // Velocidad clock en Hz
#pragma config FOSC = XT // Oscillator Selection bits
// (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit
// (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit
// (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit
// (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply)
// In-Circuit Serial Programming
// Enable bit
// (RB3 is digital I/O, HV on MCLR
// must be usedfor programming)
#pragma config CPD = OFF // Data EEPROM Memory Code
// Protection bit
// (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write
// Enable bits
// (Write protection off;
// all program memory may be written
// to by EECON control)
#pragma config CP = ON // Flash Program Memory
// Code Protection bit
// (Code protection off)
//------------------------------------------------------------------------------
//######## configuracion del TIMER1 ############################################
//------------------------------------------------------------------------------
/**** Reloj a 4 MHz ****/
#define VALOR_TMR1H 0b01011101 // 23869
#define VALOR_TMR1L 0b00111101 // 500 ms
#define NRO_INT_TIMER1_X_SEG 2 // 500 ms * 2 = 1 seg
//------------------------------------------------------------------------------
//######## macros generales ######################
//------------------------------------------------------------------------------
#define testbit(var, bitnro) ((var) & (1 <<(bitnro)))
#define bitset(var, bitnro) ((var) |= 1UL << (bitnro))
#define bitclr(var, bitnro) ((var) &= ~(1UL << (bitnro)))
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
//------------------------------------------------------------------------------
//######## variables globales ######################
//------------------------------------------------------------------------------
near int contador_interrupciones_timer1;
//------------------------------------------------------------------------------
//######## puertos ############################
//------------------------------------------------------------------------------
#define COMU_CLOCK PORTAbits.RA0
#define COMU_DATA PORTAbits.RA1
#define COMU_ESCUCHA PORTAbits.RA2
void enviar_datos( t_byte comando, t_int dato )
{
if ( COMU_ESCUCHA )
{
COMU_DATA = comando.d0;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = comando.d1;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = comando.d2;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = comando.d3;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = comando.d4;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = comando.d5;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = comando.d6;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = comando.d7;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d0;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d1;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d2;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d3;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d4;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d5;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d6;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d7;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d8;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d9;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d10;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d11;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d12;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d13;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d14;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_DATA = dato.d15;
COMU_CLOCK = 1; __delay_ms( RETARDO_ENVIO_DATOS_MS );
COMU_CLOCK = 0; PORTAbits.RA3 = 1;
}
}
#define RETARDO_ENVIO_DATOS_MS 10
//------------------------------------------------------------------------------
typedef union {
unsigned char variable;
struct {
unsigned d7:1, d6:1, d5:1, d4:1, d3:1, d2:1, d1:1, d0:1;
//unsigned b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
};
} t_byte;
typedef union {
unsigned int variable;
struct {
unsigned d15:1, d14:1, d13:1, d12:1, d11:1, d10:1, d9:1, d8:1, d7:1, d6:1, d5:1, d4:1, d3:1, d2:1, d1:1, d0:1;
//unsigned b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
};
} t_int;
void enviar_datos( t_byte comando, t_int dato );
void activar_interrupciones_PORTB_TIMER(void)
{
INTCONbits.RBIF = 1;
INTCONbits.INTF = 1;
/***** configuracion del timer 1 ******************************************/
T1CONbits.TMR1CS = 0; // Timer1 Clock Source - 0 Internal clock (FOSC/4)
T1CONbits.T1CKPS1 = 1; // prescaler
T1CONbits.T1CKPS0 = 1; // 1:8
TMR1H = VALOR_TMR1H; // 3036
TMR1L = VALOR_TMR1L; // 500 ms
T1CONbits.TMR1ON = 0; // Timer1 On bit
PIE1bits.TMR1IE = 1; // TMR1 Overflow Interrupt Enable bit
/***** configuracion de los puertos ***************************************/
INTCONbits.PEIE = 1; // Enables all unmasked peripheral interrupts
INTCONbits.RBIE = 1; // Enables the RB port change interrupt
// PORTB pull-ups are enabled by individual port latch values
OPTION_REGbits.nRBPU = 1;
// 1 = Interrupcion en flanco ascendente del pin RB0/INT
// 0 = Interrupcion en flanco descendente del pin RB0/INT
OPTION_REGbits.INTEDG = 1;
INTCONbits.RBIF = 0; // When at least one of the RB<7:4> pins changes state
// (must be cleared in software)
INTCONbits.INTF = 0; // The RB0/INT external interrupt occurred
// (must be cleared in software)
INTCONbits.INTE = 1; // Enables the RB0/INT external interrupt
INTCONbits.GIE = 1; // Enables all unmasked interrupts
/***** activacion de la int del timer1 ************************************/
T1CONbits.TMR1ON = 1; // Timer1 On bit
GIE = 1; // Enable all unmasked interrupts
PEIE = 1; // Enable all unmasked peripheral interrupts
}
//------------------------------------------------------------------------------
void inicializar_puertos()
{
/***** configuración del oscilador interno ********************************/
PCON |= 0b00001000; /* OSCF bit = 0b1 -> Fosc = 4MHz */
/***** configuración de los puertos ***************************************/
/*
* RA0 D0 LCD
* RA1 D1 LCD
* RA2 D2 LCD
* RA3 D3 LCD
* RA4 D4 LCD
* RA5 D5 LCD
* RA6 D6 LCD
* RA7 D7 LCD
*/
TRISA = 0xFF;
PORTA = 0x00; /* clear PORTA buffer */
CMCON |= 0b00000111; /* CM = 0b111, desactiva comparadores */
VRCON = 0x00; /* Vref desconectado de RA2 */
/*
* RB7 E LCD
* RB6 RW LCD
* RB5 RS LCD
* RB4 Luz LCD
* RB3
* RB2 Listo para escucha ( 1 ) salida
* RB1 Data entrada
* RB0 Clock entrada
*/
TRISB = 0b00000011;
OPTION_REG |= 0b10000000; /* desactiva pull-ups internos */
PORTB = 0x00; /* clear PORTB buffer */
}
int main(void)
{
pos = 0;
comando.variable = 0;
dato.variable = 0;
listoParaEscucha = true;
inicializar_puertos();
activar_interrupciones_PORTB_TIMER();
COMU_ESCUCHA = listoParaEscucha;
while ( true ) ;
}
/*******************************
**** Configuracion del PIC ****
*******************************/
#define _XTAL_FREQ 4000000 /* frecuencia del oscilador 4Mhz */
#pragma config FOSC = INTOSCIO // Uso de osc. interno
// E/S en RA6 y RA7
#pragma config WDTE = OFF // Deshabilita "Watchdog Timer"
#pragma config PWRTE = OFF // Deshabilita "Power-up Timer"
#pragma config MCLRE = OFF // Configura MCLR como E/digital
#pragma config CP = ON // Habilita proteccion de codigo
#pragma config CPD = OFF // Deshabilita proteccion de
// memoria de datos
#pragma config BOREN = OFF // Deshabilita "Brown Out Detect"
#pragma config LVP = OFF // Deshabilita programacion de
// bajo voltage
//------------------------------------------------------------------------------
//######## definiciones del TIMER1 ##################
//------------------------------------------------------------------------------
/**** Timer1 - para 1 seg ***********************/
/**** Reloj a 4 MHz ****/
//------------------------------------------------------
// TMR1H TMR1L
// 500 ms - 3036 - 00001011 11011100 0xBDC - 0xB / 0xDC
//------------------------------------------------------
#define VALOR_TMR1H 0xB // 0b00001011
#define VALOR_TMR1L 0xDC // 0b11011100
#define NRO_INT_TIMER1_X_SEG 2 // 500 ms * 2 = 1 seg
//------------------------------------------------------------------------------
//######## variables ############################
//------------------------------------------------------------------------------
bool listoParaEscucha;
unsigned int pos;
//------------------------------------------------------------------------------
typedef union {
unsigned char variable;
struct {
unsigned d7:1, d6:1, d5:1, d4:1, d3:1, d2:1, d1:1, d0:1;
};
} t_byte;
t_byte comando;
typedef union {
unsigned int variable;
struct {
unsigned d15:1, d14:1, d13:1, d12:1, d11:1, d10:1, d9:1, d8:1, d7:1, d6:1, d5:1, d4:1, d3:1, d2:1, d1:1, d0:1;
};
} t_int;
t_int dato;
//------------------------------------------------------------------------------
//######## puertos #############################
//------------------------------------------------------------------------------
#define COMU_CLOCK PORTBbits.RB0
#define COMU_DATA PORTBbits.RB1
#define COMU_ESCUCHA PORTBbits.RB2
//------------------------------------------------------------------------------
#define LCD_LUZ PORTBbits.RB4
#define LCD_RS PORTBbits.RB5
#define LCD_RW PORTBbits.RB6
#define LCD_E PORTBbits.RB7
//------------------------------------------------------------------------------
//######## macros #############################
//------------------------------------------------------------------------------
#define testbit(var, bit) ((var) & (1 <<(bit)))
#define bitset(var, bitno) ((var) |= 1UL << (bitno))
#define bitclr(var, bitno) ((var) &= ~(1UL << (bitno)))
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
void atender_interrupcion_clock( void )
{
if ( listoParaEscucha )
{
if ( pos == 0 ) comando.d0 = COMU_DATA;
else if ( pos == 1 ) comando.d1 = COMU_DATA;
else if ( pos == 2 ) comando.d2 = COMU_DATA;
else if ( pos == 3 ) comando.d3 = COMU_DATA;
else if ( pos == 4 ) comando.d4 = COMU_DATA;
else if ( pos == 5 ) comando.d5 = COMU_DATA;
else if ( pos == 6 ) comando.d6 = COMU_DATA;
else if ( pos == 7 ) comando.d7 = COMU_DATA;
else if ( pos == 8 ) dato.d0 = COMU_DATA;
else if ( pos == 9 ) dato.d1 = COMU_DATA;
else if ( pos == 10 ) dato.d2 = COMU_DATA;
else if ( pos == 11 ) dato.d3 = COMU_DATA;
else if ( pos == 12 ) dato.d4 = COMU_DATA;
else if ( pos == 13 ) dato.d5 = COMU_DATA;
else if ( pos == 14 ) dato.d6 = COMU_DATA;
else if ( pos == 15 ) dato.d7 = COMU_DATA;
else if ( pos == 16 ) dato.d8 = COMU_DATA;
else if ( pos == 17 ) dato.d9 = COMU_DATA;
else if ( pos == 18 ){ dato.d10 = COMU_DATA; LCD_LUZ = 1; }
else if ( pos == 19 ) dato.d11 = COMU_DATA;
else if ( pos == 20 ) dato.d12 = COMU_DATA;
else if ( pos == 21 ) dato.d13 = COMU_DATA;
else if ( pos == 22 ) dato.d14 = COMU_DATA;
else if ( pos == 23 ) dato.d15 = COMU_DATA;
if ( pos > 23 )
{
COMU_ESCUCHA = 0;
LCD_LUZ = 1;
pos = 0;
}
else
pos++;
}
}
//------------------------------------------------------------------------------
void atender_interrupcion_timer1( void )
{
}
//------------------------------------------------------------------------------
void interrupt interrupcion(void)
{
if ( INTCONbits.INTF )
atender_interrupcion_clock();
if ( PIR1bits.TMR1IF )
atender_interrupcion_timer1();
/* Reinicializa las banderas de las interrupciones de los puertos */
INTCONbits.RBIF = 0;
INTCONbits.INTF = 0;
}
hola BrunoF,
sobre el punto 1, te consulto, en mi caso si el 628 pierde sincronismo, no debería perderlo aleatoriamente? es posible que deje de recibir datos en el bit 19?
hoy que tengo algo de tiempo laboral voy a implementar el protocolo que me indicas
2) si limpio la bandera antes de atender la int no corro el riesgo de que la int vuelva a "interrumpir" antes de que termine de procesarse el evento anterior?
muchas gracias
hola GeSHi :D buen día,
me imagino que implementar un i2c por soft consumiría una cantidad importante de flash, el 628 tiene que escribir muchos mensajes en un lcd de 16x2
saludos
En cuanto al manejo de tu LCD, me pareció entender que utilizas protocolo de 8 bits... ¿Por qué no utilizas protocolo de 4 bits y así ahorrar pines? De esa manera tal vez puedas aprovechar el UART por hard del 628si, uso los 8 bits, pero el uart ocupado es el del 877, el 628 es todo mio, va en una plaqueta aparte, junto con la del lcd
Hablando del 16F877/16F628, que solo tiene un nivel de prioridad, cuando ocurre cualquier interrupción, el bit INTCON,GIE se pone a cero automáticamente. Eso impide que durante cualquier interrupción pueda ocurrir otra. Lo que sí lográs limpiando el flag inmediatamente, es que si por algún motivo ocurre nuevamente un evento que merezca interrumpir, vuelva a setear el flag de dicha interr, por lo que ni bien salgas de la rutina de interr. va volver a ingresar para antender el nuevo evento. De esa manera es menos probable que pierdas posibles eventos que necesitás atender.