电子系统综合设计作业笔记

题目要求

 平台 STM32F411CE,IO口连接如下图 

 配置CubeMX工程,暂时不开启定时器,先把每项功能调通以后再通过中断或者操作系统功能结合

 第一步开启串口,USART1开发板未引出,因此开启USART2,顺便加一个delay_us,勾选use microlib后,串口2就可以正常输出了

//串口重定向
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart2, &ch, 1, 0xffff);
  return ch;
}

void delay_us(volatile uint32_t us)
{
	volatile uint16_t i,j;  
	while(us--)
	{
		for(i=0;i<11;i++)
			j++;
	}
}

 第二步调试OLED,OLED驱动为SSD1306,IIC模式。

#include "oled.h"
#include "oledfont.h"

//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127	
//[1]0 1 2 3 ... 127	
//[2]0 1 2 3 ... 127	
//[3]0 1 2 3 ... 127	
//[4]0 1 2 3 ... 127	
//[5]0 1 2 3 ... 127	
//[6]0 1 2 3 ... 127	
//[7]0 1 2 3 ... 127 			   


/**
 * @brief	OLED写入命令
 * @param cmd - 待写入命令
 * @note	移植时,请使用自己的底层API实现 
*/
static void OLED_Write_Cmd(uint8_t cmd)
{
	uint8_t buf[2];
	buf[0] = 0x00;	//control byte
	buf[1] = cmd;
	
	//使用HAL库的API实现
	HAL_I2C_Master_Transmit(&hi2c1, 0x78, buf, 2, 0xFFFF);
}
/**
 * @brief	OLED写入数据
 * @param cmd - 待写入数据
 * @note	移植时,请使用自己的底层API实现 
*/
static void OLED_Write_Dat(uint8_t dat)
{
	uint8_t buf[2];
	buf[0] = 0x40; //control byte
	buf[1] = dat;
	
	//使用HAL库的API实现
	HAL_I2C_Master_Transmit(&hi2c1, 0x78, buf, 2, 0xFFFF);
}

/**
 * @brief	OLED设置显示位置
 * @param x - X方向位置
 * @param y - Y方向位置
*/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{ 	
	OLED_Write_Cmd(0xb0+y);
	OLED_Write_Cmd(((x&0xf0)>>4)|0x10);
	OLED_Write_Cmd((x&0x0f)|0x01);
}   	  
/**
 * @brief	OLED开启显示
*/ 
void OLED_Display_On(void)
{
	OLED_Write_Cmd(0X8D);  //SET DCDC命令
	OLED_Write_Cmd(0X14);  //DCDC ON
	OLED_Write_Cmd(0XAF);  //DISPLAY ON
}
/**
 * @brief	OLED关闭显示
*/   
void OLED_Display_Off(void)
{
	OLED_Write_Cmd(0X8D);  //SET DCDC命令
	OLED_Write_Cmd(0X10);  //DCDC OFF
	OLED_Write_Cmd(0XAE);  //DISPLAY OFF
}		   			 
/**
 * @brief	OLED清屏函数(清屏之后屏幕全为黑色)
*/ 
void OLED_Clear(void)
{  
	uint8_t i,n;		    
	for(i=0;i<8;i++)  
	{  
		OLED_Write_Cmd(0xb0+i);    //设置页地址(0~7)
		OLED_Write_Cmd(0x00);      //设置显示位置—列低地址
		OLED_Write_Cmd(0x10);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)
		{
			OLED_Write_Dat(0);
		}			
	}
}
/**
 * @brief	OLED显示全开(所有像素点全亮)
*/
void OLED_On(void)
{  
	uint8_t i,n;
	for(i=0;i<8;i++)
	{  
		OLED_Write_Cmd(0xb0+i);    //设置页地址(0~7)
		OLED_Write_Cmd(0x00);      //设置显示位置—列低地址
		OLED_Write_Cmd(0x10);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)
		{
			OLED_Write_Dat(1);
		}			
	}
}
/**
 * @brief	在指定位置显示一个ASCII字符
 * @param x - 0 - 127
 * @param y - 0 - 7
 * @param chr  - 待显示的ASCII字符
 * @param size - ASCII字符大小
 * 				字符大小有12(6*8)/16(8*16)两种大小
*/
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size)
{   
	uint8_t c=0,i=0;
	
	c = chr-' ';	
	if(x > 128-1)
	{
		x=0;
		y++;
	}
	
	if(size ==16)
	{
		OLED_Set_Pos(x,y);	
		for(i=0;i<8;i++)
		{
			OLED_Write_Dat(F8X16[c*16+i]);
		}
		OLED_Set_Pos(x,y+1);
		for(i=0;i<8;i++)
		{
			OLED_Write_Dat(F8X16[c*16+i+8]);
		}
	}
	else
	{	
		OLED_Set_Pos(x,y);
		for(i=0;i<6;i++)
		{
			OLED_Write_Dat(F6x8[c][i]);
		}
	}
}
/**
 * @brief	OLED 专用pow函数
 * @param m - 底数
 * @param n - 指数
*/
static uint32_t oled_pow(uint8_t m,uint8_t n)
{
	uint32_t result=1;	 
	while(n--)result*=m;    
	return result;
}	
/**
 * @brief	在指定位置显示一个整数
 * @param x - 0 - 127
 * @param y - 0 - 7
 * @param num - 待显示的整数(0-4294967295)
 * @param	len - 数字的位数 
 * @param size - ASCII字符大小
 * 				字符大小有12(6*8)/16(8*16)两种大小
*/
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size)
{         	
	uint8_t t,temp;
	uint8_t enshow=0;						   
	for(t=0;t<len;t++)
	{
		temp=(num/oled_pow(10,len-t-1))%10;
		if(enshow==0&&t<(len-1))
		{
			if(temp==0)
			{
				OLED_ShowChar(x+(size/2)*t,y,' ',size);
				continue;
			}else enshow=1; 
		 	 
		}
	 	OLED_ShowChar(x+(size/2)*t,y,temp+'0',size); 
	}
} 
/**
 * @brief	在指定位置显示一个字符串
 * @param x - 0 - 127
 * @param y - 0 - 7
 * @param chr - 待显示的字符串指针
 * @param size - ASCII字符大小
 * 				字符大小有12(6*8)/16(8*16)两种大小
*/
void OLED_ShowString(uint8_t x,uint8_t y,char *chr,uint8_t size)
{
	uint8_t j=0;
	while (chr[j]!='\0')
	{		OLED_ShowChar(x,y,chr[j],size);
			x+=8;
			if(x>120){x=0;y+=2;}
			j++;
	}
}
/**
 * @brief	在指定位置显示一个汉字
 * @param x  - 0 - 127
 * @param y  - 0 - 7
 * @param no - 汉字在中文字库数组中的索引(下标)
 * @note	中文字库在oledfont.h文件中的Hzk数组中,需要提前使用软件对汉字取模
*/
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
{      			    
	uint8_t t,adder=0;
	OLED_Set_Pos(x,y);	
    for(t=0;t<16;t++)
		{
				OLED_Write_Dat(Hzk[2*no][t]);
				adder+=1;
     }	
		OLED_Set_Pos(x,y+1);	
    for(t=0;t<16;t++)
			{	
				OLED_Write_Dat(Hzk[2*no+1][t]);
				adder+=1;
      }					
}
/**
 * @brief	在指定位置显示一幅图片
 * @param x1,x2  - 0 - 127
 * @param y1,y2  - 0 - 7(8表示全屏显示)
 * @param BMP - 图片数组地址
 * @note	图像数组BMP存放在bmp.h文件中
*/
void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1,uint8_t BMP[])
{ 	
 uint16_t j=0;
 uint8_t x,y;
  
  if(y1%8==0)
	{
		y=y1/8;
	}		
  else
	{
		y=y1/8+1;
	}
	for(y=y0;y<y1;y++)
	{
		OLED_Set_Pos(x0,y);
    for(x=x0;x<x1;x++)
	  {      
	    	OLED_Write_Dat(BMP[j++]);	    	
	  }
	}
} 

