Autor Tema: ads7841 interface SPI al pic18f4450  (Leído 4877 veces)

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

Desconectado hernanutn

  • PIC16
  • ***
  • Mensajes: 117
ads7841 interface SPI al pic18f4450
« en: 07 de Diciembre de 2014, 13:19:47 »
hola, mi consulta que programe  este adc en 8 bits para medir una tension, como el spi_read toma 8 bit lo guarde en una variable y despue lo multiplico por (5/255) para verlo en el lcd y me da la mitad del valor real osea para una tension de entrada de 2.5  el lcd muestra 1.2 V , entonces hice un corrimiento de un 1 bits hacia la derecha y ahi si muestra el valor real en el lcd., mi pregunta esta bien hacer eso? parece que un bit no lo carga en la variable..

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ads7841 interface SPI al pic18f4450
« Respuesta #1 en: 07 de Diciembre de 2014, 16:36:16 »
Es raro que un bit no te lo cargue en la variable, o mejor entenderlo como que no llegue al spi.

Ya que tenes un LCD para mostrar los valores e ir determinando que es lo que falla.

Al Mostrar el valor que llega al SPI, es decir lo que se recibe, si este esta mal, entonces es algo del ADC o algo en el SPI esta mal. En especial si lo haces por software.. Ya que podrias usar el SPI en hardware del PIC.
Si esta bien lo que llega no quedaria otra que mirar la multiplicacion en C y que no sea un problema de tipos de variables, pero darte justo la mitad suena algo mal en la conexcion SPI.

Desconectado hernanutn

  • PIC16
  • ***
  • Mensajes: 117
Re: ads7841 interface SPI al pic18f4450
« Respuesta #2 en: 07 de Diciembre de 2014, 17:00:01 »
Es raro que un bit no te lo cargue en la variable, o mejor entenderlo como que no llegue al spi.

Ya que tenes un LCD para mostrar los valores e ir determinando que es lo que falla.

Al Mostrar el valor que llega al SPI, es decir lo que se recibe, si este esta mal, entonces es algo del ADC o algo en el SPI esta mal. En especial si lo haces por software.. Ya que podrias usar el SPI en hardware del PIC.
Si esta bien lo que llega no quedaria otra que mirar la multiplicacion en C y que no sea un problema de tipos de variables, pero darte justo la mitad suena algo mal en la conexcion SPI.

uso el SPI por hardware  este es el codigo:
#include <18f4550.h>
#fuses XT,NOWDT     /* HS pra un crystal > 4Mhz  */

#use delay(clock=4000000)
#include "lcd.c"
#define CS PIN_B2
//#use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7, bits=8, parity=N)

int Templ=0;
int Temph=0;
int tension2=0;
 int16 Temp16Bits=0;
float temperatura=0,tension=0,valor=0;

void main(){

set_tris_b(0x1);                                        /*configuro el puerto C para el spi*/
setup_spi(spi_master|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_16);       /* SPI_CLK_DIV_16  SPI_XMIT_L_TO_H */  

lcd_init();

lcd_gotoxy(1,1);
printf(lcd_putc,"PROYECTO FINAL");
delay_ms(500);
printf(lcd_putc,"\f"); //borrar lcd
while(TRUE)
{

/*CONFIGURACION CANAL 0 CON 8 BITS*/
output_low(CS);
spi_write(159);
Temph=spi_read(0);//obtenemos el Temp alto del registro de temperatura
//Templ=spi_read(0);//obtenemos el Temp bajo del registro de temperatura
output_high(CS);
//Temp16Bits=make16(Temph,Templ);//convertimos a un registro de 16Bits

//Temp16Bits=Temp16Bits>>4;//descartamos los 4 bits menos significativos y nos queda 12 bits

//temperatura=Temp16Bits*0.122;    /*   FACTOR DE CONVERSION=(5*100/4096) */

//CANAL 1
output_low(CS);
spi_write(223);
tension2=spi_read(0);//obtenemos el Temp alto del registro de temperatura
//Templ=spi_read(0);//obtenemos el Temp bajo del registro de temperatura
output_high(CS);
tension2=tension2<<1;
Temph=Temph<<1;

valor=tension2*0.0210;
tension=Temph*0.0210;

lcd_gotoxy(1,1);
//printf(lcd_putc,"Temp=%3.1f C  \n",temperatura);
//lcd_gotoxy(1,2);
printf(lcd_putc,"Tension=%3.2f V  \n",tension);
lcd_gotoxy(1,2);
printf(lcd_putc,"tension2=%3.2f   \n",valor);
delay_ms(20);
}
}


