TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: rugs20 en 15 de Agosto de 2010, 06:03:59

Título: Problema con spi_write(var)
Publicado por: rugs20 en 15 de Agosto de 2010, 06:03:59
Hola!!

Soy nuevo en esto del CCS y en la comunicacion por SPI y me ha surgido un problema que no entiendo y no logro resolver.

En el siguiente código:
Código: [Seleccionar]
#INCLUDE <16F88.h>
#FUSES XT,NOWDT
#USE delay (clock=8M)
#USE fast_io(A)
#USE fast_io(B)
#define SS PIN_B5


//PROGRAMA PRINCIPAL
void main(){

   int8 dato=0;
  
   set_tris_a(0b00000001); //Configuración I/O
   set_tris_b(0b00000010);
   output_high(SS);
  
   setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16 ); //Configuramos hardware spi.
      
      //Enviar valor numérico:
   output_low(SS);
   spi_write(0xAA);     //Este valor se envia correctamente
   output_high(SS);
    
      //Enviar variable:
   dato=0xBB;
   output_low(SS);
   spi_write(dato);     //Al enviar la variable, se produce un error.
   output_high(SS);
      
      
      
   while(1);  
}

El problema es quecuendo envío un valor numeric fijo(ex:spi_write(0xAA)), este se envia sin más, pero cundo envio una variable(spi_write(dato)), no funciona. a continuacion incluyo laimagen del spi debugger de Proteus:

(http://img295.imageshack.us/img295/1042/spidebbug.jpg)

Aqui esta la config del spi debbuguer...

(http://img826.imageshack.us/img826/5469/debbconf.jpg)


Agradeceria mucho que alguien me explicara por que me pasa esto, no se si seráproblema del CCS, del Proteus o mio jejeje :D

hasta pronto..

Título: Re: Problema con spi_write(var)
Publicado por: rugs20 en 31 de Agosto de 2010, 13:29:02
A nadie le ha pasado esto??
que mala suerte tengo, jejeje
a ver sa alguien me puede echar una manitaaaa...

gracias.. :)
Título: Re: Problema con spi_write(var)
Publicado por: AngelGris en 31 de Agosto de 2010, 18:14:06
¿Ya probaste colocando un retardo antes de volver a hacer "0" el pin SS para enviar la variable dato?
Título: Re: Problema con spi_write(var)
Publicado por: rugs20 en 01 de Septiembre de 2010, 12:50:32
Hola!!!

Gracias por tu respuesta, ya he probado, pero sigue sin funcionar, no se donde puede estar el error :5]

a seguir probando, jeje
Título: Re: Problema con spi_write(var)
Publicado por: rugs20 en 06 de Septiembre de 2010, 14:02:20
Hola!!

No consigo saber por que me pasa esto, he estado mirando el asm gnerado por el compilador y he visto que el codigo generado por spi_write(0xAA) y el generado por spi_write(dato), son diferentes, pero no consigo entenderlos.

Si alguien ha hecho esto alguna vez y me pudiera echar una mano....

Aqui dejo una imagen del asm:

(http://img16.imageshack.us/img16/102/asmj.jpg)

gracias.
Título: Re: Problema con spi_write(var)
Publicado por: BrunoF en 06 de Septiembre de 2010, 14:19:54
Hola. Los códigos son muy similares. Lo único que noto de distinto, fuera de las diferencias lógicas, es que en el primer caso, lee el registro del SSPBUF antes de efectuar la escritura, y en el segundo no.


Primer caso:
Código: ASM
  1. MOVF       SSPBUF,W                ;mover SSPBUF a W
  2.     MOVLW    0xBB                        ;cargar W con 0xBB
  3.     MOVWF    SSPBUF                    ;y volcarlo en SSPBUF. Esto inicia automaticamente el envio
  4.  
  5.     BSF         STATUS, RP0            ;cambio a banco de memoria 1
  6.  
  7. Prox:
  8.     RRF         SSPSTAT, W             ;poner el bit 0(BF) de SSPSTAT en el Carry
  9.     BTFSS     STATUS,C                 ;verificar si el STATUS,C vale 1.Si es cierto, saltear la proxima instruccion
  10.     GOTO      Prox                         ;seguir esperando..(STATUS,C=0)


Segundo caso:
Código: ASM
  1. MOVF    DATO,W                        ;cargar W con el valor de la variable DATO
  2.     MOVWF    SSPBUF                    ;y volcarlo en SSPBUF. Esto inicia automaticamente el envio
  3.  
  4.     BSF         STATUS, RP0            ;cambio a banco de memoria 1
  5.  
  6. Prox2:
  7.     RRF         SSPSTAT, W             ;poner el bit 0(BF) de SSPSTAT en el Carry
  8.     BTFSS     STATUS,C                 ;verificar si el STATUS,C vale 1.Si es cierto, saltear la proxima instruccion
  9.     GOTO      Prox2                       ;seguir esperando..(STATUS,C=0)


Es raro lo que comentás. Probaste poniendo SPI1 a la configuracion del SPI para forzarlo a usar los pines  del SPI del uC?

Saludos.


P.D.

Revisando el datasheet:

Citar
SSPSTAT,0 es el bit BF:

BF: Buffer Full Status bit
Receive (SPI and I2 C modes):
1 = Receive complete, SSPBUF is full
0 = Receive not complete, SSPBUF is empty

Transmit (in I2 C mode only):
1 = Transmit in progress, SSPBUF is full (8 bits)
0 = Transmit complete, SSPBUF is empty

Por lo que segun el datasheet, verificar ese bit para transmitir sólo es aplicable al modo I2C, no al  SPI...
Título: Re: Problema con spi_write(var)
Publicado por: AngelGris en 06 de Septiembre de 2010, 14:26:03
Yo lo único que noto diferente es en el caso de "spr_write(0xBB)" es la instrucción "movf 13,W".

No le encuentro mucho sentido ya que luego hay un "movlw 0xBB" eso lleva el valor 0XBB al registro W. Justamente estás llevando a W el dato que querés transmitir.

En el caso de "spi_write(dato)" hace "movf 21,W" Lleva a W el dato almacenado en la dirección 21 (que seguro es la dirección de tu variable dato en "CCS")

Luego todo es similar.

"movwf 13"  llevar el valor de W a la direccion 13 -registro SSPBUF-
"bsf 3.5"  hacer "1" el bit 5 del la dirección 3 -registro STATUS-
"RRF 14,W" rota a la derecha el registro 14 -SSPCON- y almacena el resultado en W
"btfss 3.0" testea si está seteado el bit de Carry en el registro STATUS
"goto xx" vuelve a la línea de "RRF 14,w"
Título: Re: Problema con spi_write(var)
Publicado por: rugs20 en 06 de Septiembre de 2010, 15:05:41
Hola!!

Gracias por contestar.

Contestando a BrunoF:
Lo de SPI1, creo que no es para CCS, en este compilador, al utilizar la funcion setup_spi, entiende que se va a utilizar el spi por hardware. Despues, lo que comentas del bit BF, creo que al ser una comunicacion Full-duplex, si se han recivido 8 bits (no importan los que sean), se supone que tambien se han enviado los 8 bits que queriamos enviar. (Creo que será por eso, es la primera vez que usoel SPI).

No consigo entender por que pasa esto  :5]...

Segun lo que dice el proteus, solo se envia un bit cuando utilizo la función para enviar la variable "dato" (ver imagen del primer mensaje).

Muchas gracias por vestras respuestas.
Título: Re: Problema con spi_write(var)
Publicado por: rugs20 en 07 de Septiembre de 2010, 12:45:20
Hola de nuevo!

Creo que he encontrado la solucion :-/, o por lo menos eso parece...

Comparando los codigos en asm me he dado cuenta que cuando utiliza spi_write(dato), el compilador no hace la lectura del SSPBUF antes de escribir el dato a enviar:

