I would like some help using driverlib functions in non-interrupt mode to read the product identification and serial number
of the Sensiron SLF3S-4000B sensor.
I have attached the data format required.
Thanks
David Nyarko
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.
I would like some help using driverlib functions in non-interrupt mode to read the product identification and serial number
of the Sensiron SLF3S-4000B sensor.
I have attached the data format required.
Thanks
David Nyarko
Hello David,
Gotcha, looks simple enough. For a no-interrupt example that handles reading a long packet, the best starting point for you would be the example found at [Install Path]\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl-boostxl-senshub\humidity_sht21_simple
Note this is example is new to TivaWare 2.2.0.295 because we lacked a good example for a use case like yours in the prior releases.
That has a write command you can use to send the first two commands to the sensor, and then a read command which just needs some slight modification to handle your use case. You'd want to create a loop for the I2C_MASTER_CMD_BURST_RECEIVE_CONT step to continuously read until you hit Byte 17 before breaking out of the loop and finish receiving the CRC6 with the I2C_MASTER_CMD_BURST_RECEIVE_FINISH step.
Best Regards,
Ralph Jacobi
After posting all that, my eyes have started to function and I realize you are asking about an MSP432E401Y device and not a TM4C device... I'll go look for the equivalent for your actual device, but I'm going to leave that post up there as for a no-RTOS, no interrupt method you can basically reference it the same way.
I definitely see why you came to ask about this particular implementation, I'm surprised each of them is based on interrupts.
I can put together a no-interrupt version that is actually tested on Monday, but in lieu of that, these sort of functions should work for your MSP432E4 as well because the driverlib used between TivaWare and the MSP432E4 SDK is effectively the same:
//***************************************************************************** // // This function sends the specified command to the I2C slave device. // //***************************************************************************** void I2CWriteCommand(uint32_t ui32Command) { // // Set up the slave address with write transaction. // MAP_I2CMasterSlaveAddrSet(I2C7_BASE, SHT21_I2C_ADDRESS, false); // // Store the command data in I2C data register. // MAP_I2CMasterDataPut(I2C7_BASE, ui32Command); // // Start the I2C transaction. // MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_SINGLE_SEND); // // Wait until the I2C transaction is complete. // while(MAP_I2CMasterBusy(I2C7_BASE)) { } }
//***************************************************************************** // // This function will read three 8-bit data from the I2C slave. The first // two 8-bit data forms the humidity data while the last 8-bit data is the // checksum. This function illustrates three different I2C burst mode // commands to read the I2C slave device. // //***************************************************************************** void I2CReadCommand(uint32_t * pui32DataRx) { // // Modify the data direction to true, so that seeing the address will // indicate that the I2C Master is initiating a read from the slave. // MAP_I2CMasterSlaveAddrSet(I2C7_BASE, SHT21_I2C_ADDRESS, true); // // Setup for first read. Use I2C_MASTER_CMD_BURST_RECEIVE_START // to start a burst mode read. The I2C master continues to own // the bus at the end of this transaction. // MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); // // Wait until master module is done transferring. // The I2C module has a delay in setting the Busy flag in the register so // there needs to be a delay before checking the Busy bit. The below loops // wait until the Busy flag is set, and then wait until it is cleared to // indicate that the transaction is complete. This can take up to 633 CPU // cycles @ 100 kbit I2C Baud Rate and 120 MHz System Clock. Therefore, a // while loop is used instead of SysCtlDelay. // while(!MAP_I2CMasterBusy(I2C7_BASE)) { } while(MAP_I2CMasterBusy(I2C7_BASE)) { } // // Read the first byte data from the slave. // pui32DataRx[0] = MAP_I2CMasterDataGet(I2C7_BASE); // // Setup for the second read. Use I2C_MASTER_CMD_BURST_RECEIVE_CONT // to continue the burst mode read. The I2C master continues to own // the bus at the end of this transaction. // MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT); // // Wait until master module is done transferring. // while(!MAP_I2CMasterBusy(I2C7_BASE)) { } while(MAP_I2CMasterBusy(I2C7_BASE)) { } // // Read the second byte data from the slave. // pui32DataRx[1] = MAP_I2CMasterDataGet(I2C7_BASE); // // Setup for the third read. Use I2C_MASTER_CMD_BURST_RECEIVE_FINISH // to terminate the I2C transaction. At the end of this transaction, // the STOP bit will be issued and the I2C bus is returned to the // Idle state. // MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); // // Wait until master module is done transferring. // while(!MAP_I2CMasterBusy(I2C7_BASE)) { } while(MAP_I2CMasterBusy(I2C7_BASE)) { } // // Note the third 8-bit data is the checksum byte. It will be // left to the users as an exercise if they want to verify if the // checksum is correct. pui32DataRx[2] = MAP_I2CMasterDataGet(I2C7_BASE); }
If that gets you up and running before I get back to this on Monday just let me know
Best Regards,
Ralph Jacobi
Hi Ralph,
I was not able to get it up and working. I will await your code. My confusion stems from the fact that the first 2 commands are sent without a STOP so i am not sure how the drivelib functions will work.
Thanks
David
Hi David,
I was unexpectedly out for part of yesterday so I wasn't able to get around to this. It's on my docket for this afternoon.
Thanks for pointing out the two write's also do not require a stop which differs from what I sent initially, I'll see about making the code behave accordingly. That would require using a Repeated Start, I will have to review how that's implemented myself.
Best Regards,
Ralph Jacobi
Hello David,
So without a sensor that reacts correctly I can't fully test this, but here is what I believe should work:
//***************************************************************************** // // This function will read three 8-bit data from the I2C slave. The first // two 8-bit data forms the humidity data while the last 8-bit data is the // checksum. This function illustrates three different I2C burst mode // commands to read the I2C slave device. // //***************************************************************************** void I2CReadSensor(uint32_t * ui32Cmd1, uint32_t * ui32Cmd2, uint32_t * pui32DataRx) { uint8_t ui8DataIndex = 0; /* Put the Slave Address on the bus for Write */ MAP_I2CMasterSlaveAddrSet(I2C1_BASE, SLAVE_ADDRESS, false); /* Write the first byte of the command to the bus */ MAP_I2CMasterDataPut(I2C1_BASE, ui32Cmd1[0]); MAP_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START); /* Wait until the I2C transaction is complete. */ while(MAP_I2CMasterBusy(I2C1_BASE)) { } /* Send the second byte of the command to the bus */ MAP_I2CMasterDataPut(I2C1_BASE, ui32Cmd1[1]); MAP_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_CONT); /* Wait until the I2C transaction is complete. */ while(MAP_I2CMasterBusy(I2C1_BASE)) { } /* Put the Slave Address on the bus for Write */ MAP_I2CMasterSlaveAddrSet(I2C1_BASE, SLAVE_ADDRESS, false); /* Write the first byte of the command to the bus */ MAP_I2CMasterDataPut(I2C1_BASE, ui32Cmd2[0]); MAP_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START); /* Wait until the I2C transaction is complete. */ while(MAP_I2CMasterBusy(I2C1_BASE)) { } /* Send the second byte of the command to the bus */ MAP_I2CMasterDataPut(I2C1_BASE, ui32Cmd2[1]); MAP_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_CONT); /* Wait until the I2C transaction is complete. */ while(MAP_I2CMasterBusy(I2C1_BASE)) { } /* Modify the data direction to true, so that seeing the address will * indicate that the I2C Master is initiating a read from the slave. */ MAP_I2CMasterSlaveAddrSet(I2C1_BASE, SLAVE_ADDRESS, true); /* Setup for first read. Use I2C_MASTER_CMD_BURST_RECEIVE_START * to start a burst mode read. The I2C master continues to own * the bus at the end of this transaction. */ MAP_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); /* Wait until master module is done transferring. * The I2C module has a delay in setting the Busy flag in the register so * there needs to be a delay before checking the Busy bit. The below loops * wait until the Busy flag is set, and then wait until it is cleared to * indicate that the transaction is complete. This can take up to 633 CPU * cycles @ 100 kbit I2C Baud Rate and 120 MHz System Clock. Therefore, a * while loop is used instead of SysCtlDelay. */ while(!MAP_I2CMasterBusy(I2C1_BASE)) { } while(MAP_I2CMasterBusy(I2C1_BASE)) { } /* Read the first byte data from the slave. */ pui32DataRx[ui8DataIndex++] = MAP_I2CMasterDataGet(I2C1_BASE); while (ui8DataIndex < 17) { /* Setup for the next read. Use I2C_MASTER_CMD_BURST_RECEIVE_CONT * to continue the burst mode read. The I2C master continues to own * the bus at the end of this transaction. */ MAP_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT); /* Wait until master module is done transferring. */ while(!MAP_I2CMasterBusy(I2C1_BASE)) { } while(MAP_I2CMasterBusy(I2C1_BASE)) { } /* Read the next byte data from the slave. */ pui32DataRx[ui8DataIndex++] = MAP_I2CMasterDataGet(I2C1_BASE); } /* Setup for the third read. Use I2C_MASTER_CMD_BURST_RECEIVE_FINISH * to terminate the I2C transaction. At the end of this transaction, * the STOP bit will be issued and the I2C bus is returned to the * Idle state. */ MAP_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); /* Wait until master module is done transferring. */ while(!MAP_I2CMasterBusy(I2C1_BASE)) { } while(MAP_I2CMasterBusy(I2C1_BASE)) { } /* Note the third 8-bit data is the checksum byte. It will be * left to the users as an exercise if they want to verify if the * checksum is correct. */ pui32DataRx[ui8DataIndex++] = MAP_I2CMasterDataGet(I2C1_BASE); } int main(void) { uint32_t systemClock; /* Variables for I2C data and state machine */ uint32_t ui32Cmd1[2] = {0xAA, 0xBB}; uint32_t ui32Cmd2[2] = {0xCC, 0xDD}; uint32_t ui32SensorData[18] = {0x00}; /* Configure the system clock for 120 MHz */ systemClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); /* Enable clocks to GPIO Port G and configure pins as I2C */ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOG))) { } MAP_GPIOPinConfigure(GPIO_PG0_I2C1SCL); MAP_GPIOPinConfigure(GPIO_PG1_I2C1SDA); MAP_GPIOPinTypeI2C(GPIO_PORTG_BASE, GPIO_PIN_1); MAP_GPIOPinTypeI2CSCL(GPIO_PORTG_BASE, GPIO_PIN_0); /* Since there are no board pull up's we shall enable the weak internal * pull up */ GPIOG->PUR |= (GPIO_PIN_1 | GPIO_PIN_0); /* Enable the clock to I2C-1 module and configure the I2C Master */ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1); while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_I2C1))) { } /* Configure the I2C Master in standard mode and enable interrupt for Data * completion, NAK and Stop condition on the bus */ MAP_I2CMasterInitExpClk(I2C1_BASE, systemClock, false); I2CReadSensor(&ui32Cmd1[0], &ui32Cmd2[0], &ui32SensorData[0]); while(1) { } }
(Made two small edits 5 minutes after initial posting)
Best Regards,
Ralph Jacobi
Hi Ralph,
Thanks this resolved my issue. The product number and serial number are correctly displayed.
David Nyarko