PSoc™62开发板之IoT应用

实验目的

使用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.mfbz.cn/a/609857.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

汽车EDI:IAC Elmdon EDI 对接指南

近期收到客户C公司的需求&#xff0c;需要与其合作伙伴IAC Elmdon建立EDI连接&#xff0c;本文将主要为大家介绍IAC Elmdon EDI 对接指南&#xff0c;了解EDI项目的对接流程。 项目需求 传输协议&#xff1a;OFTP2 IAC Elmdon 与其供应商之间使用的传输协议为OFTP2。OFTP2是…

云南区块链商户平台优化开发

背景 云南区块链商户平台是全省统一区块链服务平台。依托于云南省发改委、阿里云及蚂蚁区块链的国内首个省级区块链平台——云南省区块链平台同步上线&#xff0c;助力数字云南整体升级。 网页版并不适合妈妈那辈人使用&#xff0c;没有记忆功能&#xff0c;于是打算自己开发…

科技查新中医学科研项目查新点如何确立与提炼?案例讲解

一、前言 医学科技查新包括立项查新和成果查新两个部分&#xff0c;其中医学立项查新&#xff0c;它是指在医学科研项目申报开题之前&#xff0c;通过在一定范围内进行该课题的相关文献检索 ( 可以根据项目委托人的具体要求&#xff0c;进行国内检索或者进行国外检索 ) &#x…

媲美Suno、Udio!AI铁了心,要砸音乐人的饭碗

5月10日凌晨&#xff0c;著名语音生成式AI平台ElevenLabs在社交平台宣布&#xff0c;推出文本生成歌曲产品ElevenLabs Music。 从其展示的效果来看&#xff0c;音乐的节奏感、和声、乐器的搭配、情感表达、创意性、风格的多样性、高/低音&#xff0c;可媲美该领域的两款头部产…

k8s StatefulSet

Statefulset 一个 Statefulset 创建的每个pod都有一个从零开始的顺序索引&#xff0c;这个会体现在 pod 的名称和主机名上&#xff0c;同样还会体现在 pod 对应的固定存储上。这些 pod 的名称是可预知的&#xff0c;它是由 Statefulset 的名称加该实例的顺序索引值组成的。不同…

【元对象系统概述】

元对象系统概述 &#x1f31f; 元对象&#x1f31f; 元对象系统&#x1f31f; QT官方文档中给出的定义&#x1f31f;《Qt5.9 C开发指南》中给出的定义 &#x1f31f; 元对象 元对象是一个描述类的信息的数据结构&#xff0c;在qt中常常与QObject的类相关联。 可以通过QObject::…

这些企业注意!推荐使用OVSSL证书

JoySSL官网 注册码230918 SSL证书作为一种重要的安全措施&#xff0c;对于确保网站数据传输的安全性至关重要。而在众多SSL证书类型中&#xff0c;OV&#xff08;Organization Validation&#xff0c;组织验证&#xff09;SSL证书以其独特的功能和适用范围&#xff0c;成为众多…

夸克网盘免费扩容N次20T的方法

上文我们用&#xff1a;夸克网盘免费领取1TB空间的方法使自己的网盘扩容到1TB&#xff0c;但只有三个月还不够大。 所以用下面的方法那个免费的把自己的网盘扩容到20TB。 一、 登录任推邦 APP 需要借助这个平台&#xff0c;这是夸克网盘的第三方服务商&#xff0c;完善注册信…

2024年自动驾驶、车辆工程与智能交通国际会议(ICADVEIT2024)

2024年自动驾驶、车辆工程与智能交通国际会议&#xff08;ICADVEIT2024&#xff09; 会议简介 2024年自动驾驶、车辆工程和智能交通国际会议&#xff08;ICADVEIT 2024&#xff09;将在中国深圳举行。会议主要聚焦自动驾驶、车辆工程和智能交通等研究领域&#xff0c;旨在为从…

智慧便民小程序源码系统 求职招聘+房产出租+相亲交友 带完整的安装代码包以及系统搭建教程

在数字化、智能化的今天&#xff0c;我们的生活节奏越来越快&#xff0c;对于各种服务的需求也越发多元化和个性化。为了满足广大市民对于便捷、高效、全面的服务需求&#xff0c;罗峰给大家分享一款智慧便民小程序源码系统&#xff0c;集求职招聘、房产出租、相亲交友三大功能…

【全开源】Java U U跑腿同城跑腿小程序源码快递代取帮买帮送源码小程序+H 5+公众号跑腿系统

特色功能&#xff1a; 智能定位与路线规划&#xff1a;UU跑腿小程序能够利用定位技术&#xff0c;为用户提供附近的跑腿服务&#xff0c;并自动规划最佳路线&#xff0c;提高配送效率。订单管理&#xff1a;包括订单查询、订单状态更新、订单评价等功能&#xff0c;全行业覆盖…

Mac YOLO V9本地训练(命令行模式)

环境&#xff1a; Mac M1 (MacOS Sonoma 14.3.1) Python 3.11PyTorch 2.1.2 一、YOLO v9工程及模型准备 详见&#xff1a;Mac YOLO V9推理测试-CSDN博客 二、数据集准备 Roboflow Universe上有许多小规模的数据集&#xff0c;很适合用来进行目标检测。 首先安装依赖 pip …

NVIDIA 配置 Jetson 扩展针座

系列文章目录 前言 每个 Jetson 开发套件包括多个扩展接头和连接器&#xff08;统称 "接头"&#xff09;&#xff1a; 40 针扩展接头&#xff1a; 可让您将 Jetson 开发套件连接到现成的 Raspberry Pi HAT&#xff08;顶部附加硬件&#xff09;&#xff0c;如 Seee…

echarts-gl 离线3D地图

1、安装依赖 echarts-gl 与 echarts 版本关系&#xff1a; "echarts": "^5.2.0", "echarts-gl": "^2.0.8"# 执行安装 yarn add echarts-gl2、下载离线地图 免费下载实时更新的geoJson数据、行政区划边界数据、区划边界坐标集合_…

笨方法自学python(一)

我觉得python和c语言有很多相似之处&#xff0c;如果有c语言基础的话学习python也不是很难。这一系列主要是学习例题来学习python&#xff1b;我用的python版本是3.12 代码编辑器我用的是notepad&#xff0c;运行py程序用cmd 现在开始写第一个程序&#xff1a; print ("…

Photoshop中绘图及图像修饰工具的应用

Photoshop中绘图及图像修饰工具的应用 Photoshop中的颜色设置与取样前景色与背景色颜色取样 Photoshop中的颜色替换工具Photoshop中的渐变工具Photoshop中的描边命令Photoshop中的填充工具采用油漆桶进行填充采用填充命令进行填充 Photoshop中的擦除工具 Photoshop中的颜色设置…

图像是AI画的吗?OpenAI新神器帮你一键识破!|TodayAI

OpenAI宣布即将推出一款新的AI图像检测工具&#xff0c;此举意在帮助用户辨认图像是否由其开发的DALL-E图像生成器制作&#xff0c;并监控由该技术生成的内容。同时&#xff0c;该公司还计划为这些AI生成的图像加入新的水印&#xff0c;以便用户更容易识别这些作品是否出自DALL…

深度学习课程论文精读——ESRGAN

目录 1.研究概述 2.论文创新 2.1 改进生成器的网络框架 2.2 改进判别器 2.3 改进感知损失 2.4 网络插值 3.实验 3.1 评价指标 3.2 训练细节 3.3 对比实验 3.4 消融实验 3.5 网络插值 4.总结 5.阅读参考 文章标题&#xff1a;《ESRGAN: Enhanced Super-Resolution…

Redis经典问题:缓存穿透

【更多精彩内容,欢迎关注小米的微信公众号“软件求生”】 大家好,我是小米,今天和大家分享一个在分布式系统和缓存应用中非常经典的问题——缓存穿透。在如今的互联网时代,缓存是一种非常常用且重要的技术手段,它能够有效提高系统的性能、稳定性和响应速度。然而,在使用…

ARM(2)ARMv8基础知识

目录 一、异常 1.1异常等级的定义 1.2异常的种类 1.2.1同步异常和异步异常 1.3改变异常等级 1.4异常后的处理 1.4.1异常处理相关寄存器 1.4.2系统调用 1.4.3对EL2/EL3的系统调用 1.4.4异常返回 1.4.5异常处理流程 二、安全状态 三、执行状态 本文介绍以下内容&…
最新文章