(http://img16.imageshack.us/img16/102/asmj.jpg)

En el data sheet, he leido algo de que el bit BF, se pone a 0 por hardware cuando se lee el registro SSPBUF (corregidme si me equivoco jeje)...

Si hago lo siguiente, parece funcionar correctamente:

Código: [Seleccionar]
   
   output_low(SS);
   #asm
   BCF    03.5
   MOVF   0x13,W     //Leo el registro SSPBUF
   #endasm
   spi_write(dato);    //Y despues envio el dato
   output_high(SS);


De esta forma, parece funcionar bien al simular en proteus.

Espero que esta sea una buena solución, si a alguien  se le ocurre otra cosa mejor que lo diga...

Gracias y hasta luegoo... ;-)
Título: Re: Problema con spi_write(var)
Publicado por: AngelGris en 07 de Septiembre de 2010, 14:08:50
No recuerdo como era la definición de "spi_write" pero me parece que también devolvía el byte leido a través del puerto SPI.

Si es que devuelve el dicho byte se podría probar de poner la sentencia de la siguiente manera

Código: C
  1. int8 dato_de_entrada; //la definicion de la variable
  2. dato_de_entrada = spi_write(dato);
Título: Re: Problema con spi_write(var)
Publicado por: rugs20 en 07 de Septiembre de 2010, 15:26:23
hola AngelGris!

Para lo que me comentas, existe la función spi_read(), que acabo de probar y tampoco funciona, cuando le doy una variable como dato de entrada, pero haciendo lo mismo que con la funcion spi_write, funciona correctamente.

Sería algo así:
Código: [Seleccionar]
   
   int8 res;
   #asm
   BCF    03.5
   MOVF   0x13,W
   #endasm
   res=spi_read(dat);
Título: Re: Problema con spi_write(var)
Publicado por: AngelGris en 07 de Septiembre de 2010, 15:48:55
Qué lo pario!  :5] :5] :5]

Por suerte encontraste esa forma de resolverlo. Habría que ver si dicho problema no es bug en la versión que estás usando. ¿Intentaste con otra versión de dicho compilador?
Título: Re: Problema con spi_write(var)
Publicado por: RALF2 en 07 de Septiembre de 2010, 23:43:04
Que tal amigos!
rugs20 te adjunto un circuito corriendo con spi_write haber si te ayuda tambien  :mrgreen:
Operando 100% con un 74hc595!  ;-)

Saludos
Título: Re: Problema con spi_write(var)
Publicado por: rugs20 en 08 de Septiembre de 2010, 10:44:33
Hola!!

Gracias al ejemplo de RALF2, he podido ver que AngelGris, tenía algo de razón con lo del retardo:

Citar
¿Ya probaste colocando un retardo antes de volver a hacer "0" el pin SS para enviar la variable dato?

solo que hay que ponerlo antes de volver a poner a 1 el pin SS, colocándolo de esta forma parece funcionar bien:
Código: [Seleccionar]
  dato=0xDD;
   output_low(SS);
   spi_write(dato);
   delay_ms(2);
   output_high(SS);  


Solo me queda una duda: ¿Por qué cuando se envia un valor ( spi_write(0xXX) ) no hay que poner ese "delay_ms()"? ¿Por qué con una variable si?

Gracias!!
Título: Re: Problema con spi_write(var)
Publicado por: rugs20 en 09 de Septiembre de 2010, 15:53:15
hola de nuevo!!

He estado probando con los retardos y para que funcione, hay que poner como mínimo un retardo de 15us (delay_us(15)).

¿Alguien sabe por que pasa esto?

¿Puede ser problema del SPI DEBUGGER del Proteus?

:shock: ESTO ME ESTA VOLVIENDO LOCO :shock:
Título: Re: Problema con spi_write(var)
Publicado por: mparra en 09 de Septiembre de 2010, 16:49:20
Hola to recientemente he tenido varios problemas con la comunicación SPI, hasta el punto de hacer por codigo la transmisión SPI. Estoy programando en C18, y tnego el ICD3. No se exactamente que circuito estas usando, pero todos los chips con protocolo SPI, tienen una frecuencia de funcionamiento máxima, y unos tiempos mínimos para todas las señales de reloj, datos y chip select/load. Cuanto tu mandas los 8 primeros bits, se queda a la espero de los siguientes 8 bit, para completar el total de 16 bit de direccion y de dato, con lo que es en este momento en que se tiene que poner a 1 el chip select, o la carga en este caso, aqui es donde necesita un retraso mínimo desde el envio del bit 0 hasta que se pone a 1 el CS. Lo que pasa que en mi caso estamos hablando de 50 ns. No se si el simulador necesita ese retardo, aunque en al realidad sea imposible de que se produzca. El pic que utilice era el 18F4550 a 48 MHz, con lo que el ciclo por instruccion es 83 ns, y segun el data sheet el tiempo máximo en las transiciones de de 50 ns, con lo que seria imposible que diese error en el proceso de carga.
No se si esto te servirá para algo, pero yo he estado dos semanas perdiendo el tiempo con el SPI, y finalmente el componente que era un driver de 4 dígitos de 7 segmentos estaba roto. Y para colmo en vez de darme los displays en cátodo comun me los suministraron en anodo comun.

Un saludo
Título: Re: Problema con spi_write(var)
Publicado por: RALF2 en 10 de Septiembre de 2010, 00:21:59
Epale rugs20!
Mira si le quitas el retardo de 2ms que coloque en mi programa veras que funciona igualmente bien  :mrgreen:
Si el circuito que estas probando es en proteus, como el que te hice, puede ser que no haga falta ese retardo. Ahora bien, en la realidad podria no funcionar, sin colocar un retardo  :? a que se debe eso, a que debes considerar que los circuitos no son ideales es decir que no responden de manera instantanea a cualquier señal de alli que el retardo que se coloca; para darle chance de que el periferico que quieres controlar pueda procesar los datos que tu le envias  :mrgreen:

Espero haberte aclarado un poco mas tus dudas.

Saludos
Título: Re: Problema con spi_write(var)
Publicado por: rugs20 en 10 de Septiembre de 2010, 11:56:49
Hola!!!

A mparra: Segun la hoja de datos del circuito, ese tiempo es de 10ns, pero ese no es el error, todavia no estoy utilizando el circuito, sino simulando en proteus con un spi debugger, ya que es la primera vez que hago esto :oops:

A RALF2: He probado quitando los retardos y funcina perfectamente con tu PIC18. Yo estoy utilizando un pic16f88, he adaptado tu código para este micro y también el circuito de proteus y no funciona. ¿Es al cambiar de micro cuando se produce el error?.... Te dejo el código y el DSN por si quieres verlo....

Código: [Seleccionar]
#include <16f88.h>
#device adc= 10
#use delay (clock= 4000000)
#fuses XT,PUT,NOWDT,NOLVP



void main()
{
   int i;
   
   SETUP_SPI(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
   output_low(pin_B5);
 
   while(true)
   {
      for(i=0;i<16;i++)
      {
          spi_write(i);
          //delay_ms(2);              //Quitando este delay, deja de funcionar con el 16f88
          output_high(pin_B5);
          output_low(pin_B5);
          delay_ms(600);
      }       
   }
}
Gracias

Título: Re: Problema con spi_write(var)
Publicado por: RALF2 en 10 de Septiembre de 2010, 18:06:44
Epale rugs20!
Si tal como indicas da fallas pero eso no es un mal de morirse, recuerda que estas simulando y podria haber un bug por el tipo de pic, pero, deberias probar en fisico a ver que tal funciona  :mrgreen:
En un circuito real debes colocar retardos porque si el micro envia los datos mas rapido de lo que el circuito que se quiere puede responder pues tendras problemas  :P

Saludos
Título: Re: Problema con spi_write(var)
Publicado por: AngelGris en 10 de Septiembre de 2010, 18:19:15
  Sí, por tal motivo siempre es conveniente leer el datasheet del periférico que se va a utilizar y así saber que tipos de retardo necesita.
Título: Re: Problema con spi_write(var)
Publicado por: rugs20 en 11 de Septiembre de 2010, 10:38:26
hola!

OK, cuando pruebe en en circuito real comentare los resultados a ver que tal.

gracias!!