Buenas gente, muy bueno el hilo, se aprende mucho de compartir experiencias.
A pesar de todo lo logro hacer andar una comunicación SPI entre dos 18Fs donde se intercambian 3 bytes.
Tengo una simulación de PROTEUS funcionando perfecto, un maestro 14k50 enviando datos sincronizados con el /SS, todo chequeado en los pines de entrada del esclavo, la info llega bien al segundo PCB, los niveles lógicos no se degradan en la transmisión.
Sin embargo, en el esclavo no salta la interrupción por recepción completa de SSP.
Aunque tiene el dato disponible y el valor de /SS bajo, o no recibe el valor, o bien la interrupción no salta a pesar de haber recibido el dato.
Les dejo el código por si tienen un ratito para mirarlo...
CODIGO MAESTRO
#include <18F14K50.h>
#device adc=8 //8 bits 256 cuentas
#FUSES INTRC_IO //High Speed Crystal/Resonator with PLL enabled
#FUSES CPUDIV2
#FUSES MCLR //Master Clear pin enabled
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOLVP //No utilizamos el modo de programación con bajo voltaje, B5(PIC18) used for I/O
#FUSES NODEBUG //No usamos codigo para debuguear
#use delay(clock=8MHz)
#define VMAX 255.00
#define AN1M 127.00
#define AN2M 127.00
#define AN_DERECHA 128
#define AN_IZQUIERDA 127
#define AN_ADELANTE 128
#define AN_ATRAS 127
#define SS PIN_B7
int8 AN1=0, AN2=0, V1, V2, direccion=0; // para atras 1
int1 adq=0;
float Vo1, Vd1, Vi1;
float Vo2, Vd2, Vi2;
////////////////////////////////////////////////////////////////////////////////
////////// INTERRUPCIONES //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#int_TIMER0
void TIMER0_isr(void)
{
set_timer0(15536); // 50ms
adq=1;
output_toggle(PIN_C1); // solo para chequeo en simulacion u operación
}
////////////////////////////////////////////////////////////////////////////////
////////// FUNCIONES ///////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void adq_pote(void)
{
set_adc_channel(7); // desplazamiento longitudinal
delay_us(10);
AN1 = read_adc();
set_adc_channel(8); // desplazamiento lateral
delay_us(10);
AN2 = read_adc();
}
void calc_vel(void)
{
V1=AN1; //calculo simplificado
V2=AN2;
}
void send(void)
{
output_low(SS);
spi_write(V1);
delay_us(10);
spi_write(V2);
delay_us(10);
spi_write(direccion);
delay_us(10);
output_high(SS);
}
////////////////////////////////////////////////////////////////////////////////
////////// PROGRAMA PRINCIPAL //////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void main()
{
set_tris_b(0b00011111);
set_tris_c(0b01001101);
setup_adc_ports(sAN7|sAN8|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(SPI_MASTER|SPI_CLK_DIV_16|SPI_XMIT_H_TO_L|SPI_SCK_IDLE_LOW);
setup_timer_0(T0_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
set_timer0(0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
output_high(PIN_C2);
output_high(PIN_B5);
output_high(SS);
while(TRUE)
{
if(adq==1) // se genero la interrupcion teporizada
{
disable_interrupts(GLOBAL);
adq_pote();
calc_vel();
send(); // se envian los valores de Vel al esclavo
adq=0;
enable_interrupts(GLOBAL);
}
}
}
CODIGO ESCLAVO
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOLVP //No utilizamos el modo de programación con bajo voltaje, B5(PIC18) used for I/O
#FUSES NODEBUG //No usamos codigo para debuguear
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES CPUDIV2 //System Clock by 2
#use delay(clock=8MHZ)
#define IN1 PIN_C0
#define IN2 PIN_C2 //CPP1 PWM
#define IN3 PIN_A6
#define IN4 PIN_C1 //CPP2 PWM
#define ENA PIN_E2
#define ENB PIN_E1
#define LED PIN_D2
int8 duty1, duty2, direccion;
int8 set=0;
#int_SSP
void SSP_isr(void)
{
disable_interrupts(global);
duty1=spi_read();
while(!spi_data_is_in());
duty2=spi_read();
while(!spi_data_is_in());
direccion=spi_read();
set=1;
output_toggle(LED); // SOLO PARA CHEQUEAR QUE ENTRO EN LA INTERRUPCION
clear_interrupt(int_ssp);
enable_interrupts(global);
}
////////////////////////////////////////////////////////////////////////////////
////////// PROGRAMA PRINCIPAL //////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void main()
{
set_tris_A(0b10111111);
set_tris_B(0b11);
set_tris_C(0b01101000);
set_tris_E(0b11111001);
set_tris_D(0b000);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); //genera los ticks que miden el pulso
setup_timer_2(T2_DIV_BY_1, 255, 1); //modulacion de frecuencia del PWM
setup_CCP1(CCP_PWM);
setup_CCP2(CCP_PWM);
setup_spi(SPI_SLAVE||SPI_XMIT_H_TO_L|SPI_SCK_IDLE_LOW);
output_high(IN1);
output_high(IN3);
set_pwm1_duty(150);
set_pwm2_duty(150);
clear_interrupt(int_ssp);
enable_interrupts(int_ssp);
enable_interrupts(global);
output_high(LED);
while (TRUE)
{
if(set==1)
{
disable_interrupts(global);
if(direccion==0)
{
output_high(IN1);
output_high(IN2);
set_pwm1_duty(255-duty1);
set_pwm2_duty(255-duty2);
}
if(direccion==1)
{
output_low(IN1);
output_low(IN2);
set_pwm1_duty(duty1);
set_pwm2_duty(duty2);
}
set=0;
enable_interrupts(global);
}
}
}
MUCHAS GRACIAS!!