
基于ESP32室内监测桌摆
简介
基于ESP32-S3开发板设计室内监测桌摆。1-支持监测室内光照、温度、湿度、压强等;2-支持无线接入数据传输,方便远程访问;3-支持图片播放;4-支持蜂鸣器提醒;5-支持当桌摆;6-支持电池充放电。
简介:基于ESP32-S3开发板设计室内监测桌摆。1-支持监测室内光照、温度、湿度、压强等;2-支持无线接入数据传输,方便远程访问;3-支持图片播放;4-支持蜂鸣器提醒;5-支持当桌摆;6-支持电池充放电。开源协议
:TAPR Open Hardware License
描述
前言
一直想要学习一下ESP32,这次终于有机会了。以前都是在keil上开发,这次跟着立创的教程走的,虽然学习之旅很坎坷,总算有所收获。不管咋样,虽然迟到,从不缺席。
都是自己一点点做成的,还是很有成就感的。
功能设计与实现情况
1-支持监测室内光照、温度、湿度、压强数据采集,已完成
2-支持无线接入数据传输,方便远程访问,AP+蓝牙功能已验证,待集成。
3-支持图片播放,已验证图像显示,功能待集成。
4-支持蜂鸣器提醒,已完成
5-支持当桌摆,已完成。
6-支持电池充放电,已完成
7-支持电量报警,已完成。
硬件设计
主控设计
采用ESP32-S3,直接在立创购买的开发板。这次也是为了学习esp32,这个主频高达240Mhz,还支持双核,这是我心动的主要原因。
该板子管脚分配电路如下:
按键设计
这里为了后续的功能增加,尽可能多的预留了按键。
同时还预留了旋转编码器接口:
上述电路均增加了消抖电容哦,这个钱不要省哦。
指示灯设计
预留了2路上拉指示灯,加上开发板还有1个指示灯。共计3个可用指示灯
显示屏设计
手上刚好1.8寸的TFT显示屏,可以利用起来。学习ESP32如何驱动彩色的SPI接口屏。这个把我坑惨了。太难调了。
充放电电路
在立创购买的TP5400,便宜好用。参加立创各种活动,基本都是用的这个。
电路简单,可靠,实用。直接抄就行。
锂电池电量监测
锂电池充满电4.2V左右,需要进行分压才能采集。不能超过3.3V,esp32的AD决定的。如下所示:
光强检测测
采用光敏电阻,光照越强,电阻越小。根据这个原理,上拉分压。esp32的AD进行采集。如下所示:
蜂鸣器
这个电路拥有各种报警。电路简单,如下所示:
USB检测
当USB插入进行充电时候,可以检测USB是插入。因为输入5V,为了保护接口,进行了分压处理。
如下所示:
传感器模块
温湿度采用AHT21B进行采集数据,大气压强采用BMP280模块。
都是IIC接口,所以接口可以共用IIC总线。如下图所示:
教程没有这两个模块的移植,自己编写太痛苦了。但是收获也是很丰富的。
锂电池接口
预留2.54的排针,可以焊接也可以直接插入。
PCB设计
采用2层板,FR-4板材。厚度1.2mm。70X80的尺寸。
外壳设计
采用立创EDA进行设计,立创的3D模型做的越来越逼真了。进步真的很快哦。国产EDA前途无量啊。
软件设计与开发
采用立创教程中的方法,安装了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


评论