1. 程式人生 > 其它 >基於I2C/SPI的溫溼度採集與OLED顯示

基於I2C/SPI的溫溼度採集與OLED顯示

基於I2C/SPI的溫溼度採集與OLED顯示

1.I2C介面實現溫溼度(AHT20)的採集

I2C介紹

1.I2C簡介

I2C匯流排是由Philips公司開發的一種簡單、雙向二線制同步序列匯流排。它只需要兩根線即可在連線於總線上的器件之間傳送資訊。

主器件用於啟動匯流排傳送資料,併產生時鐘以開放傳送的器件,此時任何被定址的器件均被認為是從器件.在總線上主和從、發和收的關係不是恆定的,而取決於此時資料傳送方向。如果主機要傳送資料給從器件,則主機首先定址從器件,然後主動傳送資料至從器件,最後由主機終止資料傳送;如果主機要接收從器件的資料,首先由主器件定址從器件.然後主機接收從器件傳送的資料,最後由主機終止接收過程。在這種情況下.主機負責產生定時時鐘和終止資料傳送。

2.軟體I2C
直接使用 CPU 核心按照 I2C 協議的要求控制 GPIO 輸出高低電平,從而模擬I2C。

軟體I2C的使用
需要在控制產生 I2C 的起始訊號時,控制作為 SCL 線的 GPIO 引腳輸出高電平,然後控制作為 SDA 線的 GPIO 引腳在此期間完成由高電平至低電平的切換,最後再控制SCL 線切換為低電平,這樣就輸出了一個標準的 I2C 起始訊號。

3.硬體I2C
直接利用 STM32 晶片中的硬體 I2C 外設。

硬體I2C的使用
只要配置好對應的暫存器,外設就會產生標準串列埠協議的時序。在初始化好 I2C 外設後,只需要把某暫存器位置 此時外設就會控制對應的 SCL 及 SDA 線自動產生 I2C 起始訊號,不需要核心直接控制引腳的電平。

實現溫溼度輸出

在網上查詢相關需要的程式碼http://www.aosong.com/class-36-2.html

自己修改main函式如下

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
 
#include<stdio.h>
#include "AHT20-21_DEMO_V1_3.h" 
 
void SystemClock_Config(void);
 
 
int fputc(int ch,FILE *f)
 
{
    HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);    
		//等待發送結束	
		while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET){
		}		
 
    return ch;
}
 
 
 
int main(void)
{
  /* USER CODE BEGIN 1 */
	uint32_t CT_data[2]={0,0};
	volatile int  c1,t1;
	
	Delay_1ms(500);
 
	HAL_Init();
 
	SystemClock_Config();
 
	MX_GPIO_Init();
	MX_DMA_Init();
	MX_USART1_UART_Init();
	
	//初始化AHT20
	AHT20_Init();
	Delay_1ms(500);
 
  while (1)
  { 
    /* USER CODE END WHILE */
		AHT20_Read_CTdata(CT_data);       //不經過CRC校驗,直接讀取AHT20的溫度和溼度資料    推薦每隔大於1S讀一次
		//AHT20_Read_CTdata_crc(CT_data);  //crc校驗後,讀取AHT20的溫度和溼度資料 
	
 
		c1 = CT_data[0]*1000/1024/1024;  //計算得到溼度值c1(放大了10倍)
		t1 = CT_data[1]*2000/1024/1024-500;//計算得到溫度值t1(放大了10倍)
		printf("正在檢測");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		printf("\r\n");
		HAL_Delay(1000);
		printf("溫度:%d%d.%d",t1/100,(t1/10)%10,t1%10);
		printf("溼度:%d%d.%d",c1/100,(c1/10)%10,c1%10);
		printf("\r\n");
		printf("等待");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		HAL_Delay(100);
		printf(".");
		printf("\r\n");
		HAL_Delay(1000);
  /* USER CODE END 3 */
	}
}
 
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
  /** 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_NONE;
  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_HSI;
  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_0) != HAL_OK)
  {
    Error_Handler();
  }
}
 
/* USER CODE BEGIN 4 */
 
/* 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
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

參考借鑑了https://blog.csdn.net/qq_43279579/article/details/111597278

2.0.96寸OLED屏顯示資料

SPI介紹

SPI是序列外設介面(Serial Peripheral Interface)的縮寫,SPI是一種高速、全雙工、同步通訊的通訊匯流排,被廣泛應用在ADC、LCD等與MCU的通訊過程中,特點就是快。序列外圍介面(SPI)匯流排是由摩托羅拉公司開發的,用於在主裝置和從裝置之間提供全雙工同步序列通訊。

使用OLED屏顯示姓名學號

通過軟體獲取需要的漢字點陣

在例項程式碼中新增修改上自己的名字即可

void TEST_MainPage(void)
{	
	GUI_ShowCHinese(28,24,16,"XXX",1);//顯示中文名
	GUI_ShowString(4,48,"631907060414",16,1);//顯示學號
	delay_ms(1500);		
	delay_ms(1500);
}

結果如下

1638015039038

總結

本次實驗學習I2C匯流排通訊協議,並理解OLED屏顯和漢字點陣編碼原理,使用STM32F103的SPI介面實現OLED屏顯示資料。