嘉立创产业服务站群
发作品签到
专业版

基于ESP32室内监测桌摆

工程标签

179
0
0
0

简介

基于ESP32-S3开发板设计室内监测桌摆。1-支持监测室内光照、温度、湿度、压强等;2-支持无线接入数据传输,方便远程访问;3-支持图片播放;4-支持蜂鸣器提醒;5-支持当桌摆;6-支持电池充放电。

简介:基于ESP32-S3开发板设计室内监测桌摆。1-支持监测室内光照、温度、湿度、压强等;2-支持无线接入数据传输,方便远程访问;3-支持图片播放;4-支持蜂鸣器提醒;5-支持当桌摆;6-支持电池充放电。
基于ESP32物联网征集令

开源协议

TAPR Open Hardware License

创建时间:2024-09-03 06:41:32更新时间:2024-09-18 01:23:00

描述

前言

一直想要学习一下ESP32,这次终于有机会了。以前都是在keil上开发,这次跟着立创的教程走的,虽然学习之旅很坎坷,总算有所收获。不管咋样,虽然迟到,从不缺席。
都是自己一点点做成的,还是很有成就感的。

image.png

功能设计与实现情况

1-支持监测室内光照、温度、湿度、压强数据采集,已完成
2-支持无线接入数据传输,方便远程访问,AP+蓝牙功能已验证,待集成。
3-支持图片播放,已验证图像显示,功能待集成。
4-支持蜂鸣器提醒,已完成
5-支持当桌摆,已完成。
6-支持电池充放电,已完成
7-支持电量报警,已完成。

硬件设计

主控设计

采用ESP32-S3,直接在立创购买的开发板。这次也是为了学习esp32,这个主频高达240Mhz,还支持双核,这是我心动的主要原因。
该板子管脚分配电路如下:

image.png

按键设计

这里为了后续的功能增加,尽可能多的预留了按键。
image.png

同时还预留了旋转编码器接口:

image.png

上述电路均增加了消抖电容哦,这个钱不要省哦。

指示灯设计

预留了2路上拉指示灯,加上开发板还有1个指示灯。共计3个可用指示灯
image.png

显示屏设计

手上刚好1.8寸的TFT显示屏,可以利用起来。学习ESP32如何驱动彩色的SPI接口屏。这个把我坑惨了。太难调了。

image.png

充放电电路

在立创购买的TP5400,便宜好用。参加立创各种活动,基本都是用的这个。
电路简单,可靠,实用。直接抄就行。

image.png

锂电池电量监测

锂电池充满电4.2V左右,需要进行分压才能采集。不能超过3.3V,esp32的AD决定的。如下所示:

image.png

光强检测测

采用光敏电阻,光照越强,电阻越小。根据这个原理,上拉分压。esp32的AD进行采集。如下所示:
image.png

蜂鸣器

这个电路拥有各种报警。电路简单,如下所示:
image.png

USB检测

当USB插入进行充电时候,可以检测USB是插入。因为输入5V,为了保护接口,进行了分压处理。
如下所示:

image.png

传感器模块

温湿度采用AHT21B进行采集数据,大气压强采用BMP280模块。
都是IIC接口,所以接口可以共用IIC总线。如下图所示:
image.png
教程没有这两个模块的移植,自己编写太痛苦了。但是收获也是很丰富的。

锂电池接口

预留2.54的排针,可以焊接也可以直接插入。
image.png

PCB设计

采用2层板,FR-4板材。厚度1.2mm。70X80的尺寸。

image.png

外壳设计

采用立创EDA进行设计,立创的3D模型做的越来越逼真了。进步真的很快哦。国产EDA前途无量啊。

image.png

软件设计与开发

采用立创教程中的方法,安装了vscode和esp-idf。
这里提醒大家一定要用教程的版本,否则各种问题,还得重新弄回来。
反正我是经历各种痛苦,既然是学习,就不要在环境搭建上耗费时间了。

后面讲解一些我花时间较多的地方,尤其是立创没有直接例程的地方。

屏幕驱动

