stm32筆記[14]-讀取STS30溫度

qsBye發表於2024-05-29

摘要

在藍橋杯物聯網的CT127C開發板上測試STS30溫度模組,透過LoRa顯示到NODE_B螢幕上.讀寫"hello"資料到EEPROM中.

關鍵資訊

  • Keil 5.35.00
  • HAL庫版本:STM32Cube FW_L0 V1.12.0
  • STM32CubeMX:6.2.1
  • 晶片:STM32L071KBU

原理簡介

STS30溫度感測器簡介

The STS3x-DIS is Sensirion’s new high accuracy digital temperature sensor. It relies on the industry proven CMOSens® technology, providing for increased intelligence, reliability and improved accuracy specifications compared to its predecessors. Its functionality includes enhanced signal processing, two distinctive and user selectable I2C addresses and
communication speeds of up to 1 MHz. The DFN package has a footprint of 2.5 x 2.5 mm2 while keeping a height of 0.9 mm. This allows for integration of the STS3x-DIS into a great variety of applications. Additionally, the wide supply voltage range of 2.15 V to 5.5 V guarantees compatibility with a wide range of applications. All in all, the STS3x-DIS incorporates more than 15 years of Sensirion’s digital sensor know-how.
STS3x-DIS 是 Sensirion 的新型高精度數字溫度感測器。它採用業界經過驗證的 CMOSens® 技術,與前輩產品相比,提供了更高的智慧、可靠性和精度規格。其功能包括增強的訊號處理、兩個獨特的、使用者可選擇 I2C 地址以及高達 1 MHz 的通訊速度。DFN 封裝具有 2.5 x 2.5 mm² 的佔地面積,同時保持 0.9 mm 的高度。這使得可以將 STS3x-DIS 整合到各種應用中。此外,2.15 V 至 5.5 V 的寬供應電壓範圍確保了與廣泛的應用相容。總的來說,STS3x-DIS 整合了 Sensirion 超過 15 年的數字感測器專業知識。

AS312紅外熱釋電感測器簡介

The product is a type of intelligent PIR sensor which integrates digital control circuit and body sensitive element in one electromagnetic shielding. The signal inputs from sensitive element to digital circuit via a high impedance differential. The digital circuit converts the input signal to 15bit ADC digital value.
When the PIR signal above the selected threshold, there will be a REL output. The parameter of time are set by resistance to control the time delay of application continuous work.
All signals are processed digitally.
該產品是一種智慧PIR感測器,將數字控制電路和人體感應元件整合在一個電磁遮蔽中。敏感元件的訊號透過高阻抗差分輸入到數位電路中。數位電路將輸入訊號轉換為15位ADC數字值。
當PIR訊號高於所選閾值時,將有一個REL輸出。時間引數透過電阻設定,以控制應用程式連續工作的時間延遲。
所有訊號都經過數字化處理。

STM32L071KBU的內建EEPROM

The STM32L071xx devices have the following features:
• 20 Kbytes of embedded SRAM accessed (read/write) at CPU clock speed with 0 wait
states. With the enhanced bus matrix, operating the RAM does not lead to any
performance penalty during accesses to the system bus (AHB and APB buses).
• The non-volatile memory is divided into three arrays:
– 64, 128 or 192 Kbytes of embedded Flash program memory
6 Kbytes of data EEPROM
– Information block containing 32 user and factory options bytes plus 8 Kbytes of
system memory
Flash program and data EEPROM are divided into two banks. This allows writing in one
bank while running code or reading data from the other bank.
The user options bytes are used to write-protect or read-out protect the memory (with
4 Kbyte granularity) and/or readout-protect the whole memory with the following options:
• Level 0: no protection
• Level 1: memory readout protected.
The Flash memory cannot be read from or written to if either debug features are
connected or boot in RAM is selected
• Level 2: chip readout protected, debug features (Cortex-M0+ serial wire) and boot in
RAM selection disabled (debugline fuse)
The firewall protects parts of code/data from access by the rest of the code that is executed
outside of the protected area. The granularity of the protected code segment or the non-
volatile data segment is 256 bytes (Flash memory or EEPROM) against 64 bytes for the
volatile data segment (RAM).
The whole non-volatile memory embeds the error correction code (ECC) feature.
Bit3 UFB:Userbankswapping
This bit is available only on category 5 devices and reserved on other categories.
It is set and cleared by software. It controls the Bank 1/2 mapping (see Table 10: NVM organization for UFB = 0 (128 Kbyte category 5 devices) and Table 12: NVM organization for UFB = 0 (64 Kbyte category 5 devices)).

  • 0: Flash Program memory Bank 1 is mapped at 0x0800 0000 (and aliased at 0x0000 0000 if MEM_MODE=00) and Data EEPROM Bank 1 at 0x0808 0000 (aliased at 0x0008 0000 if MEM_MODE=00)
  • 1: Flash Program memory Bank 2 is mapped at 0x0800 0000 (and aliased at 0x0000 0000 if MEM_MODE=00) and Data EEPROM Bank 2 at 0x0808 0000 (and aliased at 0x0008 0000 if MEM_MODE=00)
  • 0:快閃記憶體程式儲存器 Bank 1 對映在 0x0800 0000(如果 MEM_MODE=00,則別名為 0x0000 0000),資料 EEPROM Bank 1 對映在 0x0808 0000(如果 MEM_MODE=00,則別名為 0x0008 0000)。
  • 1:快閃記憶體程式儲存器 Bank 2 對映在 0x0800 0000(如果 MEM_MODE=00,則別名為 0x0000 0000),資料 EEPROM Bank 2 對映在 0x0808 0000(如果 MEM_MODE=00,則別名為 0x0008 0000)。

實現

NODE_A

  • 讀取STS30資料,讀寫EEPROM,透過LoRa傳送溫度資料
    main.c
#include "main.h"
#include "oled.h"
#include "eeprom.h"
#include "lora.h"
I2C_HandleTypeDef hi2c1;
I2C_HandleTypeDef hi2c3;
SPI_HandleTypeDef hspi1;
TIM_HandleTypeDef htim6;
UART_HandleTypeDef huart2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_I2C3_Init(void);
static void MX_SPI1_Init(void);
static void MX_TIM6_Init(void);
static void MX_I2C1_Init(void);
/* USER CODE BEGIN PFP */
float readSHS30(void);
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_I2C3_Init();
  MX_SPI1_Init();
  MX_TIM6_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
	OLED_Init();
	LORA_Init();
	unsigned char b2[16];
	// 讀寫EEPROM
	flashWrite(MCU_Start_Address_Bank1,"hello",strlen("hello"));
	uint8_t test_eeprom[strlen("hello")];
	flashRead(MCU_Start_Address_Bank1,test_eeprom,strlen("hello"));
	sprintf((char*)b2, "r:%s",test_eeprom);
	OLED_ShowString(5, 2, b2, 16);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		char b3[6];
		float temperature = readSHS30();
		sprintf(b3,"%.2f",temperature);
		OLED_ShowString(0, 0, b3, 16);
		uint8_t g_lora_tx_buf[23]; // lora傳送快取
		for(int i=0;i<6;i++){
			g_lora_tx_buf[i]= b3[i];
		}
		LORA_Tx(g_lora_tx_buf,6);
		HAL_Delay(3000);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
  RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_I2C1
                              |RCC_PERIPHCLK_I2C3;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
  PeriphClkInit.I2c3ClockSelection = RCC_I2C3CLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}
static void MX_I2C1_Init(void)
{
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x00707CBB;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief I2C3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C3_Init(void)
{

  hi2c3.Instance = I2C3;
  hi2c3.Init.Timing = 0x00707CBB;
  hi2c3.Init.OwnAddress1 = 0;
  hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c3.Init.OwnAddress2 = 0;
  hi2c3.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c3) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c3, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c3, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C3_Init 2 */
	 HAL_Delay(100); // 延時以初始化完成
  /* USER CODE END I2C3_Init 2 */

}

/**
  * @brief SPI1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI1_Init(void)
{

  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_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief TIM6 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM6_Init(void)
{

  TIM_MasterConfigTypeDef sMasterConfig = {0};

  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 0;
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 65535;
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM6_Init 2 */

  /* USER CODE END TIM6_Init 2 */

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4|GPIO_PIN_9|GPIO_PIN_10, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_5, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_SET);

  /*Configure GPIO pin : PC14 */
  GPIO_InitStruct.Pin = GPIO_PIN_14;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PC15 */
  GPIO_InitStruct.Pin = GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pins : PA4 PA9 PA10 PA11
                           PA12 */
  GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
                          |GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PB0 PB5 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */
float readSHS30(void){
	unsigned char data[2];
	
	data[0] = 0x24;//不使能時鐘伸缿 
	data[1] = 0x0B;//中重複濧測量精庿
	
	HAL_I2C_Master_Transmit(&hi2c1, 0x94, data, 2, 10);
    //0x94是鿚過0x4A向左移一位得來的_0表示冿1表示讀,這裡朿低位丿0_0X4A為STS30地址
	
	HAL_Delay(10);
	
	HAL_I2C_Master_Receive(&hi2c1, 0x95, data, 2, 10);
    //0x94是鿚過0x4A向左移一位再加一得來的,0表示冿1表示讀,這裡朿低位丿1_0X4A為STS30地址
 
	return (float)(-45)+175*(data[0]<<8|data[1])/65535;
}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */

eeprom.h

#ifndef __EEPROM_H
#define __EEPROM_H

#include "main.h"
//MAX_3KB
#define MCU_Start_Address_Bank1 0x08080000
//MAX_3KB
#define MCU_Start_Address_Bank2 0x08080C00

void flashWrite(uint32_t address,uint8_t *data,uint8_t length);
void flashRead(uint32_t address,uint8_t *data,uint8_t length);

#endif

eeprom.c

#include "eeprom.h"

//MAX 3KB
void flashWrite(uint32_t address,uint8_t *data,uint8_t length){
  HAL_FLASHEx_DATAEEPROM_Unlock();// 解鎖Flash

  for(uint8_t i=0;i< length;i++){  
    *(__IO uint8_t *)address = (uint8_t) data[i];
    address+=1;
  }

  HAL_FLASHEx_DATAEEPROM_Lock();// 上鎖Flash
}


//MAX 3KB
void flashRead(uint32_t address,uint8_t *data,uint8_t length){
  for(uint8_t i=0;i< length;i++){     
    data[i]=*(__IO uint8_t *)address;
    address+=1;
  }
}

NODE_B

  • 接收溫度資料並顯示到OLED螢幕
    main.c
/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_I2C3_Init();
MX_SPI1_Init();
MX_TIM6_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
// 初始化OLED
OLED_Init();
unsigned char b2[16];
LORA_Init();

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
fn_lora_rx_handler();
OLED_ShowString(0, 0, b2, 16);
}
/* USER CODE END 3 */
void fn_lora_rx_handler(void){
	unsigned char s_length = LORA_Rx((unsigned char*)g_lora_rx_buf);
	if(g_lora_rx_buf[0] != '\0'){
		HAL_UART_Transmit(&huart2,g_lora_rx_buf,16,160);
	}
    if(g_lora_rx_buf[0]!='\0'){
		char b3[6];
		for(int i=0;i<6;i++){
			 b3[i]=g_lora_rx_buf[i];
	}
    OLED_ShowString(28,2,(uint8_t *)b3,16);
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11,GPIO_PIN_RESET);
    HAL_Delay(1000);
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11,GPIO_PIN_SET);
  }
}

效果

NODE_B顯示NODE_A的溫度

相關文章