STM32入门二(OLED屏显示LED灯状态+温湿度DHT11)

上章介绍了stm32的LED 点亮
这章在此基础上增加OLED屏显示LED灯状态)
1:环境
STM32CUBE IDE 用这个图省事(keil5也不错)
STM32F103C8T6 64KFLASH 最小核心板(10块左右)
ST-LINKV2 (5块左右) 也可以选择 JLINK(比较贵,不推荐) 安装驱动就好
STM32 ST-LINK Utility 烧录工具(单独可以BIN HEX 烧录到flash中)–可以不安装
OLED 4针脚 I2C/SPI(这里用 I2C,SPI OLED不支持),分辨率:128*64 尺寸 0.96吋
DHT11 4脚(3个脚有用 ,一个悬空) 分别接 VCC ,GND, GPIO(这里接 B0)
在这里插入图片描述

2:I2C协议
在这里插入图片描述
驱动 网上找的(4针脚)

2:配置 I2C 默认为 复用开漏输出 ,开漏输出需要外用上拉电阻,一般 5KΩ左右(一般用.4.7K Ω),没有上拉电阻,就没有高电平,屏幕一直是黑的(一度以为oled屏坏了,跑了个以前写的,屏幕亮了,看下了以前用推免输出的),修改成推免 屏幕就亮了
在这里插入图片描述
在这里插入图片描述

main.c 连同 dht11的一起粘出来了 oled.h oled.c 1306 1315的网上一堆,一般到哪里买·的,商家会提供的

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h"
#include "stdio.h"
#include "delay.h"
#include "DHT11.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/
int  getth_v(uint16_t* temperature,uint16_t* humidity);
//u16 dht11_read_data_t(u8 buffer[5]);
//u16 dht11_read_byte_t(void);
//u16 dht11_read_bit_t(void);
int dth11step = 0;
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
  delay_init_hclk_div8();
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
  delay_ms_func(500); //20 ms
  OLED_Init();			//初始化OLED
  OLED_Clear();
 // OLED_Test();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  char szbuf[16]= {0,};
  char szbuft[16]= {0,};
   char szbufh[16]= {0,};
  uint32_t tdelay = 0 ;
  uint32_t  statecount = 0;
  ///
  int num = 0 ;
   uint16_t temperature=0;
   uint16_t humidity=0;
   int nRet  = 0 ;
   delay_ms_func(2000);
   double hum=0.0f;
   double temp=0.0f;
   u8  char_size  = 16 ; //16 //8
  while (1)
  {
    /* USER CODE END WHILE */
	//  OLED_ShowString(0,0,"#S#",8);
	  HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);//GPIO_PIN_RESET
	  	  	  	  	  sprintf(szbuf,"%s(%d)","open",++statecount);
	  	  	  	  	  OLED_ShowString(2,0,szbuf,char_size);
	  	  	  	delay_ms_func(2000);
	  	  	  	  	  ///
	  	  	  	temperature =0;
	  	  	  	humidity =0;
	  	  	  	dth11step = 0;
	  	  	  nRet=  getth_v(&temperature,&humidity);
	  	  	  	//	 		delay_ms_t(500);
	  	  	  		 	//	xsprintf(szbuf,"num=%d",shownum++);
	  	  	  		 		 int t_temp = (int)(temperature/10) ;
	  	  	  		 	sprintf(szbuft,"temp=%d",t_temp);
	  	  	  		 	int t_hum = (int)(humidity/10) ;
	  	  	  		 	sprintf(szbufh,"hum=%d",t_hum);

	  	  	  		 //	OLED_ShowString(2,0,szbuf,16);
						 OLED_ShowString(2,4,szbuft,char_size);
						OLED_ShowString(2,6,szbufh,char_size);
	  	  	  		 		/
	  	  	  	  //	delay_ms_func(2000); //18s

	  	  	  	  	  HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);//GPIO_PIN_SET
	  	  	  	  	  sprintf(szbuf,"%s(%d)","close",statecount);
	  	  	  	  	  OLED_ShowString(2,2,szbuf,char_size);
	  	  	  	  	delay_ms_func(2000);
    /* USER CODE BEGIN 3 */
  }

  /* 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_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  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_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
int  getth_v(uint16_t* temperature,uint16_t* humidity)
{
	dht11_gpio_output();
	DHT11_OUT_L;   主机将�?�线拉低(时�????>=18ms),使得DHT11能够接收到起始信号�??
   // delay_us_func(20000)   ;//19000HAL_Delay(19); 至少 18 ms
	delay_ms_func(20);
	DHT11_OUT_H;		 主机将�?�线拉高,代表起始信号结束�??
	delay_us_func(30);  //(30)  延时20~40us
	/*--------------引脚配置为输入模式,准备接收传感器回传的数据-------------------*/
	dht11_gpio_input();  配置为输入模�????
	
	uint8_t time_cnt=0;
    uint8_t i;
    uint8_t bit_position;
	while (dht11_scan() == RESET)
	{
		delay_us_func(5);
		++time_cnt;
		 if(time_cnt > 16) return -10; //DHT11_TIMEOUT;
	}
	//dth11step =1;
	//DHT11将�?�线拉高至少80us,为发�?�传感器数据做准备�??
	  time_cnt=0;
	  while(dht11_scan() == SET)
	  {
		  delay_us_func(5);
		 ++time_cnt;
		 if(time_cnt > 16) return -11;//DHT11_TIMEOUT;
	  }
	 // dth11step =2;
		  /*-------------------DHT11数据帧的接收和解�????------------------*/
	  uint8_t DHT11_recvData_[5]={0,0,0,0,0};
	  for( i=0 ; i < 40 ; ++i )
	  {
		  time_cnt = 0;
		  while( dht11_scan() == RESET )   //拉低50us作为bit信号的起始标�????
		  {
			  time_cnt++;
			  delay_us_func(5);
			  if(time_cnt>10) return -12;//DHT11_TIMEOUT;
		  }
		  time_cnt = 0;
		  while( dht11_scan() == SET )   //拉高。持�????26~28us表示bit0,持�????70us表示bit1
		  {
			  time_cnt++;
			  delay_us_func(5);
			  if(time_cnt>14) return -13;//DHT11_TIMEOUT;
		  }
		  if(time_cnt>6){    //说明是bit1
			  bit_position = 7 - i%8;
			  DHT11_recvData_[i/8] |= (uint8_t)(1<<bit_position);
			//  dth11step += 100;
		  }

	  }
	//  dth11step = dth11step>=100?(100+3):3;
	 //------------�????验和的比�????-------------
	 i = (uint8_t)(DHT11_recvData_[0] + DHT11_recvData_[1] + DHT11_recvData_[2] + DHT11_recvData_[3])  ;
	 if(i != DHT11_recvData_[4] ) return -14;//DHT11_CHECKERROR;