/**
 * @brief	OLED初始化
*/			    
void OLED_Init(void)
{ 	

	HAL_Delay(500);

	OLED_Write_Cmd(0xAE);//--display off
	OLED_Write_Cmd(0x00);//---set low column address
	OLED_Write_Cmd(0x10);//---set high column address
	OLED_Write_Cmd(0x40);//--set start line address  
	OLED_Write_Cmd(0x81); // contract control
	OLED_Write_Cmd(0xFF);//--128   
	OLED_Write_Cmd(0xA1);//set segment remap 
	OLED_Write_Cmd(0xC8);//Com scan direction
	OLED_Write_Cmd(0xA6);//--normal / reverse
	OLED_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
	OLED_Write_Cmd(0x3F);//--1/32 duty
	OLED_Write_Cmd(0xD3);//-set display offset
	OLED_Write_Cmd(0x00);//
	OLED_Write_Cmd(0xD5);//set osc division
	OLED_Write_Cmd(0x80);
	OLED_Write_Cmd(0xD9);//Set Pre-Charge Period
	OLED_Write_Cmd(0xF1);//
	OLED_Write_Cmd(0xDA);//set com pin configuartion
	OLED_Write_Cmd(0x12);//
	OLED_Write_Cmd(0xDB);//set Vcomh
	OLED_Write_Cmd(0x40);//
	OLED_Write_Cmd(0x20);
	OLED_Write_Cmd(0x02);
	OLED_Write_Cmd(0x8D);//set charge pump enable
	OLED_Write_Cmd(0x14);//
	OLED_Write_Cmd(0xA4);
	OLED_Write_Cmd(0xA6);
	OLED_Write_Cmd(0xAF);//--turn on oled panel
	
	OLED_Clear();
	OLED_Set_Pos(0,0);
}

第三步调试传感器。

#include "bsp_dht11.h"
#include "main.h"
 int Read_Byte(void)
{
	int i, temp=0;

	for(i=0;i<8;i++)    
	{	 
		
		while(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin)==GPIO_PIN_RESET);/*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/  

		/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
		 *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 
		 */
		delay_us(30); //延时x us 这个延时需要大于数据0持续的时间即可	   	  

		if(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin)==GPIO_PIN_SET)/* x us后仍为高电平表示数据“1” */
		{
			/* 等待数据1的高电平结束 */
			while(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin)==GPIO_PIN_SET);

			temp|=(uint8_t)(0x01<<(7-i)); 
		}
		else	 // x us后为低电平表示数据“0”
		{			   
			temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
		}
	}
	return temp;
}

int Read_DHT11(void)
{
	int flag;
	HAL_GPIO_WritePin(DH11_GPIO_Port,DH11_Pin,GPIO_PIN_RESET);
	delay_us(18000);//延时18ms
	HAL_GPIO_WritePin(DH11_GPIO_Port,DH11_Pin,GPIO_PIN_SET);
	delay_us(30);   //延时30us
	GPIO_InitTypeDef GPIO_InitStruct = {0};	
	GPIO_InitStruct.Pin = DH11_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
	/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/  
	if(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin) == 0) 
	{
		while(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin) == 0) ;/*轮询直到从机发出 的80us 低电平 响应信号结束*/  
		while(HAL_GPIO_ReadPin(DH11_GPIO_Port,DH11_Pin) == 1) ;/*轮询直到从机发出的 80us 高电平 标置信号结束*/
		humi_int= Read_Byte();
		humi_deci= Read_Byte();
		temp_int= Read_Byte();
		temp_deci= Read_Byte();
		check_sum= Read_Byte();	/*读取数据*/
		if(check_sum == humi_int + humi_deci + temp_int+ temp_deci)
		flag = 1;
	}	
	
	GPIO_InitStruct.Pin = 	DH11_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
	HAL_GPIO_WritePin(DH11_GPIO_Port,DH11_Pin,GPIO_PIN_SET);/*IO重新设置为输出*/
	
	if (flag) return 1;/*数据正常*/
		else return 0;
}
/********************************************************
 *
 * @file    ds18b20.c
 * @brief   ds18b20驱动
 * @author  Mculover666
***************************************************/

#include "ds18b20.h"
#include <stdio.h>
#include "main.h"

void DS18B20_InPut_Mode(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};	
	GPIO_InitStruct.Pin = DS18B20_GPIO_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void DS18B20_OutPut_Mode(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};	
	GPIO_InitStruct.Pin = 	DS18B20_GPIO_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
	HAL_GPIO_WritePin(DH11_GPIO_Port,DH11_Pin,GPIO_PIN_SET);
}	

static void DS18B20_Send_Reset_Single(void)
{
	DS18B20_OutPut_Mode();
    
    /* 拉低总线 480 - 960 us*/
	HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_RESET);
	delay_us(500);
    
    /* 释放总线 15 - 60 us */
	HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_SET);
	delay_us(15);
}

/**
  * @brief    检测DS18B20存在脉冲
  * @param    none
  * @retval   0 DS18B20设备正常
  * @retval   1  DS18B20设备响应复位信号失败
  * @retval   2  DS18B20设备释放总线失败
*/
static uint8_t DS18B20_Check_Ready_Single(void)
{
	uint8_t cnt = 0;
    
	/* 1.检测存在脉冲 */
	DS18B20_InPut_Mode();
    
    //等待DS18B20 拉低总线 (60~240 us 响应复位信号)
	while (HAL_GPIO_ReadPin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN) && cnt < 80) {
		delay_us(1);
		cnt++;
	}
    
	if (cnt > 80) {
        return 1;
    }
    
	/* 2.检测DS18B20是否释放总线 */	
	cnt = 0;
	DS18B20_InPut_Mode();
    
    //判断DS18B20是否释放总线(60~240 us 响应复位信号之后会释放总线)
	while ((!HAL_GPIO_ReadPin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN)) && cnt<80) {
		delay_us(1);
		cnt++;
	}
    
	if (cnt > 80) {
        return 2;
    } else {
        return 0;
    }
}

/**
  * @brief    检测DS18B20设备是否正常
  * @param    none
  * @retval   0 DS18B20设备正常
  * @retval   1  DS18B20设备响应复位信号失败
  * @retval   2  DS18B20设备释放总线失败
*/
static uint8_t DS18B20_Check_Device(void)
{
    /*1.主机发送复位信号*/
	DS18B20_Send_Reset_Single();
    
    /*2.检测存在脉冲*/
	return DS18B20_Check_Ready_Single();
}
/**
  * @brief    DS18B20初始化
  * @param    none
  * @retval   none
*/
void DS18B20_Init(void)
{
	/* 1.DS18B20控制引脚初始化 */
    //在main函数中已经初始化,不需要再次重复。

	/*2.检测DS18B20设备是否正常*/
	switch (DS18B20_Check_Device()) {
		case 0:	
            //printf("DS18B20_Init OK!\n");
            break;
		case 1:
            //printf("DS18B20no find\n");
            break;
		case 2:
            //printf("DS18B20alway on\n");
            break;
	}
}

/**
  * @brief    向DS18B20写一个字节
  * @param    cmd 要写入的字节
  * @retval   none
*/
static uint8_t DS18B20_Write_Byte(uint8_t cmd)
{
	uint8_t i = 0;
    
    /* 1. 设置总线为输出模式 */
	DS18B20_OutPut_Mode();
    
    /* 2. 发送数据,低位在前 */
	for (i = 0; i < 8; i++) {
		HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_RESET);
		delay_us(2); 
		HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,cmd & 0x01);
		delay_us(60);
		HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_SET);;
		cmd >>= 1;
		delay_us(2);
	}
    
	return 0;
}
 
/**
  * @brief    从DS18B20读一个字节
  * @param    none
  * @retval   读取到的一个字节数据
*/
uint8_t DS18B20_Read_Byte(void)
{
	uint8_t i = 0;
    uint8_t data = 0;
    
    /* 读取数据 */
	for (i  =0; i < 8; i++)	{
		DS18B20_OutPut_Mode();
		HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_RESET);  
		delay_us(2);
		HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_SET);  
        
		DS18B20_InPut_Mode();
		delay_us(10);
		data >>= 1 ;
		if (HAL_GPIO_ReadPin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN) ) {
            data |= 0x80;
        }
        
		delay_us(60);
		DS18B20_OutPut_Mode();	
		HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_SET);  
	}
	return data;
}

/**
  * @brief    从DS18B20读取一次数据
  * @param    none
  * @retval   读取到的温度数据
  * @note     适用于总线上只有一个DS18B20的情况
*/
void DS18B20_Read_Temperature(void)
{
    uint16_t temp = 0;
    uint8_t  temp_H, temp_L;
 
    DS18B20_Check_Device();
    
    DS18B20_Write_Byte(0xCC); //跳过ROM序列检测
    DS18B20_Write_Byte(0x44); //启动一次温度转换
    
    //等待温度转换完成
    while (DS18B20_Read_Byte() != 0xFF);
    
    DS18B20_Check_Device();   //必须,不能省略
    
    DS18B20_Write_Byte(0xCC); //跳过ROM序列检测
    DS18B20_Write_Byte(0xBE); //读取温度
    
    temp_L = DS18B20_Read_Byte(); //读取的温度低位数据
    temp_H = DS18B20_Read_Byte(); //读取的温度高位数据
    temp   = temp_L | (temp_H << 8);   //合成温度
    ds18_int   = temp >> 4 ;          /*合成实际温度整数部分****精度相对上面的更高*/ 
    ds18_deci   = temp & 0xF ;         /*合成实际温度小数部分*/

   
}

再加上eeprom

/**
 * @Copyright   (c) 2019,mculover666 All rights reserved	
 * @filename    at24C02_i2c_drv.c
 * @breif       Drive AT24C02(EEPROM) based on stm32 iic peripheral
 * @changelog   v1.0    mculover666     2019/7/15
 *              v1.1    mculover666     2021/4/15   (add WRITE_CYCLE_TIME_MS)
 *              v1.2    mculover666     2021/4/28   (add value operation)
 */

#include "AT24C02_i2c_drv.h"
#include "i2c.h"
#include "main.h"
/**
 * @brief       write a byte to any address
 * @param[in]	addr    address to write  
 * @param[in]   data    the pointer of data to write
 * @return		errcode
 * @retval      0       success
 * @retval      -1      fail
*/
int AT24C02_Write_Byte(uint16_t addr, uint8_t* dat)
{
    int ret;
    
    delay_us(WRITE_CYCLE_TIME_MS*1000);
    
    ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, 1, 100);
    
    return ret == HAL_OK ? 0 : -1;
}

/**
 * @brief       read a byte from any address
 * @param[in]	addr        address to rad  
 * @param[out]  read_buf    the pointer of buffer to save read data
 * @return		errcode
 * @retval      0       success
 * @retval      -1      fail
*/
int AT24C02_Read_Byte(uint16_t addr, uint8_t* read_buf)
{
    int ret;

    delay_us(WRITE_CYCLE_TIME_MS*1000);
    
    ret = HAL_I2C_Mem_Read(&hi2c1, AT24C02_ADDR_READ, addr, I2C_MEMADD_SIZE_8BIT, read_buf, 1, 100);
    
    return ret == HAL_OK ? 0 : -1;
}

/**
 * @brief       write amount bytes to any address
 * @param[in]	addr    address to write
 * @param[in]   data    the pointer of data buffer to write
 * @return		errcode
 * @retval      0       success
 * @retval      else      fail
*/
int AT24C02_Write_Amount_Byte(uint16_t addr, uint8_t* dat, uint16_t size)
{
    int ret;
    uint16_t i = 0;
    uint16_t cnt = 0;
    uint16_t page = 0;
    
    if (0 == addr % 8) {    // whether the addr is the starting address of the page
        if (size <= 8) {    //whether the number of bytes to be written is less than one page
            delay_us(WRITE_CYCLE_TIME_MS*1000);
            ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, size, 100);
            if (ret != HAL_OK) {
                return -1;
            }
        } else {
            page = size / 8;
            for (i = 0;i < page; i++) {
                delay_us(WRITE_CYCLE_TIME_MS*1000);
                ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], 8, 100);
                if (ret != HAL_OK) {
                    return -2;
                }
                addr += 8;
                cnt += 8;
            }
            if (cnt < size) {     //write remain bytes
                delay_us(WRITE_CYCLE_TIME_MS*1000);
                ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], size - cnt, 100);
                if (ret != HAL_OK) {
                    return -3;
                }
            }
        }
    } else {    //the address deviates from the starting page address
        if (size <= (8 - addr % 8)) {     //whether we can finish writing on this page
            delay_us(WRITE_CYCLE_TIME_MS*1000);
            ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, size, 100);
            if (ret != HAL_OK) {
                return -4;
            }
        } else {    //can't finish on this page
            //finish the page first
            cnt += 8 - addr % 8;
            delay_us(WRITE_CYCLE_TIME_MS*1000);
            ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, dat, cnt, 100);
            if (ret != HAL_OK) {
                return -5;
            }
            addr += cnt;
            
            //loops to write the entire page of data
            page = (size - cnt) / 8;
            for (i = 0;i < page; i++) { 
                delay_us(WRITE_CYCLE_TIME_MS*1000);
                ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], 8, 100);
                if (ret != HAL_OK) {
                    return -6;
                }
                addr += 8;
                cnt += 8;
            }
            if (cnt < size) {     //write remain bytes
                delay_us(WRITE_CYCLE_TIME_MS*1000);
                ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_ADDR_WRITE, addr, I2C_MEMADD_SIZE_8BIT, &dat[cnt], size - cnt, 100);
                if (ret != HAL_OK) {
                    return -7;
                }
            }
        }			
    }
    
    return 0;
}

/**
 * @brief       read amount bytes from any address
 * @param[in]	addr        address to read  
 * @param[out]  read_buf    the pointer of buffer to save read data
 * @return		errcode
 * @retval      0       success
 * @retval      -1      fail
*/
int AT24C02_Read_Amount_Byte(uint16_t addr, uint8_t* recv_buf, uint16_t size)
{
    int ret;
    delay_us(WRITE_CYCLE_TIME_MS*1000);
    //HAL_Delay(WRITE_CYCLE_TIME_MS);
    
	ret = HAL_I2C_Mem_Read(&hi2c1, AT24C02_ADDR_READ, addr, I2C_MEMADD_SIZE_8BIT, recv_buf, size, 100);
    
    return ret == HAL_OK ? 0 : -1;
}

/**
 * @brief       write value to any address
 * @param[in]	addr    address to write
 * @param[in]   ptr     the pointer of value to write
 * @return		errcode
 * @retval      0       success
 * @retval      else      fail
*/
int AT24C02_Write_Value(uint16_t addr, void *ptr, uint16_t size)
{
    int ret;
    
    if (!ptr) {
        return -1;
    }
  
    ret = AT24C02_Write_Amount_Byte(addr, (uint8_t*)ptr, size);
    
    if (ret < 0) {
        return ret;
    }
    
    return 0;
}

/**
 * @brief       read value from any address
 * @param[in]	addr    address to write
 * @param[in]   ptr     the pointer of value to read
 * @return		errcode
 * @retval      0       success
 * @retval      else      fail
*/
int AT24C02_Read_Value(uint16_t addr, void *ptr, uint16_t size)
{
    int ret;
    
    if (!ptr) {
        return -1;
    }
  
    ret = AT24C02_Read_Amount_Byte(addr, (uint8_t*)ptr, size);
    
    if (ret < 0) {
        return ret;
    }
    
    return 0;
}

最后再加上亿点点代码,就完成了

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 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 "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include <stdio.h>
#include "oled.h"
#include "bmp.h"
#include "bsp_dht11.h"
#include "stm32f4xx_hal_uart.h"
#include "ds18b20.h"
#include "string.h"
#include "at24c02_i2c_drv.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 */

int	htim5_Period =1000-1;//PWM频率
int	htim5_Period0 = 1000-1;//PWM频率
int	LED_Blue_FLAG = 0;//PWM频率
int page=0;//界面显示页数
int page0=0;//保存page的内容
int hour=23;//时间
int minute_T=5;
int minute_S=7;
int second_T=5;
int second_S=8;

int Key_User,Key_S1,Key_S2;//按键状态
int Work_State=1;//传感器状态
int Work_State0=1;//传感器状态

uint8_t period = 1;
uint8_t period0 = 1;//多少个周期发送一次
//串口缓冲区
uint8_t usart2_rxone[1];
uint8_t usart2_rxbuf[20];
int usart2_rxcounter;
//温湿度
int humi_int,humi_deci,temp_int,temp_deci,check_sum;
int ds18_int,ds18_deci;
int tem_max_int = 30;int tem_max_dec = 0;int tem_min_int = 20;int tem_min_dec = 0;
int hum_max_int = 80;int hum_max_dec = 0;int hum_min_int = 10;int hum_min_dec = 0;

//温湿度历史数据
uint8_t tem_hisbuf[20];
int tem_hisbuf_position = 0;
int tem_hisbuf_position0 = 0;
int tem_position= 0x10;
int tem_position0= 0x10;


int page0_userkey_flag ,page0_userkey_flag0,page2_userkey_flag ,page2_userkey_flag0;

uint8_t uart_Reply[]=" 13.2  , 50%, 15  - 20  , 15:23:51\r\n";
uint8_t uart_Reply_num[2]="00";

//eeprom数据
	uint8_t write_dat = '2';
	uint8_t recv_buf = 0;
/* 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 fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

void uart_call_back(void);//串口回传
void time_compute(void);//计算时间	
void temp_compute(void);//计算温度	
void delay_us(volatile uint32_t us);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);//串口中断接收
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);//按键检测
void UART2_Handle(void);//串口2接收信息处理
void key_handle(void);//按键处理
void page_handle(void);//页面显示


//1S定时器中断作为心跳
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* tim_baseHandle)
{
	
//	AT24C02_Write_Byte(10, &write_dat);
//	delay_us(50000);	
//	AT24C02_Read_Byte(10,&recv_buf);
	//HAL_UART_Transmit(&huart2,&recv_buf,sizeof(recv_buf),0xff);
	
	if(tim_baseHandle->Instance == htim2.Instance)
	{	
		if(page==4)
		{
			if(page0!=page)//位置初始化
			{
				page0 = page;
				tem_position = tem_position0;
				tem_hisbuf_position = tem_hisbuf_position0;
			}
			AT24C02_Write_Byte(tem_position, &temp_int);
			tem_hisbuf_position++;
			tem_position++;
			delay_us(150000);
			AT24C02_Write_Byte(tem_position, &temp_deci);
			tem_position++;
			tem_hisbuf_position++;
		}
		if (tem_position>0x10+20){tem_position = tem_position0;tem_hisbuf_position = tem_hisbuf_position0;}//溢出后从头开始
		
		if(usart2_rxcounter>1) 
		{
			UART2_Handle();
		}
		if(Work_State==1)
		{
			DS18B20_Read_Temperature();
			Read_DHT11();
		}
		key_handle();//按键处理
		time_compute();//计算时间	
		temp_compute();//计算温度	
		page_handle();	//界面显示
		printf("AT+CIPSEND=0,3\r\n");
		delay_us(2000);
		printf("T%d",temp_int);
		delay_us(5000);
		printf("AT+CIPSEND=0,3\r\n");
		delay_us(2000);
		printf("M%d",humi_int);
		delay_us(1000);
		if(temp_int*10+temp_deci>tem_max_int*10+tem_max_dec)
		{
				HAL_GPIO_TogglePin(LED_Blue_GPIO_Port,LED_Blue_Pin);
				HAL_TIM_PWM_Start(&htim5,TIM_CHANNEL_2);
				htim5_Period = 4000-1 ;
				if(htim5_Period != htim5_Period0 )
				{
					HAL_TIM_PWM_Stop(&htim5,TIM_CHANNEL_2);
					MX_TIM5_Init();
					HAL_TIM_PWM_Start(&htim5,TIM_CHANNEL_2);		
				}
				htim5_Period0 = htim5_Period;
				
		}
		else if(temp_int*10+temp_deci<tem_min_int*10+tem_min_dec)
		{
				if(LED_Blue_FLAG == 0)
				{
					HAL_GPIO_TogglePin(LED_Blue_GPIO_Port,LED_Blue_Pin);
					LED_Blue_FLAG = 2;
				}
				else
				{
					LED_Blue_FLAG--;				
				}
				HAL_TIM_PWM_Start(&htim5,TIM_CHANNEL_2);
				htim5_Period = 1000-1 ;
				if(htim5_Period != htim5_Period0 )
				{
					HAL_TIM_PWM_Stop(&htim5,TIM_CHANNEL_2);
					MX_TIM5_Init();
					HAL_TIM_PWM_Start(&htim5,TIM_CHANNEL_2);
				}
				htim5_Period0 = htim5_Period;
		}
		else
		{
			HAL_TIM_PWM_Stop(&htim5,TIM_CHANNEL_2);
			HAL_GPIO_WritePin(LED_Blue_GPIO_Port,LED_Blue_Pin,GPIO_PIN_RESET);
		}
		uart_call_back();//串口回传
		HAL_GPIO_TogglePin(LED_Yellow_GPIO_Port,LED_Yellow_Pin);

	}
}	


/* USER CODE END 0 */

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

uart_Reply[5] = 0xA1;uart_Reply[6] = 0xE6;uart_Reply[16] = 0xA1;uart_Reply[17] = 0xE6;uart_Reply[22] = 0xA1;uart_Reply[23] = 0xE6;//写入摄氏度
  /* 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 */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_I2C1_Init();
  MX_TIM2_Init();
  MX_USART1_UART_Init();
  MX_TIM5_Init();

	
  /* USER CODE BEGIN 2 */
	HAL_GPIO_TogglePin(OLED_nRST_GPIO_Port,OLED_nRST_Pin);//开启OLED
	OLED_Init();
	OLED_ShowString(0, 0, "Starting......", 16);
	OLED_ShowString(0, 2, "Reading History Tempreture...", 16);

	
	
	//读取at24历史记录
	for(int i = 0 ; i < 9 ; i++)
	{
		AT24C02_Read_Byte(tem_position,&tem_hisbuf[tem_hisbuf_position]);
		tem_hisbuf_position++;
		tem_position++;
		delay_us(200000);
		AT24C02_Read_Byte(tem_position,&tem_hisbuf[tem_hisbuf_position]);
		tem_hisbuf_position++;
		tem_position++;
		delay_us(200000);
	}
	tem_position = tem_position0;
	tem_hisbuf_position = tem_hisbuf_position0 ;

	HAL_Delay(1000);
	
	OLED_ShowString(0, 6, "Opening wifi...", 16);

	HAL_Delay(2000);
	printf("AT+CWMODE=2\r\n");//##配置ESP8266模块为AP模式,开启wifi热点。
	HAL_Delay(500);
	printf("AT+RST\r\n");//##重启模块使AP模式生效
	HAL_Delay(1000);
	printf("AT+CIPMUX=1\r\n");//##启动多连接,id分配顺序是0-4。
	HAL_Delay(500);
	printf("AT+CIPSERVER=1,8080\r\n");//##模块开启服务器模式,端口号8080
	HAL_Delay(500);
	
	OLED_Clear();//初始化完成
	HAL_TIM_Base_Start_IT(&htim2);//开启定时器2
	HAL_UART_Receive_IT(&huart2,usart2_rxone,1);//开始串口中断
	DS18B20_Init();//初始化温度传感器
	
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
	
	}
	

/*************************************END OF FILE******************************/

  
  /* USER CODE END 3 */
}

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

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __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_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 100;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  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_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

void time_compute(void)
{
		second_S++;
		if (second_S>=10){second_S-=10;second_T++;}
		if (second_T>=6){second_T-=6;minute_S++;}
		if (minute_S>=10){minute_S-=10;minute_T++;}
		if (minute_T>=6){minute_T-=6;hour++;}
		if (hour>=24){hour-=24;}
}

void temp_compute(void)
{
		if (tem_max_dec>=10){tem_max_dec=0;tem_max_int++;}
		if (tem_min_dec>=10){tem_min_dec=0;tem_min_int++;}
		if (tem_max_dec<0){tem_max_dec=5;tem_max_int--;}
		if (tem_min_dec<0){tem_min_dec=5;tem_min_int--;}
		
		if (tem_max_int>=100||tem_max_int<0){tem_max_int-=0;}
		if (tem_min_int>=100||tem_min_int<0){tem_min_int-=0;}
		
		if((tem_max_int*10+tem_max_dec)<(tem_min_int*10+tem_min_dec))
		{
			tem_max_int=tem_min_int;
			tem_max_dec=tem_min_dec;
		}
		if((hum_max_int*10+hum_max_dec)<(hum_min_int*10+hum_min_dec))
		{
			hum_max_int=hum_min_int;
			hum_max_dec=hum_min_dec;
		}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART2)	// 判断是由哪个串口触发的中断
	{
		//将接收到的数据放入接收usart1接收数组
		usart2_rxbuf[usart2_rxcounter] = usart2_rxone[0];
		//HAL_UART_Transmit(&huart2,usart2_rxone,1,0xff);
		usart2_rxcounter++;	//接收数量+1
		//重新使能串口1接收中断
		HAL_UART_Receive_IT(&huart2,usart2_rxone,1);		
	}
}

void delay_us(volatile uint32_t us)
{
	volatile uint16_t i,j;  
	while(us--)
	{
		for(i=0;i<6;i++)
			j++;
	}
}

void page_handle(void)
{
	if(page0!=page) OLED_Clear();
	page0 = page;
	if(Work_State0!=Work_State) OLED_Clear();
	Work_State0=Work_State;
	if(page==0)//界面0时间显示页面
		{
		OLED_DrawBMP(0, 0, 64, 8,BMP1);
		OLED_ShowString(64, 0, "Project2", 16);
		OLED_ShowString(64, 2, "20221018", 16);
		OLED_ShowString(64, 4, "Time", 16);
		OLED_ShowChar(80,6,':',16);
		OLED_ShowChar(104,6,':',16);
		OLED_ShowNum(65,6,hour,2,16);
		OLED_ShowNum(88,6,minute_T,1,16);
		OLED_ShowNum(96,6,minute_S,1,16);	
		OLED_ShowNum(112,6,second_T,1,16);
		OLED_ShowNum(120,6,second_S,1,16);
			if(page0_userkey_flag!=0)
			{
				if(page0_userkey_flag0==page0_userkey_flag)
				{
						switch(page0_userkey_flag)
					{
						case 1: OLED_ShowString(65, 6, "  ", 16);
							break;
						case 2: OLED_ShowString(88, 6, " ", 16);
							break;
						case 3: OLED_ShowString(96, 6, " ", 16);
							break;
						case 4:	OLED_ShowString(112, 6, " ", 16);
							break;
						case 5: OLED_ShowString(120, 6, " ", 16);
							break;
						default: page0_userkey_flag=0;
							break;
					}
					page0_userkey_flag0=6;
				}
				else page0_userkey_flag0--;
			}
		}
		
	if(page==1)//界面1测量确认界面
		{
		if(Work_State == 1)
			{
			OLED_ShowString(0, 0, "Press User Key", 16);
			OLED_ShowString(0, 2, "Start Work", 16);
			OLED_ShowString(80, 2, "<===", 16);
			OLED_ShowString(0, 4, "Long Press", 16);
			OLED_ShowString(0, 6, "Stop Work", 16);
			}
			else{
			OLED_ShowString(0, 0, "Press User Key", 16);
			OLED_ShowString(0, 2, "Start Work", 16);
			OLED_ShowString(0, 4, "Long Press", 16);
			OLED_ShowString(0, 6, "Stop Work", 16);
			OLED_ShowString(80, 6, "<===", 16);		
			}
			
		}
	if(page==2)//界面1
		{
			if(Work_State == 1)
			{
			//第一列信息
			OLED_ShowString(0, 0, "DH11|", 16);
			OLED_ShowString(0, 2, "    |", 16);
			OLED_ShowString(0, 4, "DS18|", 16);
			OLED_ShowString(0, 6, "Limt|", 16);
				
			//第二列温湿度	
			OLED_ShowNum(44,0,temp_int,2,16);
			OLED_ShowNum(70,0,temp_deci,1,16);	
			OLED_ShowString(62, 0, ".", 16);
			OLED_ShowString(84, 0, "Cels", 16);	

			OLED_ShowNum(44,2,humi_int,2,16);	
			OLED_ShowNum(70,2,humi_deci,1,16);	
			OLED_ShowString(62, 2, ".", 16);				
			OLED_ShowString(84, 2, "%", 16);

			OLED_ShowNum(44,4,ds18_int,2,16);	
			OLED_ShowNum(70,4,ds18_deci,1,16);	
			OLED_ShowString(84, 4, "Cels", 16);	
			OLED_ShowString(62, 4, ".", 16);
			//范围
			OLED_ShowNum(44,6,tem_max_int,2,16);		
			OLED_ShowNum(70,6,tem_max_dec,1,16);	
			OLED_ShowString(62, 6, ".", 16);
			OLED_ShowNum(84,6,tem_min_int,2,16);	
			OLED_ShowNum(108,6,tem_min_dec,1,16);	
			OLED_ShowString(100, 6, ".", 16);					
			}
			
			else{
			//第一列信息
		//第一列信息
			OLED_ShowString(0, 0, "DH11|", 16);
			OLED_ShowString(0, 2, "    |", 16);
			OLED_ShowString(0, 4, "DS18|", 16);
			OLED_ShowString(0, 6, "Limt|", 16);
				
			//第二列温湿度	
	
			OLED_ShowString(60, 0, "None", 16);	
			OLED_ShowString(60, 2, "None", 16);	
			OLED_ShowString(60, 4, "None", 16);	

			//范围
			OLED_ShowNum(44,6,tem_max_int,2,16);		
			OLED_ShowNum(70,6,tem_max_dec,1,16);	
			OLED_ShowString(62, 6, ".", 16);
			OLED_ShowNum(84,6,tem_min_int,2,16);	
			OLED_ShowNum(108,6,tem_min_dec,1,16);	
			OLED_ShowString(100, 6, ".", 16);		
			
			}		
			if(page2_userkey_flag!=0)//闪烁位置
			{
				if(page2_userkey_flag0 == page2_userkey_flag)
				{
						switch(page2_userkey_flag)
					{
						case 1: OLED_ShowString(44, 6, "  ", 16);
							break;
						case 2: OLED_ShowString(70, 6, " ", 16);
							break;
						case 3: OLED_ShowString(84, 6, "  ", 16);
							break;
						case 4:	OLED_ShowString(108,6, " ", 16);
							break;
			
						default: page0_userkey_flag=0;
							break;
					}
					page2_userkey_flag0=5;
				}
				else page2_userkey_flag0--;
			}
		}
		
//		
//uint8_t tem_int_hisbuf[9];
//int tem_int_position= 0x10;
//int tem_int_position0= 0x10;
//uint8_t tem_dec_hisbuf[9];
//int tem_dec_position= 0x20;
//int tem_dec_position0= 0x20;
		
	if(page==3)
		{
		tem_hisbuf_position = 0;
			
		OLED_ShowString(0, 0, "Tem History:", 16);
		
			
		OLED_ShowString(16, 2, ".", 16);
		OLED_ShowNum(0,2,tem_hisbuf[tem_hisbuf_position],2,16);	
		tem_hisbuf_position++;	
		OLED_ShowNum(24,2,tem_hisbuf[tem_hisbuf_position],1,16);
		tem_hisbuf_position++;
			
		OLED_ShowNum(48,2,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;		
		OLED_ShowNum(72,2,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;		
		OLED_ShowString(64, 2, ".", 16);
		
		OLED_ShowNum(96,2,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;		
		OLED_ShowNum(120,2,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;	
		OLED_ShowString(112, 2, ".", 16);
				
		OLED_ShowNum(0,4,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;		
		OLED_ShowNum(24,4,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;		
		OLED_ShowString(16, 4, ".", 16);
		
		OLED_ShowNum(48,4,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;		
		OLED_ShowNum(72,4,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;		
		OLED_ShowString(64, 4, ".", 16);
			
		OLED_ShowNum(96,4,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;		
		OLED_ShowNum(120,4,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;		
		OLED_ShowString(112, 4, ".", 16);

		OLED_ShowNum(0,6,tem_hisbuf[tem_hisbuf_position],2,16);	tem_hisbuf_position++;	
		OLED_ShowNum(24,6,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;		
		OLED_ShowString(16, 6, ".", 16);

		OLED_ShowNum(48,6,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;			
		OLED_ShowNum(72,6,tem_hisbuf[tem_hisbuf_position],1,16);tem_hisbuf_position++;		
		OLED_ShowString(64, 6, ".", 16);

		OLED_ShowNum(96,6,tem_hisbuf[tem_hisbuf_position],2,16);tem_hisbuf_position++;	
		OLED_ShowNum(120,6,tem_hisbuf[tem_hisbuf_position],1,16);	tem_hisbuf_position++;	
		OLED_ShowString(112, 6, ".", 16);

			
		}
	if(page==4)
		{
		OLED_ShowString(0, 0, "Writing Tem", 16);
		OLED_ShowString(0, 2, "Recording...", 16);
			OLED_ShowString(0, 4, "Tem Data", 16);	
	

			
	
		
		OLED_ShowNum(100,4,temp_deci,1,16);	
		OLED_ShowString(92, 4, ".", 16);
		OLED_ShowNum(76,4,temp_int,2,16);
		}
		

	if(page<0)
		{
			OLED_Clear();
			page = 0;
		}
	if(page>4)
		{
			OLED_Clear();
			page = 4;		
		}
					
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	/* 判断哪个引脚触发了中断 */
	switch(GPIO_Pin)
	{
		case S1_Pin:
			/* 处理S1_Pin:发生的中断 */
			delay_us(10);//按键消抖
			if(1 == HAL_GPIO_ReadPin(S1_GPIO_Port,S1_Pin))
			{
			Key_S1=1;
			}
			break;
		case S2_Pin:
			/* 处理GPIO3发生的中断 */
			delay_us(10);//按键消抖
			if(1 == HAL_GPIO_ReadPin(S2_GPIO_Port,S2_Pin))
			{
			Key_S2=1;
			}
			break;
			
		case User_Key_Pin:	
			/* 处理User_Key发生的中断 */	
			delay_us(10);//按键消抖
		if(0 == HAL_GPIO_ReadPin(User_Key_GPIO_Port,User_Key_Pin))
		{
			Key_User = 1;//短按
		}
		default:
			break;
	}
}



//按键处理
void key_handle(void)
{
	if(Key_S1 == 1)
	{
		Key_S1 = 0;
		if(page0_userkey_flag!=0)
		{
			switch(page0_userkey_flag)
			{
				case 1: hour--;
					break;
				case 2: minute_T--;
					break;
				case 3: minute_S--;
					break;
				case 4:	second_T--;
					break;
				case 5: second_S--;
					break;
				default: page0_userkey_flag=0;
					break;
			}
		}
		else if(page2_userkey_flag!=0)
		{		
			switch(page2_userkey_flag)
			{
				case 1: tem_max_int-=5;
					break;
				case 2: tem_max_dec-=5;
					break;
				
				case 3: tem_min_int-=5;
					break;
				case 4:	tem_min_dec-=5;
					break;
	
				default: page0_userkey_flag=0;
					break;
			}
		
		}
		else page++;
	}
	if(Key_S2 == 1)
	{
		Key_S2 = 0;
		if(page0_userkey_flag!=0)
		{
			switch(page0_userkey_flag)
			{
				case 1: hour++;
					break;
				case 2: minute_T++;
					break;
				case 3: minute_S++;
					break;
				case 4:	second_T++;
					break;
				case 5: second_S++;
					break;
				default: page0_userkey_flag=0;
					break;
			}
		
		}
		else if(page2_userkey_flag!=0)
		{
			switch(page2_userkey_flag)
			{
				case 1: tem_max_int+=5;
					break;
				case 2: tem_max_dec+=5;
					break;
				
				case 3: tem_min_int+=5;
					break;
				case 4:	tem_min_dec+=5;
					break;
				
				default: page0_userkey_flag=0;
					break;
			}	
		}
		else page--;
	}
	
	if(Key_User == 1)
	{
		if(page == 0)
		{
			page0_userkey_flag++;
			if(page0_userkey_flag>5) {page0_userkey_flag=0;}
			page0_userkey_flag0 = page0_userkey_flag;
		}
		if(page == 1)
		{
			if(Work_State ==0) Work_State=1;	
			else if(Work_State ==1) Work_State=0;	
		}
		if(page == 2)
		{
			page2_userkey_flag++;
			if(page2_userkey_flag>4) {page2_userkey_flag=0;}
			page2_userkey_flag0 = page2_userkey_flag;
		}
		
		Key_User = 0;	
	}

}



//串口2接收信息处理
void UART2_Handle(void)
{
	uint8_t start_buf[13] = "START_TEM";
	uint8_t stop_buf[13] = "STOP_TEM";
	uint8_t start_Reply[] = "Start the temperature and humidity measure\r\n";
	uint8_t stop_Reply[] = "Close the temperature and humidity measure\r\n";
	uint8_t period_Reply1[] = "Data will up load every ";
	uint8_t period_Reply2[] = " period\r\n";
	uint8_t tem_l_Reply[] = " is set as the limits of lower temperature\r\n";
	uint8_t tem_h_Reply[] = " is set as the limits of upper temperature\r\n";
	uint8_t time_Reply[] = "New time have been set as ";
	uint8_t bank_Reply[] = "\r\n";
	if(strcmp(usart2_rxbuf,start_buf)==0){Work_State=1;HAL_UART_Transmit(&huart2,start_Reply,sizeof(start_Reply),0xff);}
	if(strcmp(usart2_rxbuf,stop_buf)==0){Work_State=0;HAL_UART_Transmit(&huart2,stop_Reply,sizeof(start_Reply),0xff);}
	if(usart2_rxbuf[0]=='T')
	{
		if(usart2_rxbuf[1]=='=')
		{
			period = usart2_rxbuf[2]-'0';
			period0 = period;
			HAL_UART_Transmit(&huart2,period_Reply1,sizeof(period_Reply1),0xff);
			HAL_UART_Transmit(&huart2,&usart2_rxbuf[2],1,0xff);
			HAL_UART_Transmit(&huart2,period_Reply2,sizeof(period_Reply2),0xff);
		}
		if(usart2_rxbuf[1]=='E')
		{
			if(usart2_rxbuf[4]=='L')
			{
				tem_min_int = (usart2_rxbuf[6]-'0')*10+usart2_rxbuf[7]-'0';//TEM_L=xx.x
				tem_min_dec = 	usart2_rxbuf[9]-'0';
				HAL_UART_Transmit(&huart2,&usart2_rxbuf[6],4,0xff);
				HAL_UART_Transmit(&huart2,tem_l_Reply,sizeof(tem_l_Reply),0xff);
			}
			if(usart2_rxbuf[4]=='H')
			{
				tem_max_int = (usart2_rxbuf[6]-'0')*10+usart2_rxbuf[7]-'0';//TEM_H=xx.x
				tem_max_dec = 	usart2_rxbuf[9]-'0';
				HAL_UART_Transmit(&huart2,&usart2_rxbuf[6],4,0xff);
				HAL_UART_Transmit(&huart2,tem_h_Reply,sizeof(tem_h_Reply),0xff);
			}
		}
		if(usart2_rxbuf[1]=='I')
		{
			hour = (usart2_rxbuf[5]-'0')*10+usart2_rxbuf[6]-'0';//TIME=hh:mm:ss
			minute_T=usart2_rxbuf[8]-'0';
			minute_S=usart2_rxbuf[9]-'0';
			second_T=usart2_rxbuf[11]-'0';
			second_S=usart2_rxbuf[12]-'0';	
			HAL_UART_Transmit(&huart2,time_Reply,sizeof(time_Reply),0xff);
			HAL_UART_Transmit(&huart2,&usart2_rxbuf[5],8,0xff);
			HAL_UART_Transmit(&huart2,bank_Reply,sizeof(bank_Reply),0xff);
		}	
	}
	if(usart2_rxbuf[0]=='H')
	{	
			if(usart2_rxbuf[4]=='L')
			{
				hum_min_int = (usart2_rxbuf[6]-'0')*10+usart2_rxbuf[7]-'0';//HUM_L=xx.x(%)
				hum_min_dec = 	usart2_rxbuf[9]-'0';
			}
			if(usart2_rxbuf[4]=='H')
			{
				hum_max_int = (usart2_rxbuf[6]-'0')*10+usart2_rxbuf[7]-'0';
				hum_max_dec = 	usart2_rxbuf[9]-'0';
			}
	}
	usart2_rxcounter=0;
	memset(usart2_rxbuf,0,sizeof(usart2_rxbuf));	
}


//串口回传
void uart_call_back(void)
{
	
	uint8_t uart_BReply[]="(";
	uint8_t uart_CReply[]=")";
	uint8_t uart_workstate_Reply[]="sensor stop work, send history data\t";
	if(period0 <= 1)
	{
		if(Work_State == 0)
		{
			HAL_UART_Transmit(&huart2,uart_workstate_Reply,sizeof(uart_workstate_Reply),0xff);
		}
		HAL_UART_Transmit(&huart2,uart_BReply,1,0xff);
		if(uart_Reply_num[1]<'9')
		{uart_Reply_num[1]=uart_Reply_num[1]+1;}
		else
		{uart_Reply_num[1]='0';uart_Reply_num[0]=uart_Reply_num[0]+1;}
		if(uart_Reply_num[0]>'9') uart_Reply_num[0]='0';	
		HAL_UART_Transmit(&huart2,uart_Reply_num,2,0xff);
		HAL_UART_Transmit(&huart2,uart_CReply,1,0xff);
		uart_Reply[1]='0'+temp_int/10;
		uart_Reply[2]='0'+temp_int%10;
		uart_Reply[4]='0'+temp_deci;
		uart_Reply[9]='0'+humi_int/10;
		uart_Reply[10]='0'+humi_int%10;
		uart_Reply[14]='0'+tem_min_int/10;
		uart_Reply[15]='0'+tem_min_int%10;
		uart_Reply[20]='0'+tem_max_int/10;
		uart_Reply[21]='0'+tem_max_int%10;
		uart_Reply[26]='0'+hour/10;
		uart_Reply[27]='0'+hour%10;
		uart_Reply[29]='0'+minute_T;
		uart_Reply[30]='0'+minute_S;
		uart_Reply[32]='0'+second_T;
		uart_Reply[33]='0'+second_S;
		HAL_UART_Transmit(&huart2,uart_Reply,sizeof(uart_Reply),0xff);
		period0 = period;
	}
	else period0--;
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值