2023-02-18 02:40 AM
Greetings good people of ST community
I have a problem which I didn't manage to solve by myself, so I am hoping to get some help if possible
I have an LPS22HB sensor (https://eu.mouser.com/datasheet/2/389/lps22hb-1849683.pdf), and I want to connect it to STM32L010K8T6 MCU using SPI. The problem is, I get some temperature register readings with STM studio but they are invalid (0, 128, 255).
In settings, the MCU CS pin is a pull-up, while pins SCK, MISO, MOSI are no pull-up and no pull-down. All of them are in push-pull mode.
These are my SPI setting in the code:
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
My hardware pinout is as following:
INT_DRDY (LPS) - not connected/used
CS (LPS) - SPI_CS (MCU)
SDO/SA0 (LPS) - SPI_MISO (MCU)
SDA/SDI/SDO (LPS) - SPI_MOSI (MCU)
SCL/SPC (LPC) - SPI_SCK (MCU)
I have used this sensor with I2C where it worked (I have used an already written library and ported it to work on STM). These are parts of the main code:
// CS pin should default high
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
LPS22HBTRinit();
LPS22HBTRsetLowPower(1);
LPS22HBTRsetOutputRate(OutputRate_OneShot); // get results on demand
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
LPS22HBTRrequestOneShot();
lpstlak = LPS22HBTRreadPressure();
lpstemp = LPS22HBTRreadTemp();
LPS22HBTRrequestOneShot();
reg1 = LPS22HBTRreadRegister(LPS35HW_TEMP_OUT_L);
reg2 = LPS22HBTRreadRegister(LPS35HW_TEMP_OUT_H);
HAL_Delay(3000);
}
Here is the read and write register parts of the library (the only thing I changed in comparison to working I2C library).
uint8_t LPS22HBTRreadRegister(uint8_t regAddress)
{
uint8_t data = 0;
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, (uint8_t *)®Address, 1, 100);
HAL_SPI_Receive(&hspi1, (uint8_t *)&data, 1, 100);
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
return data;
}
uint8_t LPS22HBTRwriteRegister(uint8_t regAddress,uint8_t *dataToWrite)
{
uint8_t adresa = regAddress;
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, (uint8_t *)&adresa, 1, 100);
HAL_SPI_Transmit(&hspi1, (uint8_t *)dataToWrite, 1, 100);
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
return 1;
}
Thank you for reading
Solved! Go to Solution.
2023-02-21 02:46 AM
I found the solutions to my problems. I had two problems:
1) As KnarfB pointed out, it should be like this => hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
2) When reading the register, I didn't send the R/W bit correctly (1 == read), so I failed to get good data
The code below is what works great for me. I appreciate your help KnarfB and S.Ma.
uint8_t LPS22HBTRwriteRegister(uint8_t regAddr, uint8_t *pData)
{
uint8_t sendData[2] = {regAddr, *pData};
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, sendData, 2, 100);
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
return HAL_OK;
}
uint8_t LPS22HBTRreadRegister(uint8_t regAddr)
{
uint8_t address = regAddr | 0x80;
uint8_t senddata[2] = {address, 0};
uint8_t receivedata[2] = {0};
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, senddata, receivedata, 2, 50);
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
return receivedata[1];
}
2023-02-18 03:09 AM
If I look at the data sheet, shoudn't it be hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hth
KnarfB
2023-02-18 04:49 AM
Because pressure ODR is low sample rate per seconds compared to motion sensors, I used LPS22HH using I2C with bit bang here
Short of finding a solution, maybe this code will help you move forward then get back to SPI later on.
2023-02-21 02:46 AM
I found the solutions to my problems. I had two problems:
1) As KnarfB pointed out, it should be like this => hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
2) When reading the register, I didn't send the R/W bit correctly (1 == read), so I failed to get good data
The code below is what works great for me. I appreciate your help KnarfB and S.Ma.
uint8_t LPS22HBTRwriteRegister(uint8_t regAddr, uint8_t *pData)
{
uint8_t sendData[2] = {regAddr, *pData};
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, sendData, 2, 100);
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
return HAL_OK;
}
uint8_t LPS22HBTRreadRegister(uint8_t regAddr)
{
uint8_t address = regAddr | 0x80;
uint8_t senddata[2] = {address, 0};
uint8_t receivedata[2] = {0};
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, senddata, receivedata, 2, 50);
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
return receivedata[1];
}