604|4

224

帖子

4

TA的资源

纯净的硅(初级)

楼主
 

星火一号 - Home Assistant 【RT-Thread】 [复制链接]

 

简介

本DIY项目旨在于集成星火一号上的板载外设到Home Assistant,使其用户可以在手机端或者网页上实时的查看室内的湿度,温度,光照强度和控制灯光等。同时
可以在HA上实现自动化操作。 比如当光照强度大于50Lux的时候自动关闭或者打开灯光。

演示视频 : 点击跳转

主要程序解析

依赖模块

模块名称 说明
RW007 (软件包)提供WIFI连接
AHT10 (软件包)湿度和温度传感器
安信可VC01 离线语音模块,串口输出
Kawali MQTT (软件包)MQTT 客户端,提供基于WIFI的MQTT连接
CJSON (软件包)C语言实现的JSON解析
AP3216C (软件包)提供距离以及光照强度的检测
RT-Thread RTOS

核心文件说明

模块名称 说明
aht_10.c 负责AHT10 湿温度传感器的温度采集(生产者)
mqtt_client.c 负责MQTT的连接和消息的发布和订阅(消费者和生产者)
usart3.c 负责接收和解析VC01的串口数据包 Uart3
wifi_connection.c 负责wifi的连接
drv_matrix_led.c 板载支持包,用于LED矩阵的点亮
ap3216c.c 用于距离和光照强度的检测

实现步骤

1- 创建湿温度和光照强度的消息队列,用于MQTT消费者(发布消息)和 生产者(湿温度和光照强度传感器)的通讯

2- 主线程中,启动WIFI的连接(RW007)

wifi_connection(NULL);

wifi_connection.c

  1. #include "wifi_connection.h"
  2. #include <msh.h>
  3. #define WIFI_SSID "ImmortalWrt" /*WIFI 名称*/
  4. #define WIFI_PASSWORD "mazha1997" /*WIFI 密码*/
  5. void wifi_connection(void *args)
  6. {
  7. char wifi_scan_command[] = "wifi scan";
  8. char wifi_connection_command[] = "wifi join " WIFI_SSID " " WIFI_PASSWORD;
  9. msh_exec(wifi_scan_command, rt_strlen(wifi_scan_command));
  10. msh_exec(wifi_connection_command, rt_strlen(wifi_connection_command));
  11. }

3- 启动串口3的线程,等待VC01发送数据。若收到数据,调用drv_matrix_led.h 的函数,点亮或者熄灭LED灯

uart3_entry_point();

  1. #include <string.h>
  2. #include "usart3.h"
  3. #include "drv_matrix_led.h"
  4. #define SAMPLE_UART_NAME "uart3"
  5. /* 用于接收消息的信号量 */
  6. static struct rt_semaphore rx_sem;
  7. static rt_device_t serial;
  8. /* 接收数据回调函数 */
  9. static rt_err_t uart_input(rt_device_t dev, rt_size_t size) {
  10. rt_sem_release(&rx_sem);
  11. return RT_EOK;
  12. }
  13. static void serial_thread_entry(void *parameter) {
  14. char ch;
  15. while (1) {
  16. /* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */
  17. while (rt_device_read(serial, -1, &ch, 1) != 1) {
  18. /* 阻塞等待接收信号量,等到信号量后再次读取数据 */
  19. rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
  20. }
  21. /* 打印接收到的字节 */
  22. rt_kprintf("Received: %x\n", ch);
  23. /* 读取到的数据通过串口错位输出 */
  24. if (ch == 1) { // 对应 '\001'
  25. turn_on_red_led();
  26. } else if (ch == 2) { // 对应 '\002'
  27. // 蓝色
  28. turn_on_blue_led();
  29. } else if (ch == 3) { // 对应 '\003'
  30. // 绿色
  31. turn_on_green_led();
  32. } else if (ch == 4) { // 对应 '\004'
  33. led_matrix_rst();
  34. } else if (ch == 5) { // 对应 '\005'
  35. // 开启水泵
  36. } else if (ch == 6) { // 对应 '\006'
  37. // 关闭水泵
  38. }
  39. ch = ch + 1;
  40. rt_device_write(serial, 0, &ch, 1);
  41. }
  42. }
  43. int uart3_entry_point() {
  44. rt_err_t ret = RT_EOK;
  45. char uart_name[8] = SAMPLE_UART_NAME;
  46. /* 查找系统中的串口设备 */
  47. serial = rt_device_find(uart_name);
  48. if (!serial) {
  49. rt_kprintf("find %s failed!\n", uart_name);
  50. return RT_ERROR;
  51. }
  52. rt_kprintf("fond %s serial!\n", uart_name);
  53. /* 初始化信号量 */
  54. rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
  55. /* 以中断接收及轮询发送模式打开串口设备 */
  56. rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
  57. /* 设置接收回调函数 */
  58. rt_device_set_rx_indicate(serial, uart_input);
  59. /* 发送字符串 */
  60. /* 创建 serial 线程 */
  61. rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
  62. /* 创建成功则启动线程 */
  63. if (thread != RT_NULL) {
  64. rt_thread_startup(thread);
  65. } else {
  66. ret = RT_ERROR;
  67. }
  68. return ret;
  69. }
  70. MSH_CMD_EXPORT(uart3_entry_point, uart device dma sample);

4- 启动MQTT服务器

