Autor Tema: :: PIC18F250 nunca entra en #INT_SSP ::  (Leído 14550 veces)

0 Usuarios y 4 Visitantes están viendo este tema.

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #15 en: 19 de Junio de 2012, 10:17:00 »
Deberias poner tu ultimo codigo (completo) para ver que puede estar causandote esto, incluso alguno podria compilarlo y ver que pasa para ayudarte.
Si pones el codigo, usa GeShi y la opcion C o C++.

hola MGLSOFT

voy a poner el code:
M1:: master
S1:: esclavo 1 con interrupcion
S2:: esclavo 2 sin  interrupcion

Código: C++
  1. /*******************************************************
  2. * M1.c: libreia principal
  3. *
  4. ********************************************************/
  5. #include "M1.h"
  6.  
  7.  
  8. void main()
  9. {
  10.  
  11.    setup_adc_ports(NO_ANALOGS|VSS_VDD);
  12.    setup_adc(ADC_CLOCK_DIV_2);
  13.    setup_wdt(WDT_OFF);
  14.    setup_timer_0(RTCC_INTERNAL);
  15.    setup_timer_1(T1_DISABLED);
  16.    setup_timer_2(T2_DISABLED,0,1);
  17.    setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
  18.    setup_comparator(NC_NC_NC_NC);
  19.    setup_vref(FALSE);
  20. //Setup_Oscillator parameter not selected from Intr Oscillator Config tab
  21.  
  22.    // TODO: USER CODE!!
  23.    int8 leodato,state;
  24. int8 addr,dato;
  25.  
  26.    if(existe_addr(S1)){
  27.    printf("\n\r Se encontro %X "addr);
  28.    }
  29.    OUTPUT_HIGH(PIN_B3);
  30.    
  31.    printf("\n\r PIC MASTER: ");
  32.    printf("\n\r     enviando.... ");
  33.    addr=S1;
  34.    dato=5;
  35.    printf("\n\r ADDR: %X  dato: %d "addr,dato);
  36.    
  37.  
  38.  
  39.      
  40.       /*state = i2c_isr_state(); //lee el estado del bus
  41.       dato=i2c_read();
  42.       printf("\n\r dato: %X  state: %X" dato,state);
  43.  
  44.       delay_ms(10);
  45.     */
  46.       escribir_i2c(addr,dato);
  47.  
  48.       /*
  49.       state = i2c_isr_state(); //lee el estado del bus
  50.       dato=i2c_read();
  51.       printf("\n\r dato: %X  state: %X" dato,state);
  52.       */
  53.       delay_ms(100);
  54.       /*
  55.       state = i2c_isr_state(); //lee el estado del bus
  56.       dato=i2c_read();
  57.       printf("\n\r dato: %X  state: %X" dato,state);
  58.       */
  59.       leodato=leer_i2c(S1);
  60.      
  61.       /*
  62.       state = i2c_isr_state(); //lee el estado del bus
  63.       dato=i2c_read();
  64.      
  65.       printf("\n\r leodato:%X state: %X dato: %X" leodato,state,dato);
  66. */
  67. if(existe_addr(S1)){
  68. printf("\n\r Se encontro %X "addr);
  69. }
  70. }



Código: C++
  1. /*******************************************************
  2. * s1.h: libreia de cabeceras
  3. *
  4. ********************************************************/
  5. #include <18F2550.h>
  6. #device adc=8
  7.  
  8. #FUSES NOWDT                    //No Watch Dog Timer
  9. #FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
  10. #FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
  11. #FUSES NOPROTECT                //Code not protected from reading
  12. #FUSES NOBROWNOUT               //No brownout reset
  13. #FUSES BORV20                   //Brownout reset at 2.0V
  14. #FUSES NOPUT                    //No Power Up Timer
  15. #FUSES NOCPD                    //No EE protection
  16. #FUSES STVREN                   //Stack full/underflow will cause reset
  17. #FUSES NODEBUG                  //No Debug mode for ICD
  18. #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
  19. #FUSES NOWRT                    //Program memory not write protected
  20. #FUSES NOWRTD                   //Data EEPROM not write protected
  21. #FUSES IESO                     //Internal External Switch Over mode enabled
  22. #FUSES FCMEN                    //Fail-safe clock monitor enabled
  23. #FUSES NOPBADEN                   //PORTB pins are configured as digital I/O on RESET
  24. #FUSES NOWRTC                   //configuration not registers write protected
  25. #FUSES NOWRTB                   //Boot block not write protected
  26. #FUSES NOEBTR                   //Memory not protected from table reads
  27. #FUSES NOEBTRB                  //Boot block not protected from table reads
  28. #FUSES NOCPB                    //No Boot Block code protection
  29. #FUSES MCLR                     //Master Clear pin enabled
  30. #FUSES LPT1OSC                  //Timer1 configured for low-power operation
  31. #FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
  32. #FUSES PLL12                    //Divide By 12(48MHz oscillator input)
  33. #FUSES CPUDIV4                  //System Clock by 4
  34. #FUSES USBDIV                   //USB clock source comes from PLL divide by 2
  35. #FUSES VREGEN                   //USB voltage regulator enabled
  36.  
  37. #use delay(clock=20000000)
  38. #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
  39. #use i2c(Master,Slow,sda=PIN_B0,scl=PIN_B1)
  40.  
  41. #use fast_io(B)
  42. #include "milib.c"