根据立创的教程,从1.69彩屏的移植框架来,移植1.8寸的彩屏。

首先是管脚配置:

#ifndef __LCD_INIT_H
#define __LCD_INIT_H

#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_rom_sys.h"

#define USE_HORIZONTAL 2  //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏


#if USE_HORIZONTAL==0||USE_HORIZONTAL==1
#define LCD_W 128
#define LCD_H 160

#else
#define LCD_W 160
#define LCD_H 128
#endif

#ifndef u8
#define u8 uint8_t
#endif

#ifndef u16
#define u16 uint16_t
#endif

#ifndef u32
#define u32 uint32_t
#endif

//-----------------LCD端口移植---------------- 

#define LCD_SCL_PIN     7
#define LCD_MOSI_PIN    6
#define LCD_RES_PIN     5
#define LCD_DC_PIN      4
#define LCD_CS_PIN      3
#define LCD_BLK_PIN     2

//-----------------LCD端口定义---------------- 

#define LCD_RES_Clr()  gpio_set_level(LCD_RES_PIN,0)//RES
#define LCD_RES_Set()  gpio_set_level(LCD_RES_PIN,1)

#define LCD_DC_Clr()   gpio_set_level(LCD_DC_PIN,0)//DC
#define LCD_DC_Set()   gpio_set_level(LCD_DC_PIN,1)	     

#define LCD_BLK_Clr()  gpio_set_level(LCD_BLK_PIN,0)//BLK
#define LCD_BLK_Set()  gpio_set_level(LCD_BLK_PIN,1)

void delay_us(int us);
void delay_ms(int ms);
void LCD_GPIO_Init(void);//初始化GPIO
void LCD_Writ_Bus(u8 dat);//模拟SPI时序
void LCD_WR_DATA8(u8 dat);//写入一个字节
void LCD_WR_DATA(u16 dat);//写入两个字节
void LCD_WR_REG(u8 dat);//写入一个指令
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2);//设置坐标函数
void LCD_Init(void);//LCD初始化
#endif


其次是管脚初始化

void LCD_GPIO_Init(void)
{
    esp_err_t ret;

    spi_bus_config_t buscfg={
        .miso_io_num=NULL,
        .mosi_io_num=LCD_MOSI_PIN,
        .sclk_io_num=LCD_SCL_PIN,
        .quadwp_io_num=-1,
        .quadhd_io_num=-1,
        .max_transfer_sz= 160 *128*3+8 //最大传输大小
    };
    spi_device_interface_config_t devcfg={

        .clock_speed_hz=80*1000*1000,           //Clock out at 80 MHz
        .mode=3,                                //SPI mode 3
        .spics_io_num=LCD_CS_PIN,               //CS pin
        .queue_size=7,                          //事务队列尺寸 7个
        .pre_cb=lcd_spi_pre_transfer_callback,  // 数据传输前回调,用作D/C(数据命令)线分别处理
    };
  // 初始化SPI总线
    ret=spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);
    
  // 添加SPI总线驱动
    ret=spi_bus_add_device(SPI2_HOST, &devcfg, &spi_port);
    ESP_ERROR_CHECK(ret);


	gpio_reset_pin(LCD_RES_PIN);							//初始化引脚
	gpio_set_direction(LCD_RES_PIN, GPIO_MODE_DEF_OUTPUT);  //配置引脚为输出模式

	gpio_reset_pin(LCD_DC_PIN);								//初始化引脚
	gpio_set_direction(LCD_DC_PIN, GPIO_MODE_DEF_OUTPUT);  	//配置引脚为输出模式

	gpio_reset_pin(LCD_BLK_PIN);							//初始化引脚
	gpio_set_direction(LCD_BLK_PIN, GPIO_MODE_DEF_OUTPUT);  //配置引脚为输出模式
}

最后是屏幕初始化参数

void LCD_Init(void)
{
	LCD_GPIO_Init();//初始化GPIO
	
	LCD_RES_Clr();//复位
	delay_ms(100);
	LCD_RES_Set();
	delay_ms(100);
	LCD_BLK_Set();//打开背光
	delay_ms(100);
	
	
	//************* Start Initial Sequence **********//
	LCD_WR_REG(0x11); //Sleep out 
	delay_ms(120);              //Delay 120ms 
	//------------------------------------ST7735S Frame Rate-----------------------------------------// 
	LCD_WR_REG(0xB1); 
	LCD_WR_DATA8(0x05); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	
	LCD_WR_REG(0xB2); 
	LCD_WR_DATA8(0x05);
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_REG(0xB3); 
	LCD_WR_DATA8(0x05); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x05); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	//------------------------------------End ST7735S Frame Rate---------------------------------// 
	LCD_WR_REG(0xB4); //Dot inversion 
	LCD_WR_DATA8(0x03); 
	//------------------------------------ST7735S Power Sequence---------------------------------// 
	LCD_WR_REG(0xC0); 
	LCD_WR_DATA8(0x28); 
	LCD_WR_DATA8(0x08); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_REG(0xC1); 
	LCD_WR_DATA8(0XC0); 
	LCD_WR_REG(0xC2); 
	LCD_WR_DATA8(0x0D); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_REG(0xC3); 
	LCD_WR_DATA8(0x8D); 
	LCD_WR_DATA8(0x2A); 
	LCD_WR_REG(0xC4); 
	LCD_WR_DATA8(0x8D); 
	LCD_WR_DATA8(0xEE); 
	//---------------------------------End ST7735S Power Sequence-------------------------------------// 
	LCD_WR_REG(0xC5); //VCOM 
	LCD_WR_DATA8(0x1A); 
	LCD_WR_REG(0x36); //MX, MY, RGB mode 
	if(USE_HORIZONTAL==0){
        LCD_WR_DATA8(0x00);
    }
	else if(USE_HORIZONTAL==1){
        LCD_WR_DATA8(0xC0);
    }
	else if(USE_HORIZONTAL==2){
        LCD_WR_DATA8(0x70);
    }
	else {
        LCD_WR_DATA8(0xA0); 
    }
	//------------------------------------ST7735S Gamma Sequence---------------------------------// 
	LCD_WR_REG(0xE0); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_DATA8(0x22); 
	LCD_WR_DATA8(0x07); 
	LCD_WR_DATA8(0x0A); 
	LCD_WR_DATA8(0x2E); 
	LCD_WR_DATA8(0x30); 
	LCD_WR_DATA8(0x25); 
	LCD_WR_DATA8(0x2A); 
	LCD_WR_DATA8(0x28); 
	LCD_WR_DATA8(0x26); 
	LCD_WR_DATA8(0x2E); 
	LCD_WR_DATA8(0x3A); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_DATA8(0x01); 
	LCD_WR_DATA8(0x03); 
	LCD_WR_DATA8(0x13); 
	LCD_WR_REG(0xE1); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_DATA8(0x16); 
	LCD_WR_DATA8(0x06); 
	LCD_WR_DATA8(0x0D); 
	LCD_WR_DATA8(0x2D); 
	LCD_WR_DATA8(0x26); 
	LCD_WR_DATA8(0x23); 
	LCD_WR_DATA8(0x27); 
	LCD_WR_DATA8(0x27); 
	LCD_WR_DATA8(0x25); 
	LCD_WR_DATA8(0x2D); 
	LCD_WR_DATA8(0x3B); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_DATA8(0x01); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_DATA8(0x13); 
	//------------------------------------End ST7735S Gamma Sequence-----------------------------// 
	LCD_WR_REG(0x3A); //65k mode 
	LCD_WR_DATA8(0x05); 
	LCD_WR_REG(0x29); //Display on   	
	
} 

以上需要注意哦,错了会有各种问题哦。

AHT21B驱动

头文件

#ifndef _BSP_AHT20_H_
#define _BSP_AHT20_H_

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include 
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "rom/ets_sys.h"
#include "esp_system.h"
#include "driver/gpio.h"

#include "hardware/lcd_init.h"

//端口移植
#define AHT10_SCL_PIN   42
#define AHT10_SDA_PIN   41

//设置SDA输出模式
#define SDA_OUT()        gpio_set_direction(AHT10_SDA_PIN,GPIO_MODE_OUTPUT)
//设置SDA输入模式
#define SDA_IN()         gpio_set_direction(AHT10_SDA_PIN,GPIO_MODE_INPUT)
//获取SDA引脚的电平变化
#define SDA_GET()        gpio_get_level(AHT10_SDA_PIN)
//SDA与SCL输出
#define SDA(x)           gpio_set_level(AHT10_SDA_PIN, (x?1:0))
#define SCL(x)           gpio_set_level(AHT10_SCL_PIN, (x?1:0))

// void delay_us(unsigned int us);
// void delay_ms(unsigned int ms);
void AHT21_GPIO_Init(void);
float Get_Temperature(void);
float Get_Humidity(void);
char aht21_read_data(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Send_Ack(unsigned char ack);
unsigned char I2C_WaitAck(void);
void Send_Byte(uint8_t dat);
unsigned char Read_Byte(void);

#endif

实现函数如下:
每个函数都是一点点调试出来的,可以放心使用。



#include "hardware/bsp_aht20.h"
#include "stdio.h"

float Temperature = 0;
float Humidity = 0;

// void delay_ms(unsigned int ms)
// {
//     vTaskDelay(ms / portTICK_PERIOD_MS);
// }
// void delay_us(unsigned int us)
// {
//     ets_delay_us(us);
// }

void AHT21_GPIO_Init(void)
{
        gpio_config_t lll_config = {
            .pin_bit_mask = (1ULL << AHT10_SCL_PIN) | (1ULL << AHT10_SDA_PIN), // 配置引脚
            .mode = GPIO_MODE_OUTPUT,                                          // 输出模式
            .pull_up_en = GPIO_PULLUP_ENABLE,                                  // 使能上拉
            .pull_down_en = GPIO_PULLDOWN_DISABLE,                             // 不使能下拉
            .intr_type = GPIO_INTR_DISABLE                                     // 不使能引脚中断
        };
        gpio_config(&lll_config);
}


void IIC_Start(void)
{
        SDA_OUT();

        SDA(1);
        delay_us(5);
        SCL(1);
        delay_us(5);

        SDA(0);
        delay_us(5);
        SCL(0);
        delay_us(5);
}

void IIC_Stop(void)
{
        SDA_OUT();
        SCL(0);
        SDA(0);

        SCL(1);
        delay_us(5);
        SDA(1);
        delay_us(5);
}

void IIC_Send_Ack(unsigned char ack)
{
        SDA_OUT();
        SCL(0);
        SDA(0);
        delay_us(5);
        if (!ack)
                SDA(0);
        else
                SDA(1);
        SCL(1);
        delay_us(5);
        SCL(0);
        SDA(1);
}


unsigned char I2C_WaitAck(void)
{

        char ack = 0;
        unsigned char ack_flag = 10;
        SCL(0);
        SDA(1);
        SDA_IN();
        delay_us(5);
        SCL(1);
        delay_us(5);

        while ((SDA_GET() == 1) && (ack_flag))
        {
                ack_flag--;
                delay_us(5);
        }

        if (ack_flag <= 0)
        {
                IIC_Stop();
                return 1;
        }
        else
        {
                SCL(0);
                SDA_OUT();
        }
        return ack;
}

void Send_Byte(uint8_t dat)
{
        int i = 0;
        SDA_OUT();
        SCL(0); // 拉低时钟开始数据传输

        for (i = 0; i < 8; i++)
        {
                SDA((dat & 0x80) >> 7);
                delay_us(1);
                SCL(1);
                delay_us(5);
                SCL(0);
                delay_us(5);
                dat <<= 1;
        }
}


unsigned char Read_Byte(void)
{
        unsigned char i, receive = 0;
        SDA_IN(); // SDA设置为输入
        for (i = 0; i < 8; i++)
        {
                SCL(0);
                delay_us(5);
                SCL(1);
                delay_us(5);
                receive <<= 1;
                if (SDA_GET())
                {
                        receive |= 1;
                }
                delay_us(5);
        }
        SCL(0);
        return receive;
}

// 读取AHT21的状态寄存器
uint8_t aht21_read_status(void)
{
        uint8_t status_register_address = 0x71;
        uint8_t status_byte;
        IIC_Start();
        Send_Byte(status_register_address);
        if (I2C_WaitAck() == 1)
                printf("warning -1\r\n");

        status_byte = Read_Byte();
        IIC_Send_Ack(0);
        IIC_Stop();

        return status_byte;
}

//向AHT21发送采集命令
uint8_t aht21_send_gather_command(void)
{
    uint8_t device_addr = 0x70;//器件地址
    uint8_t gather_command = 0xac;//采集命令
    uint8_t gather_command_parameter_1 = 0x33;//采集参数1
    uint8_t gather_command_parameter_2 = 0x00;//采集参数2
    
  IIC_Start();
	Send_Byte(device_addr);//发送器件地址
	if( I2C_WaitAck() == 1 ) return 1;
	Send_Byte(gather_command);//发送采集命令
	if( I2C_WaitAck() == 1 ) return 2;
	Send_Byte(gather_command_parameter_1);//发送采集参数1
	if( I2C_WaitAck() == 1 ) return 3;
	Send_Byte(gather_command_parameter_2);//发送采集参数2
	if( I2C_WaitAck() == 1 ) return 4;
	IIC_Stop();
	return 0;
}

//通过命令字节初始化AHT21
void aht21_device_init(void)  
{	
    uint8_t device_addr = 0x70;//器件地址
    uint8_t init_command = 0xBE;//初始化命令
    uint8_t init_command_parameter_1 = 0x08;//采集参数1
    uint8_t init_command_parameter_2 = 0x00;//采集参数2

    IIC_Start();
	Send_Byte(device_addr);//发送器件地址
	if( I2C_WaitAck() == 1 ) printf("warning -5\r\n");
	Send_Byte(init_command);//发送初始化命令
	if( I2C_WaitAck() == 1 ) printf("warning -6\r\n");
	Send_Byte(init_command_parameter_1);//发送初始化参数1
	if( I2C_WaitAck() == 1 ) printf("warning -7\r\n");
	Send_Byte(init_command_parameter_2);//发送初始化参数2
	if( I2C_WaitAck() == 1 ) printf("warning -8\r\n");
	IIC_Stop();
}



/******************************************************************
 * 函 数 名 称:aht21_read_data
 * 函 数 说 明:读取温湿度
 * 函 数 形 参:无
* 函 数 返 回:1:未校准  2:读取超时  0:读取成功
 * 作       者:LC
 * 备       注:无
******************************************************************/
char aht21_read_data(void)
{
    uint8_t data[6] = {0};
    uint32_t temp = 0;
    
    uint8_t aht21_status_byte = 0;
    uint8_t timeout = 0;
    //读取AHT21的状态
    aht21_status_byte = aht21_read_status();
    //如果未校准,则返回1
    if( (aht21_status_byte & (1<<3)) == 0 ) 
    {
        aht21_device_init();
        delay_ms(50);
        return 1;
    }
    
    //发送采集命令
    aht21_send_gather_command();
    
    do
    {
        delay_ms(1);
        timeout++;
        //读取AHT21的状态
        aht21_status_byte = aht21_read_status();
    }while( ( ( aht21_status_byte & (1<<7) ) != 0 ) && ( timeout >= 80 ) );
    //如果读取超时,则返回2
    if( timeout >= 80 ) return 2;
       
    IIC_Start();
    Send_Byte(0x71);
    if( I2C_WaitAck() == 1 ) printf("error -1\r\n");
	Read_Byte();//读取状态,不需要保存
	IIC_Send_Ack(0);	
         
    //读取6位数据
    data[0] = Read_Byte();
    IIC_Send_Ack(0);
    data[1] = Read_Byte();
    IIC_Send_Ack(0);
    data[2] = Read_Byte();
    IIC_Send_Ack(0);
    data[3] = Read_Byte();
    IIC_Send_Ack(0);
    data[4] = Read_Byte();
    IIC_Send_Ack(0);
    data[5] = Read_Byte();
    IIC_Send_Ack(0);
    
    IIC_Stop();
     
    //整合湿度数据
    temp = (data[0]<<12) | (data[1]<<4);
    temp = temp | (data[2]>>4);
    //换算湿度数据
    //2的20次方 = 1048576
    Humidity = temp / 1048576.0 * 100.0;
    
    
    //整合湿度数据
    temp = ( (data[2]&0x0f)<< 16 ) | (data[3]<<8);
    temp = temp | data[4];
    //换算湿度数据
    //2的20次方 = 1048576
    Temperature = temp / 1048576.0 * 200.0 - 50;

    return 0;
}



/**********************************************************
 * 函 数 名 称:Get_Temperature
 * 函 数 功 能:获取采集后的温度数据
 * 传 入 参 数:无
 * 函 数 返 回:温度数据,单位℃
 * 作       者:LC
 * 备       注:必须先采集与数据,否则返回0或者之前的数据
 **********************************************************/
float Get_Temperature(void)
{
        return Temperature;
}

/**********************************************************
 * 函 数 名 称:Get_Humidity
 * 函 数 功 能:获取采集后的湿度数据
 * 传 入 参 数:无
 * 函 数 返 回:湿度数据,单位%RH
 * 作       者:LC
 * 备       注:必须先采集与数据,否则返回0或者之前的数据
 **********************************************************/
float Get_Humidity(void)
{
        return Humidity;
}

BMP280驱动

头文件如下

#ifndef __BMP280_H__
#define __BMP280_H__

/*********************************************************************************/

#include "hardware/bsp_aht20.h"
/*=========================================================================
    REGISTERS
    -----------------------------------------------------------------------*/

#define BMP280_REGISTER_DIG_T1                 0x88
#define BMP280_REGISTER_DIG_T2                 0x8A
#define BMP280_REGISTER_DIG_T3                0x8C

#define BMP280_REGISTER_DIG_P1                0x8E
#define BMP280_REGISTER_DIG_P2                0x90
#define BMP280_REGISTER_DIG_P3                0x92
#define BMP280_REGISTER_DIG_P4                0x94
#define BMP280_REGISTER_DIG_P5                0x96
#define BMP280_REGISTER_DIG_P6                0x98
#define BMP280_REGISTER_DIG_P7                0x9A
#define BMP280_REGISTER_DIG_P8                 0x9C
#define BMP280_REGISTER_DIG_P9                 0x9E

#define BMP280_REGISTER_CHIPID				0xD0
#define BMP280_REGISTER_VERSION				0xD1
#define BMP280_REGISTER_SOFTRESET			0xE0

#define BMP280_REGISTER_CAL26                0xE1  // R calibration stored in 0xE1-0xF0

#define BMP280_REGISTER_CONTROL              0xF4
#define BMP280_REGISTER_CONFIG               0xF5
#define BMP280_REGISTER_PRESSUREDATA          0xF7
#define  BMP280_REGISTER_TEMPDATA             0xFA


/*=========================================================================*/

/*=========================================================================
    CALIBRATION DATA
    -----------------------------------------------------------------------*/
    typedef struct
    {
      uint16_t dig_T1;
      int16_t  dig_T2;
      int16_t  dig_T3;

      uint16_t dig_P1;
      int16_t  dig_P2;
      int16_t  dig_P3;
      int16_t  dig_P4;
      int16_t  dig_P5;
      int16_t  dig_P6;
      int16_t  dig_P7;
      int16_t  dig_P8;
      int16_t  dig_P9;

      uint8_t  dig_H1;
      int16_t  dig_H2;
      uint8_t  dig_H3;
      int16_t  dig_H4;
      int16_t  dig_H5;
      int8_t   dig_H6;
    } bmp280_calib_data;
/*=========================================================================*/


    uint8_t  begin(void);
    float readTemperature(void);
    float readPressure(void);



#endif

函数实现如下


#include "BMP280.h"

void readCoefficients(void);
void write8(uint8_t reg, uint8_t value);
uint8_t read8(uint8_t reg);
uint16_t read16(uint8_t reg);
int16_t readS16(uint8_t reg);
uint16_t read16_LE(uint8_t reg); // little endian
int16_t readS16_LE(uint8_t reg); // little endian
//int8_t cs = -1;
uint8_t i2caddr = 0xEC;
// int32_t   sensorID;
int32_t t_fine;

bmp280_calib_data bmp280_calib;

uint8_t begin(void)
{

  if (read8(BMP280_REGISTER_CHIPID) != 0x58)
    return 0;

  readCoefficients();
  write8(BMP280_REGISTER_CONTROL, 0x3F);
  return 1;
}

/**************************************************************************/
/*!
    @brief  Writes an 8 bit value over I2C/SPI
*/
/**************************************************************************/
void write8(uint8_t reg, uint8_t value)
{

    IIC_Start();
    Send_Byte(i2caddr);
    if (I2C_WaitAck())
      printf("ADDR ACK ERORR\r\n");
    Send_Byte(reg);
    if (I2C_WaitAck())
      printf("REG ACK ERORR\r\n");
    Send_Byte(value);
    if (I2C_WaitAck())
      printf("Value ERORR\r\n");
    IIC_Stop();
    // release the SPI bus
  
}

/**************************************************************************/
/*!
    @brief  Reads an 8 bit value over I2C
*/
/**************************************************************************/
uint8_t read8(uint8_t reg)
{
  uint8_t value = 0;
    IIC_Start();
    Send_Byte(i2caddr);
    if (I2C_WaitAck())
      printf("ADDR ACK ERORR\r\n");
    Send_Byte(reg);
    if (I2C_WaitAck())
      printf("REG ACK ERORR\r\n");

    IIC_Start();
    Send_Byte(i2caddr + 1);
    if (I2C_WaitAck())
      printf("ADDR ACK ERORR\r\n");
    value = Read_Byte();
    IIC_Send_Ack(1);
    IIC_Stop();

  return value;
}

/**************************************************************************/
/*!
    @brief  Reads a 16 bit value over I2C
*/
/**************************************************************************/
uint16_t read16(uint8_t reg)
{
  uint16_t value=0;
  IIC_Start();
  Send_Byte(i2caddr);
  I2C_WaitAck();
  Send_Byte(reg);
  I2C_WaitAck();

  IIC_Start();
  Send_Byte(i2caddr + 1);
  I2C_WaitAck();
  value = Read_Byte();
  IIC_Send_Ack(0);
  value = (value << 8) | Read_Byte();
  IIC_Send_Ack(1);
  IIC_Stop();
  return value;
}

uint16_t read16_LE(uint8_t reg)
{
  uint16_t temp = read16(reg);
  return (temp >> 8) | (temp << 8);
}

/**************************************************************************/
/*!
    @brief  Reads a signed 16 bit value over I2C
*/
/**************************************************************************/
int16_t readS16(uint8_t reg)
{
  return (int16_t)read16(reg);
}

int16_t readS16_LE(uint8_t reg)
{
  return (int16_t)read16_LE(reg);
}

/**************************************************************************/
/*!
    @brief  Reads the factory-set coefficients
*/
/**************************************************************************/
void readCoefficients(void)
{
  bmp280_calib.dig_T1 = read16_LE(BMP280_REGISTER_DIG_T1);
  bmp280_calib.dig_T2 = readS16_LE(BMP280_REGISTER_DIG_T2);
  bmp280_calib.dig_T3 = readS16_LE(BMP280_REGISTER_DIG_T3);

  bmp280_calib.dig_P1 = read16_LE(BMP280_REGISTER_DIG_P1);
  bmp280_calib.dig_P2 = readS16_LE(BMP280_REGISTER_DIG_P2);
  bmp280_calib.dig_P3 = readS16_LE(BMP280_REGISTER_DIG_P3);
  bmp280_calib.dig_P4 = readS16_LE(BMP280_REGISTER_DIG_P4);
  bmp280_calib.dig_P5 = readS16_LE(BMP280_REGISTER_DIG_P5);
  bmp280_calib.dig_P6 = readS16_LE(BMP280_REGISTER_DIG_P6);
  bmp280_calib.dig_P7 = readS16_LE(BMP280_REGISTER_DIG_P7);
  bmp280_calib.dig_P8 = readS16_LE(BMP280_REGISTER_DIG_P8);
  bmp280_calib.dig_P9 = readS16_LE(BMP280_REGISTER_DIG_P9);
}

/**************************************************************************/
/*!

*/
/**************************************************************************/
float readTemperature(void)
{
  int32_t var1, var2;
  float T;
  int32_t adc_T = read16(BMP280_REGISTER_TEMPDATA);
  adc_T <<= 8;
  adc_T |= read8(BMP280_REGISTER_TEMPDATA + 2);
  adc_T >>= 4;

  var1 = ((((adc_T >> 3) - ((int32_t)bmp280_calib.dig_T1 << 1))) *
          ((int32_t)bmp280_calib.dig_T2)) >>
         11;

  var2 = (((((adc_T >> 4) - ((int32_t)bmp280_calib.dig_T1)) *
            ((adc_T >> 4) - ((int32_t)bmp280_calib.dig_T1))) >>
           12) *
          ((int32_t)bmp280_calib.dig_T3)) >>
         14;

  t_fine = var1 + var2;

  T = (t_fine * 5 + 128) >> 8;
  return T / 100;
}

/**************************************************************************/
/*!

*/
/**************************************************************************/
float readPressure(void)
{
  int64_t var1, var2, p;

  int32_t adc_P = read16(BMP280_REGISTER_PRESSUREDATA);
  adc_P <<= 8;
  adc_P |= read8(BMP280_REGISTER_PRESSUREDATA + 2);
  adc_P >>= 4;

  var1 = ((int64_t)t_fine) - 128000;
  var2 = var1 * var1 * (int64_t)bmp280_calib.dig_P6;
  var2 = var2 + ((var1 * (int64_t)bmp280_calib.dig_P5) << 17);
  var2 = var2 + (((int64_t)bmp280_calib.dig_P4) << 35);
  var1 = ((var1 * var1 * (int64_t)bmp280_calib.dig_P3) >> 8) +
         ((var1 * (int64_t)bmp280_calib.dig_P2) << 12);
  var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)bmp280_calib.dig_P1) >> 33;

  if (var1 == 0)
  {
    return 0; // avoid exception caused by division by zero
  }
  p = 1048576 - adc_P;
  p = (((p << 31) - var2) * 3125) / var1;
  var1 = (((int64_t)bmp280_calib.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
  var2 = (((int64_t)bmp280_calib.dig_P8) * p) >> 19;

  p = ((p + var1 + var2) >> 8) + (((int64_t)bmp280_calib.dig_P7) << 4);
  return (float)p / 256;
}

ADC驱动

这里就不贴代码了,跟着立创教程学习就行,那里肯定比我讲解的详细。

按键、LED驱动

这里也不贴代码了,跟着立创教程学习就行,那里肯定比我讲解的详细。

wifi、蓝牙驱动

立创教程非常丰富,肯定比我讲解的详细,我就不献丑了。如下教程:
https://wiki.lckfb.com/zh-hans/esp32s3r8n8/esp-idf-beginner/wifi.html

演示效果

具体见附件和B站链接哦:
https://www.bilibili.com/video/BV1GFt8eYEos/?vd_source=24f1befd6441a33d7b240715cb07c7b5

总结

千里之行始于足下,不管多难,都要先行动起来。
这次虽然时间仓促,逼着自己坚持下去,收获真的很多哦。

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

附件

序号文件名称下载次数
1
新封面.png
3
2
简单壳.png
3
3
Project_18TFT_AHT21B_BMP280_240916.bin
3
4
partition-table.bin
3
5
bootloader.bin
3
6
演示视频.mp4
2
克隆工程
添加到专辑
0
0
分享
侵权投诉

评论

全部评论(1)
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航