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.
Part Number: MSP432P401R
Tool/software: Code Composer Studio
Hello,
i want to read and write to registers on a VL53L0X and i have already gotten help here (CCS/MSP432P401R: problems connecting sensor VL53L0X via I2C - MSP low-power microcontroller forum - MSP...
I try to implement a Arduino library from github to my msp432, so i can use the tof-sensor.
My Code looks like this:
#include "driverlib.h" #include "TofSensor.h" #define SLAVE_ADDRESS_1 0x29 // Decode VCSEL (vertical cavity surface emitting laser) pulse period in PCLKs // from register value // based on VL53L0X_decode_vcsel_period() #define decodeVcselPeriod(reg_val) (((reg_val) + 1) << 1) // Encode VCSEL pulse period register value from period in PCLKs // based on VL53L0X_encode_vcsel_period() #define encodeVcselPeriod(period_pclks) (((period_pclks) >> 1) - 1) // Calculate macro period in *nanoseconds* from VCSEL period in PCLKs // based on VL53L0X_calc_macro_period_ps() // PLL_period_ps = 1655; macro_period_vclks = 2304 #define calcMacroPeriod(vcsel_period_pclks) ((((uint32_t)2304 * (vcsel_period_pclks) * 1655) + 500) / 1000) eUSCI_I2C_MasterConfig i2cConfig = { EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 3000000, // 3Mhz EUSCI_B_I2C_SET_DATA_RATE_400KBPS, // Desired I2C Clock of 400khz 0, // No byte counter threshold EUSCI_B_I2C_NO_AUTO_STOP }; bool TofSensor_Init(bool io_2v8) { // Configure P6.4 for EUSCI_B1_SPI_I2C EUSCI_B1_SPI_I2C.SCL P6.5 for EUSCI_B1_SPI_I2C EUSCI_B1_SPI_I2C.SDA MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6, GPIO_PIN4 + GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION); MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN0); /* Initializing I2C Master to SMCLK at 400khz with no autostop */ MAP_I2C_initMaster(EUSCI_B1_BASE, &i2cConfig); /* Specify slave address */ MAP_I2C_setSlaveAddress(EUSCI_B1_BASE, SLAVE_ADDRESS_1); MAP_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE); /* Enable I2C Module to start operations */ MAP_I2C_enableModule(EUSCI_B1_BASE); //Boot sensor MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6,GPIO_PIN0); __delay_cycles(1000);// Delay for sensor to be ready uint8_t address=0xC0; uint8_t regC0; MAP_I2C_masterSendSingleByte(EUSCI_B1_BASE,address); regC0 = MAP_I2C_masterReceiveSingleByte(EUSCI_B1_BASE);
Sometime it stucks in the masterSendSingleByte function at:
//Poll for transmit interrupt flag. while (!(EUSCI_B_CMSIS(moduleInstance)->rIFG.r & UCTXIFG)) ;
I can't figure out why. For your information, I wanted to use VL53L0X without interrupts and therefore GPIO1 is not connected.
Maybe someone can explain why it stucks it the function?
Thanks in advance.
>
__delay_cycles(1000);
// Delay for sensor to be ready
Supposing that your CPU is running at 3MHz, this is about 300 usec. VL53L0x data sheet (DocID029104 Rev 2) Fig 9 says that startup can take (40+1) msec. My guess is that you're getting a NACK since the device hasn't completed startup.
SendSingleByte doesn't check for NACK. One option is to use I2C_masterSendSingleByteWithTimeout. If that function times out, it does not send a Stop, so if you see a failure (returns false) you need to call something like I2C_masterReceiveMultiByteStop (don't dwell on the function's name). I'm guessing that the units for the "timeout" parameter are about 1 usec (at 3MHz).
And bump your startup delay to something like 45 msec.
thanks for you answer.
i tried it with setting a higher delay and the MAP_I2C_masterSendSingleByteWithTimeout function, with no success. It is always false.
__delay_cycles(135000);// 45ms at 3Mhz Delay for sensor to be ready //__delay_cycles(2160000);// 45ms at 48 Mhz bool test = MAP_I2C_masterSendSingleByteWithTimeout(EUSCI_B1_BASE,address,1000); if(test) { regC0 = MAP_I2C_masterReceiveSingleByte(EUSCI_B1_BASE); } else { printf("False"); }
Maybe you have another idea?
Are you seeing a NACK? Pause in the debugger, and check Registers->EUSCI_B1->IFG for UCNACKIFG.
[Edit: Also, as a matter of completeness, add a:
> MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6,GPIO_PIN0);
to make sure the device really resets (XSHUT low then high).]
thanks again for you answer.
i put MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6,GPIO_PIN0); at the beginning so that the Port is low, but it didnt change anything.
I dont get a NACK.
That is a picture of my EUSCI_B1.
I find out that it is only workin with the MAP_I2C_masterSendSingleByteWithTimeout function, MAP_I2C_masterSendSingleByte does not work.
But now i stuck at writing into a register:
void writeReg (uint8_t reg, uint8_t value) { bool reg_bool = MAP_I2C_masterSendSingleByteWithTimeout(EUSCI_B1_BASE,reg,1000); bool value_bool = MAP_I2C_masterSendSingleByteWithTimeout(EUSCI_B1_BASE,value,1000); if (reg_bool && value_bool) { printf("test"); } }
the bool values are just for testing. Do i need to use MAP_I2C_masterSendMultiByteStart for writing into a register?
Can you tell me which unit the timout is, is it seconds or ms or cpu-cycles? The documentation doesnt declare a unit: timeout is the amount of time to wait until giving up
The write sequence is a multi-byte sequence, as seen in the VL53L0x data sheet (Fig 15). You'll need the MultiByte functions in the Driverlib UG (no doc#?) Sec 12.2.
It's curious that the Timeout version works and the non-Timeout doesn't. It sounds vaguely like Erratum USCI43, but that mentions only RXIFG, not TXIFG.
As I mentioned, my estimate for the timeout unit is about 1 usec at 3MHz (decrement+branch). It's probably affected by optimization.
Sorry for my late response!
I got it working to write to the register even to a 16bit register.
But now i have a new problem... When i debug the code everything is working as expected, but if I run the code without debugging it cannot write to the registers. I think it's to fast.
I read in the vl53l0x doc about the "Bus free time between transmissions" so i added delays but i didnt work.
Here is an example:
void writeReg (uint8_t reg, uint8_t value) { __delay_cycles(96000); //2 ms 48Mhz bool reg_bool = MAP_I2C_masterSendMultiByteStartWithTimeout(EUSCI_B1_BASE,reg,1000); bool value_bool = MAP_I2C_masterSendMultiByteFinishWithTimeout(EUSCI_B1_BASE,value,1000); MAP_I2C_masterSendMultiByteStopWithTimeout(EUSCI_B1_BASE,1000); __delay_cycles(96000); //2 ms 48Mhz if (reg_bool && value_bool) { printf("writeReg success \n"); } else { printf("writeReg failed \n"); } //__delay_cycles(6000); //2 ms 3Mhz //__delay_cycles(96000); //2 ms 48Mhz }
Does anyone have any ideas?
thanks in advance!
It already fails when I try to read from i2c for the second time.
uint8_t readReg (uint8_t address) { uint8_t value=0x00; /* Wait until ready */ while (MAP_I2C_isBusBusy(EUSCI_B1_BASE)){ ; } bool reag_reg = MAP_I2C_masterSendSingleByteWithTimeout(EUSCI_B1_BASE,address,100000); if(reag_reg) { value = MAP_I2C_masterReceiveSingleByte(EUSCI_B1_BASE); printf("read success \n"); } else{ printf("read failed \n"); } //__delay_cycles(6000); //2 ms bei 3Mhz __delay_cycles(96000); //2 ms bei 48Mhz return value; }
The bus stays busy. register view:
UCBSTATW 0x0350eUSCI_Bx Status Register [Memory Mapped]
UCBCNT 00000011 Hardware byte counter value
UCSCLLOW 1 - UCSCLLOW_1 SCL low
UCGC 0 - UCGC_0 General call address received
UCBBUSY 1 - BUSY Bus busy
**Attention** This is a public forum