Código: C++
  1. /*******************************************************
  2. * milib.c: libreia de mis funciones
  3. *
  4. ********************************************************/
  5. //direcciones de dispositivos
  6.  
  7. #Define M1 0xA0 //Master
  8. #Define S1 0xA2 //Esclavo 1
  9. #Define S2 0xA4 //Esclavo 2
  10. #Define S3 0xA6 //Esclavo 3
  11.  
  12.  
  13. // --- escribir en dispositivo ---
  14.  
  15. void escribir_i2c(int8 direccion, int8 dato)
  16. {
  17.    i2c_start();
  18.    i2c_write(direccion);
  19.    //i2c_write(0);//add
  20.    i2c_write(dato);
  21.    i2c_stop();
  22.    //delay_us(50);
  23. }
  24.  
  25.  
  26. // --- leer del dispositivo ---
  27. int8 leer_i2c(int8 direccion)
  28. {
  29.    int8 dato = 0;
  30.    i2c_start();
  31.    i2c_write(direccion); //direccion device
  32.    //i2c_write(0); //add
  33.      
  34.    i2c_start();
  35.    i2c_write(direccion+1);
  36.    //dato = i2c_read();
  37.    dato = i2c_read(0);//add
  38.    return(dato);
  39.    i2c_stop();
  40.    
  41.    
  42. }
  43.  
  44.  
  45. //text de dispositivo
  46.  
  47. int8 existe_addr(int8 addr){
  48.  
  49.   i2c_start();
  50.   if(i2c_write(addr)){
  51.     return 0;
  52.   }else{
  53.     return 1;
  54.   }
  55.   i2c_stop();
  56. }

========================

Código: C++
  1. /*******************************************************
  2. * s1.c: libreia principal
  3. *
  4. ********************************************************/
  5. #include "s1.h"
  6.  
  7. #INT_SSP
  8. //void SSP_isr(void){
  9. void ssp_interrupt(void);
  10.  
  11.  
  12.  
  13. void main(){
  14.  
  15.    setup_adc_ports(NO_ANALOGS|VSS_VDD);
  16.    setup_adc(ADC_CLOCK_DIV_2);
  17.    setup_wdt(WDT_OFF);
  18.    setup_timer_0(RTCC_INTERNAL);
  19.    setup_timer_1(T1_DISABLED);
  20.    setup_timer_2(T2_DISABLED,0,1);
  21.    setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
  22.    setup_comparator(NC_NC_NC_NC);
  23.    setup_vref(FALSE);
  24.    
  25.    enable_interrupts(INT_SSP);
  26.    enable_interrupts(GLOBAL);
  27. //Setup_Oscillator parameter not selected from Intr Oscillator Config tab
  28.  
  29.    // TODO: USER CODE!!
  30.    
  31.    OUTPUT_HIGH(PIN_B3);
  32.    
  33.    printf("\n\r PIC ESCLAVO 1: ");
  34.    printf("\n\r     recibiendo.... ");
  35.    while(true){
  36.    
  37.    }
  38.  
  39. }



Código: C++
  1. /*******************************************************
  2. * s1.h: libreia de cabeceras
  3. *
  4. ********************************************************/
  5. #include <18F2550.h>
  6. #device adc=8
  7.  
  8. #FUSES NOWDT                    //No Watch Dog Timer
  9. #FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
  10. #FUSES XT                       //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
  11. #FUSES NOPROTECT                //Code not protected from reading
  12. #FUSES NOBROWNOUT               //No brownout reset
  13. #FUSES BORV20                   //Brownout reset at 2.0V
  14. #FUSES NOPUT                    //No Power Up Timer
  15. #FUSES NOCPD                    //No EE protection
  16. #FUSES STVREN                   //Stack full/underflow will cause reset
  17. #FUSES NODEBUG                  //No Debug mode for ICD
  18. #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
  19. #FUSES NOWRT                    //Program memory not write protected
  20. #FUSES NOWRTD                   //Data EEPROM not write protected
  21. #FUSES IESO                     //Internal External Switch Over mode enabled
  22. #FUSES FCMEN                    //Fail-safe clock monitor enabled
  23. #FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
  24. #FUSES NOWRTC                   //configuration not registers write protected
  25. #FUSES NOWRTB                   //Boot block not write protected
  26. #FUSES NOEBTR                   //Memory not protected from table reads
  27. #FUSES NOEBTRB                  //Boot block not protected from table reads
  28. #FUSES NOCPB                    //No Boot Block code protection
  29. #FUSES MCLR                     //Master Clear pin enabled
  30. #FUSES LPT1OSC                  //Timer1 configured for low-power operation
  31. #FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
  32. #FUSES PLL12                    //Divide By 12(48MHz oscillator input)
  33. #FUSES CPUDIV4                  //System Clock by 4
  34. #FUSES USBDIV                   //USB clock source comes from PLL divide by 2
  35. #FUSES VREGEN                   //USB voltage regulator enabled
  36.  
  37. #use delay(clock=20000000)
  38. #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
  39. #use i2c(Slave,Slow,sda=PIN_B0,scl=PIN_B1,address=0xA2)
  40.  
  41. #use fast_io(B)
  42. #include "milib.c"




