一、概述

以前的传感器是用过中断的方式进行计数的,现在已经有 I2C 通行的颜色传感器,不在需要我们像之前那样,通过计数的方式获取数据,直接通过I2C读取即可。当然有通过串口的方式获取采集数据的,串口使用就比较简单了,此笔记只针对 I2C 通信的模块。

我在某宝上随意购买了一个 TCS34725 的颜色采集模块,发现厂家提供的是 Arduino 的案例,还是用 C++ 编写的,我相信有的小伙伴还没接触过 C++ ,这里我将程序改为 C 语言编写,有需要的小伙伴可以收藏一下,

注意: 此笔记中的驱动程序不单纯针对莫一块 MCU,在 ESP32、stm32、arm中都可以使用的,甚至单片机也可稍微修改一下进行使用。

二、TCS34725 使用说明

TCS34725 多数提供的说明文档都是英文版的,英语不要的小伙伴,就有点慌了,不要怕,结合我这里的描述,相信你也能看明白是怎么回事了,下面我会把需要注意的重点进行记录分析。

  1. 传感器接线

    这个就比较简单了,相信能看到这篇笔记的小伙伴应该都没问题的,引脚如下图所示:

  2. 设备地址

  3. 设备寄存器

对于 TCS34725 编程需要注意的就上面三点内容,有这些知识点后,就可以编程了,现在是不是发现,没学过英文也可以完成 TCS34725 传感器的使用。

注意:如果不明白我为啥把说明书中这三个重点拿出的小伙伴,可能是对 I2C 原理还不怎么掌握,建议先去补充一下,然后再回来看就比较清晰了,这里我就不帖链接了,网上有很多。

三、TCS34725 驱动编程

还是老规矩,编程肯定要先配置,然后再使用,这个就不用说了,那么在 TCS34725 传感器中,使用之前主要有五个流程,分别是:读取设备识别号 → 设置集成时间 → 设置增益倍数 → 启动传感器 → 获取采集数据,分析如下所示。

  1. 可操作的寄存器地址

    在编写程序之前,先了解有哪些寄存器可以操作的,如下所示:

    #define TCS34725_address          (0x29)    // 设备地址
    #define TCS34725_COMMAND_BIT (0x80) // 命令字节 /* TCS34725传感器配置寄存器 */
    #define TCS34725_ENABLE (0x00) // 启用传感器
    #define TCS34725_ATIME (0x01) // 集成时间
    #define TCS34725_WTIME (0x03) // R / W 等待时间
    #define TCS34725_AILTL (0x04) // 清除通道下限中断阈值
    #define TCS34725_AILTH (0x05)
    #define TCS34725_AIHTL (0x06) // 清除通道上限中断阈值
    #define TCS34725_AIHTH (0x07) // 配置寄存器
    #define TCS34725_PERS (0x0C) // 中断永久性过滤器
    #define TCS34725_CONFIG (0x0C) // 中断永久性过滤器
    #define TCS34725_CONTROL (0x0F) // 增益倍数
    #define TCS34725_ID (0x12) // 设备识别号 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727
    #define TCS34725_STATUS (0x13) // 设备状态
    #define TCS34725_CDATAL (0x14) // 光照强度低字节
    #define TCS34725_CDATAH (0x15) // 光照强度高字节
    #define TCS34725_RDATAL (0x16) // 红色数据低字节
    #define TCS34725_RDATAH (0x17)
    #define TCS34725_GDATAL (0x18) // 绿色数据低字节
    #define TCS34725_GDATAH (0x19)
    #define TCS34725_BDATAL (0x1A) // 蓝色数据低字节
    #define TCS34725_BDATAH (0x1B)
  2. 命令寄存器

    这个命令寄存器的作用图中有详细描述,如下图所示:

    注意:看不懂没关系,只需要记住在进行寄存器操作时,都将寄存器地址或上一个 0x80 即可。

  3. TCS34725 与 I2C 驱动的接口函数如下

    /**
    * @brief 通过I2C驱动提供的API进行对接,作用是将一个8位数据写入对应的寄存器中
    *
    * @param reg_addr 寄存机地址
    * @param write_data 需要写入的寄存机数据
    * @return uint8_t 无错误时返回 0
    */
    static uint8_t tcs34725_write8(uint8_t reg_addr, uint8_t write_data)
    {
    return esp32_i2c_write8(TCS34725_address, TCS34725_COMMAND_BIT | reg_addr, write_data);
    } /**
    * @brief 通过I2C驱动提供的API进行对接,作用是读取一个8位的数据
    *
    * @param reg_addr 寄存器地址
    * @param read_data 数据存放地址
    * @return uint8_t 无错误时返回 0
    */
    static uint8_t tcs34725_read8(uint8_t reg_addr, uint8_t* read_data)
    {
    return esp32_i2c_read8(TCS34725_address, TCS34725_COMMAND_BIT | reg_addr, read_data);
    } /**
    * @brief 通过I2C驱动提供的API进行对接,作用是读取一个16位的数据
    *
    * @param reg_addr 寄存器地址
    * @param read_data 数据存放地址
    * @return uint8_t 无错误时返回 0
    */
    static uint8_t tcs34725_read16(uint8_t reg_addr, uint16_t* read_data)
    {
    return esp32_i2c_read16(TCS34725_address, TCS34725_COMMAND_BIT | reg_addr, read_data);
    }

    注意:

    1. 从程序中可以看出我在对每个寄存器操作前都或上了一个 0x80
    2. 我使用的 MCU 是 ESP32,所以这里对接的是 ESP32 的 I2C 接口函数,根据自己的需要进行更改即可。
    3. 需要了解 ESP 中 I2C 驱动的可以参考我之间我笔记:ESP32 I2C 总线主模式通信程序
  4. 读取设备识别号

    为什么需要做这步操作了,原因很简单,可以快速验证接线和 I2C 驱动是否正常,这样在完成后面操作是,可以排除这两个麻烦的问题导致的,不然很多小伙伴发现获取不了传感器数据就直接懵逼了。

    读取设备识别号的寄存器是 0x12 ,读取成功后会返回 0x44 或 0x4D,0x44 表示传感器是 TCS34721/TCS34725, 0x4D 表示传感器是 TCS34723/TCS34727,程序如下所示:

    /**
    * @brief 返回设备类型
    *
    * @return uint8_t 设备识别号 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727
    */
    uint8_t get_tcs34725_type(void)
    {
    uint8_t data = 0;
    tcs34725_read8(TCS34725_ID, &data);
    return data;
    }
  5. 判断设备是否正确

    /* 1.获取TCS34725型号 */
    uint8_t tcs34725_type = get_tcs34725_type();
    ESP_LOGI(TAG, "device type is : %x ", tcs34725_type);
    if (!((tcs34725_type == 0x44) && (tcs34725_type == 0x4D)))
    {
    ESP_LOGI(TAG, "Wrong device type!!!!!!!!!");
    return -1;
    }
  6. 设置集成时间

    集成时间的寄存器地址是 0x01,不同的集成时间对应的采集范围和采样时间不同,计算方式是:最大RGBC计数 = (256 - cycles) × 1024,集成时间 ≈ (256 - 255) × 2.4ms,其中 cycles 是写入 0x01 寄存器中的值。

    比如向 0x01 寄存器中写入 0xFF ,则最大RGBC计数 = (256 - 255) × 1024 = 1024,且集成时间 ≈ (256 - 255) × 2.4ms = 2.4ms 也就是说此时采集的颜色值的范围是 0 ~ 1024,需要等待的采样时间为2.4ms,下面是常用的几种设置参数,可以根据自己的需要进行添加

    /* 集成时间配置参数
    * 最大RGBC计数 = (256 - cycles) × 1024
    * 集成时间 ≈ (256 - cycles) × 2.4ms */
    typedef enum
    {
    TCS34725_INTEGRATIONTIME_2_4MS = 0xFF, // 2.4ms - 1 cycles - Max Count: 1024
    TCS34725_INTEGRATIONTIME_24MS = 0xF6, // 24ms - 10 cycles - Max Count: 10240
    TCS34725_INTEGRATIONTIME_50MS = 0xEC, // 50ms - 20 cycles - Max Count: 20480
    TCS34725_INTEGRATIONTIME_101MS = 0xD5, // 101ms - 42 cycles - Max Count: 43008
    TCS34725_INTEGRATIONTIME_154MS = 0xC0, // 154ms - 64 cycles - Max Count: 65535
    TCS34725_INTEGRATIONTIME_700MS = 0x00 // 700ms - 256 cycles - Max Count: 65535
    }
    tcs34725_integration_time_t;

    注意:

    1. 不同的集成时间,需要的采样时间不同,如果读取的时间间隔小于采样时间,那获取的颜色值都是0。
    2. 当设置的 cycles 小于 0xC0 后,需要的采样时间和采集范围不在增加。

    设置程序如下所示:

    /**
    * @brief 设置集成时间
    *
    * @param integration_time 集成时间
    * @return uint8_t 无错误时返回 0
    */
    uint8_t set_tcs34725_integration_time(tcs34725_integration_time_t integration_time)
    {
    _tcs34725_config.integration_time = integration_time;
    return tcs34725_write8(TCS34725_ATIME, integration_time);
    }
  7. 增益倍数

    增益倍数的寄存器地址是 0x0F,我不知道 TCS34725 内部的实现原理是什么,不过可以简单的从字面意思,类似将采集的值直接乘以一个倍数,作用是提高采集的敏感度,可以设置的增益倍数是:1、4、16、60。如下所示:

    /* 增益倍数 */
    typedef enum
    {
    TCS34725_GAIN_1X = 0x00, // 1X增益
    TCS34725_GAIN_4X = 0x01, // 4X增益
    TCS34725_GAIN_16X = 0x02, // 16X增益
    TCS34725_GAIN_60X = 0x03 // 60X增益
    }
    tcs34725_gain_t;

    注意:不论设置的增益倍数是多少,采集的数据不会超过集成时间中设置的最大值

    设置程序如下所示:

    /**
    * @brief 设置增益倍数
    *
    * @param gain 增益倍数
    * @return uint8_t 无错误时返回 0
    */
    uint8_t set_tcs34725_gain(tcs34725_gain_t gain)
    {
    _tcs34725_config.gain = gain;
    return tcs34725_write8(TCS34725_CONTROL, gain);
    }
  8. 启动 TCS34725 设备

    启动设置的寄存器地址是 0x00,启动分中断启动和常规启动,具体的设置值如下所示:

    /* 启动传感器 */
    #define TCS34725_ENABLE_AIEN (0x10) // RGBC中断使能
    #define TCS34725_ENABLE_WEN (0x08) // 等待启用:写1激活等待计时器,写0禁用等待计时器
    #define TCS34725_ENABLE_AEN (0x02) // RGBC启用:写1激活RGBC,写0禁用RGBC
    #define TCS34725_ENABLE_PON (0x01) // 通电:写入1激活内部振荡器,0禁用内部振荡器

    程序如下所示:

    /**
    * @brief 启动 tcs34725 设备
    *
    * @param interrupt_start 是否开启中断启动方式
    * @return uint8_t 无错误时返回 0
    */
    uint8_t tcs34725_start(bool interrupt_start)
    {
    int err = 0;
    if (tcs34725_state)
    {
    return -1;
    } err = tcs34725_write8(TCS34725_ENABLE, TCS34725_ENABLE_PON);
    err = tcs34725_write8(TCS34725_ENABLE, TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN); /* 判断是否开启中断启动 */
    if (interrupt_start)
    {
    _tcs34725_config.interrupt_start = interrupt_start;
    err = tcs34725_write8(TCS34725_ENABLE, TCS34725_ENABLE_AIEN);
    } tcs34725_state = true;
    return err;
    }
  9. 采集数据

    采集数据获取的寄存器是:0x14 ~ 0x1B ,这里需要主要的是数据的高低位是反的,所以采集完成后需要交换一下高低位数据,如下所示:

    esp_err_t esp32_i2c_read16(uint8_t dev_addr, uint8_t reg_addr, uint16_t* read_data)
    {
    #if defined(CODE_SIMPLIFY)
    uint8_t buf[2];
    esp_err_t err = 0;
    err = i2c_write(dev_addr, &reg_addr, 1);
    err = i2c_read(dev_addr, buf, 2);
    *read_data = buf[1] << 8 | buf[0];
    return err;
    #else
    return i2c_read16(dev_addr, reg_addr, read_data);
    #endif
    }

    TCS34725 传感器数据的获取程序如下所示:

    /**
    * @brief 获取RGBC的值
    *
    * @param colour_r 数据存放地址
    * @param colour_g 数据存放地址
    * @param colour_b 数据存放地址
    * @param colour_c 数据存放地址
    * @return uint8_t 无错误时返回 0
    */
    uint8_t get_tcs34725_rgbc(uint16_t *colour_r, uint16_t *colour_g, uint16_t *colour_b, uint16_t *colour_c)
    {
    uint8_t err = 0;
    err = tcs34725_read16(TCS34725_RDATAL, colour_r);
    err = tcs34725_read16(TCS34725_GDATAL, colour_g);
    err = tcs34725_read16(TCS34725_BDATAL, colour_b);
    err = tcs34725_read16(TCS34725_CDATAL, colour_c);
    return err;
    }
  10. 停止 TCS34725 设备

    停止是设置的寄存器和启动是一样的,都是 0x00,程序如下所示:

    /**
    * @brief 停止 tcs34725 设备
    *
    * @return uint8_t 无错误时返回 0
    */
    uint8_t tcs34725_stop(void)
    {
    uint8_t err = 0;
    uint8_t data = 0;
    err = tcs34725_read8(TCS34725_ENABLE, &data);
    err = tcs34725_write8(TCS34725_ENABLE, data & ~(TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN)); /* 通过中断启动后时,需要关闭中断设置 */
    if (_tcs34725_config.interrupt_start)
    {
    err = tcs34725_write8(TCS34725_ENABLE, data & ~TCS34725_ENABLE_AIEN);
    } tcs34725_state = false;
    return err;
    }
  11. 范围计算和白平衡

    这里的范围计算和白平衡调节就多种多样了,可以采集完成后根据自己的需要完成。

    这里提供一个简单的思想,因为颜色的范围是 0 ~ 255,所以首先将自己的设置的范围换算到 0 ~ 25,然后再进行一个简单的白平衡校准即可。

四、TCS34725驱动程序

头文件

/**
* @file tcs34725.h
*
*/ #ifndef _TCS34725_H_
#define _TCS34725_H_ #ifdef __cplusplus
extern "C" {
#endif /*********************
* INCLUDES
*********************/
#include <stdlib.h>
#include <stdbool.h>
/*********************
* DEFINES
*********************/ #define TCS34725_address (0x29) // 设备地址
#define TCS34725_COMMAND_BIT (0x80) // 命令字节 /* TCS34725传感器配置寄存器 */
#define TCS34725_ENABLE (0x00) // 启用传感器
#define TCS34725_ATIME (0x01) // 集成时间
#define TCS34725_WTIME (0x03) // R / W 等待时间
#define TCS34725_AILTL (0x04) // 清除通道下限中断阈值
#define TCS34725_AILTH (0x05)
#define TCS34725_AIHTL (0x06) // 清除通道上限中断阈值
#define TCS34725_AIHTH (0x07) // 配置寄存器
#define TCS34725_PERS (0x0C) // 中断永久性过滤器
#define TCS34725_CONFIG (0x0C) // 中断永久性过滤器
#define TCS34725_CONTROL (0x0F) // 增益倍数
#define TCS34725_ID (0x12) // 设备识别号 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727
#define TCS34725_STATUS (0x13) // 设备状态
#define TCS34725_CDATAL (0x14) // 光照强度低字节
#define TCS34725_CDATAH (0x15) // 光照强度高字节
#define TCS34725_RDATAL (0x16) // 红色数据低字节
#define TCS34725_RDATAH (0x17)
#define TCS34725_GDATAL (0x18) // 绿色数据低字节
#define TCS34725_GDATAH (0x19)
#define TCS34725_BDATAL (0x1A) // 蓝色数据低字节
#define TCS34725_BDATAH (0x1B) /* 启动传感器 */
#define TCS34725_ENABLE_AIEN (0x10) // RGBC中断使能
#define TCS34725_ENABLE_WEN (0x08) // 等待启用:写1激活等待计时器,写0禁用等待计时器
#define TCS34725_ENABLE_AEN (0x02) // RGBC启用:写1激活RGBC,写0禁用RGBC
#define TCS34725_ENABLE_PON (0x01) // 通电:写入1激活内部振荡器,0禁用内部振荡器 /**********************
* TYPEDEFS
**********************/ /* 集成时间配置参数
* 最大RGBC计数 = (256 - cycles) × 1024
* 集成时间 ≈ (256 - cycles) × 2.4ms */
typedef enum
{
TCS34725_INTEGRATIONTIME_2_4MS = 0xFF, // 2.4ms - 1 cycles - Max Count: 1024
TCS34725_INTEGRATIONTIME_24MS = 0xF6, // 24ms - 10 cycles - Max Count: 10240
TCS34725_INTEGRATIONTIME_50MS = 0xEC, // 50ms - 20 cycles - Max Count: 20480
TCS34725_INTEGRATIONTIME_101MS = 0xD5, // 101ms - 42 cycles - Max Count: 43008
TCS34725_INTEGRATIONTIME_154MS = 0xC0, // 154ms - 64 cycles - Max Count: 65535
TCS34725_INTEGRATIONTIME_700MS = 0x00 // 700ms - 256 cycles - Max Count: 65535
}
tcs34725_integration_time_t; /* 增益倍数 */
typedef enum
{
TCS34725_GAIN_1X = 0x00, // 1X增益
TCS34725_GAIN_4X = 0x01, // 4X增益
TCS34725_GAIN_16X = 0x02, // 16X增益
TCS34725_GAIN_60X = 0x03 // 60X增益
}
tcs34725_gain_t; /**********************
* GLOBAL PROTOTYPES
**********************/
struct tcs34725_config
{
char name[20];
bool interrupt_start;
tcs34725_integration_time_t integration_time;
tcs34725_gain_t gain;
}tcs34725_config_t; uint8_t tcs34725_start(bool interrupt_start);
uint8_t tcs34725_stop(void);
uint8_t get_tcs34725_type(void);
uint8_t set_tcs34725_integration_time(tcs34725_integration_time_t integration_time);
uint8_t set_tcs34725_gain(tcs34725_gain_t gain);
uint8_t get_tcs34725_rgbc(uint16_t *colour_r, uint16_t *colour_g, uint16_t *colour_b, uint16_t *colour_c);
tcs34725_integration_time_t get_tcs34725_integration_time(void);
tcs34725_gain_t get_tcs34725_gain(void); /**********************
* MACROS
**********************/ #ifdef __cplusplus
} /* extern "C" */
#endif #endif /* _TCS34725_H_ */

程序源码

#include "tcs34725.h"
#include "esp32_i2c_drive.h" /***************************************************************
文件名 : tcs34725.c
作者 : jiaozhu
版本 : V1.0
描述 : tcs34725 传感器驱动文件。
其他 : 无
日志 : 初版 V1.0 2022/12/30
***************************************************************/ /* TCS34725设备启动状态 */
static bool tcs34725_state = false; /* 设备默认配置参数 */
struct tcs34725_config _tcs34725_config =
{
.name = "TCS34725",
.interrupt_start = false,
}; /**
* @brief 通过I2C驱动提供的API进行对接,作用是将一个8位数据写入对应的寄存器中
*
* @param reg_addr 寄存机地址
* @param write_data 需要写入的寄存机数据
* @return uint8_t 无错误时返回 0
*/
static uint8_t tcs34725_write8(uint8_t reg_addr, uint8_t write_data)
{
return esp32_i2c_write8(TCS34725_address, TCS34725_COMMAND_BIT | reg_addr, write_data);
} /**
* @brief 通过I2C驱动提供的API进行对接,作用是读取一个8位的数据
*
* @param reg_addr 寄存器地址
* @param read_data 数据存放地址
* @return uint8_t 无错误时返回 0
*/
static uint8_t tcs34725_read8(uint8_t reg_addr, uint8_t* read_data)
{
return esp32_i2c_read8(TCS34725_address, TCS34725_COMMAND_BIT | reg_addr, read_data);
} /**
* @brief 通过I2C驱动提供的API进行对接,作用是读取一个16位的数据
*
* @param reg_addr 寄存器地址
* @param read_data 数据存放地址
* @return uint8_t 无错误时返回 0
*/
static uint8_t tcs34725_read16(uint8_t reg_addr, uint16_t* read_data)
{
return esp32_i2c_read16(TCS34725_address, TCS34725_COMMAND_BIT | reg_addr, read_data);
} /**
* @brief 启动 tcs34725 设备
*
* @param interrupt_start 是否开启中断启动方式
* @return uint8_t 无错误时返回 0
*/
uint8_t tcs34725_start(bool interrupt_start)
{
int err = 0;
if (tcs34725_state)
{
return -1;
} err = tcs34725_write8(TCS34725_ENABLE, TCS34725_ENABLE_PON);
err = tcs34725_write8(TCS34725_ENABLE, TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN); /* 判断是否开启中断启动 */
if (interrupt_start)
{
_tcs34725_config.interrupt_start = interrupt_start;
err = tcs34725_write8(TCS34725_ENABLE, TCS34725_ENABLE_AIEN);
} tcs34725_state = true;
return err;
} /**
* @brief 停止 tcs34725 设备
*
* @return uint8_t 无错误时返回 0
*/
uint8_t tcs34725_stop(void)
{
uint8_t err = 0;
uint8_t data = 0;
err = tcs34725_read8(TCS34725_ENABLE, &data);
err = tcs34725_write8(TCS34725_ENABLE, data & ~(TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN)); /* 通过中断启动后时,需要关闭中断设置 */
if (_tcs34725_config.interrupt_start)
{
err = tcs34725_write8(TCS34725_ENABLE, data & ~TCS34725_ENABLE_AIEN);
} tcs34725_state = false;
return err;
} /**
* @brief 返回设备类型
*
* @return uint8_t 设备识别号 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727
*/
uint8_t get_tcs34725_type(void)
{
uint8_t data = 0;
tcs34725_read8(TCS34725_ID, &data);
return data;
} /**
* @brief 设置集成时间
*
* @param integration_time 集成时间
* @return uint8_t 无错误时返回 0
*/
uint8_t set_tcs34725_integration_time(tcs34725_integration_time_t integration_time)
{
_tcs34725_config.integration_time = integration_time;
return tcs34725_write8(TCS34725_ATIME, integration_time);
} /**
* @brief 获取设置的集成时间
*
* @return tcs34725_integration_time_t
*/
tcs34725_integration_time_t get_tcs34725_integration_time(void)
{
return _tcs34725_config.integration_time;
} /**
* @brief 设置增益倍数
*
* @param gain 增益倍数
* @return uint8_t 无错误时返回 0
*/
uint8_t set_tcs34725_gain(tcs34725_gain_t gain)
{
_tcs34725_config.gain = gain;
return tcs34725_write8(TCS34725_CONTROL, gain);
} /**
* @brief 获取设置的增益倍数
*
* @return tcs34725_gain_t
*/
tcs34725_gain_t get_tcs34725_gain(void)
{
return _tcs34725_config.gain;
} /**
* @brief 获取RGBC的值
*
* @param colour_r 数据存放地址
* @param colour_g 数据存放地址
* @param colour_b 数据存放地址
* @param colour_c 数据存放地址
* @return uint8_t 无错误时返回 0
*/
uint8_t get_tcs34725_rgbc(uint16_t *colour_r, uint16_t *colour_g, uint16_t *colour_b, uint16_t *colour_c)
{
uint8_t err = 0;
err = tcs34725_read16(TCS34725_RDATAL, colour_r);
err = tcs34725_read16(TCS34725_GDATAL, colour_g);
err = tcs34725_read16(TCS34725_BDATAL, colour_b);
err = tcs34725_read16(TCS34725_CDATAL, colour_c);
return err;
}

注意:到此笔记也结束了,上面程序还有不完善的地方,只能自行更改了。当然上面的程序也是可以直接只用的,但是程序只供学习使用,有什么为题概不负责。最后有写得不好的地方,望各位大佬多多指教。

TCS34725 颜色传感器设备驱动程序的更多相关文章

  1. 【情人节选帽子】TCS34725颜色传感器和Python图形界面编程(STM32 HAL库)

    截图 描述: l  STM32 HAL库编程 l  使用模拟IIC通信,方便程序移植 l  Python界面编写,蘑菇头的帽子是什么颜色 l  STM32 HAL库串口通信 l  Python界面使用 ...

  2. 嵌入式Linux设备驱动程序:用户空间中的设备驱动程序

    嵌入式Linux设备驱动程序:用户空间中的设备驱动程序 Embedded Linux device drivers: Device drivers in user space Interfacing ...

  3. LCD设备驱动程序

    LCD是Liquid  Crystal  Display的简称,也就是经常所说的液晶显示器 LCD能够支持彩色图像的显示和视频的播放,是一种非常重要的输出设备 Framebuffer 是Linux系统 ...

  4. linux设备驱动程序--在用户空间注册文件接口

    linux字符设备驱动程序--创建设备节点 基于4.14内核,运行在beagleBone green 在上一讲中,我们写了第一个linux设备驱动程序--hello_world,在驱动程序中,我们什么 ...

  5. linux设备驱动程序--hello-world

    linux字符设备驱动程序--hello_world 基于4.14内核, beagleBone green平台 PC端的设备驱动程序 有过电脑使用经验的人都知道,当我们将外部硬件设备比如鼠标键盘插入到 ...

  6. linux设备驱动程序-i2c(0)-i2c设备驱动源码实现

    (基于4.14内核版本) 为了梳理清楚linux内核中的i2c实现框架,从本文开始,博主将分几个章节分别解析i2c总线在linux内核中的形成过程.匹配过程.以及设备驱动程序源码实现. 在介绍linu ...

  7. linux设备驱动程序--串行通信驱动框架分析

    linux 串行通信接口驱动框架 在学习linux内核驱动时,不论是看linux相关的书籍,又或者是直接看linux的源码,总是能在linux中看到各种各样的框架,linux内核极其庞杂,linux各 ...

  8. 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入

    字符设备驱动程序 应用程序是调用C库中的open read write等函数.而为了操作硬件,所以引入了驱动模块. 构建一个简单的驱动,有一下步骤. 1. 创建file_operations 2. 申 ...

  9. YL-64 颜色传感器

    TCS3200颜色传感器是一款全彩的颜色检测器,包括了一块TAOS TCS3200RGB感应芯片和4个白光LED灯,TCS3200能在一定的范围内检测和测量几乎所有的可见光.它适合于色度计测量应用领域 ...

  10. 装系统提示缺少所需的CD/DVD驱动器设备驱动程序

    昨晚用ultraISO和win7 旗舰版(ultimate)的镜像做了个启动U盘,插在自己新电脑上安装过程中提示“缺少所需的CD/DVD驱动器设备驱动程序”,用网上的很多办法都不行,最后找官网的客服问 ...

随机推荐

  1. SDOI2017树点染色

    题目链接 发现1操作很像lct中的access,然后它每次染的又是一个新颜色,因此同一个颜色就在同一颗splay里了,且一个点到根的权值val[i]也就是到根路径上虚边的个数,然后看access时会对 ...

  2. Vue中使用Switch开关用来控制商品的上架与下架情况、同时根据数据库商品的状态反应到前台、前台修改商品状态保存到数据库

    一般后台对商品的信息管理.包含商品的上架与下架.为了提高用户的体验.将商品上下架的操作做成开关的形式.同时后台数据库中保存的商品状态能够根据开关状态改变. 1.效果展示 这种效果:== 当开关是开启状 ...

  3. SQL分层查询

    数据中可能存在层次关系,本文章主要介绍查询这种关系的实例.会大量使用递归式 CTE. Emps 表中 EName 员工和 MGR 上级之间的关系如下: 每个上级也同样是员工,主管和员工之间为父子关系. ...

  4. 一次 Java log4j2 漏洞导致的生产问题

    一.问题 近期生产在提交了微信小程序审核后(后面会讲到),总会出现一些生产告警,而且持续时间较长.我们查看一些工具和系统相关的,发现把我们的 gateway 差不多打死了. 有一些现象. 网关有很多接 ...

  5. 基于PCIe DMA的8通道视频采集&显示IP,兼容V4L2

    基于PCIe DMA的8通道视频采集&显示IP,兼容V4L2 Video Capture&Display IP for V4L2 在主机端视频设备内核驱动V4L2 的控制和调度下,Vi ...

  6. python中的字符串学习

    # 1.字符串的下标(索引) # 取字符串中的子串 print('1.字符串的下标(索引)') str1 = 'PYTHON' print(str1[0]) print(str1[-4]) # 2.字 ...

  7. Python基础之模块:7、项目开发流程和项目需求分析及软件开发目录

    一.项目开发流程 1.项目需求分析 明确项目具体功能: 明确到底要写什么东西,实现什么功能,在这个阶段的具体要询问项目经理和客户的需求 参与人员: 产品经理.架构师.开发经理 技术人员主要职责: 引导 ...

  8. java学习之socket编程

    0x00前言和思维导图 Socks实际上是什么:实际上是提供了精彩通信的端口,在通信之前双方都必须要创造一个端点才能通信,其实感觉socket跟计算机的三次握手有些相似,分为三个步骤: (1)服务器监 ...

  9. 万字干货_JDK动态代理及其源码解析 拿捏了

    目录 代理模式 静态代理 静态代理和动态代理的区别?什么是静态.动态? 静态代理的使用步骤 示例 静态代理的缺陷 解决静态代理的缺陷的思路 JDK动态代理 JDK 动态代理类使用步骤 示例 底层原理 ...

  10. K8s如何启用cgroup2支持?

    什么是 cgroup ️Reference: control groups(控制组),通常被称为cgroup,是Linux内核的一项功能.它允许将进程组织成分层的组,然后限制和监控各种资源的使用. 内 ...