在本次項目中,限於空間要求咱們選用了STM32F030F4做爲控制芯片。這款MCU不但封裝緊湊,並且自帶的Flash空間也很是有限,因此咱們選擇了LL庫實現。本篇咱們將基於LL庫採用模擬I2C接口的方式實現溫溼度採集。函數
1、SHT70簡述spa
SHT70是一款集溫溼度測量於一體的傳感器,如今對其做簡要介紹。其引腳定義以下:blog
SHT7X溫溼度傳感器使用的2線通信,類似於I2C總線,但並不相同,使用普通的GPIO就可實現通信。這次採用STM32F030F4來操做SHT70,具體的鏈接方式以下:接口
SCK 用於微處理器與SHT1x 之間的通信同步。因爲接口包含了徹底靜態邏輯,於是不存在最小SCK 頻率。ci
DATA 引腳爲三態結構,用於讀取傳感器數據 . 當向傳感器發送命令時, DATA 在 SCK 上升沿有效且在 SCK 高電平時必須保持穩定。 DATA 在 SCK 降低沿以後改變。爲避免信號衝突,微處理器應驅動DATA 在低電平。須要一個外部的上拉電阻(例如:10kΩ)將信號提拉至高電平。上拉電阻一般已包含在微處理器的I/O 電路中。同步
2、軟件實現it
咱們瞭解了SHT70的相關特色,基於它類I2C的通信方式,咱們採用相關的GPIO來模擬I2C通信。這裏所說的I2C,並不是常規意義上的I2C,而是面向SHT70的協議的I2C。io
2.1、端口配置table
所謂的端口配置其實就是對應的GPIO引腳的配置,其實就是將用於模擬I2C通信的引腳按須要配置爲不一樣的GPIO輸入輸出特性。具體代碼以下:bfc
*溫溼度變送器GPIO端口配置*/
static void SHT_GPIO_Configuration(void)
{
LL_GPIO_InitTypeDef GPIO_InitStruct;
/* 使能GPIO端口時鐘 */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
LL_GPIO_SetOutputPin(I2C_SCL_GPIO_Port, I2C_SCL_Pin);
LL_GPIO_SetOutputPin(I2C_SDA_GPIO_Port, I2C_SDA_Pin);
/* 配置SHT15通信接口GPIO PA9、PA10 */
GPIO_InitStruct.Pin = I2C_SCL_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
LL_GPIO_Init(I2C_SCL_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = I2C_SDA_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
LL_GPIO_Init(I2C_SDA_GPIO_Port, &GPIO_InitStruct);
}
2.2、I2C操做函數
前面咱們介紹了SHT70採用的是相似I2C的通信接口,因此咱們須要按照SHT70的要求來寫這個類I2C的操做函數。主要有3個內容:
(1)SCK時鐘線的輸出操做
/*操做SCK引腳,設置高低操做*/
static void OperationSckPin(BusPinValue value)
{
if (value==Set)
{
LL_GPIO_SetOutputPin(I2C_SCL_GPIO_Port, I2C_SCL_Pin);
}
else if(value==Reset)
{
LL_GPIO_ResetOutputPin(I2C_SCL_GPIO_Port, I2C_SCL_Pin);
}
}
(2)SDA數據線的輸出操做
/*操做DATA引腳,設置高低操做*/
static void OperationDataPin(BusPinValue value)
{
if (value==Set)
{
LL_GPIO_SetOutputPin(I2C_SDA_GPIO_Port, I2C_SDA_Pin);
}
else if(value==Reset)
{
LL_GPIO_ResetOutputPin(I2C_SDA_GPIO_Port, I2C_SDA_Pin);
}
}
(3)SDA數據線的方向操做
/*將DATA線設置爲輸入輸出方向模式*/
void SetDataPineDirection(IODirection direction)
{
LL_GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = I2C_SDA_Pin;
if(direction)
{
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
}
else
{
GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
}
LL_GPIO_Init(I2C_SDA_GPIO_Port, &GPIO_InitStruct);
}
2.3、通信函數
如今說明一下傳感器通信的實現。首先看一看其操做命令。傳感器的命令包含三個地址位(目前只支持000,這就是隻能掛接在空閒的IIC總線上的緣由)和五個命令位。SHT1x 會如下述方式表示已正確地接收到指令:在第8個SCK 時鐘的降低沿以後,將DATA 下拉爲低電平(ACK 位)。在第9個SCK 時鐘的降低沿以後,釋放DATA(恢復高電平)。命令集以下:
命令 |
代碼 |
預留 |
0000x |
溫度測量 |
00011 |
溼度測量 |
00101 |
讀狀態寄存器 |
00111 |
寫狀態寄存器 |
00110 |
預留 |
0101x-1110x |
軟復位, 接口復位, 狀態寄存器復位即恢復爲默認狀態.在要發送下一個命令前,至少等待 11ms. |
11110 |
而關於各類該命令操做的實現,SHT70與SHT1x是徹底相同的,在咱們前面的文章中曾詳述。並且這部分與LL其實是不要緊的,準確的說與任何庫都不要緊,因此再也不重複,有興趣能夠產看前面的文章。
3、總結
咱們已經完成可SHT70的相關函數與端口配置,咱們還須要對咱們的代碼進行驗證。將程序下載到目標板,監視結果以下:
從上圖,咱們能夠看到溫溼度的數據與實際一致。
歡迎關注: