在本次項目中,限於空間要求我們選用了STM32F030F4作為控制芯片。這款MCU不但封裝緊湊,而且自帶的Flash空間也非常有限,所以我們選擇了LL庫實現。在本文中我們說明一下,使用LL庫實現MS5536C的SPI通訊。
1、MS5536C簡述
MS5536C是一個系列的高分辨率工廠校准壓力傳感器。該設備包括一個壓阻式壓力傳感器和一個ADC,采用三線SPI接口。該設備以16位數據字的形式提供數字壓力和溫度信息。其結構圖如下:
MS5536C具有64位的單獨校准的補償系數,允許高度精確的軟件補償過程傳播和溫度效應。4個字的位排序組合為6個有效系數,具體如下:
MS5536C中,壓力數據是一個16為的數據,讀取的時序需要在發送命令和接受數據時采用不同的時鍾沿。
MS5536C中,溫度數據是一個16為的數據,讀取溫度數據的時序與眼里數據一樣,也需要在發送命令和接受數據時采用不同的時鍾沿。
MS5536C中,修正系數是有4個字組成,其實是6個系數,前面已經介紹了它的格式,讀取這幾個數據的時序也需要在發送命令和接受數據時采用不同的時鍾沿。字1和字3的時序圖如下:
讀取字2和字4的時序圖如下:
此外,還有復位信號,擔復位信號沒有什么特別,只需按時序圖實現就好。其時序圖如下:
關於這幾個時序圖的軟件實現我們會在后面給出。在這里,我們可以總結一下,對於MS5536C表壓傳感器,在MCU發送信號時,使用時鍾上升沿;在MCU接收數據時,采用時鍾下降沿。
2、SPI通訊配置
MS5536C表壓傳感器采用的是SPI通訊,所以我們需要看看STM32F030F4中的SPI通訊。STM32F030F4中的SPI的結構如下:
要實現SPI通訊,需要對SPI的寄存器進行配置,主要是個寄存器:SPI控制寄存器1(SPIx_CR1)和SPI控制寄存器2(SPIx_CR2)。
SPI控制寄存器1(SPIx_CR1)的結構如下:
在SPIx_CR1中有幾位是需要配置的:SSM,SSI,SPE,BR,MSTR,CPOL,CPHA等。SSM:軟件從站管理,說的簡單一點就是忽略NSS引腳信號,在我們的應用中需要置位。SSI:內部從站選擇,在SSM置位的情況下才有效。SPE:SPI使能,這個是必須的,但配置需要注意,在后續我們還會說明。BR:波特率控制,用於設置時鍾分頻。MSTR主站選擇,CPOL時鍾極性,CPHA時鍾相位不再多說。
SPI控制寄存器2(SPIx_CR2)的結構如下:
在SPI控制寄存器2(SPIx_CR2)中,有FRXTH,FIFO接收閾值;DS,SPI傳送數據位數需要配置。
3、軟件實現
在前面我們已經說明了SPI的配置和MS5536C表壓傳感器的通訊要求,接下來就根據我們的分析實現之。
首先來看SPI的配置,有一些配置可以通過LL庫提供的初始化函數來完成。這部分我們需要給予相應的參數值然后調用初始化函數。還有一部分配置需要調用相應的函數來執行。具體配置如下:
/* SPI1 初始化配置 */
static void SPI1_Init_Configuration(void)
{
/* SPI1 端口參數配置*/
LL_SPI_InitTypeDef SPI_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* 相關外設時鍾使能 */
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SPI1);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
/**SPI1 GPIO配置:PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI */
GPIO_InitStruct.Pin = LL_GPIO_PIN_5;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_6;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* SPI1 參數配置 */
SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV256;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct.CRCPoly = 7;
LL_SPI_Init(SPI1, &SPI_InitStruct);
LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER);
LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
LL_SPI_EnableNSSPulseMgt(SPI1);
}
配置成功后,控制寄存器的狀態如下圖所示:
這里需要說明一下的是使能SPI,如果只在初始化時使能,最后的結果可能是一項不到的。所以最好的做法是在每次實現數據發送前,檢測SPI的狀態,若沒使能則調用LL_SPI_Enable(SPI1)使能SPI
關於MS5536C表壓傳感器,我們查看了時序圖后其實很容易實現,只需要在下發命令和接收數據時,注意轉換SPI的相位設定就可以了。我們在這里只列出讀取溫度和壓力測量值的代碼。
/* 讀取測量數據 */
static uint16_t ReadMeasureData(MS5536cTypeDef *ms,uint16_t command)
{
uint8_t txData[2];
uint8_t rxData[2];
uint16_t result=0;
txData[0]=(uint8_t)(command>>8);
txData[1]=(uint8_t)command;
ms->ReadWriteMS(txData,rxData,2);
ms->Delayms(23);
ms->SetPhase(false);
ms->Delayms(10);
txData[0]=0x00;
txData[1]=0x00;
ms->ReadWriteMS(txData,rxData,2);
result=(rxData[0]<<8)+rxData[1];
ms->SetPhase(true);
ms->Delayms(10);
return result;
}
對於讀取校准數據,讀取寄存器,軟件復位等都只需按時序圖實現就可以了,這里不再詳述。
4、總結
我們已經基於LL庫實現了STM32F030F4和MS5536C表壓傳感器的代碼,將其下在到目標板,監視器結果正確,如下圖所示:
歡迎關注: