Hola de nuevo, os pongo código del master PUS:
//++++++++++++++++++++++++++++++++++++++++++++++++++++++//
#include <16F628a.h>
#FUSES INTRC_IO,NOWDT,PUT,NOMCLR,BROWNOUT,PROTECT,CPD
#use delay(clock=4000000)
//#use rs232(baud=19200,rcv=PIN_A3,BITS=8,sample_early)
#zero_ram
//+++++++++++++++++++++++++++++++++++++++++//
#define LED1 PIN_A0
#define LED2 PIN_A1
#define SW1 PIN_A4
#define SW2 PIN_A5
#define PUS_PC PIN_B0
#define PUS_PD PIN_B1
#define IN_SEN PIN_B2
//+++++++++++++++++++++++++++++++++++++++++//
#define CMD_ON 0x01
#define CMD_OFF 0x02
#define CMD_FADER_FAST 0x03
#define CMD_FADER_SLOW 0x04
#define CMD_INC_FAST 0x05
#define CMD_INC_SLOW 0x06
#define CMD_DEC_FAST 0x07
#define CMD_DEC_SLOW 0x08
//+++++++++++++++++++++++++++++++++++++++++
//
//
// Protocolo Unidireccional Serie (PUS) ;-)
//
// Dos Lineas:
// PD : Dato
// PC : Reloj
//
// Dato se lee en flanco de subida PD y debe permanecer
// hasta siguiente flanco de bajada, si no Error o START.
//
// Condicion START:
// PD = 0 en flanco de subida de PC.
// PD = 1 en siguiente flanco de bajada de PC.
//
// ____ ____ ____ ____
// __| |____| |____| |____| |____ PC
//
// ____ _______ _______
// ____| |_| |_| |___________| PD
//
// ^
// START
// 1 1 0
// Formato paquete
// A3 A2 A1 A0 C3 C2 C1 C0
//
// A : Direccion ( 15 posibles, 0 reservado)
// C : Comando ( 15 posibles, 0 reservado)
//
////+++++++++++++++++++++++++++++++++++++++++
//
void PUS_write(int8 add,int8 cmd);
////+++++++++++++++++++++++++++++++++++++++++
////+++++++++++++++++++++++++++++++++++++++++
void main(){
setup_comparator(NC_NC_NC_NC); //Comparador deshabilitado
output_A(0x00); //Latch
set_tris_A(0B0110000); //Input A4 y A5
output_B(0x00); //Latch
set_tris_B(0B0000100); //Input B2
//--------- PROGRAMA PRINCIPAL -----------------------------\\\\
// Prueba de envio ON/OFFF
while (1) {
PUS_write (0x01,CMD_ON);
PUS_write (0x02,CMD_OFF);
delay_ms(1000);
PUS_write (0x01,CMD_OFF);
PUS_write (0x02,CMD_ON);
delay_ms(1000);
}//end while
}//end main
////+++++++++++++++++++++++++++++++++++++++++
#define PERIODO_BIT_US 500
void PUS_write(int8 add,int8 cmd)
{
int8 dato, nbits, mask;
dato = (add << 4) & 0xF0;
dato |= (cmd & 0x0F);
output_low(PUS_PD);
output_low(PUS_PC);
// Condicion START
delay_us (2 * PERIODO_BIT_US);
output_high(PUS_PC);
delay_us (PERIODO_BIT_US / 2);
output_high(PUS_PD);
delay_us (PERIODO_BIT_US / 2);
output_low(PUS_PC);
// Envio de los bits
mask = 0x80;
for (nbits = 0; nbits < 8; nbits++)
{
delay_us (PERIODO_BIT_US / 2);
if ((dato & mask) > 0)
output_high(PUS_PD);
else
output_low(PUS_PD);
delay_us (PERIODO_BIT_US / 2);
output_high(PUS_PC);
delay_us (PERIODO_BIT_US);
output_low(PUS_PC);
mask = mask >> 1;
}
delay_us (PERIODO_BIT_US);
output_low(PUS_PD);
delay_us (PERIODO_BIT_US);
// TODO : Envio de paridad
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++//
Y ahora el de de un nodo receptor:
//++++++++++++++++++++++++++++++++++++++++++++++++++++++//
#include <12F629.h>
#FUSES INTRC_IO,NOWDT,PUT,NOMCLR,BROWNOUT,PROTECT,CPD
#use delay(clock=4M)
#use fast_io(A)
#zero_ram
//+++++++++++++++++++++++++++++++++++++++++//
#define LED PIN_A0
#define PUS_PC PIN_A3
#define PUS_PD PIN_A4
//+++++++++++++++++++++++++++++++++++++++++//
#define MAX_LED 100
#define CMD_ON 0x01
#define CMD_OFF 0x02
#define CMD_FADER_FAST 0x03
#define CMD_FADER_SLOW 0x04
#define CMD_INC_FAST 0x05
#define CMD_INC_SLOW 0x06
#define CMD_DEC_FAST 0x07
#define CMD_DEC_SLOW 0x08
char dato_rx = 0;
volatile int8 pwm_act_led = 0;
int8 pwm_led = 0;
// Variable control seceuncia de inicio
//
#define SEQ_INIT_START 0
#define SEQ_INIT_F1 1
#define SEQ_INIT_F2 2
#define SEQ_INIT_F3 3
#define SEQ_INIT_END 4
int16 cont_seq_inicio = 0;
int8 seq_inicio = SEQ_INIT_START;
int8 comando,address;
int8 fader(int8 speed,int1 inicio );
//+++++++++++++++++++++++++++++++++++++++++
//
//
// Protocolo Unidireccional Serie (PUS) ;-)
//
// Dos Lineas:
// PD : Dato
// PC : Reloj
//
// Dato se lee en flanco de subida PD y debe permanecer
// hasta siguiente flanco de bajada, si no Error o START.
//
// Condicion START:
// PD = 0 en flanco de subida de PC.
// PD = 1 en siguiente flanco de bajada de PC.
//
// ____ ____ ____ ____
// __| |____| |____| |____| |____ PC
//
// ____ _______ _______
// ____| |_| |_| |___________| PD
//
// ^
// START
// 1 1 0
// Formato paquete
// A3 A2 A1 A0 C3 C2 C1 C0
//
// A : Direccion ( 15 posibles, 0 reservado)
// C : Comando ( 15 posibles, 0 reservado)
//
////+++++++++++++++++++++++++++++++++++++++++
//
int8 PUS_dato = 0;
#define PUS_ADDR 0x01
////+++++++++++++++++++++++++++++++++++++++++
////+++++++++++++++++++++++++++++++++++++++++
void main(){
setup_comparator(NC_NC_NC_NC); //Comparador deshabilitado
output_A(0x00); //Latch
set_tris_A(0B011000); //MCLR=A3= RX input Int_RA3 on Change
enable_interrupts(GLOBAL); //Interrupciones Habilitadas
enable_interrupts(INT_TIMER1); //Habilitamos interrupcion desborde TMR1
// Timer1 para conseguir un tick cada 100us @ 4Mhz
set_timer1(65436); // 65536-(.000100/(4/4000000))
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
enable_interrupts(INT_RA3); //Habilitamos interrupcion por cambio de estado
//en pin RA3
//--------- PROGRAMA PRINCIPAL -----------------------------\\\\
//while (fader(100,1)) delay_ms(200);
while (1) {
//
// Estamos en sequencia de inicio
//
if (seq_inicio != SEQ_INIT_END)
{
switch (seq_inicio)
{
case SEQ_INIT_START : pwm_led = MAX_LED; break;
case SEQ_INIT_F1 : pwm_led = MAX_LED/2; break;
case SEQ_INIT_F2 : pwm_led = MAX_LED/4; break;
case SEQ_INIT_F3 : pwm_led = 0; break;
}
if (cont_seq_inicio++ > 10000)
{
cont_seq_inicio = 0;
seq_inicio++;
}
}
else
//
// Ejecucion normal : chequeamos dato recibido por PUS
//
dato_rx = PUS_dato;
PUS_dato = 0;
if (dato_rx != 0)
{
comando = dato_rx & 0x0F;
address = (dato_rx >> 4) & 0x0F;
if (address == PUS_ADDR)
{
switch (comando)
{
case CMD_OFF : pwm_led = 0; break;
case CMD_ON : pwm_led = MAX_LED; break;
}
}
dato_rx = 0;
}//if rx
}//end while
}//end main
// ++++++++++++++++++++++++++++++++++++++++++++++++
#define MAX_LED_FADER 8
const int8 led_valor[MAX_LED_FADER] = {0,10,20,30,50,70,80,100};
#define FADER_STOP 0
#define FADER_UP 1
#define FADER_DOWN 2
int8 fase_fader = FADER_STOP;
int8 idx_valor;
int8 speed_fader;
//
// fader
//
// speed : velocidad de la secuencia "fader"
// inicio : flag arranque secuencia
//
// devuelve 0 al finalizar el ciclode "fader", 1 en caso contrario.
//
int8 fader(int8 speed,int1 inicio )
{
if ((fase_fader == FADER_STOP) && (inicio))
{
pwm_led = 0;
speed_fader= speed;
fase_fader = FADER_UP;
idx_valor = 0;
}
if (fase_fader == FADER_UP )
{
pwm_led = led_valor[idx_valor++];
if (idx_valor > MAX_LED_FADER)
{
fase_fader = FADER_DOWN;
idx_valor = MAX_LED_FADER-1;
}
}
if (fase_fader == FADER_DOWN)
{
if (idx_valor == 0)
{
fase_fader = FADER_STOP;
}
else
{
pwm_led = led_valor[idx_valor--];
}
}
return (fase_fader != FADER_STOP);
}
//+++++++++++++++ INTERRUPCIONES +++++++++++++++++++//
#INT_TIMER1
void desborde_TMR1(){ //Interrupcion por desborde de timer cada 100 us
//
// Control PWM del LED
//
pwm_act_led++;
if (pwm_act_led > pwm_led)
output_low(LED);
else
output_high(LED);
// El ciclo se repite cada 100 * 100us = 10ms. (100Hz)
if (pwm_act_led > MAX_LED) pwm_act_led = 0;
set_timer1(65436); // 65536-(.000100/(4/4000000))
} // interrupcion TMR1
//
// Gestion del protocolo PUS por interrupcion
//
#define PUS_IDLE 0
#define PUS_START 1
#define PUS_RX 2
int8 PUS_temp = 0;
int8 PUS_nbit = 0;
int8 PUS_status = PUS_IDLE;
int1 PUS_bit = 0;
int8 PUS_error_data = 0;
int8 PUS_error_start = 0;
#INT_RA
void PUS_recepcion(){ //Interrupcion por cambio de estado en pines
if (input_state(PUS_PC) == 1) // Flanco subida PC
{
switch(PUS_status)
{
case PUS_IDLE :
// Chequeo inicio de condicion de START
if (input_state(PUS_PD) == 0)
{
PUS_status = PUS_START;
}
break;
case PUS_START : break;
case PUS_RX :
// detectamos inicio de bit.
PUS_bit = input_state(PUS_PD);
break;
}
}
else // Flando bajada PC
{
switch(PUS_status)
{
case PUS_IDLE : break;
case PUS_START :
// Chequeo de condicion de START completa
if (input_state(PUS_PD) == 1)
{
PUS_status = PUS_RX;
PUS_temp = 0;
}
else // ERROR, reinicio
{
PUS_status = PUS_IDLE;
PUS_error_start++;
}
break;
case PUS_RX:
// Condicion de START ya detectada
// Bit en PD se ha mantenido, guardamos
if (PUS_bit == input_state(PUS_PD))
{
PUS_temp <<= 1;
if (PUS_bit)
PUS_temp |= 0x01;
else
PUS_temp &= 0xFE;
PUS_nbit++;
// Dato completo recibido ?
if (PUS_nbit > 7)
{
PUS_nbit = 0;
PUS_status= PUS_IDLE;
PUS_dato = PUS_temp;
PUS_temp = 0;
}
}
else // ERROR, reinicio dato
{
PUS_dato = 0;
PUS_nbit = 0;
PUS_status= PUS_IDLE;
PUS_error_data++;
}
break;
}
}
} //int_ra3
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++//
Saludos.