Hi to everyone and good 2015 summer!
I’m designing a multi-channel measurement system combining two LMP90100
And connecting them to a Energy Micro EFM32G290 Cortex-M3 microcontroller.
I connect each of the SPI channels to a different SPI port in the MCU, and I have also configured the SPI_DRDYB_D6 of each LMP90100 to 2 input GPIO pins in the
MCU, so when I have a sample, the MCU activate the GPIO interrupt routine to get the converted samples.
I have some problems configuring the LMP90100:
1-the ODR:
I try to configure 3 differential channels in each of the LMP90100, and if I put more than 13.42 sps in the channels (register CHx_CONFIG), then when I start measuring
The signals vanishes after having measured only a few samples . Why???
2-the stability of the samples.
When I get the samples (ODR configured to 13.42 sps), there are problems with the stability of the signals measured, because there are great variations in the converted samples with time, having the channels connected to calibrators (of different type, for example Pt100, RTD, mA and V). I don’t know the reason for that, but I presume it’s related with the ODR configuration, cause in a higher ODR config, I get some samples without variation, but very spaced in time.
Can anyone give an anwer to these 2 questions?
I give the configuration of the internal LMP90100 registers and also the config of the SPI channels in the MCU (pay attention that many of the parameters are in the define section with a value different that the final value in the TI_LMP90100_WriteRegSettings procedure, because there are 2 different LMP90100 chips, with different parameters to configure):
#define TI_LMP90100_RESETCN_REG_VALUE (0xC3) /* Register and Conversion Reset */
#define TI_LMP90100_SPI_HANDSHAKECN_REG_VALUE (0x00)//(0x01) /* SPI SDO High Z Delayed */
#define TI_LMP90100_SPI_STREAMCN_REG_VALUE (0x84)//(0x82)//(0x00)
/*(0x84) SPI Control Streaming mode: 5 bytes */
#define TI_LMP90100_PWRCN_REG_VALUE (0x00) /* Active Mode */
#define TI_LMP90100_DATA_ONLY_1_REG_VALUE (0x1A) /* Active Mode */
#define TI_LMP90100_DATA_ONLY_2_REG_VALUE (0x02) /* Active Mode */
#define TI_LMP90100_ADC_RESTART_REG_VALUE (0x00)
#define TI_LMP90100_GPIO_DIRCN_REG_VALUE (0x40)
#define TI_LMP90100_GPIO_DAT_REG_VALUE (0x40)
#define TI_LMP90100_BGCALCN_REG_VALUE (0x00)
#define TI_LMP90100_SPI_DRDYBCN_REG_VALUE (0x83)
#define TI_LMP90100_ADC_AUXCN_REG_VALUE (0x0A)
#define TI_LMP90100_SPI_CRC_CN_REG_VALUE (0x00)
#define TI_LMP90100_SENDIAG_THLDH_REG_VALUE (0x00)
#define TI_LMP90100_SENDIAG_THLDL_REG_VALUE (0x00)
#define TI_LMP90100_SCALCN_REG_VALUE (0x00)
#define TI_LMP90100_ADC_DONE_REG_VALUE (0xFF)
#define TI_LMP90100_SENDIAG_FLAGS_REG_VALUE (0x00)
#define TI_LMP90100_ADC_DOUT2_REG_VALUE (0x00)
#define TI_LMP90100_ADC_DOUT1_REG_VALUE (0x00)
#define TI_LMP90100_ADC_DOUT0_REG_VALUE (0x00)
#define TI_LMP90100_SPI_CRC_DAT_REG_VALUE (0x00)
#define TI_LMP90100_CH_STS_REG_VALUE (0x00)
#define TI_LMP90100_CH_SCAN_REG_VALUE (0xD0)
#define TI_LMP90100_CH0_INPUTCN_REG_VALUE (0x01)
#define TI_LMP90100_CH0_CONFIG_REG_VALUE (0x35)
#define TI_LMP90100_CH1_INPUTCN_REG_VALUE (0x53)
#define TI_LMP90100_CH1_CONFIG_REG_VALUE (0x34)
#define TI_LMP90100_CH2_INPUTCN_REG_VALUE (0x25)
#define TI_LMP90100_CH2_CONFIG_REG_VALUE (0x30)
#define TI_LMP90100_CH3_INPUTCN_REG_VALUE (0x37)
#define TI_LMP90100_CH3_CONFIG_REG_VALUE (0x70)
#define TI_LMP90100_CH4_INPUTCN_REG_VALUE (0x01)
#define TI_LMP90100_CH4_CONFIG_REG_VALUE (0x70)
#define TI_LMP90100_CH5_INPUTCN_REG_VALUE (0x13)
#define TI_LMP90100_CH5_CONFIG_REG_VALUE (0x70)
#define TI_LMP90100_CH6_INPUTCN_REG_VALUE (0x25)
#define TI_LMP90100_CH6_CONFIG_REG_VALUE (0x70)
#define TI_LMP90100_CH0_SCAL_OFFSET2_REG_VALUE (0x00)
#define TI_LMP90100_CH0_SCAL_OFFSET1_REG_VALUE (0x00)
#define TI_LMP90100_CH0_SCAL_OFFSET0_REG_VALUE (0x00)
#define TI_LMP90100_CH0_SCAL_GAIN2_REG_VALUE (0x80)
#define TI_LMP90100_CH0_SCAL_GAIN1_REG_VALUE (0x00)
#define TI_LMP90100_CH0_SCAL_GAIN0_REG_VALUE (0x00)
#define TI_LMP90100_CH0_SCAL_SCALING_REG_VALUE (0x00)
#define TI_LMP90100_CH0_SCAL_BITS_SELECTOR_REG_VALUE (0x00)
#define TI_LMP90100_CH1_SCAL_OFFSET2_REG_VALUE (0x00)
#define TI_LMP90100_CH1_SCAL_OFFSET1_REG_VALUE (0x00)
#define TI_LMP90100_CH1_SCAL_OFFSET0_REG_VALUE (0x00)
#define TI_LMP90100_CH1_SCAL_GAIN2_REG_VALUE (0x80)
#define TI_LMP90100_CH1_SCAL_GAIN1_REG_VALUE (0x00)
#define TI_LMP90100_CH1_SCAL_GAIN0_REG_VALUE (0x00)
#define TI_LMP90100_CH1_SCAL_SCALING_REG_VALUE (0x00)
#define TI_LMP90100_CH1_SCAL_BITS_SELECTOR_REG_VALUE (0x00)
#define TI_LMP90100_CH2_SCAL_OFFSET2_REG_VALUE (0x00)
#define TI_LMP90100_CH2_SCAL_OFFSET1_REG_VALUE (0x00)
#define TI_LMP90100_CH2_SCAL_OFFSET0_REG_VALUE (0x00)
#define TI_LMP90100_CH2_SCAL_GAIN2_REG_VALUE (0x80)
#define TI_LMP90100_CH2_SCAL_GAIN1_REG_VALUE (0x00)
#define TI_LMP90100_CH2_SCAL_GAIN0_REG_VALUE (0x00)
#define TI_LMP90100_CH2_SCAL_SCALING_REG_VALUE (0x00)
#define TI_LMP90100_CH2_SCAL_BITS_SELECTOR_REG_VALUE (0x00)
#define TI_LMP90100_CH3_SCAL_OFFSET2_REG_VALUE (0x00)
#define TI_LMP90100_CH3_SCAL_OFFSET1_REG_VALUE (0x00)
#define TI_LMP90100_CH3_SCAL_OFFSET0_REG_VALUE (0x00)
#define TI_LMP90100_CH3_SCAL_GAIN2_REG_VALUE (0x80)
#define TI_LMP90100_CH3_SCAL_GAIN1_REG_VALUE (0x00)
#define TI_LMP90100_CH3_SCAL_GAIN0_REG_VALUE (0x00)
#define TI_LMP90100_CH3_SCAL_SCALING_REG_VALUE (0x00)
#define TI_LMP90100_CH3_SCAL_BITS_SELECTOR_REG_VALUE (0x00)
#endif
void TI_LMP90100_WriteRegSettings(USART_TypeDef *spi, uint8_t *pURA)
{
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_RESETCN_REG,
TI_LMP90100_RESETCN_REG_VALUE, pURA);
// register and conversion reset
//TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_SPI_RESET_REG,0x00,pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_SPI_HANDSHAKECN_REG,
TI_LMP90100_SPI_HANDSHAKECN_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_SPI_STREAMCN_REG,
0x85, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_PWRCN_REG,
TI_LMP90100_PWRCN_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi, TI_LMP90100_DATA_ONLY_1_REG,
TI_LMP90100_DATA_ONLY_1_REG_VALUE, pURA); TI_LMP90100_SPIWriteReg(spi, TI_LMP90100_DATA_ONLY_2_REG,
TI_LMP90100_DATA_ONLY_2_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_ADC_RESTART_REG,
TI_LMP90100_ADC_RESTART_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_GPIO_DIRCN_REG,
TI_LMP90100_GPIO_DIRCN_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_GPIO_DAT_REG,
TI_LMP90100_GPIO_DAT_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_BGCALCN_REG,
TI_LMP90100_BGCALCN_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_SPI_DRDYBCN_REG,
TI_LMP90100_SPI_DRDYBCN_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_ADC_AUXCN_REG,
TI_LMP90100_ADC_AUXCN_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_SPI_CRC_CN_REG,
TI_LMP90100_SPI_CRC_CN_REG_VALUE, pURA);
// Disable CRC
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_SENDIAG_THLDH_REG,
TI_LMP90100_SENDIAG_THLDH_REG_VALUE, pURA);
// Sensor Diagnostic Threshold High
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_SENDIAG_THLDL_REG,
TI_LMP90100_SENDIAG_THLDL_REG_VALUE, pURA);
// Sensor Diagnostic Threshold Low
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_SCALCN_REG,
TI_LMP90100_SCALCN_REG_VALUE, pURA);
// Normal mode
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_ADC_DONE_REG,
TI_LMP90100_ADC_DONE_REG_VALUE, pURA);
// ADC Data unavailable
// Set up scan register for conversion
while (TI_LMP90100_SPIReadReg(spi,(TI_LMP90100_CH_STS_REG
& TI_LMP90100_CH_SCAN_NRDY), pURA));
// wait if CH_SCAN_NRDY
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH_SCAN_REG, 0xD0 , pURA); // single CH continuous scan, ch# = 0
// CH0 in uses4
if(spi == USART2)//AFE1
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH0_INPUTCN_REG, 0xC1, pURA); // diable sensor diagnostics, default ref, vinp0 vinn1
else if(spi==USART0)//AFE2
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH0_INPUTCN_REG, 0x81, pURA); // diable sensor diagnostics, default ref, vinp0 vinn1
if(spi == USART2)//AFE1 Pt100
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH0_CONFIG_REG, 0x35, pURA);
else if(spi==USART0)//AFE2 PH
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH0_CONFIG_REG, 0x37, pURA);
// CH1 in use
if(spi == USART2)
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH1_INPUTCN_REG,
0xD3, pURA);
else if(spi==USART0)
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH1_INPUTCN_REG,
0x93/*0x13*/, pURA); // disable sensor diagnostics, default ref, vinp2 vinn3
if(spi == USART2)//afe1
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH1_CONFIG_REG, 0x36 , pURA); // 26.83SPS, FGA off, buffer in signal path
else if(spi == USART0) //afe2
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH1_CONFIG_REG, 0x3B , pURA); // 26.83SPS, FGA off, buffer in signal path
// CH2 in use
if(spi==USART2)
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH2_INPUTCN_REG,
0xE5, pURA);
else if(spi==USART0)
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH2_INPUTCN_REG,
0xA5, pURA);
if(spi==USART2)
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH2_CONFIG_REG,
0x40, pURA);
else if(spi==USART0)
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH2_CONFIG_REG,
0x30, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH3_INPUTCN_REG,
TI_LMP90100_CH3_INPUTCN_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH3_CONFIG_REG,
TI_LMP90100_CH3_CONFIG_REG_VALUE, pURA);
// CH4 not used
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH4_INPUTCN_REG,
TI_LMP90100_CH4_INPUTCN_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH4_CONFIG_REG,
TI_LMP90100_CH4_CONFIG_REG_VALUE, pURA);
// CH5 not used
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH5_INPUTCN_REG,
TI_LMP90100_CH5_INPUTCN_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH5_CONFIG_REG,
TI_LMP90100_CH5_CONFIG_REG_VALUE, pURA);
// CH6 not used
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH6_INPUTCN_REG,
TI_LMP90100_CH6_INPUTCN_REG_VALUE, pURA);
TI_LMP90100_SPIWriteReg(spi,TI_LMP90100_CH6_CONFIG_REG,
TI_LMP90100_CH6_CONFIG_REG_VALUE, pURA);
}
void SPI_setup(uint8_t spiNumber, uint8_t location, bool master)
{
USART_TypeDef *spi;
/* Determining USART */
switch (spiNumber)
{
case 0:
spi = USART0;
break;
case 1:
spi = USART1;
break;
case 2:
spi = USART2;
break;
default:
return;
}
/* Setting baudrate */
spi->CLKDIV = 512;//4096;//2048;//1024;//512*2;// 512*16;//ok 512;//512*64;// ok* (SPI_PERCLK_FREQUENCY / SPI_BAUDRATE - 2);
/* Configure SPI */
/* Using synchronous (SPI) mode*/
spi->CTRL = USART_CTRL_SYNC;
/* Clearing old transfers/receptions, and disabling interrupts */
spi->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX ;//| USART_CMD_RXBLOCKDIS;
spi->IEN = 0;
/* Enabling pins and setting location */
spi->ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CLKPEN | USART_ROUTE_CSPEN | (location << 8);
/* Set GPIO config to slave */
GPIO_Mode_TypeDef gpioModeMosi = gpioModeInput;
GPIO_Mode_TypeDef gpioModeMiso = gpioModePushPull;
GPIO_Mode_TypeDef gpioModeCs = gpioModeInput;
GPIO_Mode_TypeDef gpioModeClk = gpioModeInput;
/* Set to master and to control the CS line */
if (master)
{
/* Enabling Master, TX and RX */
spi->CMD = USART_CMD_MASTEREN | USART_CMD_TXEN | USART_CMD_RXEN;
spi->CTRL |= USART_CTRL_AUTOCS;
spi->CTRL |= USART_CTRL_MSBF;
//spi->FRAME |= USART_FRAME_DATABITS_SIXTEEN;
/* Set GPIO config to master */
gpioModeMosi = gpioModePushPull;
gpioModeMiso = gpioModeInput;
gpioModeCs = gpioModePushPull;
gpioModeClk = gpioModePushPull;
}
else
{
/* Enabling TX and RX */
spi->CMD = USART_CMD_TXEN | USART_CMD_RXEN;
}
/* Clear previous interrupts */
spi->IFC = _USART_IFC_MASK;
/* IO configuration */
switch(spiNumber)
{
case 0: switch(location)
{
case 0: /* IO configuration (USART 0, Location #0) */
GPIO_PinModeSet(gpioPortE, 10, gpioModeMosi, 0); /* MOSI */
GPIO_PinModeSet(gpioPortE, 11, gpioModeMiso, 0); /* MISO */
GPIO_PinModeSet(gpioPortE, 13, gpioModeCs, 0); /* CS */
GPIO_PinModeSet(gpioPortE, 12, gpioModeClk, 0); /* Clock */
break;
case 1: /* IO configuration (USART 0, Location #1) */
GPIO_PinModeSet(gpioPortE, 7, gpioModeMosi, 0); /* MOSI */
GPIO_PinModeSet(gpioPortE, 6, gpioModeMiso, 0); /* MISO */
GPIO_PinModeSet(gpioPortE, 4, gpioModeCs, 0); /* CS */
GPIO_PinModeSet(gpioPortE, 5, gpioModeClk, 0); /* Clock */
break;
case 2: /* IO configuration (USART 0, Location #2) */
GPIO_PinModeSet(gpioPortC, 11, gpioModeMosi, 0); /* MOSI */
GPIO_PinModeSet(gpioPortC, 10, gpioModeMiso, 0); /* MISO */
GPIO_PinModeSet(gpioPortC, 8, gpioModeCs, 0); /* CS */
GPIO_PinModeSet(gpioPortC, 9, gpioModeClk, 0); /* Clock */
//GPIO_PinModeSet(gpioPortF, 8, gpioModeCs, 0);/* CS1*/
break;
default: break;
}
break;
case 1: switch(location)
{
case 0: /* IO configuration (USART 1, Location #0) */
GPIO_PinModeSet(gpioPortC, 0, gpioModeMosi, 0); /* MOSI */
GPIO_PinModeSet(gpioPortC, 1, gpioModeMiso, 0); /* MISO */
GPIO_PinModeSet(gpioPortB, 8, gpioModeCs, 0); /* CS */
GPIO_PinModeSet(gpioPortB, 7, gpioModeClk, 0); /* Clock */
break;
case 1: /* IO configuration (USART 1, Location #1) */
GPIO_PinModeSet(gpioPortD, 0, gpioModeMosi, 0); /* MOSI */
GPIO_PinModeSet(gpioPortD, 1, gpioModeMiso, 0); /* MISO */
GPIO_PinModeSet(gpioPortD, 3, gpioModeCs, 0); /* CS */
GPIO_PinModeSet(gpioPortD, 2, gpioModeClk, 0); /* Clock */
break;
//NUEVA PARA SPI FLASH
//case 2: /* IO configuration (USART 1, Location #2) */
// GPIO_PinModeSet(gpioPortB, 15, gpioModeMosi, 0); /* MOSI */
// GPIO_PinModeSet(gpioPortB, 14, gpioModeMiso, 0); /* MISO */
// GPIO_PinModeSet(gpioPortB, 12, gpioModeCs, 0); /* CS */
// GPIO_PinModeSet(gpioPortB, 13, gpioModeClk, 0); /* Clock */
// break;
default: break;
}
break;
case 2: switch(location)
{
case 0: /* IO configuration (USART 2, Location #0) */
GPIO_PinModeSet(gpioPortC, 2, gpioModeMosi, 0); /* MOSI */
GPIO_PinModeSet(gpioPortC, 3, gpioModeMiso, 0); /* MISO */
GPIO_PinModeSet(gpioPortC, 5, gpioModeCs, 0); /* CS */
GPIO_PinModeSet(gpioPortC, 4, gpioModeClk, 0); /* Clock */
break;
case 1: /* IO configuration (USART 2, Location #1) */
GPIO_PinModeSet(gpioPortB, 3, gpioModeMosi, 0); /* MOSI */
GPIO_PinModeSet(gpioPortB, 4, gpioModeMiso, 0); /* MISO */
GPIO_PinModeSet(gpioPortB, 6, gpioModeCs, 0); /* CS */
GPIO_PinModeSet(gpioPortB, 5, gpioModeClk, 0); /* Clock */
break;
default: break;
}
break;
default: break;
}
}