ka_mqtt();

  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <rtthread.h>
  4. #include <rtdevice.h>
  5. #include <board.h>
  6. #include "mqttclient.h"
  7. #include <msh.h>
  8. #include "cJSON.h"
  9. #include "drv_matrix_led.h"
  10. #ifndef KAWAII_MQTT_HOST
  11. #define KAWAII_MQTT_HOST "jiejie01.top"
  12. #endif
  13. #ifndef KAWAII_MQTT_PORT
  14. #define KAWAII_MQTT_PORT "1883"
  15. #endif
  16. #ifndef KAWAII_MQTT_CLIENTID
  17. #define KAWAII_MQTT_CLIENTID "rtthread001"
  18. #endif
  19. #ifndef KAWAII_MQTT_USERNAME
  20. #define KAWAII_MQTT_USERNAME "rt-thread"
  21. #endif
  22. #ifndef KAWAII_MQTT_PASSWORD
  23. #define KAWAII_MQTT_PASSWORD "rt-thread"
  24. #endif
  25. #ifndef KAWAII_MQTT_SUBTOPIC
  26. #define KAWAII_MQTT_SUBTOPIC "rtt-sub"
  27. #endif
  28. #ifndef KAWAII_MQTT_PUBTOPIC
  29. #define KAWAII_MQTT_PUBTOPIC "rtt-pub"
  30. #endif
  31. mqtt_client_t *client = NULL;
  32. rt_sem_t sem_mqtt_connection = RT_NULL;
  33. extern rt_mq_t mq;
  34. extern rt_mq_t lux_mq;
  35. extern rt_mq_t rgb_mq;
  36. static void sub_topic_handle1(void *client, message_data_t *msg) {
  37. (void) client;
  38. RGBColor_TypeDef rgb;
  39. rgb.R = 255;
  40. rgb.G = 255;
  41. rgb.B = 255;
  42. cJSON *json = cJSON_Parse(msg->message->payload);
  43. //获取开关状态
  44. cJSON *name = cJSON_GetObjectItem(json, "state");
  45. // 获取 color 对象
  46. cJSON *color = cJSON_GetObjectItem(json, "color");
  47. if (color != NULL) {
  48. // 获取 r, g, b 属性
  49. cJSON *r = cJSON_GetObjectItem(color, "r");
  50. cJSON *g = cJSON_GetObjectItem(color, "g");
  51. cJSON *b = cJSON_GetObjectItem(color, "b");
  52. // 检查 r, g, b 属性是否存在并打印其值
  53. if (r != NULL && cJSON_IsNumber(r)) {
  54. rgb.R = r->valueint;
  55. rt_kprintf("r: %d\n", r->valueint);
  56. } else {
  57. rt_kprintf("The attribute 'r' does not exist or is not a number.\n");
  58. }
  59. if (g != NULL && cJSON_IsNumber(g)) {
  60. rgb.G = g->valueint;
  61. rt_kprintf("g: %d\n", g->valueint);
  62. } else {
  63. rt_kprintf("The attribute 'g' does not exist or is not a number.\n");
  64. }
  65. if (b != NULL && cJSON_IsNumber(b)) {
  66. rgb.B = b->valueint;
  67. rt_kprintf("b: %d\n", b->valueint);
  68. } else {
  69. rt_kprintf("The attribute 'b' does not exist or is not a number.\n");
  70. }
  71. }
  72. cJSON_Delete(json);
  73. turn_on_led(rgb, name->valuestring);
  74. }
  75. static void sub_topic_handle2(void *client, message_data_t *msg) {
  76. (void) client;
  77. KAWAII_MQTT_LOG_I("-----------------------------------------------------------------------------------");
  78. KAWAII_MQTT_LOG_I("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name,
  79. (char *) msg->message->payload);
  80. KAWAII_MQTT_LOG_I("-----------------------------------------------------------------------------------");
  81. }
  82. static void mqtt_connection(void *parameter) {
  83. client = NULL;
  84. rt_thread_delay(6000);
  85. mqtt_log_init();
  86. client = mqtt_lease();
  87. mqtt_set_host(client, KAWAII_MQTT_HOST);
  88. mqtt_set_port(client, KAWAII_MQTT_PORT);
  89. mqtt_set_user_name(client, KAWAII_MQTT_USERNAME);
  90. mqtt_set_password(client, KAWAII_MQTT_PASSWORD);
  91. mqtt_set_client_id(client, KAWAII_MQTT_CLIENTID);
  92. mqtt_set_clean_session(client, 1);
  93. KAWAII_MQTT_LOG_I("The ID of the Kawaii client is: %s \r\n", KAWAII_MQTT_CLIENTID);
  94. int index = mqtt_connect(client);
  95. if (index == KAWAII_MQTT_CONNECT_FAILED_ERROR) {
  96. //尝试重连一次
  97. rt_kprintf("connection failed ! re-connecting.....\r\n");
  98. index = mqtt_connect(client);
  99. if (index == KAWAII_MQTT_CONNECT_FAILED_ERROR) {
  100. char command[] = "reboot";
  101. rt_kprintf("connection failed ! rebooting.....\r\n");
  102. msh_exec(command, rt_strlen(command));
  103. }
  104. }
  105. rt_sem_release(sem_mqtt_connection);
  106. mqtt_subscribe(client, "home/rgb1/set", QOS0, sub_topic_handle1);
  107. mqtt_subscribe(client, "home/bedroom/switch1/set", QOS0, sub_topic_handle2);
  108. }
  109. static void temperature_humidity_publish(void *parameter) {
  110. char payload[PACKAGE_SIZE];
  111. while (1) {
  112. if (rt_mq_recv(mq, &payload, sizeof(payload), 1000) > 0) {
  113. mqtt_message_t msg;
  114. memset(&msg, 0, sizeof(msg));
  115. msg.qos = QOS1;
  116. // msg.payload 直接指向接收到的 payload
  117. msg.payload = (void *) payload;
  118. mqtt_publish(client, "office/sensor1", &msg);
  119. }
  120. }
  121. }
  122. static void lux_publish_task(void *parameter) {
  123. char payload[LUX_PACKAGE_SIZE]; // Buffer to hold the string representation of the receive value
  124. while (1) {
  125. if (rt_mq_recv(lux_mq, &payload, sizeof(payload), 1000) > 0) {
  126. mqtt_message_t msg;
  127. memset(&msg, 0, sizeof(msg));
  128. msg.qos = QOS1;
  129. // msg.payload 直接指向接收到的 payload
  130. msg.payload = (void *) payload;
  131. mqtt_publish(client, "hah", &msg);
  132. }
  133. }
  134. }
  135. int ka_mqtt(void) {
  136. rt_thread_t tid_mqtt, second_publish, lux_publish;
  137. sem_mqtt_connection = rt_sem_create("mqtt_connection", 1, RT_IPC_FLAG_FIFO);
  138. rt_sem_take(sem_mqtt_connection, RT_WAITING_FOREVER);
  139. tid_mqtt = rt_thread_create("mqtt_connection_task", mqtt_connection, RT_NULL, 2048, 17, 10);
  140. if (tid_mqtt == RT_NULL) {
  141. return -RT_ERROR;
  142. }
  143. rt_thread_startup(tid_mqtt);
  144. rt_sem_take(sem_mqtt_connection, RT_WAITING_FOREVER);
  145. second_publish = rt_thread_create("temp_hum_publish_task", temperature_humidity_publish, RT_NULL, 2048, 17, 10);
  146. if (second_publish == RT_NULL) {
  147. return -RT_ERROR;
  148. }
  149. rt_thread_startup(second_publish);
  150. rt_sem_release(sem_mqtt_connection);
  151. lux_publish = rt_thread_create("lux_publish_task", lux_publish_task, RT_NULL, 2048, 17, 10);
  152. if (lux_publish == RT_NULL) {
  153. return -RT_ERROR;
  154. }
  155. rt_thread_startup(lux_publish);
  156. return RT_EOK;
  157. }
  158. MSH_CMD_EXPORT(ka_mqtt, Kawaii MQTT client test program);

5- 启动湿温度Task和 光照强度的Task

启动湿温度Task

rt_thread_t thread = rt_thread_create("aht_10_task", AHT_test_entry, RT_NULL, 2048, 24, 10); rt_thread_startup(thread);

  1. #include "aht_10.h"
  2. #include "mqttclient.h"
  3. //I2C_BUS设备指针,用于等会寻找与记录AHT挂载的I2C总线
  4. struct rt_i2c_bus_device *i2c_bus = RT_NULL;
  5. extern rt_mailbox_t mailbox;
  6. extern rt_mq_t mq;
  7. //AHT命令的空参数
  8. rt_uint8_t Parm_Null[2] = {0, 0};
  9. //写命令(主机向从机传输数据)
  10. rt_err_t write_reg(struct rt_i2c_bus_device *Device, rt_uint8_t reg, rt_uint8_t *data) {
  11. //代写入的数据
  12. //数组大小为3的原因:buf[0]--命令(即上面的AHT_CALIBRATION_CMD、AHT_NORMAL_CMD、AHT_GET_DATA_CMD
  13. // buf[1]/buf[2]为命令后跟的参数,AHT有些命令后面需要加上参数,具体可查看数据手册
  14. rt_uint8_t buf[3];
  15. //记录数组大小
  16. rt_uint8_t buf_size;
  17. //I2C传输的数据结构体
  18. struct rt_i2c_msg msgs;
  19. buf[0] = reg;
  20. if (data != RT_NULL) {
  21. buf[1] = data[0];
  22. buf[2] = data[1];
  23. buf_size = 3;
  24. } else {
  25. buf_size = 1;
  26. }
  27. msgs.addr = AHT_ADDR; //消息要发送的地址:即AHT地址
  28. msgs.flags = RT_I2C_WR; //消息的标志位:读还是写,是否需要忽视ACK回应,是否需要发送停止位,是否需要发送开始位(用于拼接数据使用)...
  29. msgs.buf = buf; //消息的缓冲区:待发送/接收的数组
  30. msgs.len = buf_size; //消息的缓冲区大小:待发送/接收的数组的大小
  31. if (rt_i2c_transfer(Device, &msgs, 1) == 1) {
  32. return RT_EOK;
  33. } else {
  34. return RT_ERROR;
  35. }
  36. }
  37. //读数据(从机向主机返回数据)
  38. rt_err_t read_reg(struct rt_i2c_bus_device *Device, rt_uint8_t len, rt_uint8_t *buf) {
  39. struct rt_i2c_msg msgs;
  40. msgs.addr = AHT_ADDR; //消息要发送的地址:即AHT地址
  41. msgs.flags = RT_I2C_RD; //消息的标志位:读还是写,是否需要忽视ACK回应,是否需要发送停止位,是否需要发送开始位(用于拼接数据使用)...
  42. msgs.buf = buf; //消息的缓冲区:待发送/接收的数组
  43. msgs.len = len; //消息的缓冲区大小:待发送/接收的数组的大小
  44. //传输函数,上面有介绍
  45. if (rt_i2c_transfer(Device, &msgs, 1) == 1) {
  46. return RT_EOK;
  47. } else {
  48. return RT_ERROR;
  49. }
  50. }
  51. //读取AHT的温湿度数据
  52. void read_temp_humi(float *Temp_Data, float *Humi_Data) {
  53. //根据数据手册我们可以看到要读取一次数据需要使用到的数组大小为6
  54. rt_uint8_t Data[6];
  55. write_reg(i2c_bus, AHT_GET_DATA_CMD, Parm_Null); //发送一个读取命令,让AHT进行一次数据采集
  56. rt_thread_mdelay(500); //等待采集
  57. read_reg(i2c_bus, 6, Data); //读取数据
  58. //根据数据手册进行数据处理
  59. *Humi_Data = (Data[1] << 12 | Data[2] << 4 | (Data[3] & 0xf0) >> 4) * 100.0 / (1 << 20);
  60. *Temp_Data = ((Data[3] & 0x0f) << 16 | Data[4] << 8 | Data[5]) * 200.0 / (1 << 20) - 50;
  61. }
  62. //AHT进行初始化
  63. void AHT_Init(const char *name) {
  64. //寻找AHT的总线设备
  65. i2c_bus = rt_i2c_bus_device_find(name);
  66. if (i2c_bus == RT_NULL) {
  67. rt_kprintf("Can't Find I2C_BUS Device"); //找不到总线设备
  68. } else {
  69. write_reg(i2c_bus, AHT_NORMAL_CMD, Parm_Null); //设置为正常工作模式
  70. rt_thread_mdelay(400);
  71. rt_uint8_t Temp[2]; //AHT_CALIBRATION_CMD需要的参数
  72. Temp[0] = 0x08;
  73. Temp[1] = 0x00;
  74. write_reg(i2c_bus, AHT_CALIBRATION_CMD, Temp);
  75. rt_thread_mdelay(400);
  76. }
  77. }
  78. void AHT_test_entry(void *args) {
  79. float humidity, temperature;
  80. char payload[PACKAGE_SIZE];
  81. AHT_Init(AHT_I2C_BUS_NAME); //进行设备初始化
  82. while (1) {
  83. read_temp_humi(&temperature, &humidity); //读取数据
  84. snprintf(payload, sizeof(payload), "{\"humidity\":%.1f,\"temperature\":%.1f}", humidity, temperature);
  85. rt_mq_send(mq, payload, sizeof(payload));
  86. rt_thread_mdelay(1000);
  87. }
  88. }

启动光照传感器

//启动光照传感器 rt_thread_t thread3 = rt_thread_create("lux_task", task_entry, RT_NULL, 2048, 24, 10); rt_thread_startup(thread3);

  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-08-20 Ernest Chen the first version
  9. */
  10. #include "rt-thread/include/rtthread.h"
  11. #include "rt-thread/include/rthw.h"
  12. #include "rtdevice.h"
  13. #include "finsh.h"
  14. #include "stdio.h"
  15. #include <string.h>
  16. #include "ap3216c.h"
  17. #ifdef PKG_USING_AP3216C
  18. #define DBG_ENABLE
  19. #define DBG_SECTION_NAME "ap3216c"
  20. #define DBG_LEVEL DBG_LOG
  21. #define DBG_COLOR
  22. #include "rt-thread/include/rtdbg.h"
  23. //System Register
  24. #define AP3216C_SYS_CONFIGURATION_REG 0x00 //default
  25. #define AP3216C_SYS_INT_STATUS_REG 0x01
  26. #define AP3216C_SYS_INT_CLEAR_MANNER_REG 0x02
  27. #define AP3216C_IR_DATA_L_REG 0x0A
  28. #define AP3216C_IR_DATA_H_REG 0x0B
  29. #define AP3216C_ALS_DATA_L_REG 0x0C
  30. #define AP3216C_ALS_DATA_H_REG 0x0D
  31. #define AP3216C_PS_DATA_L_REG 0x0E
  32. #define AP3216C_PS_DATA_H_REG 0x0F
  33. //ALS Register
  34. #define AP3216C_ALS_CONFIGURATION_REG 0x10 //range 5:4,persist 3:0
  35. #define AP3216C_ALS_CALIBRATION_REG 0x19
  36. #define AP3216C_ALS_THRESHOLD_LOW_L_REG 0x1A //bit 7:0
  37. #define AP3216C_ALS_THRESHOLD_LOW_H_REG 0x1B //bit 15:8
  38. #define AP3216C_ALS_THRESHOLD_HIGH_L_REG 0x1C //bit 7:0
  39. #define AP3216C_ALS_THRESHOLD_HIGH_H_REG 0x1D //bit 15:8
  40. //PS Register
  41. #define AP3216C_PS_CONFIGURATION_REG 0x20
  42. #define AP3216C_PS_LED_DRIVER_REG 0x21
  43. #define AP3216C_PS_INT_FORM_REG 0x22
  44. #define AP3216C_PS_MEAN_TIME_REG 0x23
  45. #define AP3216C_PS_LED_WAITING_TIME_REG 0x24
  46. #define AP3216C_PS_CALIBRATION_L_REG 0x28
  47. #define AP3216C_PS_CALIBRATION_H_REG 0x29
  48. #define AP3216C_PS_THRESHOLD_LOW_L_REG 0x2A //bit 1:0
  49. #define AP3216C_PS_THRESHOLD_LOW_H_REG 0x2B //bit 9:2
  50. #define AP3216C_PS_THRESHOLD_HIGH_L_REG 0x2C //bit 1:0
  51. #define AP3216C_PS_THRESHOLD_HIGH_H_REG 0x2D //bit 9:2
  52. #define AP3216C_ADDR 0x1e /*0x3c=0x1e<<1*/
  53. extern rt_mq_t lux_mq;
  54. static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t data)
  55. {
  56. struct rt_i2c_msg msgs;
  57. rt_uint8_t temp[2];
  58. temp[0] = reg;
  59. temp[1] = data;
  60. msgs.addr = AP3216C_ADDR;
  61. msgs.flags = RT_I2C_WR;
  62. msgs.buf = temp;
  63. msgs.len = 2;
  64. if (rt_i2c_transfer(bus, &msgs, 1) == 1)
  65. {
  66. return RT_EOK;
  67. }
  68. else
  69. {
  70. LOG_E("Writing command error");
  71. return -RT_ERROR;
  72. }
  73. }
  74. static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *buf)
  75. {
  76. struct rt_i2c_msg msgs[2];
  77. msgs[0].addr = AP3216C_ADDR;
  78. msgs[0].flags = RT_I2C_WR;
  79. msgs[0].buf = ®
  80. msgs[0].len = 1;
  81. msgs[1].addr = AP3216C_ADDR;
  82. msgs[1].flags = RT_I2C_RD;
  83. msgs[1].buf = buf;
  84. msgs[1].len = len;
  85. if (rt_i2c_transfer(bus, msgs, 2) == 2)
  86. {
  87. return RT_EOK;
  88. }
  89. else
  90. {
  91. LOG_E("Reading command error");
  92. return -RT_ERROR;
  93. }
  94. }
  95. rt_err_t ap3216c_reset_sensor(ap3216c_device_t dev)
  96. {
  97. if (dev == RT_NULL)
  98. {
  99. return -RT_EINVAL;
  100. }
  101. write_reg(dev->i2c, AP3216C_SYS_CONFIGURATION_REG, AP3216C_MODE_SW_RESET); //reset
  102. rt_thread_mdelay(15); /* need to wait at least 10ms */
  103. return RT_EOK;
  104. }
  105. /**
  106. * This function is convenient to getting data except including high and low data for this sensor.
  107. * note:after reading lower register first,reading higher add one.
  108. */
  109. static rt_uint32_t read_low_and_high(ap3216c_device_t dev, rt_uint8_t reg, rt_uint8_t len)
  110. {
  111. rt_uint32_t data;
  112. rt_uint8_t buf = 0;
  113. read_regs(dev->i2c, reg, len, &buf); //low
  114. data = buf;
  115. read_regs(dev->i2c, reg + 1, len, &buf); //high
  116. data = data + (buf << len * 8);
  117. return data;
  118. }
  119. #ifdef AP3216C_USING_HW_INT
  120. /**
  121. * This function is only used to set threshold without filtering times
  122. *
  123. * @param dev the name of ap3216c device
  124. * @param cmd first register , and other cmd count by it.
  125. * @param threshold threshold and filtering times of als threshold
  126. */
  127. static void set_threshold(ap3216c_device_t dev, ap3216c_cmd_t cmd, ap3216c_threshold_t threshold)
  128. {
  129. ap3216c_set_param(dev, cmd, (threshold.min & 0xff));
  130. ap3216c_set_param(dev, (ap3216c_cmd_t)(cmd + 1), (threshold.min >> 8));
  131. ap3216c_set_param(dev, (ap3216c_cmd_t)(cmd + 2), (threshold.max & 0xff));
  132. ap3216c_set_param(dev, (ap3216c_cmd_t)(cmd + 3), threshold.max >> 8);
  133. }
  134. static void ap3216c_hw_interrupt(void *args)
  135. {
  136. ap3216c_device_t dev = (ap3216c_device_t)args;
  137. if (dev->als_int_cb)
  138. {
  139. dev->als_int_cb(dev->als_int_cb);
  140. }
  141. if (dev->ps_int_cb)
  142. {
  143. dev->ps_int_cb(dev->ps_int_cb);
  144. }
  145. }
  146. static void ap3216c_int_init(ap3216c_device_t dev)
  147. {
  148. RT_ASSERT(dev);
  149. rt_pin_mode(AP3216C_INT_PIN, PIN_MODE_INPUT_PULLUP);
  150. rt_pin_attach_irq(AP3216C_INT_PIN, PIN_IRQ_MODE_FALLING, ap3216c_hw_interrupt, (void *)dev);
  151. rt_pin_irq_enable(AP3216C_INT_PIN, PIN_IRQ_ENABLE);
  152. }
  153. /**
  154. * This function registers als interrupt with callback function
  155. *
  156. * @param dev the name of ap3216c device
  157. * @param enabled enable or disenable als interrupt
  158. * @param threshold threshold and filtering times of als threshold
  159. *
  160. * @param int_cb callback funtion is defined by user.
  161. */
  162. void ap3216c_int_als_cb(ap3216c_device_t dev, rt_bool_t enabled, ap3216c_threshold_t threshold, ap3216c_int_cb int_cb)
  163. {
  164. RT_ASSERT(dev);
  165. if (enabled)
  166. {
  167. dev->als_int_cb = int_cb;
  168. set_threshold(dev, AP3216C_ALS_LOW_THRESHOLD_L, threshold);
  169. }
  170. else
  171. {
  172. dev->als_int_cb = RT_NULL;
  173. }
  174. }
  175. /**
  176. * This function registers ps interrupt with callback function
  177. *
  178. * @param dev the name of ap3216c device
  179. * @param enabled enable or disenable ps interrupt
  180. * @param threshold threshold and filtering times of ps threshold
  181. *
  182. * @param int_cb callback funtion is defined by user.
  183. */
  184. void ap3216c_int_ps_cb(ap3216c_device_t dev, rt_bool_t enabled, ap3216c_threshold_t threshold, ap3216c_int_cb int_cb)
  185. {
  186. RT_ASSERT(dev);
  187. if (enabled)
  188. {
  189. dev->ps_int_cb = int_cb;
  190. set_threshold(dev, AP3216C_PS_LOW_THRESHOLD_L, threshold);
  191. }
  192. else
  193. {
  194. dev->ps_int_cb = RT_NULL;
  195. }
  196. }
  197. #endif /* AP3216C_USING_HW_INT */
  198. /**
  199. * This function initializes ap3216c registered device driver
  200. *
  201. * @param dev the name of ap3216c device
  202. *
  203. * <a href="https://bbs.eeworld.com.cn/home.php?mod=space&uid=784970" target="_blank">@return</a> the ap3216c device.
  204. */
  205. ap3216c_device_t ap3216c_init(const char *i2c_bus_name)
  206. {
  207. ap3216c_device_t dev;
  208. RT_ASSERT(i2c_bus_name);
  209. dev = rt_calloc(1, sizeof(struct ap3216c_device));
  210. if (dev == RT_NULL)
  211. {
  212. LOG_E("Can't allocate memory for ap3216c device on '%s' ", i2c_bus_name);
  213. rt_free(dev);
  214. return RT_NULL;
  215. }
  216. dev->i2c = rt_i2c_bus_device_find(i2c_bus_name);
  217. if (dev->i2c == RT_NULL)
  218. {
  219. LOG_E("Can't find ap3216c device on '%s'", i2c_bus_name);
  220. rt_free(dev);
  221. return RT_NULL;
  222. }
  223. dev->lock = rt_mutex_create("mutex_ap3216c", RT_IPC_FLAG_FIFO);
  224. if (dev->lock == RT_NULL)
  225. {
  226. LOG_E("Can't create mutex for ap3216c device on '%s'", i2c_bus_name);
  227. rt_free(dev);
  228. return RT_NULL;
  229. }
  230. /* reset ap3216c */
  231. ap3216c_reset_sensor(dev);
  232. ap3216c_set_param(dev, AP3216C_SYSTEM_MODE, AP3216C_MODE_ALS_AND_PS);
  233. #ifdef AP3216C_USING_HW_INT
  234. /* init interrupt mode */
  235. ap3216c_int_init(dev);
  236. #endif /* AP3216C_USING_HW_INT */
  237. return dev;
  238. }
  239. /**
  240. * This function releases memory and deletes mutex lock
  241. *
  242. * @param dev the pointer of device driver structure
  243. */
  244. void ap3216c_deinit(ap3216c_device_t dev)
  245. {
  246. RT_ASSERT(dev);
  247. rt_mutex_delete(dev->lock);
  248. rt_free(dev);
  249. }
  250. /**
  251. * This function reads temperature by ap3216c sensor measurement
  252. *
  253. * @param dev the pointer of device driver structure
  254. *
  255. * @return the ambient light converted to float data.
  256. */
  257. float ap3216c_read_ambient_light(ap3216c_device_t dev)
  258. {
  259. float brightness = 0.0; // default error data
  260. rt_err_t result;
  261. rt_uint32_t read_data;
  262. rt_uint8_t temp;
  263. RT_ASSERT(dev);
  264. result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
  265. if (result == RT_EOK)
  266. {
  267. read_data = read_low_and_high(dev, AP3216C_ALS_DATA_L_REG, 1);
  268. ap3216c_get_param(dev, AP3216C_ALS_RANGE, &temp);
  269. if (temp == AP3216C_ALS_RANGE_20661)
  270. {
  271. brightness = 0.35 * read_data; //sensor ambient light converse to reality
  272. }
  273. else if (temp == AP3216C_ALS_RANGE_5162)
  274. {
  275. brightness = 0.0788 * read_data; //sensor ambient light converse to reality
  276. }
  277. else if (temp == AP3216C_ALS_RANGE_1291)
  278. {
  279. brightness = 0.0197 * read_data; //sensor ambient light converse to reality
  280. }
  281. else if (temp == AP3216C_ALS_RANGE_323)
  282. {
  283. brightness = 0.0049 * read_data; //sensor ambient light converse to reality
  284. }
  285. else
  286. {
  287. LOG_E("Failed to get range of ap3216c");
  288. }
  289. }
  290. else
  291. {
  292. LOG_E("Failed to reading ambient light");
  293. }
  294. rt_mutex_release(dev->lock);
  295. return brightness;
  296. }
  297. /**
  298. * This function reads temperature by ap3216c sensor measurement
  299. *
  300. * @param dev the pointer of device driver structure
  301. *
  302. * @return the proximity data.
  303. */
  304. uint16_t ap3216c_read_ps_data(ap3216c_device_t dev)
  305. {
  306. rt_uint16_t proximity = 0;
  307. rt_err_t result;
  308. RT_ASSERT(dev);
  309. result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
  310. if (result == RT_EOK)
  311. {
  312. rt_uint32_t read_data;
  313. read_data = read_low_and_high(dev, AP3216C_PS_DATA_L_REG, 1); //read two data
  314. if (1 == ((read_data >> 6) & 0x01 || (read_data >> 14) & 0x01))
  315. {
  316. LOG_I("The data of PS is invalid for high intensive IR light ");
  317. }
  318. proximity = (read_data & 0x000f) + (((read_data >> 8) & 0x3f) << 4); //sensor proximity converse to reality
  319. }
  320. else
  321. {
  322. LOG_E("Failed to reading ps data ");
  323. }
  324. rt_mutex_release(dev->lock);
  325. return proximity;
  326. }
  327. /**
  328. * This function sets parameter of ap3216c sensor
  329. *
  330. * @param dev the pointer of device driver structure
  331. * @param cmd the parameter cmd of device
  332. * @param value for setting value in cmd register
  333. *
  334. * @return the setting parameter status,RT_EOK reprensents setting successfully.
  335. */
  336. rt_err_t ap3216c_set_param(ap3216c_device_t dev, ap3216c_cmd_t cmd, rt_uint8_t value)
  337. {
  338. RT_ASSERT(dev);
  339. switch (cmd)
  340. {
  341. case AP3216C_SYSTEM_MODE:
  342. {
  343. if (value > AP3216C_MODE_ALS_AND_PS_ONCE)
  344. {
  345. LOG_E("Setting system mode parameter is wrong !");
  346. return -RT_ERROR;
  347. }
  348. /* default 000,power down */
  349. write_reg(dev->i2c, AP3216C_SYS_CONFIGURATION_REG, value);
  350. break;
  351. }
  352. case AP3216C_INT_PARAM:
  353. {
  354. if (value > AP3216C_ALS_CLEAR_MANNER_BY_SOFTWARE)
  355. {
  356. LOG_E("Setting int parameter is wrong !");
  357. return -RT_ERROR;
  358. }
  359. write_reg(dev->i2c, AP3216C_SYS_INT_CLEAR_MANNER_REG, value);
  360. break;
  361. }
  362. case AP3216C_ALS_RANGE:
  363. {
  364. rt_uint8_t args;
  365. if (!(value == AP3216C_ALS_RANGE_20661 || value == AP3216C_ALS_RANGE_5162 || value == AP3216C_ALS_RANGE_1291 || value == AP3216C_ALS_RANGE_323))
  366. {
  367. LOG_E("Setting als dynamic range is wrong, please refer als_range");
  368. return -RT_ERROR;
  369. }
  370. read_regs(dev->i2c, AP3216C_ALS_CONFIGURATION_REG, 1, &args);
  371. args &= 0xcf;
  372. args |= value << 4;
  373. write_reg(dev->i2c, AP3216C_ALS_CONFIGURATION_REG, args);
  374. break;
  375. }
  376. case AP3216C_ALS_PERSIST:
  377. {
  378. rt_uint8_t args = 0;
  379. if (value > 0x0f)
  380. {
  381. LOG_E("Setting als persist overflows ");
  382. return -RT_ERROR;
  383. }
  384. read_regs(dev->i2c, AP3216C_ALS_CONFIGURATION_REG, 1, &args);
  385. args &= 0xf0;
  386. args |= value;
  387. write_reg(dev->i2c, AP3216C_ALS_CONFIGURATION_REG, args);
  388. break;
  389. }
  390. case AP3216C_ALS_LOW_THRESHOLD_L:
  391. {
  392. write_reg(dev->i2c, AP3216C_ALS_THRESHOLD_LOW_L_REG, value);
  393. break;
  394. }
  395. case AP3216C_ALS_LOW_THRESHOLD_H:
  396. {
  397. write_reg(dev->i2c, AP3216C_ALS_THRESHOLD_LOW_H_REG, value);
  398. break;
  399. }
  400. case AP3216C_ALS_HIGH_THRESHOLD_L:
  401. {
  402. write_reg(dev->i2c, AP3216C_ALS_THRESHOLD_HIGH_L_REG, value);
  403. break;
  404. }
  405. case AP3216C_ALS_HIGH_THRESHOLD_H:
  406. {
  407. write_reg(dev->i2c, AP3216C_ALS_THRESHOLD_HIGH_H_REG, value);
  408. break;
  409. }
  410. case AP3216C_PS_GAIN:
  411. {
  412. rt_uint8_t args = 0;
  413. if (value > 0x3)
  414. {
  415. LOG_E("Setting ps again overflows ");
  416. return -RT_ERROR;
  417. }
  418. read_regs(dev->i2c, AP3216C_PS_CONFIGURATION_REG, 1, &args);
  419. args &= 0xf3;
  420. args |= value;
  421. write_reg(dev->i2c, AP3216C_PS_CONFIGURATION_REG, args);
  422. break;
  423. }
  424. case AP3216C_PS_PERSIST:
  425. {
  426. rt_uint8_t args = 0;
  427. if (value > 0x3)
  428. {
  429. LOG_E("Setting ps persist overflows ");
  430. return -RT_ERROR;
  431. }
  432. read_regs(dev->i2c, AP3216C_PS_CONFIGURATION_REG, 1, &args);
  433. args &= 0xfc;
  434. args |= value;
  435. write_reg(dev->i2c, AP3216C_PS_CONFIGURATION_REG, args);
  436. break;
  437. }
  438. case AP3216C_PS_LOW_THRESHOLD_L:
  439. {
  440. if (value > 0x3)
  441. {
  442. LOG_E("Setting ps low threshold of low bit is wrong !");
  443. return -RT_ERROR;
  444. }
  445. write_reg(dev->i2c, AP3216C_PS_THRESHOLD_LOW_L_REG, value);
  446. break;
  447. }
  448. case AP3216C_PS_LOW_THRESHOLD_H:
  449. {
  450. write_reg(dev->i2c, AP3216C_PS_THRESHOLD_LOW_H_REG, value);
  451. break;
  452. }
  453. case AP3216C_PS_HIGH_THRESHOLD_L:
  454. {
  455. if (value > 0x3)
  456. {
  457. LOG_E("Setting ps high threshold of low bit is wrong !");
  458. return -RT_ERROR;
  459. }
  460. write_reg(dev->i2c, AP3216C_PS_THRESHOLD_HIGH_L_REG, value);
  461. break;
  462. }
  463. case AP3216C_PS_HIGH_THRESHOLD_H:
  464. {
  465. write_reg(dev->i2c, AP3216C_PS_THRESHOLD_HIGH_H_REG, value);
  466. break;
  467. }
  468. default:
  469. {
  470. return -RT_ERROR;
  471. }
  472. }
  473. return RT_EOK;
  474. }
  475. /**
  476. * This function gets parameter of ap3216c sensor
  477. *
  478. * @param dev the pointer of device driver structure
  479. * @param cmd the parameter cmd of device
  480. * @param value to get value in cmd register
  481. *
  482. * @return the getting parameter status,RT_EOK reprensents getting successfully.
  483. */
  484. rt_err_t ap3216c_get_param(ap3216c_device_t dev, ap3216c_cmd_t cmd, rt_uint8_t *value)
  485. {
  486. RT_ASSERT(dev);
  487. switch (cmd)
  488. {
  489. case AP3216C_SYSTEM_MODE:
  490. {
  491. read_regs(dev->i2c, AP3216C_SYS_CONFIGURATION_REG, 1, value);
  492. if (*value > AP3216C_MODE_ALS_AND_PS_ONCE)
  493. {
  494. LOG_E("Getting system mode parameter is wrong !");
  495. return -RT_ERROR;
  496. }
  497. break;
  498. }
  499. case AP3216C_INT_PARAM:
  500. {
  501. read_regs(dev->i2c, AP3216C_SYS_INT_CLEAR_MANNER_REG, 1, value);
  502. if (*value > AP3216C_ALS_CLEAR_MANNER_BY_SOFTWARE)
  503. {
  504. LOG_E("Getting int parameter is wrong !");
  505. return -RT_ERROR;
  506. }
  507. break;
  508. }
  509. case AP3216C_ALS_RANGE:
  510. {
  511. rt_uint8_t temp;
  512. read_regs(dev->i2c, AP3216C_ALS_CONFIGURATION_REG, 1, value);
  513. temp = (*value & 0xff) >> 4;
  514. if (!(temp == AP3216C_ALS_RANGE_20661 || temp == AP3216C_ALS_RANGE_5162 || temp == AP3216C_ALS_RANGE_1291 || temp == AP3216C_ALS_RANGE_323))
  515. {
  516. LOG_E("Getting als dynamic range is wrong, please refer als_range");
  517. return -RT_ERROR;
  518. }
  519. *value = temp;
  520. break;
  521. }
  522. case AP3216C_ALS_PERSIST:
  523. {
  524. rt_uint8_t temp;
  525. read_regs(dev->i2c, AP3216C_ALS_CONFIGURATION_REG, 1, value);
  526. temp = *value & 0x0f;
  527. if (temp > 0x0f)
  528. {
  529. LOG_E("Getting als persist is wrong, please refer als_range");
  530. return -RT_ERROR;
  531. }
  532. *value = temp;
  533. break;
  534. }
  535. case AP3216C_ALS_LOW_THRESHOLD_L:
  536. {
  537. read_regs(dev->i2c, AP3216C_ALS_THRESHOLD_LOW_L_REG, 1, value);
  538. break;
  539. }
  540. case AP3216C_ALS_LOW_THRESHOLD_H:
  541. {
  542. read_regs(dev->i2c, AP3216C_ALS_THRESHOLD_LOW_H_REG, 1, value);
  543. break;
  544. }
  545. case AP3216C_ALS_HIGH_THRESHOLD_L:
  546. {
  547. read_regs(dev->i2c, AP3216C_ALS_THRESHOLD_HIGH_L_REG, 1, value);
  548. break;
  549. }
  550. case AP3216C_ALS_HIGH_THRESHOLD_H:
  551. {
  552. read_regs(dev->i2c, AP3216C_ALS_THRESHOLD_HIGH_H_REG, 1, value);
  553. break;
  554. }
  555. case AP3216C_PS_GAIN:
  556. {
  557. rt_uint8_t temp;
  558. read_regs(dev->i2c, AP3216C_PS_CONFIGURATION_REG, 1, &temp);
  559. *value = (temp & 0xc) >> 2;
  560. break;
  561. }
  562. case AP3216C_PS_PERSIST:
  563. {
  564. rt_uint8_t temp;
  565. read_regs(dev->i2c, AP3216C_PS_CONFIGURATION_REG, 1, &temp);
  566. *value = temp & 0x3;
  567. break;
  568. }
  569. case AP3216C_PS_LOW_THRESHOLD_L:
  570. {
  571. read_regs(dev->i2c, AP3216C_PS_THRESHOLD_LOW_L_REG, 1, value);
  572. if ((*value & 0xff) > 0x3)
  573. {
  574. LOG_E("Getting ps low threshold of low bit is wrong !");
  575. return -RT_ERROR;
  576. }
  577. break;
  578. }
  579. case AP3216C_PS_LOW_THRESHOLD_H:
  580. {
  581. read_regs(dev->i2c, AP3216C_PS_THRESHOLD_LOW_H_REG, 1, value);
  582. break;
  583. }
  584. case AP3216C_PS_HIGH_THRESHOLD_L:
  585. {
  586. read_regs(dev->i2c, AP3216C_PS_THRESHOLD_HIGH_L_REG, 1, value);
  587. if ((*value & 0xff) > 3)
  588. {
  589. LOG_E("Getting ps high threshold of low bit is wrong !");
  590. return -RT_ERROR;
  591. }
  592. break;
  593. }
  594. case AP3216C_PS_HIGH_THRESHOLD_H:
  595. {
  596. read_regs(dev->i2c, AP3216C_PS_THRESHOLD_HIGH_H_REG, 1, value);
  597. break;
  598. }
  599. default:
  600. {
  601. return -RT_ERROR;
  602. }
  603. }
  604. return RT_EOK;
  605. }
  606. void ap3216c(int argc, char *argv[])
  607. {
  608. static ap3216c_device_t dev = RT_NULL;
  609. if (argc > 1)
  610. {
  611. if (!strcmp(argv[1], "probe"))
  612. {
  613. if (argc > 2)
  614. {
  615. /* initialize the sensor when first probe */
  616. if (!dev || strcmp(dev->i2c->parent.parent.name, argv[2]))
  617. {
  618. /* deinit the old device */
  619. if (dev)
  620. {
  621. ap3216c_deinit(dev);
  622. }
  623. dev = ap3216c_init(argv[2]);
  624. }
  625. }
  626. else
  627. {
  628. rt_kprintf("ap3216c probe <dev_name> - probe sensor by given name\n");
  629. }
  630. }
  631. else if (!strcmp(argv[1], "read"))
  632. {
  633. if (dev)
  634. {
  635. rt_uint16_t ps_data;
  636. float brightness;
  637. /* read the sensor */
  638. ps_data = ap3216c_read_ps_data(dev);
  639. // if (ps_data == 0)
  640. // {
  641. // rt_kprintf("object is not proximity of sensor \n");
  642. // }
  643. // else
  644. // {
  645. // rt_kprintf("ap3216c read current ps data : %d\n", ps_data);
  646. // }
  647. char payload[LUX_PACKAGE_SIZE];
  648. brightness = ap3216c_read_ambient_light(dev);
  649. // rt_kprintf("ap3216c measure current brightness: %d.%d(lux) \n", (int)brightness, ((int)(10 * brightness) % 10));
  650. snprintf(payload, sizeof(payload), "{\"psData\":%d,\"brightness\":%.1f}", ps_data, brightness);
  651. rt_mq_send(lux_mq,payload ,sizeof(payload));
  652. }
  653. else
  654. {
  655. rt_kprintf("Please using 'ap3216c probe <dev_name>' first\n");
  656. }
  657. }
  658. else
  659. {
  660. rt_kprintf("Unknown command. Please enter 'ap3216c' for help\n");
  661. }
  662. }
  663. else
  664. {
  665. rt_kprintf("Usage:\n");
  666. rt_kprintf("ap3216c probe <dev_name> - probe sensor by given name\n");
  667. rt_kprintf("ap3216c read - read sensor ap3216c data\n");
  668. }
  669. }
  670. void task_entry(void * args)
  671. {
  672. char *argv[] = {
  673. "ap3216c",
  674. "probe",
  675. "i2c2",
  676. NULL
  677. };
  678. char *argv_read[] = {
  679. "ap3216c",
  680. "read",
  681. NULL
  682. };
  683. ap3216c(3, argv);
  684. while(1)
  685. {
  686. ap3216c(2, argv_read);
  687. rt_thread_delay(200);
  688. }
  689. }
  690. MSH_CMD_EXPORT(ap3216c, ap3216c sensor function);
  691. #endif /* PKG_USING_AP3216C */

Home assistant 配置

1- 配置湿温度传感器实体

docker exec -it [容器ID] /bin/bash

使用 vi 编辑 configuration.yaml. 在MQTT的下级节点增加。 如下则为订阅office/sensor1 主题,解析主题消息的temperature 作为温度,解析humidity
作为湿度显示在Home Assistant中

  1. sensor:
  2. - name: "Temperature"
  3. unique_id: temperature
  4. state_topic: "office/sensor1"
  5. suggested_display_precision: 1
  6. unit_of_measurement: "..C"
  7. value_template: "{{ value_json.temperature }}"
  8. - name: "Humidity"
  9. unique_id: humidity
  10. state_topic: "office/sensor1"
  11. unit_of_measurement: "%"
  12. value_template: "{{ value_json.humidity }}"

重载Home assistant 配置

在配置-> 集成 -> 实体。 在实体目录下可以找到,命名为Temperature 和 Humidity

在dashboard中可以按照下图顺序配置对应的湿度和温度实体。(其他添加卡片的方式和这个步骤一致。后面不再赘述)

2 - 配置光照和距离传感器实体

使用 vi 编辑 configuration.yaml. 在MQTT的下级节点的sensor下增加。

  1. - name: "Distance"
  2. unique_id: distance
  3. state_topic: "hah"
  4. suggested_display_precision: 1
  5. unit_of_measurement: "cm"
  6. value_template: "{{ value_json.psData }}"
  7. - name: "Lux"
  8. unique_id: lux
  9. state_topic: "hah"
  10. unit_of_measurement: "Lux"
  11. value_template: "{{ value_json.brightness }}"

3 - 配置RGB灯

使用 vi 编辑 configuration.yaml. 在MQTT的下级节点增加light节点。

  1. light:
  2. - schema: json
  3. unique_id: light
  4. optimistic: true
  5. name: mqtt_json_light_1
  6. state_topic: "home/rgb122"
  7. command_topic: "home/rgb1/set"
  8. brightness: true
  9. supported_color_modes: ["rgb"]

MQTT 配置

MQTT需要新建以下的Topic

1 - home/rgb1/set

2 - hah

3 - office/sensor1

最新回复

请问是怎么处理的各线程之间的通信?初学不太了解这部分   详情 回复 发表于 2024-8-7 19:17
点赞 关注(2)
 

回复
举报

196

帖子

1

TA的资源

一粒金砂(高级)

沙发
 

大佬是怎么分配各线程的的呢

点评

你说的是线程的堆栈还是如何创建线程?  详情 回复 发表于 2024-8-7 16:00
 
个人签名

没用比没有强

 
 

回复

224

帖子

4

TA的资源

纯净的硅(初级)

板凳
 
电子烂人 发表于 2024-8-7 13:24 大佬是怎么分配各线程的的呢

你说的是线程的堆栈还是如何创建线程?

点评

请问是怎么处理的各线程之间的通信?初学不太了解这部分  详情 回复 发表于 2024-8-7 19:17
 
 
 