//	             *humidity    = DHT11_recvData_[0];  //回传湿度数据
//	             *temperature = DHT11_recvData_[2];  //回传温度数据

	 //放大{[10]}倍数
	 *humidity    = (uint16_t)(DHT11_recvData_[0])*10+DHT11_recvData_[1];  //回传湿度数据
	 *temperature = (uint16_t)(DHT11_recvData_[2])*10+DHT11_recvData_[3];  //回传温度数据
	// dth11step = DHT11_recvData_[2]>0?(1000*(int)(DHT11_recvData_[2])+dth11step):dth11step ;
	 return DHT11_OK;


}
/
/* 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 */

说明下12864 就是 88=64 也就是8页 一个字节 8bit 64 就是8个 8bit
u8 char_size = 16 ; //16 //8 //字体为16 只有4页 为8 可以有8页

3:延时函数,延时函数不精确的话,DHT11 得不到温湿度的

为什么是200000 SysTick->LOAD 只有24bit(3BYTE 最大16777215)这里用的是最大72M
所以 1us =72 那么 tus*72 <=16777215 求得 tus = 233016.875, 这里取200000,也可以取 233016
同理 1ms =72 000 ,那么 tms 最大 取 233,取个200就可以了
大的 使用循环次数加余数 , deylay_1_us 执行时间绝对大于1us,次数多了,就不准确了