con 12 bit pasa algo parecido, cuando tengo una variable de 16bit y debo correr 4 bit para obtener 12 tambien me da la mitad pero si hago un corrimiento de 3 anda bien..

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ads7841 interface SPI al pic18f4450
« Respuesta #3 en: 07 de Diciembre de 2014, 19:02:33 »
A mi me ocurrio algo parecido pero con otro micro y una pantalla LCD tactil, mi problema fue que tomaba mal los flancos, que es seguro que te este ocasionando eso. ya que yo tambinen perdia 1 bit.

Como te dije probar leer el valor del SPI en el LCD y ahi te vas a dar cuenta xD.

Si no podes cambiarle el modo

#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

Diagrama de tiempos:
http://elm-chan.org/docs/spi_e.html

Podrias usar el modo 3 y probar:

setup_spi(spi_master|SPI_H_TO_L|SPI_XMIT_L_TO_H|SPI_CLK_DIV_16);

Desconectado hernanutn

  • PIC16
  • ***
  • Mensajes: 117
Re: ads7841 interface SPI al pic18f4450
« Respuesta #4 en: 07 de Diciembre de 2014, 19:13:16 »
A mi me ocurrio algo parecido pero con otro micro y una pantalla LCD tactil, mi problema fue que tomaba mal los flancos, que es seguro que te este ocasionando eso. ya que yo tambinen perdia 1 bit.

Como te dije probar leer el valor del SPI en el LCD y ahi te vas a dar cuenta xD.

Si no podes cambiarle el modo

#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

Diagrama de tiempos:
http://elm-chan.org/docs/spi_e.html

Podrias usar el modo 3 y probar:

setup_spi(spi_master|SPI_H_TO_L|SPI_XMIT_L_TO_H|SPI_CLK_DIV_16);


probe lo que me dijiste y sigue igual, lo que me decis tomar el valor del SPI osea la cuenta Temph=spi_read(0); es decir mostrar el valor Temph por el lcd, si es eso ya lo probe sin el corrimiento da 63 y con el corrimiento el doble para una tension de 2.5

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ads7841 interface SPI al pic18f4450
« Respuesta #5 en: 07 de Diciembre de 2014, 23:44:30 »
A mi me paso que estaba leyendo mal, es decir en otro flanco, pero lo hice con un micro de TI. En realidad transporte un codigo de los tantos dando vuelta para los LCD tactil que usan un AD similar en configuracion y transmision ads7843. Por eso y al ver que tenias el mismo problema que me ocurria a mi, te dije que probaras eso. Eso si , todos los codigos que encontre eran hecho con SPI en software para los PIC o arduino

Otra de las cosas era que :

spi_write(159);
Temph=spi_read(0);//obtenemos el Temp alto del registro de temperatura
//Templ=spi_read(0);//obtenemos el Temp bajo del registro de temperatura

Yo no podia hacer eso.. Ya que no poseo esas funciones En mi caso el spi_write, escribiria pero a su ves meteria 0x00 al buffer de recepcion por el cual tenia que leer eso para eliminarlo.
Tambien tenia que escribir 0x00 para que llegaran los demas datos, imagino que todo eso lo hara el spi_read de por si. Con lo cual no deberia haber problema en tu caso (ya que veo que estas recibiendo).

Podrias probar lo siguiente.. puede que te tome un flanco mas cuando haces Temph=spi_read();
Si le sacas el comment a Templ

Temph=spi_read(0);//obtenemos el Temp alto del registro de temperatura
Templ=spi_read(0);//obtenemos el Temp bajo del registro de temperatura

Imagino que Templ deberia tener el ultimo bit que te falta.
Como hacer para darle ese clock extra no se que decirte, imagino que por eso todos los drivers hechos para PIC que encontre para los LCD tactiles esos estaban hechos con un SPI por software. A mi me funciono en hardware.
Y me acabo de fijar y usa el modo 0 como lo tenias. Lamentablemente mi programa es para otro integrado de otra marca el cual no te serviria.

Aca hay un ejemplo para el AD7843 como te digo es MUY similar en cuanto a la interfaz ( por no decir igual ), hasta la misma frecuencia de cristal, la unica diferencia es que esta puesto spi_master en mayuscula, el clk dividido por 4, y un delay. Y parece que anda.
http://www.ccsinfo.com/forum/viewtopic.php?t=44786

Desconectado hernanutn

  • PIC16
  • ***
  • Mensajes: 117
Re: ads7841 interface SPI al pic18f4450
« Respuesta #6 en: 08 de Diciembre de 2014, 00:37:07 »
bueno gracias pór la ayuda, la verdad no se que es, haciendo el corrimiento anda para cualquier tension que le pongo a la entrada del adc y tambien para un sensor de temperatura lm35, si hago que el factor de conversion sea 5/128 y sin hacer el corrimiento tambien da lo mismo, parece que usa 7 bit y no 8, capaz que se no leer bien la hoja de datos del adc ya que es la primera vez que uso este protocolo..
« Última modificación: 08 de Diciembre de 2014, 01:46:07 por hernanutn »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ads7841 interface SPI al pic18f4450
« Respuesta #7 en: 08 de Diciembre de 2014, 02:59:24 »
Estas perdiendo un bit :/

Incluso podrias probar hacerlo por software. Este es el driver de Suky
http://www.todopic.com.ar/foros/index.php?topic=32655.0

Lamento no poder haber sido de ayuda. Pero no se como funcionan exactamente las funciones spi de ccs pero no deberia haber problema. Y como digo son similares, escribis 8bytes y luego recibis 8/12 segun como lo configuras.
En tu caso estas perdiendo el ultimo (yo perdia el primero) asi que podes hacer entre el enviar y el recibir, poner a 1 y luego a 0 la salida del clk asi le da 1 pulso mas, y luego llegan si los 8. Es decir enviar un pulso mas de clk, si te fijas en el codigo de suky hace eso.

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: ads7841 interface SPI al pic18f4450
« Respuesta #8 en: 08 de Diciembre de 2014, 09:40:24 »
  Estoy de acuerdo con KILLERJC, estás perdiendo un bit. Eso suele ocurrir cuando el micro y el dispositivo no están trabajando bajo el mismo modo de SPI.
  ¿Probaste en todos los modos de SPI?
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: ads7841 interface SPI al pic18f4450
« Respuesta #9 en: 08 de Diciembre de 2014, 11:16:03 »
Estas operando a 8 bits o a 12bits?
Porque me pareces que configuras el adc a 8bits y luego lees a 12bits?  :?
Debes primero configurar el adc para 8 bits (en tu caso), escribiendo en este, el modo debe ser 0.
si es a 8bits que los vas a usar, mandas a escribir 0 por el spi para que este lea simultaneamente 8 bits y listo ya tienes el dato.
Para una mejor compresion te dejo este codigo en arduino facilmente convertible a ccs.

https://gist.github.com/madvoid/3648305

Saludos


Desconectado hernanutn

  • PIC16
  • ***
  • Mensajes: 117
Re: ads7841 interface SPI al pic18f4450
« Respuesta #10 en: 08 de Diciembre de 2014, 11:47:42 »
mira KILLERJC en la hoja de datos en el apartado 2.3 ads7841 creo que pierde un bit en la conversion osea una resolucion de 11

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ads7841 interface SPI al pic18f4450
« Respuesta #11 en: 08 de Diciembre de 2014, 12:36:42 »
Estas operando a 8 bits o a 12bits?

Esta usando 8 bits. 12-bits (LOW) or 8-bits (HIGH) es el bit 3.
Y esta usando 0x9F ( 1001 1111 ) Asi que es 8 bits.

mira KILLERJC en la hoja de datos en el apartado 2.3 ads7841 creo que pierde un bit en la conversion osea una resolucion de 11

Existe distintas formas de leerlo.
Una es utilizar 2 ciclos completos de 8 bits como lo estas haciendo, es decir 16 cliclos para 8bits, o 3 de 8bits, 24 ciclos para 12 bits
Pero tambien podes achicar estos tiempos, no necesariamente necesitas 24 ciclos para 12 bits, podes usar 16 ciclos para leer tambien 12 bits ( y los lees completos a los 12 bits ) o podes usar 15 ciclos y perder 1 bit como es lo que mostras en esa nota de aplicacion.

Tu problema esta en la "falta" de un ciclo de reloj o puede que el reloj se encuentre invertido o algo asi. tendrias que estudiar exactamente eso. Es la unica explicacion que tiene sentido a lo que te esta pasando. Por que tanto en 8 como en 12 bit te ocurre lo mismo. Proba agregarle el delay de unos uS despues de la escritura haber si lo soluciona aunque no creo que sea eso.
En fin de poder sacarse las dudas que es lo que pasa pasaria por mirar el ASM de eso. Si el ASM esta bien pasaria a debuggearlo en el PIC aunque sea con un osciloscopio xD
« Última modificación: 08 de Diciembre de 2014, 13:27:41 por KILLERJC »

Desconectado hernanutn

  • PIC16
  • ***
  • Mensajes: 117
Re: ads7841 interface SPI al pic18f4450
« Respuesta #12 en: 08 de Diciembre de 2014, 14:34:10 »
tengo un  tlc2543  que ya lo simule en el proteus y anda, pero al parecer necesita y crystal mayor a  4Mhz(es el que estoy utilizando) , ya que en la hoja dice f(I/O CLOCK)= 4.1 MHz(supongo que hace referencia al crystal) y me guie por este ejemplo TLC2543
« Última modificación: 08 de Diciembre de 2014, 16:37:32 por hernanutn »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ads7841 interface SPI al pic18f4450
« Respuesta #13 en: 08 de Diciembre de 2014, 16:52:48 »
tengo un  tlc2543  que ya lo simule en el proteus y anda, pero la parecer necesita y crystal mayor  4Mhz(es el que estoy utilizando) , ya que en la hoja dice f(I/O CLOCK)= 4.1 MHz(supongo que hace referencia al crystal) y me guie por este ejemplo TLC2543

Para nada ahi el esta usando un cristal y tal ves un PLL para llevarlo a 16Mhz ( lo ves en el clock=16000000 )
Vos estas usando tu cristal en 4 Mhz (Al menos es lo que dice tu codigo) y si queres podes usar el PLL para elevarlo a 96Mhz y luego dividirlo hasta tener 48Mhz/32/24/16 MHz (lo ves en la seccion del oscilador del datasheet )

Lo que tenes que fijarte es que tu SPI no supere esa velocidad. Como dije el tiene sus 16Mhz de entrada luego dividido por 4 por el SPI, quedando en 4Mhz, es decir dentro del margen de 0 a 4.1Mhz q expecifica el TLC2543, pero para eso por que no usar el A/D del micro ?. El ADS7841 es diferencial, aunque lo usas singled ended. Pero no es mi asunto si queres usar ese vamos por ese xD

Lo que si en ese ejemplo que pasaste respeta los tiempos (tal ves por demas ) o al menos se asegura que todo este bien agregandole un par de delays, por eso te decia que probaras poniendo unos delays entre medio de las escrituras y lecturas.

Citar
int8 ADC_get(void)
{  
   output_low(ad_cs);
   delay_ms(10);
   value=spi_read(0x04);
   delay_ms(100);
   output_high(ad_cs);
   return(value);
}

Podrias probar eso o tambien aumentarle la velocidad a 16Mhz o tal ves dividir el reloj por un divisor menor como 4 y ver si anda o no xD.

https://gist.github.com/madvoid/3648305

Mirando el codigo que paso RALF2:

msb = msb & 0x7F;
lsb = lsb >> 3;

El primer bit no lo toma y le quedan 5 en la segunda lectura si observas solo lo corre 3 veces. es decir le queda uno atras. Parece que es como funciona, mirando el datasheet hace eso.
Asi que directamente o lees 2 veces con spi_read(0); Correlo una ves y cargale el ultimo bit del otro xD Y no perdes ningun bit.
Sigo pensando que deberia entrar en 2 operaciones de 8 pero leer 2 vecesy la de agregar un ciclo de clock entre la escritura y la lectura serian la mas faciles de las soluciones a mi parecer

Código: [Seleccionar]
output_low(CS);
spi_write(159);
Temph=spi_read(0);//obtenemos el Temp alto del registro de temperatura
Templ=spi_read(0);//obtenemos el Temp bajo del registro de temperatura
output_high(CS);
Y aca haces el corrimiento

O

Código: [Seleccionar]
output_low(CS);
spi_write(159);
output_high(CLK); //el pin de clock
output_low(CLK);
Temph=spi_read(0);//obtenemos el Temp alto del registro de temperatura
output_high(CS);

Vuelvo a decir, probar no cuesta nada. Y obviamente todo esto si te interesa ese bit, que ya demasiado lo acortaste a 8 bits, para encima achicarlo a 7, si vas a leer 2 veces entonces directamente usa los 12 bits y listo. Estarias usando el mismo tiempo.
« Última modificación: 08 de Diciembre de 2014, 17:10:25 por KILLERJC »

Desconectado hernanutn

  • PIC16
  • ***
  • Mensajes: 117
Re: ads7841 interface SPI al pic18f4450
« Respuesta #14 en: 08 de Diciembre de 2014, 18:49:59 »
claro, antes habia hecho temp16bits=make16(Temph,Templ), y al temp16bits como  es de 16 bit lo corria 4 y quedaba con 12 bit (supuestamente)y me daba la mitad del valor  perdiendo el bit0(pensando que el bit12 de la conversion estaba en la parte mas alta en la variable, pero esta en el bit15 por eso lo corria 3 y daba)  entonces hice esto y funciona

Temph = Temph & 0x7F;
Temp16Bits=make16(Temph,Templ);//convertimos a un registro de 16Bits

Temp16Bits=Temp16Bits>>3;

temperatura=Temp16Bits*0.122;    /*   FACTOR DE CONVERSION=(5*100/4095)  */


« Última modificación: 08 de Diciembre de 2014, 19:51:02 por hernanutn »


 

anything