Hello,
i am trying to program my MSP430 with ADS1248 via SPI.
Can someone post me some example codes for the IAR compiler?
Best regards,
Diego V.
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello,
i am trying to program my MSP430 with ADS1248 via SPI.
Can someone post me some example codes for the IAR compiler?
Best regards,
Diego V.
Diego,
Unfortunately we do not have a direct example for you to run on IAR at this time. However I should be able to help you get things going. What MSP430 are you using? Are you mostly concerned about setting up the SPI or reading and writing the device?
Best regards,
Bob B
Bob,
Thanks for your answer.I am using a MSP430F2132.
In a previous project achieved successfully communicate with an AD7793 (Analog Device) via SPI. Now I want to change the ADC by the type of application, and chose the ADS1248. I can use the application note: sbaa121 "Interfacing the ADS1241 to MSP430 Processors"?
Best regards,
Diego V.
Diego,
The code example you mentioned should get you started. Obviously the header definition will be different as the register set is different. Also, some of the commands/functions might not be compatible with IAR as the project was written for GCC, but it should be mostly ok. Let me know if you have specific questions about getting things to work and I'll be glad to help you through them.
Best regards,
Bob B
Bob,
I'm trying to read the temperature of a three-wire RTD, using the circuit of Figure 2 (sbaa180.pdf).
They do not work the excitation current sources. The control registers write the following values:
MUX0 = 0x01
VBIAS = 0x00
MUX1 = 0x20
SYS0 = 0x60 (PGA = 64)
IDAC0 = 0x06 (Idac = 1mA)
IDAC1 = 0x01 (AIN0->IDAC1 , AIN1->IDAC2)
Using Rbias = 1K would have to measure a Vref = 2V but I measure 0V.
The result of the conversion is = 8388607 (use RDATA command) -> Rtd = 31.25 ohms????
Diego,
It looks like your settings are correct assuming you are connected to REF0 for your reference. Can you send me scope shots of your communication just to verify your communication is correct? Have you read back your register values after setting them to make sure they are what you expect? The other thing is to verify that you are actually getting good connections to the ADS1248. Can you send me a picture of your setup?
Something else seems to be wrong. You should read different values (like full-scale) if you don't have a reference voltage. I would verify my communication to the device with an oscilloscope. Your data should be stable on the falling edge of SCLK.
Best regards,
Bob B
Bob,
The reference is connected to REF0.
These are the registers values after the configuration (command RREG):
MUX0 = 0x01
VBIAS = 0x00
MUX1 = 0x20
SYS0 = 0x60
OFC0 = 0x00
OFC1 = 0x00
OFC2 = 0x00
FSC0 = 0x00
FSC1 = 0x1A
FSC2 = 0x40
IDAC0 = 0x86
IDAC1 = 0x01
GPIOCFG = 0x00
GPIODIR = 0x00
GPIODAT = 0x00
Best regards,
Diego V.
Diego,
For the analog portions to be active, START must be logic high. Is START high? Also, do you have any scope shots of the communications?
Best regards,
Bob B
Bob
Yes, START is active. Unfortunately I haven't high-frequency oscilloscope.
I find it strange that Vref = 0V. The current sources not seem to work.
Best regards,
Diego V.
Diego,
I suspect you have communication issues. Are you able to read the registers and verify the contents have been written as you would expect? Can you send me a code snippet of how you are setting up the USCI peripheral?
Best regards,
Bob B
Bob,
These are the registers values after the configuration (command RREG):
MUX0 = 0x01
VBIAS = 0x00
MUX1 = 0x20
SYS0 = 0x60
OFC0 = 0x00
OFC1 = 0x00
OFC2 = 0x00
FSC0 = 0x80
FSC1 = 0x1C
FSC2 = 0x40
IDAC0 = 0x86
IDAC1 = 0x01
GPIOCFG = 0x00
GPIODIR = 0x00
GPIODAT = 0x00
Attached code used:
/*============================================================================* * * * FICHERO....: main.c * * PROYECTO...: * * AUTORES....: * * FECHA......: * * VERSI�N:.... * * ESTADO.....: * * * * DESCRIPCION: * * * *============================================================================*/ /*----------------------------------------------------------------------------* * DEFINICI�N DE LAS CABECERAS A INCLUIR * *----------------------------------------------------------------------------*/ #include "math.h" #include "stdbool.h" #include "SPIADS1248.h" #include "Medidas.h" #include "msp430x21x2.h" /*----------------------------------------------------------------------------* * C�DIGO DE LAS FUNCIONES GLOBALES DEL M�DULO * *----------------------------------------------------------------------------*/ void Inicia (void); /*============================================================================* * Comienzo de la funci�n main() * * * * Programa principal, se encarga de inicializar todos los perif�ricos y del * * tratamiento de los datos capturados. es un bucle que se est� siempre * * ejecut�ndose y se corresponde con el proceso de menor prioridad. * *============================================================================*/ int main(void) { //Variables locales de la funci�n float Rtd = 0; //Almacenna el resultado calculado de las medidas unsigned int i=0,j=0; unsigned long Code=0; //Valor de Lectura Instantaneo //C�digo de la funci�n Inicia(); //iniciar perifricos del uP ADS1248CargaInicial(); //Bucle infinito del programa principal while(1) //Ejecutar siempre { Code = ADS1248ReadData(); //Usando una PT100 //Rtd = 2*Rref*Code/((2^23-1)*Gain) Rref=1K Gain=64 Rtd = 3.725290742E-6*(float)(Code); } } //Fin de la funci�n main() /*============================================================================* * Comienzo de la funci�n Inicia() * * * * Se encarga de inicializar los perif�ricos, los puertos de E/S y de * * arrancar las comunicaciones modbus. * *============================================================================*/ void Inicia (void) { //Variables locales de la funci�n int i=0; //Variable auxiliar para recorrer las tablas //C�digo de la funci�n P1DIR|=1; //Se configuran los puertos de salida //P1.0 Led de Indicacion //P1.1 Boton de Reset para Ajustes por Defecto P1OUT&=(~BIT0); //Se apaga el Led WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer //Inicializaci�n de los relojes de forma segura, tal y como recomienda TI //Cuando Inicia el MCLK esta aliemntado con el DCO a aprox. 1.1Mhz __delay_cycles(250000); //Realim b zamos una pausa aprox 150uS es el TURN ON del Regulador if (CALBC1_8MHZ ==0xFF || CALDCO_8MHZ == 0xFF) { while(1); // If calibration constants erased // do not load, trap CPU!! } BCSCTL1 = CALBC1_8MHZ; // Set DCO to 8MHz DCOCTL = CALDCO_8MHZ; } //Fin de la funci�n Inicia()
/*============================================================================* * * * FICHERO....: SPIAD1248.c * * PROYECTO...: Modulo Remoto de Entradas Analogicas* * AUTORES....: Diego Villarraza * * FECHA......: 14 de Julio de 2012 * * VERSI�N:.... 1.0 * * ESTADO.....: Inicio * * * * DESCRIPCION:Funciones para comunicarse via SPI con el AD ADS1248 * * * *============================================================================*/ #include "msp430x21x2.h" #include "SPIADS1248.h" /*----------------------------------------------------------------------------* * DEFINICI�N DE VARIABLES GLOBALES DEL M�DULO * *----------------------------------------------------------------------------*/ unsigned char regreadads[15]; //Tabla con los registros de control del AD unsigned char regwriteads[15]; //Tabla con los registros de control del AD /*----------------------------------------------------------------------------* * C�DIGO DE LAS FUNCIONES GLOBALES DEL M�DULO * *----------------------------------------------------------------------------*/ void ADS1248AssertCS( int fAssert) { if (fAssert) P3OUT &= ~ADS1248_CS; else P3OUT |= ADS1248_CS; } int ADS1248SPIInit(void) { //Configuramos el puerto 3 para utilizar las siguientes salidas //P3.3 SCLK -> Serial Clock Out (Salida) //P3.1 UCBOTXD -> Master Out (Salida) //P3.2 UCBORXD -> Master In (Entrada) P3SEL |= ADS1248_SCLK + ADS1248_DOUT_DRDY + ADS1248_DIN; // P3.1,2,3 USCI_B0 option select P3DIR |= ADS1248_CS; //P3.7 Como salida para manejar la habilitacion del AD P1DIR |= ADS1248_RESET + ADS1248_START; //P1.5 (Salida) Reset del AD //P1.6 (Salida) Start el AD //P1.7 (Entrada) DRDY el AD //Definimos el registro de control: 8 bit, Modo Master, MSB se recibe primero, Modo Sincronico UCB0CTL0 |= UCMST + UCMSB + UCSYNC; //Definimos el segundo registro de control: Fuente de Reloj SMCLK UCB0CTL1 |= UCSSEL_2; // SMCLK //Pre-escalamos el Clk a SMCLK/2 = 8Mhz/2 UCB0BR0 = 0x02; // /2 UCB0BR1 = 0; // //UCB0MCTL = 0; // No modulation //Habilitamos para que funcione el Modulo de Comunicacion UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** //Secuencia de Encendido ADS1248AssertCS(0); P3OUT |= ADS1248_START; //Start High P3OUT |= ADS1248_RESET; //Reset High __delay_cycles(128000); //Pausa de 16ms -> Fosc*16ms=8Mhz*16ms = 128000 segun datasheet ADS1248AssertCS(1); return 0; } int ADS1248CargaInicial(void) { int i; int resultado; //Iniciamos puertos del uC para comunicarse con el AD y configuramos el UART para utilizar SPI ADS1248SPIInit(); //Realizamos un reset del AD ADS1248SendResetCommand(); //Enviamos el comando SDATAC ya que por default el AD empieza con RDATAC ADS1248Stop(); //Leemos todos los registros del AD para guardar los registros que nos se modifican y despues //poder comparar todos los registros ADS1248ReadRegister(); //Copiamos registro tabla de registros leidos a tabla de registros a escribir for(i=0;i<15;i++) regwriteads[i] = regreadads[i]; //Configuramos los primeros cuatro registros /* MUX0 = 00 Corriente de Burnout off 000 AIN0 es positivo 001 AIN1 es negativo = 0x01 */ regwriteads[ADS1248_MUX0_REGISTER] = 0x01; /* VBIAS = 0x00 No se aplica Vbias */ regwriteads[ADS1248_VBIAS_REGISTER] = 0x00; /* MUX1 = 0 Oscilador Interno 01 Referencia interna siempre ON (necesario para usar IDAC) 00 REF0 se utiliza una Rbias externa 000 Operacion Normal = 0x20 */ regwriteads[ADS1248_MUX1_REGISTER] = 0x20; /*SYS0 = 0 Siempre es 0 110 Ganancia es 64 0000 5SPS = 0x60 */ regwriteads[ADS1248_SYS0_REGISTER] = 0x60; //Escribimos los primeros cuatro registros ADS1248WriteRegister(ADS1248_MUX0_REGISTER , 4); //Configuramos registro IDAC0 y IDAC1 /*IDAC0 = 0000 siempre es 0 0 DOUT//DRDY funcionamiento pin solo como datos de salida 110 IDAC = 1ma = 0x06*/ regwriteads[ADS1248_IDAC0_REGISTER] = 0x06; /*IDAC1 = 0000 La primer fuente de corriente en AIN0 0001 La segunda fuente de corriente en AIN1 = 0x01*/ regwriteads[ADS1248_IDAC1_REGISTER] = 0x01; //Escribimos registro ADS1248WriteRegister(ADS1248_IDAC0_REGISTER , 2); //Leemos registros para comprobar que la escritura fue exitosa ADS1248ReadRegister(); //Comparamos registros resultado = 0; for(i=0;i<15;i++) { if (regwriteads[i] != regreadads[i]) resultado = 1; } __delay_cycles(10000); //Pausa return resultado; } /* ****************************************************************************** */ /*Escribe los parametros en los registros de control*/ int ADS1248WriteRegister(int StartAddress, int NumRegs) { int i; unsigned char dummy; unsigned char reg[15]; //Tabla que datos a escribir //Copia datos de tabla general a tabla a transmitir for (i=0;i<NumRegs;++i) { reg[i] = regwriteads[StartAddress + i]; } ADS1248Stop(); //Detiene la recopilacion de datos // assert CS to start transfer ADS1248AssertCS(1); // CS goes low //Primer Comando: La direccion del primer registro a escribir while(!(IFG2 & UCB0TXIFG)); UCB0TXBUF= ADS1248_CMD_WREG + StartAddress; //Segundo Comando: El numero de Registros a escribir while(!(IFG2 & UCB0RXIFG)); dummy=UCB0RXBUF; while(!(IFG2 & UCB0TXIFG)); UCB0TXBUF=NumRegs - 1; //Bytes de Datos: Datos de los registros a escribir while(!(IFG2 & UCB0RXIFG)); dummy=UCB0RXBUF; for (i=0;i<NumRegs;++i) { while(!(IFG2 & UCB0TXIFG)); UCB0TXBUF=reg[i]; while(!(IFG2 & UCB0RXIFG)); dummy=UCB0RXBUF; } __delay_cycles(1000); //Pausa ADS1248AssertCS(0); // CS goes high return 0; } /*Lee los datos de los registros de control*/ void ADS1248ReadRegister() { unsigned char dummy; unsigned char reg[15]; int i; ADS1248Stop(); //Detiene la recopilacion de datos __delay_cycles(40); //Pausa // Reset SPI ADS1248AssertCS(0); // CS goes high __delay_cycles(10); //Pausa ADS1248AssertCS(1); // CS goes low while(!(IFG2 & UCB0TXIFG)); UCB0TXBUF=ADS1248_CMD_RREG; // Command for register read while(!(IFG2 & UCB0RXIFG)); dummy=UCB0RXBUF; while(!(IFG2 & UCB0TXIFG)); UCB0TXBUF=0x0E; // Command for number of registers to read while(!(IFG2 & UCB0RXIFG)); dummy=UCB0RXBUF; for (i=0; i<15; ++i) { UCB0TXBUF=0xff; while(!(IFG2 & UCB0RXIFG)); reg[i]=UCB0RXBUF; // Lee los datos de los registros } //Copia tabla leida a la tabla general for(i=0;i<15;i++) regreadads[i] = reg[i]; ADS1248AssertCS(0); // CS goes high } //Lee u long ADS1248ReadData() { char dummy; unsigned int data1, data2, data3; long dato; // assert CS to start transfer ADS1248AssertCS(1); // CS goes low //Espero por RDY sea bajo while(P1IN & ADS1248_DRDY); //Se envia comando RDATA while(!(IFG2 & UCB0TXIFG)); UCB0TXBUF=ADS1248_CMD_RDATA; while(!(IFG2 & UCB0RXIFG)); dummy=UCB0RXBUF; __delay_cycles(20); //Pausa //Lee datos como palabra de 24 bits. UCB0TXBUF=0xff; while(!(IFG2 & UCB0RXIFG)); data1=UCB0RXBUF; //MSB //Lee datos como palabra de 24 bits. UCB0TXBUF=0xff; while(!(IFG2 & UCB0RXIFG)); data2=UCB0RXBUF; //Mid-Byte //Lee datos como palabra de 24 bits. UCB0TXBUF=0xff; while(!(IFG2 & UCB0RXIFG)); data3=UCB0RXBUF; //LSB dato = ((long)data1<<16)+((long)data2<<8)+((long)data3); ADS1248AssertCS(0); // CS goes high return dato; } int ADS1248SendResetCommand(void) { char dummy; // assert CS to start transfer ADS1248AssertCS(1); // CS goes low // send the command byte while(!(IFG2 & UCB0TXIFG)); UCB0TXBUF= ADS1248_CMD_RESET; while(!(IFG2 & UCB0RXIFG)); dummy=UCB0RXBUF; // de-assert CS ADS1248AssertCS(0); // CS goes high __delay_cycles(48000); //Pausa de 0.6ms -> Fosc*0.6ms=8Mhz*0.6ms = 128000 segun datasheet return 0; } /* stop collecting data */ void ADS1248Stop(void) { unsigned char dummy; // Reset SPI ADS1248AssertCS(0); // CS goes high __delay_cycles(30); //Pausa ADS1248AssertCS(1); // CS goes low // Command to stop taking continous readings //Analizar espera que DRDY sea bajo //Espero por RDY sea bajo while(P1IN & ADS1248_DRDY); while(!(IFG2 & UCB0TXIFG)); UCB0TXBUF=ADS1248_CMD_SDATAC; while(!(IFG2 & UCB0RXIFG)); dummy=UCB0RXBUF; __delay_cycles(20); //Pausa ADS1248AssertCS(0); // CS goes high }
To test, We replaced the AD by an equal. In this case the readings are different values. Before reading only = 8388607.
Best regards,
Diego V.
Diego,
I can't find anything obviously wrong with your code. I did notice that you do not sign extend your data when reading the result. You need to sign extend from 24 bit value to 32 bit as the data result is a signed value.
I would still try to verify the communication with an oscilloscope if possible. I would also verify all my analog connections, especially ground. Can you send me a picture of your setup?
Best regards,
Bob B
Bob,
Ok, I will try to send them.
When should the reference voltage appear?. After writing the control registers, or when executo RDATA command.
Best regards,
Diego V.
Diego,
You should see the reference voltage as soon as the internal reference and IDACs are turned on. This happens as soon as you complete the register write.
Best regards,
Bob B
Bob,
Finally, I found the problem and now works fine. VREFCOM pin should be grounded.
What is the maximum value of the PGA gain that I can use? When Idac = 1mA and Rbias = 1K. Using a RTD in the range of -50 ° C to 50 ° C. Rcomp unused.
Best regards,
Diego V.
Diego,
Oh, yes, VREFCOM should be grounded and there should be a cap between VREFOUT and VREFCOM. Sorry I missed that before. As far as setting the bias point and determining maximum gain, my colleague has put together information regarding the calculations. It can be found here:
Best regards,
Bob B
Bob,
Finally everything works great.
Given that the circuit will be used in an industrial environment. I have to try to make it suitable for this.
What type of power supply isolated is recommended to have an has a Vin = 24Vdc and Vout = 5v and 3.3 V?
How can isolate the sensor inputs?
Does the SPI communication between UC and the AD should be isolated?
Best regards,
Diego
Diego,
Glad to hear you are making progress. For the supply, it is best to have a linear, well regulated, low noise supply. You will need to determine your current needs to find a regulator that fits your requirement. The place to start is:
http://www.ti.com/lsds/ti/analog/powermanagement/power_portal.page
Sensor connecttions to the analog inputs can be as simple as a filtering circuit using R-L-Cs or something much more elaborate. This will depend on what sensors are being connected, and whether true isolation is necessary or just noise filtering. Sometimes Schottky or TVS diodes are used as overvoltage protection.
Digital isolation is usually not necessary. However, if the digital section is extremely noisy isolation can be used. You can do a search for isolators similar to the power products search. One part that may work is the ISO7240.
Best regards,
Bob B
Bob
Now I need to change the type of temperature sensor. I will use a thermistor 10K@25ºC.
What kind of topology is recommended to use? I'm testing with radiometric topology. Two-Wire RTD Application (figure 1 sbaa180.pdf).
Because I want to measure in the range of -50 ° C to 50 ° C then resistance range 670k to 3.6 K. If we use IDAC = 100uA -> Vin = 100uA * 670k =67V. To avoid this I put in parallel 10K resistor.
I use a Rbias = 20K. (Vref = 100ua*20K = 2V)
Best regards,
Diego V.
Diego,
The circuit you are describing should work. I don't know of any specific recommendation as there are a number of variables, including self-heating of the thermistor. There are generally two main considerations. One is the amount of current to reduce self-heating effects (and you might want to consider 50uA instead of 100uA.) The other consideration is linearization for the desired temperature range. The parallel resistor should help with this, but there are a variety of methods that can be used for this purpose.
Best regards,
Bob B
Bob,
We designed and constructed the circuit to measure temperature with thermistors, using Idac a Rbias and a resistor in parallel with each sensor.
In the lab, everything works perfectly, when we place the sensors in an industrial environment unfortunately did not work well.
What lowpass filter circuit recommended for entries AIN0 ... AIN7?.
What data rate is better?
We note that there is too much interference between channels.
Please any suggestion is accepted we can not find a solution and we need it urgently.
Best regards,
Diego
Diego,
Can you send me your schematic and board layout? If you don't want to post it publicly you can start a conversation with me by clicking on my name, and then click on start a conversation on the upper right corner of the page.
Best regards,
Bob B
Hi Thuy,
our forum is used to help customers with questions regarding devices from Texas Instruments. If you have questions regarding devices from Analog Devices please contact them through a different channel. I am hoping for your understanding.
However you might want to have a look at our new ADS1220 which would be an ideal solution to implement a 4-20mA measurement.
Other alternatives to the devices you mentioned would be ADS1247 and ADS1248.
Regards,