Código: C++
  1. /*******************************************************
  2. * milib.c: libreia de mis funciones
  3. *
  4. ********************************************************/
  5. //direcciones de dispositivos
  6.  
  7. #Define M1 0xA0 //Master
  8. #Define S1 0xA2 //Esclavo 1
  9. #Define S2 0xA4 //Esclavo 2
  10. #Define S3 0xA6 //Esclavo 3
  11.  
  12.  
  13. // --- escribir en dispositivo ---
  14.  
  15. void escribir_i2c(int8 direccion, int8 dato)
  16. {
  17.    i2c_start();
  18.    i2c_write(direccion);
  19.    //i2c_write(0);//add
  20.    i2c_write(dato);
  21.    i2c_stop();
  22.    delay_us(150);
  23. }
  24.  
  25.  
  26. // --- leer del dispositivo ---
  27. int8 leer_i2c(int8 direccion)
  28. {
  29.    int8 dato = 0;
  30.    i2c_start();
  31.    i2c_write(direccion); //direccion device
  32.    //i2c_write(0); //add
  33.      
  34.    i2c_start();
  35.    i2c_write(direccion+1);
  36.    //dato = i2c_read();
  37.    dato = i2c_read(0);//add
  38.    i2c_stop();
  39.    
  40.    return(dato);
  41. }
  42. // -- funcion interrupcion ---
  43.  
  44. void ssp_interrupt(void){
  45.    int8 state, buffer[];
  46.    int8 i2c_dato_entrada,i2c_dato_funcion;
  47.  
  48.    state = i2c_isr_state();
  49.    if(state >= 0x80){                    //master pide un dato
  50.       i2c_write(buffer[i2c_dato_entrada]);          
  51.    }
  52.    else if(state == 0x01){               //Master esta enviando datos
  53.       i2c_dato_entrada = i2c_read();
  54.       buffer[i2c_dato_funcion] = i2c_dato_entrada;
  55.    }
  56.  
  57. }

======================


Código: C++
  1. /*******************************************************
  2. * s2.c: libreia principal
  3. *
  4. ********************************************************/
  5. #include "s2.h"
  6. //#int_SSP
  7. //void ssp_interrupt(void);
  8.  
  9.  
  10.  
  11. void main()
  12. {
  13.  
  14.    setup_adc_ports(NO_ANALOGS|VSS_VDD);
  15.    setup_adc(ADC_CLOCK_DIV_2);
  16.    setup_wdt(WDT_OFF);
  17.    setup_timer_0(RTCC_INTERNAL);
  18.    setup_timer_1(T1_DISABLED);
  19.    setup_timer_2(T2_DISABLED,0,1);
  20.    setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
  21.    setup_comparator(NC_NC_NC_NC);
  22.    //setup_vref(FALSE);
  23.    
  24.    //enable_interrupts(INT_SSP);// las deshabilito porque lee cosas raras
  25.    //enable_interrupts(GLOBAL); // las deshabilito porque lee cosas raras
  26. //Setup_Oscillator parameter not selected from Intr Oscillator Config tab
  27.  
  28.    // TODO: USER CODE!!
  29.    printf("\n\r PIC ESCLAVO 2: ");
  30.    printf("\n\r     recibiendo.... ");
  31.    
  32.    int8 state,leo,dato;
  33.    
  34.    //OUTPUT_HIGH(PIN_B3);
  35.    
  36.    //while (true) {
  37.        
  38.     delay_us(10);
  39.    state = i2c_isr_state(); //lee el estado del bus
  40.    if(state <0x80 || state >=0x80){
  41.    //leo=i2c_read();
  42.    dato=i2c_read(0);
  43.    printf("\n\r leo: %X  state: %X  dato: %X "leo,state,dato);
  44.    }
  45.    //delay_ms(1000);
  46.    //state = i2c_isr_state(); //lee el estado del bus
  47.    //leo=i2c_read();
  48.    //printf("\n\r leo: %X  state: %X  "leo,state);
  49.    
  50.   // }//fin while
  51.  
  52. }