回复

196

帖子

1

TA的资源

一粒金砂(高级)

4
 
御坂10032号 发表于 2024-8-7 16:00 你说的是线程的堆栈还是如何创建线程?

请问是怎么处理的各线程之间的通信?初学不太了解这部分

点评

用的消息队列。 因为邮箱只能处理32bIts的  详情 回复 发表于 2024-8-8 01:56
 
个人签名

没用比没有强

 
 

回复

224

帖子

4

TA的资源

纯净的硅(初级)

5
 
电子烂人 发表于 2024-8-7 19:17 请问是怎么处理的各线程之间的通信?初学不太了解这部分

用的消息队列。 因为邮箱只能处理32bIts的

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
未来计算机与计算机技术

未来计算机与计算机技术 计算机的关键技术继续发展,未来的计算机技术将向超高速、超小型、平行处理、智能化的方向发展。尽 ...

【献给初学者】一些关于DSP的问题和解答之系列(一)

一、时钟和电源问: DSP的电源设计和时钟设计应该特别注意哪些方面?外接晶振选用有源的好还是无源的好? 答:时钟一般使用晶 ...

Piccolo TMS320F28027PTT-48Pin评估板

acai1123赠送的Piccolo TMS320F28027PTT-48Pin评估板,谢谢acai1123,谢谢eeworld。 用摄像头拍了一下,效果不好,但是用 ...

表羡慕ArduinoNano啦,动手做LaunchPad Nano吧!

刚做完,不早了所以跳过吐槽、灌水、骗稿费的部分(稿费……汗),直接进入正题。 在羡慕ArduinoNano的小巧?MSP430也可以Nan ...

下载有好礼!罗姆带您学习电源设计应用小技巧

与传统的硅器件相比,碳化硅(SiC)器件由于拥有低导通电阻特性以及出色的高温、高频和高压性能,已经成为下一代低损耗半导体可 ...

今天520,作为理工科的男生,你们是如何给另一半惊喜的?

一年一度的表白日又来了,不管是对爱人、亲人、朋友还是同事,总有你今天相对他表达自己心里最想说的。作为理工科的你们,你们是 ...

仿真AWR学习网站

596235 细致到PCB与cadence

[HPM-DIY]littlevgl benchmark比分? 先楫hpm6750 or 意法stm32h747 winer?

本帖最后由 RCSN 于 2022-8-6 15:55 编辑 对比数据这种,其实也没啥必要,但是趋于好奇心,也搞个对比数据看看,需要说明的 ...

【得捷Follow me第3期】使用Xiao开发板给他过一个难忘的生日

本帖最后由 大波丁 于 2023-12-17 21:58 编辑 有幸入围本次的【Follow Me第三期】活动,从得捷DigiKey采购了以下物料: ...

家电补贴大家享受没?

本帖最后由 freebsder 于 2024-11-25 18:00 编辑 这波家电补贴蛮划得来,亲身体验。 周末给媳妇买了个笔记本,asus的1 ...

关闭
站长推荐上一条 1/10 下一条
有奖探索 | 和村田一起,深挖 GNSS 开发!
活动时间:即日起-5月11日
活动奖励:智能手环、螺丝刀套装、双肩包

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 14

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表