PSoc™62开发板之IoT应用

news2024/11/28 12:32:55

实验目的

使用PSoc62™开发板驱动OLED模块,实时监控室内的光照强度、温度信息

实验准备

  • PSoc62™开发板
  • SSD1309 OLED模块
  • DS18B20温度传感器
  • BH1750光照传感器

模块电路

SSD1309

OLED模块的电路连接和模块配置教程请参考之前的文章,这里不详细展开描述

BH1750

模块SCL、SDA、GND引脚分别接CON5的P8.0、P8.1、GND引脚,VCC则接CON6的3.3V引脚

在这里插入图片描述

实物连接图

在这里插入图片描述

i2c引脚配置,需要在RT-Thread Studio里边配置使用模拟i2c引脚P8.0和P8.1(分别对应编号64、65)

在这里插入图片描述
有需要的可以使能i2c-tools这个包
在这里插入图片描述

模块的设备地址用i2c-tools查看是0x23

在这里插入图片描述

DS18B20

模块out引脚连接CON8处的P10.5引脚,VCC、GND可以连接CON6处的3.3V、GND,模块已经接了上拉电阻,这里不需要额外配置

在这里插入图片描述

实物连接图

在这里插入图片描述

程序设计

SSD1309

OLED模块的程序设计请参考之前的文章

DS18B20

传感器驱动代码

#define DS18B20_PIN         GET_PIN(10, 5)
#define DS18B20_DQ_OUT(x)   rt_pin_write(DS18B20_PIN, x)
#define DS18B20_DQ_IN       rt_pin_read(DS18B20_PIN)

// 复位DS18B20
static void ds18b20_reset(void)
{
    DS18B20_DQ_OUT(0);  
    rt_hw_us_delay(750);      
    DS18B20_DQ_OUT(1); 
    rt_hw_us_delay(15);      
}

// 等待DS18B20的回应
uint8_t ds18b20_check(void)
{
    uint8_t retry = 0;
    uint8_t rval = 0;

    while (DS18B20_DQ_IN && retry < 200)  
    {
        retry++;
        rt_hw_us_delay(1);
    }

    if (retry >= 200)
    {
        rval = 1;
    }
    else
    {
        retry = 0;

        while (!DS18B20_DQ_IN && retry < 240) 
        {
            retry++;
            rt_hw_us_delay(1);
        }

        if (retry >= 240) rval = 1;
    }

    return rval;
}

// 从DS18B20读取一个位
static uint8_t ds18b20_read_bit(void)
{
    uint8_t data = 0;
    DS18B20_DQ_OUT(0);
    rt_hw_us_delay(2);
    DS18B20_DQ_OUT(1);
    rt_hw_us_delay(12);

    if (DS18B20_DQ_IN)
    {
        data = 1;
    }

    rt_hw_us_delay(50);
    return data;
}

// 从DS18B20读取一个字节
static uint8_t ds18b20_read_byte(void)
{
    uint8_t i, b, data = 0;

    for (i = 0; i < 8; i++)
    {
        b = ds18b20_read_bit(); 

        data |= b << i;       
    }

    return data;
}

// 写一个字节到DS18B20
static void ds18b20_write_byte(uint8_t data)
{
    uint8_t j;

    for (j = 1; j <= 8; j++)
    {
        if (data & 0x01)
        {
            DS18B20_DQ_OUT(0); 
            rt_hw_us_delay(2);
            DS18B20_DQ_OUT(1);
            rt_hw_us_delay(60);
        }
        else
        {
            DS18B20_DQ_OUT(0); 
            rt_hw_us_delay(60);
            DS18B20_DQ_OUT(1);
            rt_hw_us_delay(2);
        }

        data >>= 1;             
    }
}

// 开始温度转换
static void ds18b20_start(void)
{
    ds18b20_reset();
    ds18b20_check();
    ds18b20_write_byte(0xcc);   /*  skip rom */
    ds18b20_write_byte(0x44);   /*  convert */
}

// 初始化DS18B20的IO口 DQ 同时检测DS18B20的存在
uint8_t ds18b20_init(void)
{
    rt_pin_mode(DS18B20_PIN, PIN_MODE_OUTPUT_OD);
//    rt_pin_write(DS18B20_PIN, PIN_HIGH);

    ds18b20_reset();
    return ds18b20_check();
}

// 从ds18b20得到温度值(精度:0.1C)
short ds18b20_get_temperature(void)
{
    uint8_t flag = 1;           /* 默认温度为正数 */
    uint8_t TL, TH;
    short temp;

    ds18b20_start();            /*  ds1820 start convert */
    ds18b20_reset();
    ds18b20_check();
    ds18b20_write_byte(0xcc);   /*  skip rom */
    ds18b20_write_byte(0xbe);   /*  convert */
    TL = ds18b20_read_byte();   /*  LSB */
    TH = ds18b20_read_byte();   /*  MSB */

    if (TH > 7)
    {
        TH = ~TH;
        TL = ~TL;
        flag = 0;   /* 温度为负 */
    }

    temp = TH;      /* 获得高八位 */
    temp <<= 8;
    temp += TL;     /* 获得底八位 */
    temp = (double)temp * 0.625;    /* 转换 */

    if (flag == 0)
    {
        temp = -temp;   /* 将温度转换成负温度 */
    }

    return temp;
}

读取温度值

// ds18b20
ds18b20_init();

// ssd1309
OLED_Init();
OLED_Clear();

for (;;)
{
    // ds18b20
    int val = ds18b20_get_temperature();
    rt_memset(buff, 20, 0);
    rt_sprintf(buff, "temp : %d.%d'C  ", val / 10, val % 10);
    OLED_ShowString(10, 2, buff);
    rt_thread_mdelay(200);
}

用逻辑分析仪抓一下单总线的读写时序,读取的数据(0x0185,大概是室温20来度)是OK的

在这里插入图片描述

BH1750

模块驱动代码,用的是i2c1总线

#define BH1750_I2C_BUS_NAME     "i2c1"
#define BH1750_ADDR             0x23

static rt_uint8_t buffer[2];
static uint16_t light = 0;
static struct rt_i2c_bus_device *i2c_bus;

static int read_i2c_reg(rt_uint8_t reg_addr, rt_uint8_t *data, rt_uint8_t len)
{
    struct rt_i2c_msg msgs[2];
    msgs[0].addr = BH1750_ADDR;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf = &reg_addr;
    msgs[0].len = 1;

    msgs[1].addr = BH1750_ADDR;
    msgs[1].flags = RT_I2C_RD;
    msgs[1].buf = data;
    msgs[1].len = len;

    if (rt_i2c_transfer(i2c_bus, msgs, 2) == 2)
    {
        return RT_EOK;
    }
    else
        return -RT_ERROR;
}

static int8_t write_i2c_reg(uint8_t data)
{
    struct rt_i2c_msg msgs[2];

    msgs[0].addr  = BH1750_ADDR;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf   = NULL;
    msgs[0].len   = 0;

    msgs[1].addr  = BH1750_ADDR;
    msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;
    msgs[1].buf   = &data;
    msgs[1].len   = 1;

    if (rt_i2c_transfer(i2c_bus, msgs, 2) != 2)
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}

void BH1750_Init()
{
    write_i2c_reg(0x10);
}

读取光照强度值

// bh1750
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(BH1750_I2C_BUS_NAME);
if (i2c_bus == RT_NULL)
{
    rt_kprintf("can't find %s device!\n", BH1750_I2C_BUS_NAME);
    return RT_ERROR;
}

BH1750_Init();
rt_thread_mdelay(500);

// ssd1309
OLED_Init();
OLED_Clear();

for (;;)
{
    // bh1750
    BH1750_Init();
    rt_thread_mdelay(200);
    read_i2c_reg(0, buffer, 2);
    light = ((buffer[0] << 8) | buffer[1]) / 1.2;
    rt_memset(buff, 20, 0);
    rt_sprintf(buff, "light : %d lx      ", light);
    OLED_ShowString(10, 5, buff);
    rt_thread_mdelay(150);
}

整合代码

以下代码用于读取DS18B20的温度值、BH1750的光照强度

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_gpio.h"

#define DS18B20_PIN         GET_PIN(10, 5)
#define DS18B20_DQ_OUT(x)   rt_pin_write(DS18B20_PIN, x)
#define DS18B20_DQ_IN       rt_pin_read(DS18B20_PIN)

// 复位DS18B20
static void ds18b20_reset(void)
{
    DS18B20_DQ_OUT(0);  /* 拉低DQ,复位 */
    rt_hw_us_delay(750);      /* 拉低750us */
    DS18B20_DQ_OUT(1);  /* DQ=1, 释放复位 */
    rt_hw_us_delay(15);       /* 延迟15US */
}

// 等待DS18B20的回应
uint8_t ds18b20_check(void)
{
    uint8_t retry = 0;
    uint8_t rval = 0;

    while (DS18B20_DQ_IN && retry < 200)    /* 等待DQ变低, 等待200us */
    {
        retry++;
        rt_hw_us_delay(1);
    }

    if (retry >= 200)
    {
        rval = 1;
    }
    else
    {
        retry = 0;

        while (!DS18B20_DQ_IN && retry < 240)   /* 等待DQ变高, 等待240us */
        {
            retry++;
            rt_hw_us_delay(1);
        }

        if (retry >= 240) rval = 1;
    }

    return rval;
}

// 从DS18B20读取一个位
static uint8_t ds18b20_read_bit(void)
{
    uint8_t data = 0;
    DS18B20_DQ_OUT(0);
    rt_hw_us_delay(2);
    DS18B20_DQ_OUT(1);
    rt_hw_us_delay(12);

    if (DS18B20_DQ_IN)
    {
        data = 1;
    }

    rt_hw_us_delay(50);
    return data;
}

// 从DS18B20读取一个字节
static uint8_t ds18b20_read_byte(void)
{
    uint8_t i, b, data = 0;

    for (i = 0; i < 8; i++)
    {
        b = ds18b20_read_bit(); /* DS18B20先输出低位数据 ,高位数据后输出 */

        data |= b << i;         /* 填充data的每一位 */
    }

    return data;
}

// 写一个字节到DS18B20
static void ds18b20_write_byte(uint8_t data)
{
    uint8_t j;

    for (j = 1; j <= 8; j++)
    {
        if (data & 0x01)
        {
            DS18B20_DQ_OUT(0);  /*  Write 1 */
            rt_hw_us_delay(2);
            DS18B20_DQ_OUT(1);
            rt_hw_us_delay(60);
        }
        else
        {
            DS18B20_DQ_OUT(0);  /*  Write 0 */
            rt_hw_us_delay(60);
            DS18B20_DQ_OUT(1);
            rt_hw_us_delay(2);
        }

        data >>= 1;             /* 右移,获取高一位数据 */
    }
}

// 开始温度转换
static void ds18b20_start(void)
{
    ds18b20_reset();
    ds18b20_check();
    ds18b20_write_byte(0xcc);   /*  skip rom */
    ds18b20_write_byte(0x44);   /*  convert */
}

// 初始化DS18B20的IO口 DQ 同时检测DS18B20的存在
uint8_t ds18b20_init(void)
{
    rt_pin_mode(DS18B20_PIN, PIN_MODE_OUTPUT_OD);
//    rt_pin_write(DS18B20_PIN, PIN_HIGH);

    ds18b20_reset();
    return ds18b20_check();
}

// 从ds18b20得到温度值(精度:0.1C)
short ds18b20_get_temperature(void)
{
    uint8_t flag = 1;           /* 默认温度为正数 */
    uint8_t TL, TH;
    short temp;

    ds18b20_start();            /*  ds1820 start convert */
    ds18b20_reset();
    ds18b20_check();
    ds18b20_write_byte(0xcc);   /*  skip rom */
    ds18b20_write_byte(0xbe);   /*  convert */
    TL = ds18b20_read_byte();   /*  LSB */
    TH = ds18b20_read_byte();   /*  MSB */

    if (TH > 7)
    {
        TH = ~TH;
        TL = ~TL;
        flag = 0;   /* 温度为负 */
    }

    temp = TH;      /* 获得高八位 */
    temp <<= 8;
    temp += TL;     /* 获得底八位 */
    temp = (double)temp * 0.625;    /* 转换 */

    if (flag == 0)
    {
        temp = -temp;   /* 将温度转换成负温度 */
    }

    return temp;
}

///

#include "stdlib.h"
#include "oledfont.h"

// 绑定PSoc62板子的GPIO
#define CS_PIN      GET_PIN(10, 0)
#define DC_PIN      GET_PIN(10, 1)
#define RES_PIN     GET_PIN(10, 2)
#define SDA_PIN     GET_PIN(10, 3)
#define SCL_PIN     GET_PIN(10, 4)
#define WR_PIN      GET_PIN(0, 1)
#define RD_PIN      GET_PIN(0, 1)

// OLED模式设置
#define OLED_MODE   0
#define SIZE        16
#define XLevelL     0x00
#define XLevelH     0x10
#define Max_Column  128
#define Max_Row     64
#define Brightness  0xFF
#define X_WIDTH     128
#define Y_WIDTH     64

// OLED端口定义
#define OLED_CS_Clr()   rt_pin_write(CS_PIN, PIN_LOW)
#define OLED_CS_Set()   rt_pin_write(CS_PIN, PIN_HIGH)
#define OLED_RST_Clr()  rt_pin_write(RES_PIN, PIN_LOW)
#define OLED_RST_Set()  rt_pin_write(RES_PIN, PIN_HIGH)
#define OLED_DC_Clr()   rt_pin_write(DC_PIN, PIN_LOW)
#define OLED_DC_Set()   rt_pin_write(DC_PIN, PIN_HIGH)
#define OLED_SDIN_Clr() rt_pin_write(SDA_PIN, PIN_LOW)
#define OLED_SDIN_Set() rt_pin_write(SDA_PIN, PIN_HIGH)
#define OLED_SCLK_Clr() rt_pin_write(SCL_PIN, PIN_LOW)
#define OLED_SCLK_Set() rt_pin_write(SCL_PIN, PIN_HIGH)
#define OLED_WR_Clr()   rt_pin_write(WR_PIN, PIN_LOW)
#define OLED_WR_Set()   rt_pin_write(WR_PIN, PIN_HIGH)
#define OLED_RD_Clr()   rt_pin_write(RD_PIN, PIN_LOW)
#define OLED_RD_Set()   rt_pin_write(RD_PIN, PIN_HIGH)

#define OLED_CMD  0 // 写命令
#define OLED_DATA 1 // 写数据

#define u8 unsigned char
#define u32 unsigned int

static u8 buff[20];

// 向SSD1309写入一个字节数据:dat -> 要写入的数据 or命令,cmd -> 数据or命令
void OLED_WR_Byte(u8 dat, u8 cmd)
{
    u8 i;
    if(cmd)
        OLED_DC_Set();
    else
        OLED_DC_Clr();
    OLED_CS_Clr();
    for(i=0; i < 8; i++)
    {
        OLED_SCLK_Clr();
        if(dat & 0x80)
            OLED_SDIN_Set();
        else
            OLED_SDIN_Clr();
        OLED_SCLK_Set();
        dat <<= 1;
    }
    OLED_CS_Set();
    OLED_DC_Set();
}

// 设置绘制的坐标
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
    OLED_WR_Byte(0xb0 + y, OLED_CMD);
    OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
    OLED_WR_Byte((x & 0x0f) | 0x01, OLED_CMD);
}

// 开启OLED显示
void OLED_Display_On(void)
{
    OLED_WR_Byte(0X8D, OLED_CMD);
    OLED_WR_Byte(0X14, OLED_CMD);
    OLED_WR_Byte(0XAF, OLED_CMD);
}

// 关闭OLED显示
void OLED_Display_Off(void)
{
    OLED_WR_Byte(0X8D, OLED_CMD);
    OLED_WR_Byte(0X10, OLED_CMD);
    OLED_WR_Byte(0XAE, OLED_CMD);
}

// 清屏函数,屏幕会置为黑色
void OLED_Clear(void)
{
    u8 i,n;
    for(i=0;i<8;i++)
    {
        OLED_WR_Byte (0xb0 + i, OLED_CMD);      // 设置页地址(0~7)
        OLED_WR_Byte (0x00, OLED_CMD);          // 设置显示位置—列低地址
        OLED_WR_Byte (0x10, OLED_CMD);          // 设置显示位置—列高地址
        for(n = 0; n < 128; n++)
            OLED_WR_Byte(0, OLED_DATA);
    }
}

// 绘制字符
void OLED_ShowChar(u8 x,u8 y,u8 chr)
{
    unsigned char c=0,i=0;
    c=chr-' ';//得到偏移后的值
    if(x>Max_Column-1)
    {
        x=0;
        y=y+2;
    }
    if(SIZE ==16)
    {
        OLED_Set_Pos(x,y);
        for(i=0;i<8;i++)
            OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
        OLED_Set_Pos(x,y+1);
        for(i=0;i<8;i++)
            OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
    }
    else {
        OLED_Set_Pos(x,y+1);
        for(i=0;i<6;i++)
            OLED_WR_Byte(F6x8[c][i],OLED_DATA);

    }
}

// 显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr)
{
    unsigned char j=0;
    while (chr[j]!='\0')
    {
        OLED_ShowChar(x,y,chr[j]);
        x+=8;
        if(x>120)
        {
            x=0;y+=2;
        }
        j++;
    }
}

// 显示数字
void OLED_ShowNum(u8 x,u8 y,u32 num)
{
    rt_memset(buff, 20, 0);
    rt_sprintf(buff, "%d", num);
    OLED_ShowString(x, y, buff);
}

// 显示汉字
void OLED_ShowCHinese(u8 x,u8 y,u8 no)
{
    u8 t,adder=0;
    OLED_Set_Pos(x,y);
    for(t=0;t<16;t++)
    {
        OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
        adder+=1;
    }
    OLED_Set_Pos(x,y+1);
    for(t=0;t<16;t++)
    {
        OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
        adder+=1;
    }
}


// 初始化SSD1309
void OLED_Init(void)
{
    // init gpios
    rt_pin_mode(CS_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(DC_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(RES_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(SDA_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(SCL_PIN, PIN_MODE_OUTPUT);

    OLED_RST_Set();
    rt_thread_mdelay(100);
    OLED_RST_Clr();
    rt_thread_mdelay(100);
    OLED_RST_Set();

    OLED_WR_Byte(0xAE,OLED_CMD);    //--turn off oled panel
    OLED_WR_Byte(0x00,OLED_CMD);    //---set low column address
    OLED_WR_Byte(0x10,OLED_CMD);    //---set high column address
    OLED_WR_Byte(0x40,OLED_CMD);    //--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
    OLED_WR_Byte(0x81,OLED_CMD);    //--set contrast control register
    OLED_WR_Byte(0xCF,OLED_CMD);    // Set SEG Output Current Brightness
    OLED_WR_Byte(0xA1,OLED_CMD);    //--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    OLED_WR_Byte(0xC8,OLED_CMD);    //Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    OLED_WR_Byte(0xA6,OLED_CMD);    //--set normal display
    OLED_WR_Byte(0xA8,OLED_CMD);    //--set multiplex ratio(1 to 64)
    OLED_WR_Byte(0x3f,OLED_CMD);    //--1/64 duty
    OLED_WR_Byte(0xD3,OLED_CMD);    //-set display offset   Shift Mapping RAM Counter (0x00~0x3F)
    OLED_WR_Byte(0x00,OLED_CMD);    //-not offset
    OLED_WR_Byte(0xd5,OLED_CMD);    //--set display clock divide ratio/oscillator frequency
    OLED_WR_Byte(0x80,OLED_CMD);    //--set divide ratio, Set Clock as 100 Frames/Sec
    OLED_WR_Byte(0xD9,OLED_CMD);    //--set pre-charge period
    OLED_WR_Byte(0xF1,OLED_CMD);    //Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    OLED_WR_Byte(0xDA,OLED_CMD);    //--set com pins hardware configuration
    OLED_WR_Byte(0x12,OLED_CMD);
    OLED_WR_Byte(0xDB,OLED_CMD);    //--set vcomh
    OLED_WR_Byte(0x40,OLED_CMD);    //Set VCOM Deselect Level
    OLED_WR_Byte(0x20,OLED_CMD);    //-Set Page Addressing Mode (0x00/0x01/0x02)
    OLED_WR_Byte(0x02,OLED_CMD);    //
    OLED_WR_Byte(0x8D,OLED_CMD);    //--set Charge Pump enable/disable
    OLED_WR_Byte(0x14,OLED_CMD);    //--set(0x10) disable
    OLED_WR_Byte(0xA4,OLED_CMD);    // Disable Entire Display On (0xa4/0xa5)
    OLED_WR_Byte(0xA6,OLED_CMD);    // Disable Inverse Display On (0xa6/a7)
    OLED_WR_Byte(0xAF,OLED_CMD);    //--turn on oled panel

    OLED_WR_Byte(0xAF,OLED_CMD);    /*display ON*/
    OLED_Clear();
    OLED_Set_Pos(0,0);
}

//
#define BH1750_I2C_BUS_NAME     "i2c1"
#define BH1750_ADDR             0x23

static rt_uint8_t buffer[2];
static uint16_t light = 0;
static struct rt_i2c_bus_device *i2c_bus;

static int read_i2c_reg(rt_uint8_t reg_addr, rt_uint8_t *data, rt_uint8_t len)
{
    struct rt_i2c_msg msgs[2];
    msgs[0].addr = BH1750_ADDR;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf = &reg_addr;
    msgs[0].len = 1;

    msgs[1].addr = BH1750_ADDR;
    msgs[1].flags = RT_I2C_RD;
    msgs[1].buf = data;
    msgs[1].len = len;

    if (rt_i2c_transfer(i2c_bus, msgs, 2) == 2)
    {
        return RT_EOK;
    }
    else
        return -RT_ERROR;
}

static int8_t write_i2c_reg(uint8_t data)
{
    struct rt_i2c_msg msgs[2];

    msgs[0].addr  = BH1750_ADDR;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf   = NULL;
    msgs[0].len   = 0;

    msgs[1].addr  = BH1750_ADDR;
    msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;
    msgs[1].buf   = &data;
    msgs[1].len   = 1;

    if (rt_i2c_transfer(i2c_bus, msgs, 2) != 2)
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}

void BH1750_Init()
{
    write_i2c_reg(0x10);
}

int main(void)
{
    // ds18b20
    ds18b20_init();

    // bh1750
    i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(BH1750_I2C_BUS_NAME);
    if (i2c_bus == RT_NULL)
    {
        rt_kprintf("can't find %s device!\n", BH1750_I2C_BUS_NAME);
        return RT_ERROR;
    }

    BH1750_Init();
    rt_thread_mdelay(500);

    // ssd1309
    OLED_Init();
    OLED_Clear();

    for (;;)
    {
        // ds18b20
        int val = ds18b20_get_temperature();
        rt_memset(buff, 20, 0);
        rt_sprintf(buff, "temp : %d.%d'C  ", val / 10, val % 10);
        OLED_ShowString(10, 2, buff);
        rt_thread_mdelay(200);

        // bh1750
        BH1750_Init();
        rt_thread_mdelay(200);
        read_i2c_reg(0, buffer, 2);
        light = ((buffer[0] << 8) | buffer[1]) / 1.2;
        rt_memset(buff, 20, 0);
        rt_sprintf(buff, "light : %d lx      ", light);
        OLED_ShowString(10, 5, buff);
        rt_thread_mdelay(150);
    }
}

实验效果

实时读取环境的温度和光照强度,正值夜晚光照强度在0-100 lx范围内

在这里插入图片描述

注意事项

这里有三个关键的模块,连接线比较复杂

  • 千万不要接错电源和地
  • i2c不能接错数据线和时钟线,spi接线也不例外
  • 读取不到数据可以借助一些工具排查一下,比如i2c-tools、逻辑分析仪

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1659216.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通配符证书是什么意思?使用起来有什么优势?

通配符证书就像是一个万能钥匙&#xff0c;但它专门用于网站的安全。当你运营一个网站时&#xff0c;特别是有很多子网站&#xff0c;每个都需要安全连接&#xff08;比如开头是https的网址&#xff09;&#xff0c;通常你需要为每个子网站买一个证书来保证访问者的安全。但是&…

ICLR 2024 杰出论文出炉:“大模型”成最大赢家

源自&#xff1a;北京科技大学机械工程学院 作者&#xff1a;陈哲涵 黎学臻 ““人工智能技术与咨询” 发布 国际表征学习大会&#xff08;International Conference on Learning Representations&#xff0c;ICLR&#xff09;公布了 ICLR 2024 杰出论文。 声明:公众号转载的…

5月游戏市场迎来新的体验,网易两款游戏重磅出炉

易采游戏网5月9日消息&#xff0c;随着科技的飞速发展&#xff0c;手机游戏已经成为人们休闲娱乐的重要方式。在这个领域&#xff0c;网易作为国内领先的游戏开发商&#xff0c;一直致力于为玩家带来高品质的游戏体验。近日&#xff0c;网易携手国际大厂Square Enix&#xff0c…

Azure Windows2012升级2016

Azure Windows2012升级2016 在自己电脑配置Azure PowerShell前置条件PowerShell 登录到 Azure Azure 中运行 Windows Server 的 VM 的就地升级前置条件&#xff0c;生成一块OS磁盘将生成的OS磁盘附件到需升级的服务器执行就地升级到 Windows Server 2016 升级后配置故障恢复 在…

Allegro PCB designer放置振列过空,Via Array,

首先 Place >>Via Array, 然后配置options 选项卡。 最后鼠标左击一下&#xff0c;拉个区域框&#xff0c;再点击一下。如下图 尤其注意鼠标左击一下再左击一下。

可持续未来:含镍废水处理工艺的革新探索

在向可持续能源转型的全球大潮中&#xff0c;高性能动力电池的生产扮演着举足轻重的角色。这些电池核心材料包含镍、钴、锰和铝等贵重元素&#xff0c;极大地提升了电池的能效&#xff0c;但同时也带来了含镍废水处理的严峻挑战。本文旨在深入探讨当前处理含镍废水的四大主流技…

HTML4(三):表单

文章目录 表单1. 基本结构2. 常用表单控件2.1 文本输入框2.2 密码输入框2.3 单选框2.4 复选框2.5 隐藏域2.6 提交按钮2.7 重置按钮2.8 普通按钮2.9 文本域2.10 下拉框2.11 示例 3. 禁用表单控件4. lable标签5. fieldset与legend标签6. 总结 表单 概念&#xff1a;一种包含交互…

链表第5/9题--两两交换链表中的节点--递归法

LeetCode24&#xff1a; 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4…

【PX4-AutoPilot教程-TIPS】Matlab使用ROS Toolbox编译MAVROS2消息报错缺少geographic_msgs消息

Matlab使用ROS Toolbox编译MAVROS2消息报错缺少geographic_msgs消息的解决方法 问题描述解决方法 环境&#xff1a; MATLAB : R2022b ROS Toolbox : 1.6 Windows &#xff1a;Windows 10 22H2 ROS &#xff1a;ROS2 Foxy 问题描述 在使用Matlab的ROS Toolbox工具箱编译与…

蓝桥杯EDA客观题

目录 前言 一、PCB类知识点和题目分析 1.电阻 2.电容 3.封装类 4.单位转换类 5.电路板结构类 6.PCB绘制规则 7.立创软件 8.PCB硬件 线性电源和开关电源 二、数电知识点和题目分析 1.门电路 2.逻辑代数 3.组合逻辑电路 4.触发器 5.时序逻辑电路 6.其他 三、模…

怎么编辑百度百科

百度百科是一个开放、免费的在线百科平台&#xff0c;由百度公司推出&#xff0c;旨在创造一个涵盖各领域知识的中文信息收集平台。任何人都可以通过注册百度账号并登录后&#xff0c;对符合条件的词条进行编辑和修改。以下是编辑百度百科的步骤和注意事项&#xff1a; 注册和登…

河北公司推行精益管理咨询时需要注意哪些问题?

近年来&#xff0c;越来越多的河北公司开始关注并推行精益管理咨询&#xff0c;以期通过优化流程、降低成本、提高效率来获得竞争优势。然而&#xff0c;在实施过程中&#xff0c;公司需要注意一系列问题&#xff0c;以确保精益管理咨询能够顺利推进并取得预期效果。天行健精益…

Java实现Excel导入和校验

文章目录 效果实现1,添加依赖2,实体类Member.javaMemberVO.java3,校验、监听器ValidationTool.javaExcelReadListener.java4,请求接口参考博文效果 输入:导入测试.xlsx postman调用实例: postman输出结果: 日志输出: 实现 1,添加依赖 easyexcel要去掉poi-ooxm…

Web地理空间引擎

Web地理空间引擎是指用于在Web上创建和显示地理空间信息的软件平台。它们通常提供一组API和工具&#xff0c;用于加载、可视化和分析地理空间数据。Web地理空间引擎被广泛应用于各种应用&#xff0c;例如地图、导航、位置服务、游戏和模拟等。北京木奇移动技术有限公司&#xf…

021、Python+fastapi,第一个Python项目走向第21步:ubuntu 24.04 docker 安装mysql8集群、redis集群(二)

系列文章目录 pythonvue3fastapiai 学习_浪淘沙jkp的博客-CSDN博客https://blog.csdn.net/jiangkp/category_12623996.html 前言 安装redis 我会以三种方式安装&#xff0c;在5月4号修改完成 第一、直接最简单安装&#xff0c;适用于测试环境玩玩 第二、conf配置安装 第三…

面试智慧:巧妙应对,展现真我风采

你是否曾经因为面试时太过“老实”&#xff0c;而错失了心仪的职位&#xff1f;很多人学历高、经验足&#xff0c;却在面试中未能如愿以偿。其实&#xff0c;面试不仅仅是考察你的能力和经验&#xff0c;更是考察你如何巧妙地展现自己。 下面&#xff0c;我将为你揭示一些常见的…

python循环结构练习

目录 前言 1、使用while实现模拟用户登录 1.1 题目要求 1.2 解题 2、输入数字&#xff0c;生成对应等腰三角形 2.1 题目要求 2.2 解题 3、输入数字&#xff0c;生成对应的菱形 3.1 题目要求 3.2 解题 总结 前言 本系列主要是讲解python中的题目&#xff0c;目的是为…

【网站项目】SpringBoot819图书馆管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

ASP.NET MVC 如何使用 Form Authentication?

前言 .NET 的 Form Authentication 是一种基于表单的简单且灵活的身份验证机制&#xff0c;用户通过输入用户名和密码来登录应用程序&#xff0c;并且通过配置来控制用户访问权限。 在使用 Form Authentication 时&#xff0c;我们需要在 web.config 文件中配置身份验证和授权…

【资源分享】最新版PS2024免费和谐安装教程

“时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;——时问桫椤 非…