Código: C++
  1. /*******************************************************
  2. * s2.h: libreia de cabeceras
  3. *
  4. ********************************************************/
  5. #include <18F2550.h>
  6. #device adc=8
  7.  
  8. #FUSES NOWDT                    //No Watch Dog Timer
  9. #FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
  10. #FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
  11. #FUSES NOPROTECT                //Code not protected from reading
  12. #FUSES NOBROWNOUT               //No brownout reset
  13. #FUSES BORV20                   //Brownout reset at 2.0V
  14. #FUSES NOPUT                    //No Power Up Timer
  15. #FUSES NOCPD                    //No EE protection
  16. #FUSES STVREN                   //Stack full/underflow will cause reset
  17. #FUSES NODEBUG                  //No Debug mode for ICD
  18. #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
  19. #FUSES NOWRT                    //Program memory not write protected
  20. #FUSES NOWRTD                   //Data EEPROM not write protected
  21. #FUSES IESO                     //Internal External Switch Over mode enabled
  22. #FUSES FCMEN                    //Fail-safe clock monitor enabled
  23. #FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
  24. #FUSES NOWRTC                   //configuration not registers write protected
  25. #FUSES NOWRTB                   //Boot block not write protected
  26. #FUSES NOEBTR                   //Memory not protected from table reads
  27. #FUSES NOEBTRB                  //Boot block not protected from table reads
  28. #FUSES NOCPB                    //No Boot Block code protection
  29. #FUSES MCLR                     //Master Clear pin enabled
  30. #FUSES LPT1OSC                  //Timer1 configured for low-power operation
  31. #FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
  32. #FUSES PLL12                    //Divide By 12(48MHz oscillator input)
  33. #FUSES CPUDIV4                  //System Clock by 4
  34. #FUSES USBDIV                   //USB clock source comes from PLL divide by 2
  35. #FUSES VREGEN                   //USB voltage regulator enabled
  36.  
  37. #use delay(clock=20000000)
  38. #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
  39. #use i2c(Slave,Slow,sda=PIN_B0,scl=PIN_B1,address=0xA4)
  40.  
  41. #use fast_io(B)
  42. #include "milib.c"

=================


Código: C++
  1. /*******************************************************
  2. * milib.c: libreia de mis funciones
  3. *
  4. ********************************************************/
  5. //direcciones de dispositivos
  6.  
  7. #Define M1 0xA0 //Master
  8. #Define S1 0xA2 //Esclavo 1
  9. #Define S2 0xA4 //Esclavo 2
  10. #Define S3 0xA6 //Esclavo 3
  11.  
  12.  
  13. // --- escribir en dispositivo ---
  14.  
  15. void escribir_i2c(int8 direccion, int8 dato)
  16. {
  17.    i2c_start();
  18.    i2c_write(direccion);
  19.    i2c_write(dato);
  20.    i2c_stop();
  21.    delay_us(50);
  22. }
  23.  
  24.  
  25. // --- leer del dispositivo ---
  26. int8 leer_i2c(int8 direccion)
  27. {
  28.    int8 dato = 0;
  29.    i2c_start();
  30.    i2c_write(direccion); //direccion device
  31.    //i2c_write(0); //add
  32.      
  33.    i2c_start();
  34.    i2c_write(direccion+1);
  35.    //dato = i2c_read();
  36.    dato = i2c_read(0);//add
  37.    i2c_stop();
  38.    
  39.    return(dato);
  40. }
  41. // -- funcion interrupcion ---
  42.  
  43. void ssp_interrupt(void){
  44.    int8 state, buffer[];
  45.    int8 i2c_dato_entrada,i2c_dato_funcion;
  46.    
  47.    printf("\n\r interrupcion");
  48.    state = i2c_isr_state();
  49.    if(state >= 0x80){                    //master pide un dato
  50.       i2c_write(buffer[i2c_dato_entrada]);          
  51.    }
  52.    else if(state == 0x01){               //Master esta enviando datos
  53.       i2c_dato_entrada = i2c_read();
  54.       buffer[i2c_dato_funcion] = i2c_dato_entrada;
  55.    }
  56.  
  57. }

con fichero de proteus de pos anteriores se puede simular es el mismo
pero si quieren les dejo el fichero de nuevo su version es 7.2 sp6.


Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #16 en: 19 de Junio de 2012, 10:35:42 »
Creo que el nudo lo has creado tu mismo, queriendo hacer todo en librerias externas.
Prueba a hacer un solo programa para cada PIC, porque esta muy enredado y me parece que tienes que poner el codigo de interrupcion directamente dentro de la rutina, porque no soporta declaracion de funciones en la interrupcion.
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #17 en: 19 de Junio de 2012, 11:23:23 »
Creo que el nudo lo has creado tu mismo, queriendo hacer todo en librerias externas.
Prueba a hacer un solo programa para cada PIC, porque esta muy enredado y me parece que tienes que poner el codigo de interrupcion directamente dentro de la rutina, porque no soporta declaracion de funciones en la interrupcion.

Hola
eso de integrar todo en uno ya lo intente la vez anterior,
 de poner la interrupcion dentro del  main y el comportamiento era el mismo.

tiene que haber otra forma ..¿ has programado algo en i2c,... que codigo usaste?

un saludo.

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #18 en: 19 de Junio de 2012, 11:51:54 »
La verdad es que mi experiencia con el I2C no es de las mas gandes, solo use un IC de reloj y unas memorias, y nunca lo use con interrupciones, asi que no creo ser el mejor para decirte si asi como las usas esta bien o mal, pero en mi opinion deberias arrancar con un solo esclavo y un maestro, sin interrupciones y luego ir creciendo despacio, hasta que le tomes la mano bien al tema.
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #19 en: 19 de Junio de 2012, 12:05:52 »
No es recomendable colocar printf dentro de una interrupción, mejor utiliza leds si quieres saber si ingreso a ella. Yo en un proyecto con 16F como esclavo la interrupción por SSP  es idéntica a la que posteas.

Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #20 en: 19 de Junio de 2012, 12:28:02 »
  Viendo las dificultades de este post, hice lo propio pero con el compilador HiTech y pude comprobar que sí entra en la interrupción.
  Ahora bien, sucede algo que creo no es lo correcto, lo detallo... Cuando mandaba la dirección del esclavo1, entraba en la interrupción del mismo y por supuesto respondía con ACK. De manera inmediata le enviaba un dato, pero ahora ingresaba en la interrupción de los dos esclavos y me da la sensación que es el segundo esclavo el que está respondiendo con ACK lo cual estaría mal.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #21 en: 19 de Junio de 2012, 14:26:31 »
La verdad es que mi experiencia con el I2C no es de las mas gandes, solo use un IC de reloj y unas memorias, y nunca lo use con interrupciones, asi que no creo ser el mejor para decirte si asi como las usas esta bien o mal, pero en mi opinion deberias arrancar con un solo esclavo y un maestro, sin interrupciones y luego ir creciendo despacio, hasta que le tomes la mano bien al tema.

Hola AngelGris

yo anteriormente use i2c para el ds1307 y para expasores pcf8574x
pero nunca antes me puse acomunicar entre ambos pic usando i2c.

El problemilla de la interrupcion INT_SSP me esta dando mucho quebraderos de cabeza.


Hola Suky 
tomare nota de lo de los led en vez de printf.


Seguiremos insistiendo

Un Saludo.

« Última modificación: 19 de Junio de 2012, 14:28:46 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #22 en: 19 de Junio de 2012, 20:20:11 »
  Creo que descubrí el error en mi código. Aparentemente se me está activando el bit SSPOV (overflow) que indica que llegó un nuevo dato pero seguía estando lleno el SSPBUF (registro que almacena la información que llega). El SSPBUF se llena cuando coincide el address y también cuando llega un dato.
  Aparentemente es el programa que hagamos quien se tiene que encargar de procesar dicha información y darle utilidad o desecharla.
  Imagino que tendré que leer el registro SSPBUF para limpiarlo y así no se genere el overflow para poder procesar correctamente la información.

  Voy a investigar un poco el tema, y cuando logre algo te subo el código en HiTech, para que veas como va.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #23 en: 19 de Junio de 2012, 21:59:56 »
  Hasta ahora logré, con los códigos que siguen, que trabajen bien ambos esclavos, pero creo que la rutina de interrupción para el uso del dato podría ser mejorada... Seguiré haciendo pruebas.
  Más allá de posibles errores o mejoras en la rutina, los esclavos trabajan bien y en ambos casos lo hacen a partir de la interrupción SSP.

  Los códigos están simulados con proteus para pic 16F876A a 10 MHz. La frecuencia de I2C es de 100 KHz.

Código maestro
Código: C
  1. #include <htc.h>
  2.  
  3. __CONFIG (HS & WDTDIS & LVPDIS);
  4.  
  5. #define PIC_CLK     10000000
  6. #define _XTAL_FREQ 10000000
  7. #define I2C_BAUD    100000
  8.  
  9. #include "HardI2c.c"
  10.  
  11. void main(void)
  12. {
  13.  
  14.   setup_i2c(I2C_MASTER);
  15.   __delay_ms(250);
  16.   __delay_ms(250);
  17.   __delay_ms(250);
  18.   __delay_ms(250);
  19.  
  20.  
  21.   start_i2c();
  22.   write_i2c(0x1E);  // direccion esclavo 1, escritura
  23.   write_i2c(0xAB);  // dato para esclavo 1
  24.   stop_i2c();
  25.  
  26.   __delay_ms(5);
  27.   start_i2c();
  28.   write_i2c(0x1F);  // direccion esclavo 1, lectura
  29.   read_i2c(1);      // leo el dato y no respondo
  30.   stop_i2c();
  31.  
  32.   __delay_ms(5);
  33.   start_i2c();
  34.   write_i2c(0xFE);  // direccion esclavo 2, escritura
  35.   write_i2c(0x99);  // dato para esclavo 2
  36.   stop_i2c();
  37.  
  38.   __delay_ms(5);
  39.   start_i2c();
  40.   write_i2c(0x1E);  // direccion esclavo 1, escritura
  41.   write_i2c(0xCC);  // dato para esclavo 1
  42.   stop_i2c();
  43.  
  44.   __delay_ms(5);
  45.   start_i2c();
  46.   write_i2c(0xFF);  // direccion esclavo 2, lectura
  47.   read_i2c(1);      // leo el dato y no respondo
  48.   stop_i2c();
  49.  
  50.   while(1);
  51. }

Código esclavo 1
Código: C
  1. #include <htc.h>
  2.  
  3. __CONFIG (HS & WDTDIS & LVPDIS);
  4.  
  5. #define __XTAL_FREQ 10000000
  6. #define PIC_CLK     10000000
  7. #define I2C_BAUD    100000
  8.  
  9. #include "HardI2c.c"
  10.  
  11. char lectura;
  12.  
  13. void interrupt ISR(void)
  14. {
  15.   if (SSPIF == 1)  // interrupcion por SSP
  16.   {    
  17.     if (SSPOV == 1) // si hay overflow leo el buffer y borro dicho flag
  18.     {
  19.       lectura = read_i2c(1);
  20.       SSPOV = 0;
  21.     }
  22.     else             // si no hay overflow proceso el dato
  23.     {
  24.       if (BF == 1)  // si hay dato
  25.       {
  26.         if (RW == 0)  // esclavo para escritura
  27.         {    
  28.           lectura = read_i2c(0);
  29.           if (DA == 1) PORTB = lectura; // si llego un dato, lo mando al puerto
  30.         }      
  31.       }
  32.       if (RW == 1) write_i2c(0x77); // esclavo para lectura
  33.     }
  34.     SSPIF = 0;  
  35.   }
  36. }
  37.  
  38. void main(void)
  39. {
  40.   char nada;
  41.  
  42.   TRISB = 0;              // Puerto B como salida
  43.   PORTB = 0;              // Puerto B todo en 0
  44.   SSPADD = 0x1E;          // Direccion del esclavo 1
  45.   setup_i2c (I2C_SLAVE);  // Configuro como esclavo
  46.   CKP = 1;
  47.   nada = SSPBUF;          // Limpio el Buffer
  48.   SSPOV = 0;              // Limpio el flag de overflow
  49.   SSPIE = 1;              // Habilito interrupcion por SSP
  50.   PEIE = 1;               // Habilito interrupcion de perifericos
  51.   GIE = 1;                // Habilito las interrupciones globales
  52.   while(1)
  53.   {
  54.   }
  55. }

Código esclavo 2
Código: C
  1. #include <htc.h>
  2.  
  3. __CONFIG (HS & WDTDIS & LVPDIS);
  4.  
  5. #define _XTAL_FREQ 10000000
  6. #define PIC_CLK    10000000
  7. #define I2C_BAUD   100000
  8.  
  9. #include "HardI2c.c"
  10.  
  11. void interrupt isr(void)
  12. {
  13.   char dato;
  14.  
  15.   if (SSPIF == 1)  // interrupcion SSP
  16.   {
  17.     if (SSPOV == 1)  // si hay overflow leo el buffer y borro dicho flag
  18.     {
  19.       dato = read_i2c(1);
  20.       SSPOV = 0;
  21.     }
  22.     else  // si no hay overflow proceso el dato
  23.     {
  24.       if (BF == 1) // si esta lleno el buffer
  25.       {
  26.         if (RW == 0)
  27.         {
  28.           dato = read_i2c(1); // leo el buffer
  29.           if (DA == 1)  // si es un dato lo mando al puerto B
  30.           {
  31.             PORTB = dato;
  32.           }
  33.         }        
  34.       }
  35.       if (RW == 1) write_i2c(0x11);
  36.     }
  37.     SSPIF = 0;  // borro el flag de interrupcion
  38.   }
  39. }
  40.  
  41. void main(void)
  42. {
  43.   char nada;
  44.  
  45.   TRISB = 0;              // Puerto B como salida
  46.   PORTB = 0;              // Puerto B todo en 0
  47.   SSPADD = 0xFE;          // Direccion del esclavo
  48.   setup_i2c(I2C_SLAVE);   // configuro como esclavo
  49.   SSPIE = 1;              // Habilito la interrupcion de SSP
  50.   PEIE = 1;               // Habilito las interrupciones de perifericos
  51.   GIE = 1;                // Habilito las interrupciones globales
  52.  
  53.   while(1);
  54.  
  55. }
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #24 en: 22 de Junio de 2012, 09:25:33 »
 Viendo las dificultades de este post, hice lo propio pero con el compilador HiTech y pude comprobar que sí entra en la interrupción.
  Ahora bien, sucede algo que creo no es lo correcto, lo detallo... Cuando mandaba la dirección del esclavo1, entraba en la interrupción del mismo y por supuesto respondía con ACK. De manera inmediata le enviaba un dato, pero ahora ingresaba en la interrupción de los dos esclavos y me da la sensación que es el segundo esclavo el que está respondiendo con ACK lo cual estaría mal.

Hola AngelGris


En el codigo que yo puse , el master envia un dato a un esclavo
y el esclavo 1 que es el correspondinete debia de responder
pero no lo hace.

en caso contrario como el esclavo 2 tiene un bucle while y deberia de hacer algo cuando hay
eventos en el bus ya que se forzo con un bucle a la lectura perpetua.

con el esclavo 2 veo que es la direcion A2 que envio el master y que segun el retardo
me visualiza el bit 00+ o el 80+ pero no el dato.

Por ello meti al esclavo 2 en un while para que me rastreara todos los eventos del bus

con eso veo todos los eventos del bus,pero el esclavo 1 no se entera.

con esto se me plantea una nueva duda !!!

si el master indica con quien se quiere comunicar.
¿Quien es el que detecta la direcion o discrimina la direcion,..es el propio esclavo?

La funcion de ccs tiene errores..!

AngelGris como configuraste tu el master y el eclavo1 y el esclavo 2?

ambos actuan mediante interrupcion en tu codigo?

Creo que si.., me puedes confirmar..

Sigo analizando tu codigo...


« Última modificación: 22 de Junio de 2012, 09:36:09 por pajaro »

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #25 en: 22 de Junio de 2012, 14:57:52 »
Citar
si el master indica con quien se quiere comunicar.
¿Quien es el que detecta la direcion o discrimina la direcion,..es el propio esclavo?

Si fuera el bus SPI, que tiene un pin de ChipSelect o CS, que obliga al esclavo a atender, diria que no, porque el direccionamiento es por hardware.
En el caso del I2C, el maestro envia la direccion del esclavo que debe responder a los comandos (lectura o escritura) y el esclavo (en realidad todos los esclavos que estan en el bus) comparan esa direccion con la suya propia, y responde el que corresponde a esa direccion solamente.

Una cosa que nunca revisamos de tu codigo es eso, que direccion tienen tus esclavos y cuales son las que consulta el maestro !!
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #26 en: 22 de Junio de 2012, 16:22:13 »
Citar
si el master indica con quien se quiere comunicar.
¿Quien es el que detecta la direcion o discrimina la direcion,..es el propio esclavo?

Si fuera el bus SPI, que tiene un pin de ChipSelect o CS, que obliga al esclavo a atender, diria que no, porque el direccionamiento es por hardware.
En el caso del I2C, el maestro envia la direccion del esclavo que debe responder a los comandos (lectura o escritura) y el esclavo (en realidad todos los esclavos que estan en el bus) comparan esa direccion con la suya propia, y responde el que corresponde a esa direccion solamente.

Una cosa que nunca revisamos de tu codigo es eso, que direccion tienen tus esclavos y cuales son las que consulta el maestro !!

Hola
esa info esta en la libreria milib.c

en esta defini las funciones de escritura y de lectura del i2c y justo en su cabecera las direciones para los dispositivos
del esclavo o esclavos y la del master.

Pero si es asi como dices y creo que dices bien, ya que es lo razonable..
¿por que s2 ve el dato del bus si no va para el,
solo deberia de ver la direcion no el dato.



ahora que nombras el spi.. el cs o selecionador de chip, cada esclavo tiene 4 cables y el master otros tantos, pero como selecionan el esclavo .. un cable para cada esclavo ¿ eso es un derroche en pines?

porcierto ..mirando el code del amigo veo que lee con un 1 no con un 0 como recomiendan muchos post por ahi.
cual es la explicacion

i2c_read(1);

¿Hay alguna diferencia entre leer con 1 o leer con 0 ?¿o entre no poner nada?

AngelGris tengo una curiosidad con respectoa tu code, es por software o por hardware?

estoy intentado comparar el tuyo con el mio..

SSPIF == 1)  // interrupcion SSP


equivale a la funcion:

i2c_isr_state(); o i2c_poll()

yo no uso i2c_poll() ya que no  fuerzo a hardware el i2c



en mi code seleciona el B0 y B1 que son pines de hardware pero en el code no fuerzo ni hardware , ni software

sigo analizando tu codigo....



« Última modificación: 22 de Junio de 2012, 16:26:45 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #27 en: 22 de Junio de 2012, 16:41:12 »
  Yo lo hago por HardWare.
  Los dos esclavos responden por interrupción.

  "if (SSP == 1)" lo uso para testear si se activó la interrupción del SSP.
  En HiTech no se hace una función por cada interrupción, sino que hay una sola función y dentro de la misma se testea cual es la que se activó.

  Leer con 1 o con 0, "i2c_read(1)" o "i2c_read(0)" dependerá de como sea la comunicación con el esclavo. Con algunos dispositivos, si se quiere leer sólo un byte hay que responder con NOACK y luego el bit de STOP. Por lo tanto la lectura deberá realizarse con "i2c_read(1)".
  Si quieres leer 2 bytes seguidos (dentro de un mismo ciclo de START-STOP, o trama) la primer lectura indefectiblemente la tienes que hacer con "i2c_read(0)" para indicarle al dispositivo que recibiste el byte y éste te mande el siguiente byte.


  ¿Por qué no fuerzas en tu configuración a que utilice hardware? Tal vez sea la única forma que tome las interrupciones del módulo SSP.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #28 en: 22 de Junio de 2012, 17:54:15 »
Hola AngelGris

La idea es muchos PIC tienen i2c y otros no tienen,
y los que tienen solo tienen un canal, asi que por eso lo intento sin forzar hardware
 aunque los pines  del i2c son los pines fisico.

Por el momento desconozco si tendra alguna diferencia entre forzar harware,
forzar software o no poner la sentencia que especifica ese estado,
 por el contrario no se si al no especificar nada al compilador este le pondra una por defecto y tal caso
cual tomara o que caso le aplicara.
 se de leer por ahi que por hardware es el hardware el que configura retardos y tiempos
miestras por software lo tienes que hacer tu de esas maneras.

Tambien desconozco si se pone en el master, o en el esclavo o se pone en ambos,
(no lo confirme o contraste con otras fuentes) tambien deconozco si se puede
combinar dispositivos forzados en harware y dispositivos forzados en sofware
dentro del mismo bus.

La logica me dice que se deberia de poder hacer esto a nivel independiente de dispositivo no de bus,
me gustaria poder probarlo pero con esto de la interrupcion me tiene aqui bien cogido.

¿Tu probaste por ambos metodos.. ¿ te dejaria?

¿que es eso de la interrupcion de dispositivo?

sigo con el codigo..


Segun el manual de ccs si no pones nada lo toma como si fuese por software,
y recuedo que con el asistente de proyectos te genera los pines i2c virtuales
en diferentes a los fisicos.

sigo con el codigo..



« Última modificación: 22 de Junio de 2012, 18:57:56 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PIC18F250 nunca entra en #INT_SSP ::
« Respuesta #29 en: 22 de Junio de 2012, 19:36:42 »
Hola AngelGris

La idea es muchos PIC tienen i2c y otros no tienen,
y los que tienen solo tienen un canal, asi que por eso lo intento sin forzar hardware
 aunque los pines  del i2c son los pines fisico.

Por el momento desconozco si tendra alguna diferencia entre forzar harware,
forzar software o no poner la sentencia que especifica ese estado,
 por el contrario no se si al no especificar nada al compilador este le pondra una por defecto y tal caso
cual tomara o que caso le aplicara.
 se de leer por ahi que por hardware es el hardware el que configura retardos y tiempos
miestras por software lo tienes que hacer tu de esas maneras.

Tambien desconozco si se pone en el master, o en el esclavo o se pone en ambos,
(no lo confirme o contraste con otras fuentes) tambien deconozco si se puede
combinar dispositivos forzados en harware y dispositivos forzados en sofware
dentro del mismo bus.

La logica me dice que se deberia de poder hacer esto a nivel independiente de dispositivo no de bus,
me gustaria poder probarlo pero con esto de la interrupcion me tiene aqui bien cogido.

  Se pueden mezclar PICs que tengas I2C por SoftWare y otros con HardWare y otros dispositivos como memorias sin ningún problema. Yo comuniqué un 16F876A utilizando I2C por HardWare con un 16F628A utilizando I2C por SoftWare.


¿Tu probaste por ambos metodos.. ¿ te dejaria?


¿que es eso de la interrupcion de dispositivo?

  ¿A que te referís con ello?
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas