Autor Tema: Esclavo I2c no lee rs232  (Leído 2663 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado krofta00

  • PIC10
  • *
  • Mensajes: 7
Esclavo I2c no lee rs232
« en: 11 de Enero de 2012, 09:09:34 »
Hola a todos,
       Aunque ya os leo desde hace tiempo, este es mi primer post, y como imaginareis para pediros ayuda, ya que hasta ahora me solucionasteis las dudas con los post que hay en el foro sin falta de preguntaros ( y no fueron pocas), pero sobre el problema que tengo no encontre nada.
        La cuestion es que estoy intentando programar dos pics que se comunicaran via I2C. Uno de ellos (16F876) seria esclavo y estaría encargado de leer el puerto RS232 del ordenador y adquirir unos valores, los cuales luego se pasaran a traves de I2C al pic maestro (16F877). He implementado por un lado la rutina de comunicacion entre pics por I2c y esta funcionando, por otro lado he implementado la rutina de adquisicion de datos del pic esclavo y tambien esta funcionando. Al unir los dos programas se plantea el problema.
       Todo funciona bien, excepto la recepcion del puerto RS232 en el pic esclavo. El pic transmite correctamente por el puerto, pero no recibe. Haciendo pruebas ha funcionado, pero siempre y cuando ponga ese pic como maestro. En el momento que defino el pic como esclavo en I2C, el puerto serie (por hardware) deja de recibir los datos.
       Se que estareis pensado que una solucion es poner a ese como maestro y al otro como esclavo, pero en el montaje final del circuito habrá otro pic mas encargado de otro puerto RS232, con lo que ambos deberian de ser esclavos y el principal, encargado de recibir y procesar los datos de estos dos, seria el maestro.
       La otra opcion que se me ocurre es ponerlos todos como multi_master, pero es mi primera incursion en I2C y se me queda grande.
       ¿ Alguien ha tenido problemas al intentar leer el RS232 desde un esclavo?.
       Esto pasa en la simulacion en el proteus, ya que antes de montarlo todo fisicamente queria hacerlo funcionar en la simulacion.
       Perdonar el tostón que os acbo de soltar, pero es que no encuentro la solucion.
      Un saludo y muchisimas gracias por anticipado.

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Esclavo I2c no lee rs232
« Respuesta #1 en: 11 de Enero de 2012, 09:32:11 »
  Lo ideal sería que subas los programas, lo podes mostrar con la opción GeSHi en el editor de mensajes. Para poder escribirlos directamente en el cuerpo del mensaje.

  Tal vez el problema venga de como estás trabajando las comunicaciones.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado krofta00

  • PIC10
  • *
  • Mensajes: 7
Re: Esclavo I2c no lee rs232
« Respuesta #2 en: 11 de Enero de 2012, 10:08:29 »
Hola,
 
     Gracias por contestar tan rapido. Voy a poner el codigo, aunque esta aun pendiente de completar cosas, ya que en principio estaba con el tema de las comunicaciones.
    Este seria el programa del esclavo. Al simularlo en el proteus, no recibe el puerto rs232, pero cambiando unicamente la definicion del pic de sclavo a master (incluso a multi_master), el pic recibe bien el puerto serie, pero evidentemente no recibe lo que el otro pic le envia por I2C.
    Con el pic como esclavo, al recibir las tramas de datos del puerto serie, la linea RX no aparece con los colores azul y rojo correspondientes a los estados logicos, sino que aparece en rojo y amarillo, es como si el nivel logico 0 no lo alcanzara nunca.

Código: CSS
  1. #include <16f876a.h>                            // Definiciones del PIC 16F877A.
  2. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT    // Los Fuses de siempre.
  3. #use delay(clock=20000000)                      // Oscilador a 20 Mhz.
  4. #use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7)  // Configuración del RS232.
  5. #use I2C(slave,SDA=PIN_C4,SCL=PIN_C3,slow,address=0x20)
  6. #use fast_io (B)                                // Puerto B para BCD
  7.  
  8.  
  9. // CONSTANTES /////////////////////////////////////////////////////////////////
  10.  
  11. int const lenbuff=40;                           // Longitud de buffer RS232.
  12.  
  13. // VARIABLES EN RAM ///////////////////////////////////////////////////////////
  14.  
  15. int  xbuff=0x00;                                // Índice: siguiente char en cbuff.
  16. char cbuff[lenbuff];                            // Buffer.
  17. char rcvchar=0x00;                              // Ultimo caracter recibido.
  18. int1 flagcommand=0;                             // Flag para indicar comando disponible.
  19. int16 frecuencia;                               // Valor de la frecuencia.
  20. int timeout;                                    // Valor para temporizar los envios RS232.
  21. int intentos;                                   // Variable de intentos de comunicacion RS232
  22. int mode=1;                                     // Valor del modo de obtencion frecuencia.
  23. int32  BAND=0x00;                               // Variable banda para ICOM y BCD.
  24. byte instruccion[10];
  25. int16 Frec[lenbuff];                            // Argumento de comando.
  26.  
  27. #byte SSPSTAT = 0xFC7
  28. #bit BFBIT=SSPSTAT.0
  29. #bit STARTBIT=SSPSTAT.3
  30. #bit STOPBIT=SSPSTAT.4
  31.  
  32. #byte SSPCON1=0xFC6
  33. // Declaración de Funciones ///////////////////////////////////////////////////
  34.  
  35. void inicbuff(void);                            // Borra buffer.
  36. int  addcbuff(char c);                          // añade caracter recibido al buffer.
  37. void procesa_comando(void);                     // Procesa comando.
  38. void envia_IF(void);                            // Envia comando IF;.
  39. void procesa_i2c(void);
  40.  
  41.  
  42. // INTERRUPCIONES /////////////////////////////////////////////////////////////
  43.  
  44.  
  45. #int_rda
  46. void serial_isr() {                             // Interrupción recepción serie USART.
  47.    rcvchar=0x00;                                // Inicializo caracter recibido.                    
  48.    if(kbhit()){                                 // Si hay algo pendiente de recibir ...
  49.       rcvchar=getc();                           // lo descargo y ...
  50.       addcbuff(rcvchar);                        // lo añado al buffer y ...
  51.    }
  52. }
  53.  
  54. #int_ssp
  55. void i2c_isr()    {
  56.    
  57.    int state=0;
  58.    state=i2c_isr_state();
  59.  
  60.    if(state < 0x80)                     //Maestro está enviando datos
  61.    {
  62.                                        //Para SSPCON1 = 0x3E;//0b00111110;//Si no se pone esta registro así no entra aquí para el bit de start y de stop
  63.       if (state == 0) //O bien es el bit de start o es el Address
  64.       {
  65.          if (!BFBIT) //Si no hay datos, el BFBIT=0 y por tanto es el START, el STARTBIT está a 1 en toda la trama menos cuando se eleva el STOPBIT
  66.          {
  67.             //Si ponemos antes el i2c_read(); vaciaremos el buffer y por BFBIT se pondrá a cero y no sabremos si es el address o el BITSTART
  68.            
  69.          }
  70.          else
  71.          {
  72.            
  73.          }      
  74.       }      
  75.       else if (state > 0)                        //Más bytes recividos, es data
  76.       {
  77.          if(!STOPBIT)
  78.          {
  79.            instruccion[state-1] = i2c_read();
  80.            if (instruccion[state-1]==0x3b) procesa_i2c();
  81.            
  82.          }
  83.          else
  84.          {
  85.             //Entra aqui si es el bit de stop, fin de trama de datos
  86.            
  87.             SSPSTAT=0x00; //Reseteamos el registro...no me digais...el compilador no lo hace solo con SSPCON1=0b00111110
  88.            
  89.          }
  90.       }  
  91.    }
  92.  
  93.    if(state == 0x80) //Master esta requiriendo datos
  94.    {
  95.       // received a START + ( I2C_ADR | 1)
  96.       // i2c_write(data) must be used to write a byte
  97.       i2c_write(0x05);
  98.      
  99.    }
  100.  
  101.    if(state > 0x80) //Master esta requiriendo datos
  102.    {
  103.       // master has read the byte sent by the slave.
  104.       // i2c_write(data) must be used to write a byte
  105.    }
  106.  
  107. }
  108.  
  109.  
  110. // Desarrollo de Funciones ////////////////////////////////////////////////////
  111.  
  112.  
  113. void inicbuff(void){                            // Inicia a \0 cbuff.
  114.    int i;
  115.  
  116.    for(i=0;i<lenbuff;i++){                      // Bucle que pone a 0 todos los
  117.       cbuff[i]=0x00;                            // caracteres en el buffer.
  118.    }
  119.    xbuff=0x00;                                  // Inicializo el indice de siguiente
  120.                                                 // caracter.
  121. }
  122.  
  123. int addcbuff(char c){                           // Añade a cbuff.
  124.  
  125.    if (xbuff==38) C=0x3B;                       // Si el buffer esta lleno procesarlo.            
  126.    switch(c){
  127.       case 0x3B:                                // ";" -> Habilita Flag para procesar
  128.          flagcommand=1;                         // Comando en Main.
  129.          break;
  130.       default:
  131.          cbuff[xbuff++]=c;                      // Añade caracter recibido al Buffer.
  132.    }
  133.      
  134. }
  135.  
  136.  
  137. // Programa Principal /////////////////////////////////////////////////////////
  138.  
  139.  
  140. void main() {                                   // Funciòn principal.
  141.    int band1;
  142.    inicbuff();                                  // Borra buffer al inicio.
  143.    SSPCON1 = 0x3E;//0b00111110;
  144.    enable_interrupts(global);                   // Habilito interrupciones globales.
  145.    
  146.    enable_interrupts(int_ssp);                 // Habilita la interrupcion I2C.
  147.    setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);    // Configura timer para temporizar.
  148.    port_b_pullups(TRUE);                        // Activo pull-up internas.  
  149.    do{  
  150.       while (mode==1){                          // Modo manual.
  151.       }
  152.       while (mode==2){
  153.          band1=band;                            // Capturo la banda para compararla con la siguiente lectura
  154.          BAND=(input_B()& 0x1F);                // Leo valor BDC en puerto B
  155.          
  156. // ENVIAR VALOR DE LA BANDA si band1!=BAND
  157.       }        
  158.                                                      
  159.       while (mode==4){                          // modo serie
  160.          enable_interrupts(int_rda);                  // Habilita Interrupción RS232.
  161.          if (get_timer1()>=65500)timeout++;     // Si desborda el timer incrementamos contador.
  162.          if (timeout>=30){                      // Miramos si el contador externo del timer desborda
  163.          if (intentos >= 5){
  164. // NO HAY COMUNICACION SERIE
  165.          }  
  166.          envia_IF();
  167.          }                                      // timer desborda y enviamos comando.
  168.          if(flagcommand) procesa_comando();     // Si hay comando pendiente
  169.       }                                         // de procesar ... lo procesa.
  170.          
  171.    }while(true);      
  172.  
  173. }
  174.  
  175.  
  176. // Procesador de Comandos /////////////////////////////////////////////////////
  177.  
  178.  
  179. void procesa_comando(void){                     // Función de procesado de comando.
  180.  
  181.    int i;
  182.    int16 frecuencia1;
  183.    
  184.    flagcommand=0;                               // Desactivo flag de comando pendiente.
  185.      
  186.    for(i=0;i<lenbuff;i++){                      // Bucle que pone a 0 todos los
  187.       Frec[i]=0x00;                             // caracteres en el argumento.
  188.    }
  189.    if(cbuff[0]=='I'&&cbuff[1]=='F'){            // Comparo inicio del buffer con comando "IF".
  190.       i=5;  
  191.       do{                                       // Extraemos argumento del buffer
  192.          Frec[i-5]=(cbuff[i]-48);               // a partir del 6º byte y hasta ";".
  193.       }while(cbuff[++i]!=0x3B);
  194.       frecuencia1=frecuencia;                   // Guardo temporalmente la frecuencia anterior
  195.       frecuencia=(Frec[0]*10000)+(Frec[1]*1000)+(Frec[2]*100)+(Frec[3]*10)+(Frec[4]);
  196.      
  197. // ENVIAR VALOR DE LA FRECUENCIA si frecuencia1!=frecuencia
  198.      
  199.       intentos=0;                               // Reinicio intentos de comunicacion RS232      
  200.       timeout=0;                                // Reinicio el contador del timer.
  201.       set_timer1(0);                            // Reinicio el timer1.
  202.    }
  203.    inicbuff();                                  // Borro buffer.
  204.  
  205. }
  206.  
  207.  
  208. void envia_IF(){                                // Funcion de envio de comando.
  209.    printf ("I");                                // Envio instruccion ...
  210.    delay_ms(120);                               // para que el TS850SAT ...
  211.    printf ("F");                                // envie la informacion ...
  212.    delay_ms(120);                               // de la frecuencia ...
  213.    printf (";");                                // Fin de trasmision.
  214.    timeout=0;                                   // Reinicio el contador del timer.
  215.    set_timer1(0);                               // Reinicion el timer1.
  216.    intentos=++intentos;
  217. }
  218.  
  219.  
  220. void procesa_i2c(){                             // Funcion de procesado de instruccion I2C
  221. int mode1;                                      // Variable temporal para guardar el modo actual
  222.    if (instruccion[0]==0x6d){                    // Modo en que debe adquirir la frecuencia
  223.       mode1=mode;                                // Guardo temporalmente el modo anterior
  224.       mode=instruccion[1];                      // Actualizo el modo con el actual
  225.       if (mode!=4 && mode1==4)output_low(pin_C5); // Si paso a modo NO rs232 bloqueo recepcion.
  226.       if (mode==4) output_high(pin_C5);         // Si el modo actual es rs232 activo recepcion
  227.       break;
  228.    }
  229. }

  Este seri el programa del master, solamente se limita (de momento) a enviar 3 bytes, los cuales los recibe correctamente el otro pic siempre que esté definido como esclavo evidentemente.
Código: CSS
  1. // programa pic principal para la presentacion
  2. // y procesado de la informacion, asi como
  3. // el envio de la decision a la cabeza remota
  4. #include <16f877a.h>                            // Definiciones del PIC 16F877A.
  5. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT    // Los Fuses de siempre.
  6. #use delay(clock=20000000)  // Oscilador a 20 Mhz..C>
  7. #use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7)  // Configuración del RS232.                    
  8. #use I2C(master,SDA=PIN_C4,SCL=PIN_C3,slow,force_hw,RESTART_WDT)
  9. #include <LCD(CHINA).C>
  10.  
  11. // Programa Principal /////////////////////////////////////////////////////////
  12. char cbuff[15];
  13. int i;
  14. int result=10;
  15.  
  16. void main (){
  17.  
  18.  
  19.       delay_ms(1000);
  20.       i2c_start();
  21.       i2c_write(0x20);
  22.       delay_ms(3);
  23.      
  24.      
  25.       i2c_write(0x6D);
  26.       i2c_write(0x04);
  27.       i2c_write(0x3b);
  28.       i2c_stop();
  29.      
  30.      
  31.       delay_ms(50);
  32.     while(true){
  33.    
  34.   }  
  35.      
  36.  
  37.    }


   Quiero que tengais en cuenta que es mi primer programa para pic, por lo que espero no seais excesivamente criticos con la programación jijijijiji.
   Un saludo
« Última modificación: 11 de Enero de 2012, 10:11:42 por krofta00 »

Desconectado krofta00

  • PIC10
  • *
  • Mensajes: 7
Re: Esclavo I2c no lee rs232
« Respuesta #3 en: 11 de Enero de 2012, 19:35:10 »
Hola de nuevo

  En el post anterior os puse el codigo del programa que estoy haciendo, pero es muy lioso y posiblemente solo lo entienda yo jijjiji.
  He realizado una prueba mas simple y pasa lo mismo. El ejemplo es este.
Código: CSS
  1. #include <16f876a.h>                            // Definiciones del PIC 16F877A.
  2. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT    // Los Fuses de siempre.
  3. #use delay(clock=20000000)                      // Oscilador a 20 Mhz.
  4. #use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7)  // Configuración del RS232.
  5. #use I2C(slave, sda=PIN_C4, scl=PIN_C3)
  6.  
  7.  
  8.  
  9.  
  10. // VARIABLES EN RAM ///////////////////////////////////////////////////////////
  11.  
  12.  
  13. char rcvchar=0x00;                              
  14.  
  15.  
  16. void main() {                                   // Funcion principal.
  17.    do {                                         // Bucle infinito.
  18.       rcvchar=getc();
  19.    } while (TRUE);                              // de procesar ... lo procesa.
  20. }

     Si en el proteus simuláis el circuito (solamente el pic y el puerto serie), veréis que al mandar un carácter por el puerto serie no lo recibe, en cambio si en la linea de definición del I2C cambiáis el slave por master, funciona perfectamente y el carácter que le mandéis por el puerto RS232 lo guarda en la variable rcvchar.
     Un saludo.

Desconectado japifer_22

  • PIC18
  • ****
  • Mensajes: 405
Re: Esclavo I2c no lee rs232
« Respuesta #4 en: 12 de Enero de 2012, 11:23:10 »
hola prueba configurando con esto

Código: [Seleccionar]
#USE RS232(BAUD=4800, BITS=8 ,PARITY=N, XMIT=PIN_C6, RCV=PIN_C7, stream=slave)
y luego lees con esto:
Código: [Seleccionar]
leo_UART=getc(slave);
de todas formas , te recomiendo que uses la interrupcion serial

Código: [Seleccionar]
#int_RDA   //interrupcion para la resepcion del master
void rda_isr()
{
//lectura_radio=0x00;
 if(kbhit()) {   //Esto es para que no se cuelgue el pic
             leo_UART=fGETC(slave);  //guarda el valor enviado por el puerto serie
             }
}
main {
   enable_interrupts(INT_RDA);   
   enable_interrupts(GLOBAL);      //todas las interrupciones activadas
while(TRUE){
//aquí has lo que quieras con con el comando que entra por el puerto serial (leo_UART)
}

saludos
« Última modificación: 12 de Enero de 2012, 11:30:35 por japifer_22 »

Desconectado krofta00

  • PIC10
  • *
  • Mensajes: 7
Re: Esclavo I2c no lee rs232
« Respuesta #5 en: 12 de Enero de 2012, 11:55:47 »
Hola japifer_22,

     Muchas gracias por el comentario.
     Te comento que estaba utilizando la interrupcion RDA. He seguido haciendo pruebas y a la conclusion a la que he llegado es que ese fallo de la recepcion en el puerto RS232 se produce cuando defino el pic como esclavo y el pin SCL=C3. Si cambio el pin, aunque quede como el pic esclavo si recibe las tramas del puerto serie, Otra forma en la que no se produce el fallo es definiendolo como master (independiente de definir el pin C3 como clock). Resumiento, solo se produce el fallo cuando se utiliza el pin C3 para SCL y a la vez está como esclavo.
     Tambien he visto que al simularlo en proteus y comprobar la linea RX del puerto serie con el osciloscopio del simulador, se confirma lo que habia comentado, es decir, la linea se mantiene a nivel alto (+5v), pero cuando envia la trama, el tren de pulsos es correct0 pero no pasa a 0v (nivel logico 0), sino que solo baja 2,5v. Comprobando cuando recibe bien, el 1 logico es 5v y el 0 logico s 0v (en el osciloscopio), pero cuando falla el nivel logico 1 es 5v, pero el nivel logico 0 es 2,5v.
     Voy a probar (no lo habia hecho) definiendo el stream en el rs232 como me comentas y con la interrupcion que me apuntas.
     Cuando lo pruebe comento los resultados.
     Un saludo y muchisimas gracias.
« Última modificación: 12 de Enero de 2012, 12:03:24 por krofta00 »

Desconectado krofta00

  • PIC10
  • *
  • Mensajes: 7
Re: Esclavo I2c no lee rs232
« Respuesta #6 en: 12 de Enero de 2012, 20:10:12 »
Ultimas pruebas........

   He probado lo que comentabas en el post japifer_22, pero malas noticias.........todo sigue igual, el pic sigue sin leer el puerto serie.
   Al final he montado el pic en una placa para probarlo fisicamente para descartar un problema de la simulación. Para hacer lo mas simple posible, hice un programa con las definiciones y un bucle infinito en el main, sin nada mas, solo eso, y despues de montarlo (solo el pic, sin conectar a nada (ni puerto serie ni i2c ni nada) y grabar en el pic varias posibilidades he observado lo siguiente:
  
                       Definiendo el puerto RS232 (sin definir I2C)---------> tension de la patilla RX del pic=5v.
                       Definiendo el puerto RS232 y el I2C como master --> tension de la patilla RX del pic=5v.
                       Definiendo el puerto RS232 y el I2C como esclavo con RCL=C1 y SDA=C4-----> tension de la patilla RX del pic=5v.
                       Definiendo el puerto RS232 y el I2C como esclavo con SCL=C3 y SDA=C1-----> tension de la patilla RX del pic=5v.
                       Definiendo el puerto RS232 y el I2C como esclavo con SCL=C3 y SDA=C4-----> tension de la patilla RX del pic=0.15v.

    Algo pasa al intentar utilizar el UART y el I2C (como esclavo) por hardware en la linea de RX, pero algo fisico, ya que probé tambien el programa que tenia hecho para ver que pasaba y en la linea RX me aparecian trenes de pulsos periodicos(comprobado fisicamente con un osciloscopio)..... que al ponerlo como master desaparecian.
    Voy a tener que buscar otra solucion al tema, o bien utilizar multimaster (ya busque por la red y no encuentro algo base para trabajar sobre ello), bien utilizar el rs232 con puertas logicas para poder comunicar 3 pics entre ellos con solo un bus o la otra opcion es utilizar comunicacion serie por 1 solo hilo, de  lo que hay unos ejemplos en el CSS y algo hay por red.... a ver por lo que me decido, no obstante seguire mirando estos dias a ver si encuentro algo de esto que pasa.
    Un saludo y muchas gracias a todos por leer y aguantar estas parrafadas y por intentar ayudar con lo que sabeis (que no es poco).
« Última modificación: 12 de Enero de 2012, 20:24:32 por krofta00 »

Desconectado krofta00

  • PIC10
  • *
  • Mensajes: 7
Re: Esclavo I2c no lee rs232
« Respuesta #7 en: 12 de Enero de 2012, 20:12:17 »
.
« Última modificación: 12 de Enero de 2012, 20:22:58 por krofta00 »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Esclavo I2c no lee rs232
« Respuesta #8 en: 12 de Enero de 2012, 22:44:05 »
  Sí que está bien raro el asunto.... Probaste con otra versión del compilador... tal vez se trate de un bug de CCS y te estás volviendo loco.  :5] :5] :5]

  Yo no uso CCS pero ni bien logre hacerme un tiempito veré de hacer dichos programas con HiTech a ver que ocurre con los PICs
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado krofta00

  • PIC10
  • *
  • Mensajes: 7
Re: Esclavo I2c no lee rs232
« Respuesta #9 en: 15 de Enero de 2012, 07:10:53 »
Hola de nuevo,


     Pues creo que ya está solucionado el tema.......... Despues de dar un monton de vueltas con el tema, parece ser que este hilo deberia de estar puesto mas arriba, en el de bugs del ccs ijjijijijji.
     Actualizado a la ultima version ya no lo hace, era problema del compilador.
     Muchas gracias a todos.


 

anything