//不管是8分还是不分 都可以用 8分时,const int baseus = 200000 ;  可以*8 = 200000*8
//不分  SystemCoreClock = 72 000 000  8分时 = 9 000 000
//count_us=SystemCoreClock/1000000; //1us 多少计数
//count_ms=SystemCoreClock/1000; //1ms 多少计数
下面的不精确 
//		while( nus-- != 0){
//				deylay_1us();//调用1微秒的延时 //每次都初始化次,执行时间大于1us,N次 可能多N/(3-10) us,
//}
void deylay_1_us(){
// 使能SysTick时钟源
		SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;

		// 设置SysTick的重载值
		SysTick->LOAD = count_us - 1;

		// 清除当前值
		SysTick->VAL = 0;

		// 使能SysTick中断和SysTick定时器
		SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

		 // 等待SysTick定时器溢出(即延时n毫秒)
		 while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
		 //	    // 清除溢出标志位
			SysTick->CTRL |= SysTick_CTRL_COUNTFLAG_Msk;
	 //
	 //	    // 关闭SysTick定时器
			SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
void deylay_n_us(uint32_t tus){
// 使能SysTick时钟源
		SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;

		// 设置SysTick的重载值
		SysTick->LOAD = tus*count_us - 1;

		// 清除当前值
		SysTick->VAL = 0;

		// 使能SysTick中断和SysTick定时器
		SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

		 // 等待SysTick定时器溢出(即延时n毫秒)
		 while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
		 //	    // 清除溢出标志位
			SysTick->CTRL |= SysTick_CTRL_COUNTFLAG_Msk;
	 //
	 //	    // 关闭SysTick定时器
			SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
void delay_us_func(unsigned int nus)
{
	const int baseus = 200000 ; //200000
	if ( nus <= baseus) {
		deylay_n_us(nus);// 72*nus <= 16777215 nus max value 233016.875
	}else{
		int nmul = nus/baseus ;
		int remain = nus%baseus;
		while(nmul-- >0){
			deylay_n_us(baseus);
		}
		if (remain > 0){
			deylay_n_us(remain);
		}
		//下面的不精确
//		while( nus-- != 0){
//
//				deylay_1us();//调用1000毫秒的延时
//			}
	}

参考 https://www.dfrobot.com.cn/image/data/DFR0067/DFR0067_DS_10.pdf 或取官方查找
在这里插入图片描述
4 运行效果
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
5:DEMO工程
有需要再上传(现在多加了个同时显示led灯亮灭状态),oled屏及dht11一样
如果觉得有用,麻烦点个赞,加个收藏
前期的DEMO 下载地址 dhtoledshow

基于STM32CubeMX配置DHT11传感器并将其数据展示在OLED幕上通常需要几个步骤: 1. **硬件连接**: - 将DHT11传感器的VCC连接到STM32的3.3V电源,数据线(D4)连接到GPIO口,接地线(GND)接到STM32的地。 - OLED一般通过SPI接口连接,将相应的MOSI、SCLK、CS(选通信号)和RST连接到对应的STM32 GPIO口。 2. **软件配置**: - 使用STM32CubeMX生成配置文件,确保选择了正确的外设和驱动,比如GPIO用于数据传输,SPI用于OLED控制。 - 更新项目设置以包含DHT11库和必要的驱动支持(例如HAL库或固件库)。 3. **编写主程序**: - 引入所需头文件,如`dht.h`、`stm32fxxxx_hal Spi.c`等。 - 初始化DHT11传感器,如`dht11_init(hal_GPIO_TypeDef* gpio)`,其中`gpio`指代连接数据线的GPIO实例。 - 定义获取数据的函数,并在适当的时间间隔内调用,如`uint8_t data = dht11_read_data()`。 4. **处理和显示数据**: - 获取到DHT11的数据后(通常是湿度和温度),解析并转换成合适格式。 - 利用OLED库(如SSD1306或ILI9341)绘制数据显示,可能涉及到字符数组、字符串操作和坐标定位。 5. **循环刷新**: - 将显示内容更新到OLED上,然后回到第一步等待下一次读取。 ```cpp // 示例代码片段 void display_on_oled(dht11_data_t data) { // OLED显示代码,这里假设使用ssd1306库 oled_clear(); oled_set_text_position(0, 0); oled_write_string("Temperature: "); oled_write_number(data.temperature); oled_goto_next_line(); oled_write_string("Humidity: "); oled_write_number(data.humidity); oled_display(); } int main() { // 硬件初始化和配置... while (1) { dht11_data_t sensor_data = dht11_read_data(); display_on_oled(sensor_data); HAL_Delay(2000); // 每隔两秒读取一次数据 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值