活动介绍

typedef struct { uint8_t id; float temp; uint8_t humi; }TempHumiSensor;

时间: 2023-08-12 12:59:13 浏览: 161
这是一个C语言中的结构体定义,名为`TempHumiSensor`,包含三个成员变量: - `id`:无符号8位整数类型(`uint8_t`),用于存储传感器的ID。 - `temp`:浮点数类型(`float`),用于存储温度值。 - `humi`:无符号8位整数类型(`uint8_t`),用于存储湿度值。 通过定义这个结构体,你可以创建`TempHumiSensor`类型的变量,并使用它们来存储传感器的相关数据。例如: ```c TempHumiSensor sensor1; sensor1.id = 1; sensor1.temp = 25.5; sensor1.humi = 60; ``` 这样,你就可以通过`sensor1.id`、`sensor1.temp`和`sensor1.humi`来访问和操作结构体中的数据。
相关问题

typedef struct _packed { uint8_t id; float temp; uint8_t humi; }TempHumiSensor;

这段代码定义了一个名为TempHumiSensor的结构体,并使用typedef关键字为其创建了一个别名。 TempHumiSensor结构体包含了三个成员变量: - id:一个无符号8位整数,用于存储传感器的ID。 - temp:一个浮点数,用于存储温度值。 - humi:一个无符号8位整数,用于存储湿度值。 使用_packed修饰符对结构体进行了紧凑布局,以减少内存的使用。这在某些嵌入式系统中非常有用,可以节省内存空间。 通过typedef关键字,该结构体被命名为TempHumiSensor,并可以直接使用TempHumiSensor作为类型声明,而不需要每次都写完整的结构体名。这样做可以简化代码,提高可读性。

typedef _packed struct { uint8_t id; float temp; uint8_t humi; }TempHumiSensor;

这段代码定义了一个名为TempHumiSensor的结构体,并使用typedef关键字为其创建了一个别名。 TempHumiSensor结构体包含了三个成员变量: - id:一个无符号8位整数,用于存储传感器的ID。 - temp:一个浮点数,用于存储温度值。 - humi:一个无符号8位整数,用于存储湿度值。 使用_packed修饰符对结构体进行了紧凑布局,以减少内存的使用。这在某些嵌入式系统中非常有用,可以节省内存空间。 通过typedef关键字,该结构体被命名为TempHumiSensor,并可以直接使用TempHumiSensor作为类型声明,而不需要每次都写完整的结构体名。这样做可以简化代码,提高可读性。
阅读全文

相关推荐

#include "stm32f10x.h" // Device header #include "Delay.h" #include "DHT11.h" void DHT11_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(DHT11_Out_RCC, ENABLE); GPIO_InitStructure.GPIO_Pin = DHT11_Out_Pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11, &GPIO_InitStructure); GPIO_SetBits(DHT11, DHT11_Out_Pin); } static void DHT11_Mode_IPU(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_Out_Pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; GPIO_Init(DHT11, &GPIO_InitStructure); } static void DHT11_Mode_Out_PP(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_Out_Pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11, &GPIO_InitStructure); } static uint8_t Read_Byte(void) { uint8_t i, temp=0; for (i=0; i<8; i++) { while (DHT11_DATA_IN() == Bit_RESET); Delay_us(40); if (DHT11_DATA_IN() == Bit_SET) { while(DHT11_DATA_IN() == Bit_SET); temp |= (uint8_t)(0x01 << (7 - i)); } else { temp &= (uint8_t) ~ (0x01<<(7-i)); } } return temp; } uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data) { DHT11_Mode_Out_PP(); DHT11_DATA_OUT(LOW); Delay_ms(18); DHT11_DATA_OUT(HIGH); Delay_us(30); DHT11_Mode_IPU(); if(DHT11_DATA_IN() == Bit_RESET) { while(DHT11_DATA_IN() == Bit_RESET); while(DHT11_DATA_IN() == Bit_SET); DHT11_Data -> humi_int = Read_Byte(); DHT11_Data -> humi_deci = Read_Byte(); DHT11_Data -> temp_int = Read_Byte(); DHT11_Data -> temp_deci = Read_Byte(); DHT11_Data -> check_sum= Read_Byte(); DHT11_Mode_Out_PP(); DHT11_DATA_OUT(HIGH); if (DHT11_Data -> check_sum == DHT11_Data -> humi_int + DHT11_Data -> humi_deci + DHT11_Data -> temp_int + DHT11_Data -> temp_deci) return SUCCESS; else return ERROR; } else { return ERROR; } }uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data)详细解释这个函数

#include "stm32f10x.h" // Device header #include "Delay.h" #include "DHT11.h" void DHT11_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(DHT11_Out_RCC, ENABLE); GPIO_InitStructure.GPIO_Pin = DHT11_Out_Pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11, &GPIO_InitStructure); GPIO_SetBits(DHT11, DHT11_Out_Pin); } static void DHT11_Mode_IPU(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_Out_Pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; GPIO_Init(DHT11, &GPIO_InitStructure); } static void DHT11_Mode_Out_PP(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_Out_Pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11, &GPIO_InitStructure); } static uint8_t Read_Byte(void) { uint8_t i, temp=0; for (i=0; i<8; i++) { while (DHT11_DATA_IN() == Bit_RESET); Delay_us(40); if (DHT11_DATA_IN() == Bit_SET) { while(DHT11_DATA_IN() == Bit_SET); temp |= (uint8_t)(0x01 << (7 - i)); } else { temp &= (uint8_t) ~ (0x01<<(7-i)); } } return temp; } uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data) { DHT11_Mode_Out_PP(); DHT11_DATA_OUT(LOW); Delay_ms(18); DHT11_DATA_OUT(HIGH); Delay_us(30); DHT11_Mode_IPU(); if(DHT11_DATA_IN() == Bit_RESET) { while(DHT11_DATA_IN() == Bit_RESET); while(DHT11_DATA_IN() == Bit_SET); DHT11_Data -> humi_int = Read_Byte(); DHT11_Data -> humi_deci = Read_Byte(); DHT11_Data -> temp_int = Read_Byte(); DHT11_Data -> temp_deci = Read_Byte(); DHT11_Data -> check_sum= Read_Byte(); DHT11_Mode_Out_PP(); DHT11_DATA_OUT(HIGH); if (DHT11_Data -> check_sum == DHT11_Data -> humi_int + DHT11_Data -> humi_deci + DHT11_Data -> temp_int + DHT11_Data -> temp_deci) return SUCCESS; else return ERROR; } else { return ERROR; } }->是什么意思

#include <stdio.h> #include <string.h> #include <math.h> #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "freertos/semphr.h" #include "driver/rmt_tx.h" #include "led_ws2812.h" #include "driver/gpio.h" #include "driver/adc.h" #include "driver/i2c.h" #include "nvs_flash.h" #include "mqtt_client.h" #include "simple_wifi_sta.h" // 网络配置 #define MQTT_ADDRESS "114.55.64.216" // MQTT连接地址 #define MQTT_PORT 1863 // MQTT连接端口号 #define MQTT_CLIENT "soil_0001" // Client ID #define MQTT_USERNAME "devname" // MQTT用户名 #define MQTT_PASSWORD "devpwd" // MQTT密码 #define MQTT_PUBLIC_TOPIC "/gws/soil_0001" // 推送消息主题 #define MQTT_SUBSCRIBE_TOPIC "/gws/soil_0001" // 订阅主题 // 定义事件组,用于通知WIFI连接成功 #define WIFI_CONNECT_BIT BIT0 static EventGroupHandle_t s_wifi_ev = NULL; // MQTT客户端操作句柄 static esp_mqtt_client_handle_t s_mqtt_client = NULL; // MQTT连接标志 static bool s_is_mqtt_connected = false; // 灯带配置 #define WS2812_GPIO_NUM GPIO_NUM_45 #define WS2812_LED_NUM 6 TaskHandle_t RgbTaskHandle = NULL; // 添加RGB任务控制事件组 static EventGroupHandle_t rgb_event_group; #define RGB_RUN_BIT BIT0 // RGB任务运行标志位 // 雷达配置 #define LED_GPIO GPIO_NUM_16 #define LEIDA_GPIO GPIO_NUM_4 TaskHandle_t RadarTaskHandle = NULL; // ADC配置 #define ADC_GPIO GPIO_NUM_8 // IO8对应ADC1通道7 #define ADC_CHANNEL ADC1_CHANNEL_7 TaskHandle_t AdcTaskHandle = NULL; // I2C参数配置 #define I2C_MASTER_SCL_IO 2 // SCL引脚 #define I2C_MASTER_SDA_IO 1 // SDA引脚 #define I2C_MASTER_NUM I2C_NUM_0 // I2C控制器编号 #define I2C_MASTER_FREQ_HZ 100000 // I2C频率100kHz #define I2C_MASTER_TX_BUF_DISABLE 0 // 禁用发送缓冲区 #define I2C_MASTER_RX_BUF_DISABLE 0 // 禁用接收缓冲区 TaskHandle_t IicTaskHandle = NULL; // 传感器地址 #define BH1750_ADDR 0x23 // BH1750地址 #define SHT20_ADDR 0x40 // SHT20温湿度传感器地址 #define BMP280_ADDR 0x76 // BMP280 I2C地址 // BH1750寄存器定义 #define BH1750_POWER_DOWN 0x00 #define BH1750_POWER_ON 0x01 #define BH1750_RESET 0x07 #define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // SHT20寄存器定义 #define SHT20_TRIGGER_TEMP_MEASUREMENT 0xF3 #define SHT20_TRIGGER_HUMIDITY_MEASUREMENT 0xF5 #define SHT20_SOFT_RESET 0xFE // BMP280相关定义 #define BMP280_REG_ID 0xD0 #define BMP280_REG_RESET 0xE0 #define BMP280_REG_STATUS 0xF3 #define BMP280_REG_CTRL_MEAS 0xF4 #define BMP280_REG_CONFIG 0xF5 #define BMP280_REG_PRESS_MSB 0xF7 #define BMP280_REG_TEMP_MSB 0xFA #define BMP280_REG_CALIB 0x88 // BMP280校准参数结构体 typedef struct { uint16_t dig_T1; int16_t dig_T2; int16_t dig_T3; uint16_t dig_P1; int16_t dig_P2; int16_t dig_P3; int16_t dig_P4; int16_t dig_P5; int16_t dig_P6; int16_t dig_P7; int16_t dig_P8; int16_t dig_P9; } bmp280_calib_t; // 传感器数据结构体(全局共享) typedef struct { float temp; // 温度(°C) float humi; // 湿度(%) float press; // 气压(Pa) float lux; // 光照(lx) float adc_voltage;// ADC电压(V) float adc_resist; // 土壤电阻(Ω) } sensor_data_t; // 全局传感器数据及互斥锁 static sensor_data_t g_sensor_data = { 0 }; static SemaphoreHandle_t g_sensor_mutex; static const char* TAG = "main"; static const char* TAG2 = "adc_radar"; static const char* TAG_ADC = "adc"; static const char* TAG_I2C = "I2C_Sensors"; /** * mqtt连接事件处理函数 */ static void aliot_mqtt_event_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { esp_mqtt_event_handle_t event = event_data; esp_mqtt_client_handle_t client = event->client; switch ((esp_mqtt_event_id_t)event_id) { case MQTT_EVENT_CONNECTED: // 连接成功 ESP_LOGI(TAG, "mqtt connected"); s_is_mqtt_connected = true; // 连接成功后订阅主题 esp_mqtt_client_subscribe_single(s_mqtt_client, MQTT_SUBSCRIBE_TOPIC, 1); break; case MQTT_EVENT_DISCONNECTED: // 连接断开 ESP_LOGI(TAG, "mqtt disconnected"); s_is_mqtt_connected = false; break; case MQTT_EVENT_SUBSCRIBED: // 收到订阅ACK ESP_LOGI(TAG, "mqtt subscribed ack, msg_id=%d", event->msg_id); break; case MQTT_EVENT_DATA: // 收到订阅消息 printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); printf("DATA=%.*s\r\n", event->data_len, event->data); break; case MQTT_EVENT_ERROR: ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); break; default: break; } } /** 启动mqtt连接 */ void mqtt_start(void) { esp_mqtt_client_config_t mqtt_cfg = { 0 }; mqtt_cfg.broker.address.transport = MQTT_TRANSPORT_OVER_TCP; mqtt_cfg.broker.address.hostname = MQTT_ADDRESS; mqtt_cfg.broker.address.port = MQTT_PORT; mqtt_cfg.credentials.client_id = MQTT_CLIENT; mqtt_cfg.credentials.username = MQTT_USERNAME; mqtt_cfg.credentials.authentication.password = MQTT_PASSWORD; ESP_LOGI(TAG, "mqtt connect->clientId:%s,username:%s", mqtt_cfg.credentials.client_id, mqtt_cfg.credentials.username); s_mqtt_client = esp_mqtt_client_init(&mqtt_cfg); esp_mqtt_client_register_event(s_mqtt_client, ESP_EVENT_ANY_ID, aliot_mqtt_event_handler, s_mqtt_client); esp_mqtt_client_start(s_mqtt_client); } /** wifi事件通知 */ void wifi_event_handler(WIFI_EV_e ev) { if (ev == WIFI_CONNECTED) { xEventGroupSetBits(s_wifi_ev, WIFI_CONNECT_BIT); } } /** I2C主控制器初始化 */ static esp_err_t i2c_master_init(void) { i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .scl_io_num = I2C_MASTER_SCL_IO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = I2C_MASTER_FREQ_HZ, }; ESP_ERROR_CHECK(i2c_param_config(I2C_MASTER_NUM, &conf)); return i2c_driver_install(I2C_MASTER_NUM, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); } /** 初始化BH1750环境光传感器 */ bool bh1750_init(void) { ESP_LOGI(TAG_I2C, "Initializing BH1750..."); // 软复位 i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BH1750_ADDR << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, BH1750_RESET, true); i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK) { ESP_LOGE(TAG_I2C, "BH1750 reset failed: 0x%x", ret); return false; } vTaskDelay(pdMS_TO_TICKS(10)); // 启动连续高分辨率模式 cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BH1750_ADDR << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, BH1750_CONTINUOUS_HIGH_RES_MODE, true); i2c_master_stop(cmd); ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK) { ESP_LOGE(TAG_I2C, "BH1750 mode set failed: 0x%x", ret); return false; } ESP_LOGI(TAG_I2C, "BH1750 initialized successfully"); return true; } /** 读取BH1750环境光强度 */ float bh1750_read_light(void) { uint8_t data[2] = { 0 }; i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BH1750_ADDR << 1) | I2C_MASTER_READ, true); i2c_master_read_byte(cmd, &data[0], I2C_MASTER_ACK); i2c_master_read_byte(cmd, &data[1], I2C_MASTER_NACK); i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK) { ESP_LOGE(TAG_I2C, "BH1750 read failed: 0x%x", ret); return -1; } // 计算光照强度(lx) uint16_t light = (data[0] << 8) | data[1]; return light / 1.2; // 根据数据手册计算 } /** 初始化SHT20温湿度传感器 */ bool sht20_init(void) { ESP_LOGI(TAG_I2C, "Initializing SHT20..."); // 软复位 i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (SHT20_ADDR << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, SHT20_SOFT_RESET, true); i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK) { ESP_LOGE(TAG_I2C, "SHT20 reset failed: 0x%x", ret); return false; } vTaskDelay(pdMS_TO_TICKS(15)); // 等待复位完成 ESP_LOGI(TAG_I2C, "SHT20 initialized successfully"); return true; } /** 读取SHT20测量值 */ static bool sht20_read_measurement(uint8_t command, float* value, bool is_temperature) { // 发送测量命令 i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (SHT20_ADDR << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, command, true); i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK) { ESP_LOGE(TAG_I2C, "SHT20 measurement trigger failed: 0x%x", ret); return false; } // 等待测量完成(温度100ms,湿度40ms) vTaskDelay(pdMS_TO_TICKS(is_temperature ? 100 : 40)); // 读取测量结果(3字节:MSB, LSB, CRC) uint8_t data[3] = { 0 }; cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (SHT20_ADDR << 1) | I2C_MASTER_READ, true); i2c_master_read_byte(cmd, &data[0], I2C_MASTER_ACK); i2c_master_read_byte(cmd, &data[1], I2C_MASTER_ACK); i2c_master_read_byte(cmd, &data[2], I2C_MASTER_NACK); i2c_master_stop(cmd); ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK) { ESP_LOGE(TAG_I2C, "SHT20 read failed: 0x%x", ret); return false; } // 提取原始值(清除状态位) uint16_t raw_value = (data[0] << 8) | data[1]; raw_value &= 0xFFFC; // 清除最后两位状态位 // 计算实际值 if (is_temperature) { *value = -46.85 + (175.72 * raw_value) / 65536.0; } else { *value = -6.0 + (125.0 * raw_value) / 65536.0; } return true; } /** 读取SHT20温度 */ float sht20_read_temperature(void) { float temperature = 0.0; if (!sht20_read_measurement(SHT20_TRIGGER_TEMP_MEASUREMENT, &temperature, true)) { ESP_LOGE(TAG_I2C, "Failed to read SHT20 temperature"); return -1; } return temperature; } /** 读取SHT20湿度 */ float sht20_read_humidity(void) { float humidity = 0.0; if (!sht20_read_measurement(SHT20_TRIGGER_HUMIDITY_MEASUREMENT, &humidity, false)) { ESP_LOGE(TAG_I2C, "Failed to read SHT20 humidity"); return -1; } return humidity; } /** 初始化BMP280气压传感器 */ bool bmp280_init(bmp280_calib_t* calib) { ESP_LOGI(TAG_I2C, "Initializing BMP280..."); // 重置设备 i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BMP280_ADDR << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, BMP280_REG_RESET, true); i2c_master_write_byte(cmd, 0xB6, true); // 复位值 i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK) { ESP_LOGE(TAG_I2C, "BMP280 reset failed: 0x%x", ret); return false; } vTaskDelay(pdMS_TO_TICKS(10)); // 等待复位完成 // 检查设备ID uint8_t id = 0; cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BMP280_ADDR << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, BMP280_REG_ID, true); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BMP280_ADDR << 1) | I2C_MASTER_READ, true); i2c_master_read_byte(cmd, &id, I2C_MASTER_NACK); i2c_master_stop(cmd); ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK || id != 0x58) { // BMP280 ID为0x58 ESP_LOGE(TAG_I2C, "BMP280 ID check failed: 0x%02X", id); return false; } // 读取校准参数 uint8_t calib_data[24] = { 0 }; cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BMP280_ADDR << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, BMP280_REG_CALIB, true); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BMP280_ADDR << 1) | I2C_MASTER_READ, true); i2c_master_read(cmd, calib_data, sizeof(calib_data), I2C_MASTER_LAST_NACK); i2c_master_stop(cmd); ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK) { ESP_LOGE(TAG_I2C, "BMP280 calibration read failed: 0x%x", ret); return false; } // 解析校准参数 calib->dig_T1 = (calib_data[1] << 8) | calib_data[0]; calib->dig_T2 = (calib_data[3] << 8) | calib_data[2]; calib->dig_T3 = (calib_data[5] << 8) | calib_data[4]; calib->dig_P1 = (calib_data[7] << 8) | calib_data[6]; calib->dig_P2 = (calib_data[9] << 8) | calib_data[8]; calib->dig_P3 = (calib_data[11] << 8) | calib_data[10]; calib->dig_P4 = (calib_data[13] << 8) | calib_data[12]; calib->dig_P5 = (calib_data[15] << 8) | calib_data[14]; calib->dig_P6 = (calib_data[17] << 8) | calib_data[16]; calib->dig_P7 = (calib_data[19] << 8) | calib_data[18]; calib->dig_P8 = (calib_data[21] << 8) | calib_data[20]; calib->dig_P9 = (calib_data[23] << 8) | calib_data[22]; // 配置传感器 (温度x2 + 气压x16,正常模式) cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BMP280_ADDR << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, BMP280_REG_CTRL_MEAS, true); i2c_master_write_byte(cmd, 0b10110111, true); // 温度x2,气压x16,正常模式 i2c_master_stop(cmd); ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK) { ESP_LOGE(TAG_I2C, "BMP280 config failed: 0x%x", ret); return false; } ESP_LOGI(TAG_I2C, "BMP280 initialized successfully"); return true; } /** 读取BMP280温度和气压原始值 */ static bool bmp280_read_raw(int32_t* temp_raw, int32_t* press_raw) { uint8_t data[6] = { 0 }; i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BMP280_ADDR << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, BMP280_REG_PRESS_MSB, true); i2c_master_start(cmd); i2c_master_write_byte(cmd, (BMP280_ADDR << 1) | I2C_MASTER_READ, true); i2c_master_read(cmd, data, sizeof(data), I2C_MASTER_LAST_NACK); i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(100)); i2c_cmd_link_delete(cmd); if (ret != ESP_OK) { ESP_LOGE(TAG_I2C, "BMP280 read raw failed: 0x%x", ret); return false; } *press_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4); *temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4); return true; } /** 计算实际温度和气压值 */ static void bmp280_compensate(const bmp280_calib_t* calib, int32_t adc_T, int32_t adc_P, float* temperature, float* pressure) { // 补偿温度 int32_t var1, var2, T; var1 = (((double)adc_T) / 16384.0 - ((double)calib->dig_T1) / 1024.0) * ((double)calib->dig_T2); var2 = (((double)adc_T) / 131072.0 - ((double)calib->dig_T1) / 8192.0) * (((double)adc_T) / 131072.0 - ((double)calib->dig_T1) / 8192.0) * ((double)calib->dig_T3); int32_t t_fine = (int32_t)(var1 + var2); T = (var1 + var2) / 5120.0; // 温度补偿值 *temperature = (float)T * 100; // 单位:°C // 补偿气压 int64_t p, var3, var4; var1 = ((double)t_fine / 2.0) - 64000.0; var2 = var1 * var1 * (double)calib->dig_P6 / 32768.0; var2 = var2 + ((var1 * (double)calib->dig_P5) * 2.0); var2 = (var2 / 4.0) + (((double)calib->dig_P4) * 65536.0); var1 = (((double)calib->dig_P3) * var1 * var1 / 524288.0 + ((double)calib->dig_P2) * var1) / 524288.0; var1 = (1.0 + var1 / 32768.0) * ((double)calib->dig_P1); p = 1048576 - (double)adc_P; p = (p - (var2 / 4096.0)) * 6250.0 / var1; var1 = ((double)calib->dig_P9) * p * p / 2147483648.0; var2 = p * ((double)calib->dig_P8) / 32768.0; p = p + (var1 + var2 + ((double)calib->dig_P7)) / 16.0; *pressure = (float)p; // 单位:Pa } /** 读取BMP280温度和气压 */ bool bmp280_read(const bmp280_calib_t* calib, float* temperature, float* pressure) { int32_t temp_raw, press_raw; if (!bmp280_read_raw(&temp_raw, &press_raw)) { return false; } bmp280_compensate(calib, temp_raw, press_raw, temperature, pressure); *temperature /= 100.0; // 转换为°C return true; } /** I2C传感器任务(处理BH1750、SHT20和BMP280) */ void task_i2c_sensors(void* pvParameters) { // 初始化I2C ESP_ERROR_CHECK(i2c_master_init()); // 初始化传感器 bool bh1750_initialized = bh1750_init(); bool sht20_initialized = sht20_init(); bmp280_calib_t bmp280_calib; bool bmp280_initialized = bmp280_init(&bmp280_calib); vTaskDelay(pdMS_TO_TICKS(150)); // 等待传感器初始化完成 while (1) { // 读取传感器数据 float temp = -1, humi = -1, press = -1, lux = -1; float bmp_temp = -1; if (sht20_initialized) { temp = sht20_read_temperature(); humi = sht20_read_humidity(); } if (bmp280_initialized) { if (bmp280_read(&bmp280_calib, &bmp_temp, &press) && temp < 0) { temp = bmp_temp; // 若SHT20温度读取失败,使用BMP280温度 } } if (bh1750_initialized) { lux = bh1750_read_light(); } // 打印传感器数据 ESP_LOGI(TAG_I2C, "Temp: %.2f°C, Humi: %.2f%%, Press: %.2fPa, Lux: %.2flx, bmp280_temp: %.2f°C", temp, humi, press, lux, bmp_temp); // 更新全局传感器数据(加锁保护) if (xSemaphoreTake(g_sensor_mutex, pdMS_TO_TICKS(100)) == pdTRUE) { g_sensor_data.temp = temp; g_sensor_data.humi = humi; g_sensor_data.press = press; g_sensor_data.lux = lux; xSemaphoreGive(g_sensor_mutex); } // 读取间隔 vTaskDelay(pdMS_TO_TICKS(1500)); } } /** 全局亮度控制变量 */ float global_brightness = 0.2f; // 默认亮度为50% /** * 设置全局亮度 * @param brightness 亮度值 (0.0-1.0) */ void set_global_brightness(float brightness) { // 限制亮度范围 if (brightness < 0.0f) brightness = 0.0f; if (brightness > 1.0f) brightness = 1.0f; global_brightness = brightness; ESP_LOGI(TAG, "Brightness set to: %.2f", global_brightness); } /** * HSV转RGB颜色空间并调整亮度 * @param h 色相 (0.0-360.0) * @param s 饱和度 (0.0-1.0) * @param v 明度 (0.0-1.0) * @param brightness 亮度调整因子 (0.0-1.0) * @param r 输出红色值 (0-255) * @param g 输出绿色值 (0-255) * @param b 输出蓝色值 (0-255) */ void hsv_to_rgb(float h, float s, float v, float brightness, uint8_t *r, uint8_t *g, uint8_t *b) { int i; float f, p, q, t; // 应用亮度调整(使用非线性曲线增强暗部细节) v *= brightness * brightness; // 平方曲线使暗部更细腻 if (s == 0) { // 无饱和度(灰色) *r = *g = *b = (uint8_t)(v * 255); return; } h /= 60.0f; // 转换为0-6范围 i = (int)floor(h) % 6; f = h - floor(h); // 小数部分 p = v * (1 - s); q = v * (1 - s * f); t = v * (1 - s * (1 - f)); // 使用更精确的浮点数计算和舍入 switch (i) { case 0: *r = (uint8_t)(v*255.0f + 0.5f); *g = (uint8_t)(t*255.0f + 0.5f); *b = (uint8_t)(p*255.0f + 0.5f); break; case 1: *r = (uint8_t)(q*255.0f + 0.5f); *g = (uint8_t)(v*255.0f + 0.5f); *b = (uint8_t)(p*255.0f + 0.5f); break; case 2: *r = (uint8_t)(p*255.0f + 0.5f); *g = (uint8_t)(v*255.0f + 0.5f); *b = (uint8_t)(t*255.0f + 0.5f); break; case 3: *r = (uint8_t)(p*255.0f + 0.5f); *g = (uint8_t)(q*255.0f + 0.5f); *b = (uint8_t)(v*255.0f + 0.5f); break; case 4: *r = (uint8_t)(t*255.0f + 0.5f); *g = (uint8_t)(p*255.0f + 0.5f); *b = (uint8_t)(v*255.0f + 0.5f); break; default: *r = (uint8_t)(v*255.0f + 0.5f); *g = (uint8_t)(p*255.0f + 0.5f); *b = (uint8_t)(q*255.0f + 0.5f); break; } } /** RGB任务(平滑波浪彩虹效果) */ void task_rgb(void* pvParameters) { gpio_reset_pin(WS2812_GPIO_NUM); ws2812_strip_handle_t ws2812_handle = NULL; ws2812_init(WS2812_GPIO_NUM, WS2812_LED_NUM, &ws2812_handle); // 初始化熄灭所有LED for (int index = 0; index < WS2812_LED_NUM; index++) { ws2812_write(ws2812_handle, index, 0, 0, 0); } // 色相偏移量(控制彩虹波浪移动) - 使用浮点数提高精度 float hue_offset = 0.0f; // 波浪速度控制(数值越小速度越快) const float wave_speed = 0.5f; // 每个LED的色相间隔(减小步长使颜色过渡更平滑) const float hue_step = 8.0f; // 帧率控制(减少延迟提高帧率) const TickType_t frame_delay = pdMS_TO_TICKS(30); ESP_LOGI(TAG, "RGB task initialized with smooth rainbow wave effect"); while (1) { // 等待RGB运行标志 xEventGroupWaitBits(rgb_event_group, RGB_RUN_BIT, pdFALSE, // 不自动清除位 pdTRUE, // 等待位被设置 portMAX_DELAY); ESP_LOGI(TAG, "Smooth rainbow wave effect started"); // 持续运行彩虹效果,直到标志位被清除 while ((xEventGroupGetBits(rgb_event_group) & RGB_RUN_BIT) != 0) { // 为每个LED设置颜色 for (int index = 0; index < WS2812_LED_NUM; index++) { // 使用浮点数计算色相,避免整数截断 float hue = fmodf(hue_offset + index * hue_step, 360.0f); uint8_t r, g, b; // 转换HSV到RGB,使用全局亮度控制 hsv_to_rgb(hue, 1.0f, 0.9f, global_brightness, &r, &g, &b); // 设置LED颜色 ws2812_write(ws2812_handle, index, r, g, b); } // 更新色相偏移(使用浮点数提高精度) hue_offset = fmodf(hue_offset + wave_speed, 360.0f); // 减少延迟,提高帧率,使动画更流畅 vTaskDelay(frame_delay); } // 标志位被清除,熄灭所有LED for (int index = 0; index < WS2812_LED_NUM; index++) { ws2812_write(ws2812_handle, index, 0, 0, 0); } ESP_LOGI(TAG, "Smooth rainbow wave effect stopped"); } } /** 雷达任务 */ void task_radar(void* pvParameters) { gpio_reset_pin(LED_GPIO); gpio_reset_pin(LEIDA_GPIO); gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT); gpio_set_level(LED_GPIO, 1); // 初始熄灭 gpio_config_t radar_cfg = { .pin_bit_mask = (1ULL << LEIDA_GPIO), .mode = GPIO_MODE_INPUT, .pull_up_en = GPIO_PULLUP_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE }; gpio_config(&radar_cfg); ESP_LOGI(TAG2, "Radar task started"); static TickType_t rgb_start_tick = 0; const TickType_t rgb_duration = pdMS_TO_TICKS(50000); // 50秒 while (1) { bool detected = gpio_get_level(LEIDA_GPIO); gpio_set_level(LED_GPIO, !detected); // 检测到物体时点亮LED if (detected) { // 设置RGB运行标志 if ((xEventGroupGetBits(rgb_event_group) & RGB_RUN_BIT) == 0) { xEventGroupSetBits(rgb_event_group, RGB_RUN_BIT); ESP_LOGI(TAG2, "RGB activated by radar"); } rgb_start_tick = xTaskGetTickCount(); // 更新启动时间 } // 超时检查:50秒无检测则关闭RGB if ((xEventGroupGetBits(rgb_event_group) & RGB_RUN_BIT) && (xTaskGetTickCount() - rgb_start_tick > rgb_duration)) { xEventGroupClearBits(rgb_event_group, RGB_RUN_BIT); ESP_LOGI(TAG2, "RGB deactivated by timeout"); } vTaskDelay(pdMS_TO_TICKS(10)); } } /** ADC任务(土壤传感器) */ void task_adc(void* pvParameters) { // 配置ADC adc1_config_width(ADC_WIDTH_BIT_12); adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN_DB_11); const float vref = 3.3f; // 参考电压 const float adc_max = 4095.0f; // 12位ADC最大值 while (1) { int adc_value = adc1_get_raw(ADC_CHANNEL); float voltage = adc_value * vref / adc_max; float I_value = voltage / 1000.0f; // 电流计算 float V_value = 3.3f - voltage; // 土壤两侧电压 float R_value = (I_value > 0) ? (V_value / I_value) : -1; // 电阻计算 ESP_LOGI(TAG_ADC, "ADC: %d, Voltage: %.2fV, Resist: %.2fΩ", adc_value, voltage, R_value); // 更新全局ADC数据 if (xSemaphoreTake(g_sensor_mutex, pdMS_TO_TICKS(100)) == pdTRUE) { g_sensor_data.adc_voltage = voltage; g_sensor_data.adc_resist = R_value; xSemaphoreGive(g_sensor_mutex); } vTaskDelay(pdMS_TO_TICKS(1500)); } } /** MQTT发送任务 */ static void task_wifi_mqtt(void* pvParameters) { // 初始化NVS esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ESP_ERROR_CHECK(nvs_flash_init()); } s_wifi_ev = xEventGroupCreate(); EventBits_t ev = 0; // 初始化WIFI wifi_sta_init(wifi_event_handler); // 等待WIFI连接成功 ev = xEventGroupWaitBits(s_wifi_ev, WIFI_CONNECT_BIT, pdTRUE, pdFALSE, portMAX_DELAY); if (ev & WIFI_CONNECT_BIT) { mqtt_start(); } static char mqtt_json[512]; sensor_data_t temp_data; // 临时存储数据 while (1) { // 每5秒发送一次数据 if (s_is_mqtt_connected) { // 读取全局传感器数据(加锁保护) if (xSemaphoreTake(g_sensor_mutex, pdMS_TO_TICKS(100)) == pdTRUE) { temp_data = g_sensor_data; xSemaphoreGive(g_sensor_mutex); } // 构建JSON格式数据 snprintf(mqtt_json, sizeof(mqtt_json), "{\"opt\":\"dev_sta\",\"val\":{" "\"temp\":%.2f," "\"humi\":%.2f," "\"press\":%.2f," "\"light\":%.2f," "\"adc_voltage\":%.2f," "\"adc_resist\":%.2f" "}}", temp_data.temp, temp_data.humi, temp_data.press, temp_data.lux, temp_data.adc_voltage, temp_data.adc_resist); // 发送MQTT消息 int msg_id = esp_mqtt_client_publish(s_mqtt_client, MQTT_PUBLIC_TOPIC, mqtt_json, strlen(mqtt_json), 1, // QoS=1 0); // 不保留 ESP_LOGI(TAG, "MQTT published: %s (msg_id=%d)", mqtt_json, msg_id); } vTaskDelay(pdMS_TO_TICKS(3000)); // 2.5秒发送一次 } } void app_main(void) { // 初始化互斥锁保护传感器数据 g_sensor_mutex = xSemaphoreCreateMutex(); configASSERT(g_sensor_mutex); // 初始化RGB控制事件组 rgb_event_group = xEventGroupCreate(); // 启动各任务 xTaskCreate(task_adc, "adc_task", 4096, NULL, 8, &AdcTaskHandle); xTaskCreate(task_i2c_sensors, "i2c_sensors_task", 8192, NULL, 10, &IicTaskHandle); xTaskCreate(task_rgb, "rgb_task", 4096, NULL, 9, &RgbTaskHandle); xTaskCreate(task_radar, "radar_task", 4096, NULL, 9, &RadarTaskHandle); // 启动WIFI和MQTT任务 xTaskCreate(task_wifi_mqtt, "wifi_mqtt_task", 8192, NULL, 10, NULL); }在此基础上增加蓝牙配网功能

/*************************************************** This is a library for the SHT31 Digital Humidity & Temp Sensor Designed specifically to work with the SHT31 Digital sensor from Adafruit ----> https://www.adafruit.com/products/2857 These displays use I2C to communicate, 2 pins are required to interface Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. BSD license, all text above must be included in any redistribution ****************************************************/ #include "Adafruit_SHT31.h" Adafruit_SHT31::Adafruit_SHT31() { } boolean Adafruit_SHT31::begin(uint8_t i2caddr) { Wire.begin(); _i2caddr = i2caddr; reset(); //return (readStatus() == 0x40); return true; } uint16_t Adafruit_SHT31::readStatus(void) { writeCommand(SHT31_READSTATUS); Wire.requestFrom(_i2caddr, (uint8_t)3); uint16_t stat = Wire.read(); stat <<= 8; stat |= Wire.read(); //Serial.println(stat, HEX); return stat; } void Adafruit_SHT31::reset(void) { writeCommand(SHT31_SOFTRESET); delay(10); } void Adafruit_SHT31::heater(boolean h) { if (h) writeCommand(SHT31_HEATEREN); else writeCommand(SHT31_HEATERDIS); } float Adafruit_SHT31::readTemperature(void) { if (! readTempHum()) return NAN; return temp; } float Adafruit_SHT31::readHumidity(void) { if (! readTempHum()) return NAN; return humidity; } boolean Adafruit_SHT31::readTempHum(void) { uint8_t readbuffer[6]; writeCommand(SHT31_MEAS_HIGHREP); delay(500); Wire.requestFrom(_i2caddr, (uint8_t)6); if (Wire.available() != 6) return false; for (uint8_t i=0; i<6; i++) { readbuffer[i] = Wire.read(); // Serial.print("0x"); Serial.println(readbuffer[i], HEX); } uint16_t ST, SRH; ST = readbuffer[0]; ST <<= 8; ST |= readbuffer[1]; if (readbuffer[2] != crc8(readbuffer, 2)) return false; SRH = readbuffer[3]; SRH <<= 8; SRH |= readbuffer[4]; if (readbuffer[5] != crc8(readbuffer+3, 2)) return false; // Serial.print("ST = "); Serial.println(ST); double stemp = ST; stemp *= 175; stemp /= 0xffff; stemp = -45 + stemp; temp = stemp; // Serial.print("SRH = "); Serial.println(SRH); double shum = SRH; shum *= 100; shum /= 0xFFFF; humidity = shum; return true; } void Adafruit_SHT31::writeCommand(uint16_t cmd) { Wire.beginTransmission(_i2caddr); Wire.write(cmd >> 8); Wire.write(cmd & 0xFF); Wire.endTransmission(); } uint8_t Adafruit_SHT31::crc8(const uint8_t *data, int len) { /* * * CRC-8 formula from page 14 of SHT spec pdf * * Test data 0xBE, 0xEF should yield 0x92 * * Initialization data 0xFF * Polynomial 0x31 (x8 + x5 +x4 +1) * Final XOR 0x00 */ const uint8_t POLYNOMIAL(0x31); uint8_t crc(0xFF); for ( int j = len; j; --j ) { crc ^= *data++; for ( int i = 8; i; --i ) { crc = ( crc & 0x80 ) ? (crc << 1) ^ POLYNOMIAL : (crc << 1); } } return crc; } /*********************************************************************/解释代码并将其用HAL库重写

int main(void) { uint32_t bufe[5]; OLED_Init(); DHT11_Init(); Fan_Init(); LightSensor_Init(); SoilMoisture_Init(); OLED_ShowChinese(0, 0, "温度:"); OLED_ShowChinese(94, 0, "℃"); OLED_ShowChinese(0, 16, "湿度:"); OLED_ShowChinese(0, 32, "光照强度:"); OLED_ShowString(94,16,"RH",OLED_8X16); OLED_ShowChinese(0, 47, "土壤:"); OLED_ShowString(112,47,"%",OLED_8X16); OLED_ShowString(112,32,"LX",OLED_8X16); OLED_Update(); while(1) { if(DHT11_Read_Data(&temp,&humi) == SUCCESS) { filtered_temp = filtered_temp * 0.7 + temp * 0.3; char temp_str[8]; sprintf(temp_str, "%2.1f", filtered_temp); if(fabs(filtered_temp - last_display_temp) >= 0.3) { OLED_ShowString(32,0,temp_str,OLED_8X16); last_display_temp = filtered_temp; bufe[0]=temp; bufe[1]=humi; OLED_ShowNum(32,16,bufe[1],2,OLED_8X16); if(filtered_temp > TEMP_THRESHILD){ Fan_On(); }else{ Fan_Off(); } //将OLED显存数组更新到OLED屏幕 } uint16_t light_raw = Get_LightIntensity(); uint16_t light_value = (uint16_t)((light_raw * 999.0f) / 4095.0f); OLED_ShowNum(64, 32, light_value, 3, OLED_8X16); uint8_t moisture = Get_SoilMoisture_Percent(); soil_percent = Get_SoilMoisture_Percent(); OLED_ShowNum(40, 48, soil_percent, 3, OLED_8X16); OLED_Update(); Delay_ms(2000); } } }"土", 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, "壤", 0x10,0xFF,0x10,0x00,0x82,0xBA,0xEA,0xBA,0x83,0xBA,0xEA,0xBA,0x82,0x00,0x00, 0x08,0x18,0x0F,0x04,0x48,0x4A,0x2A,0xFF,0x8A,0x4A,0x1A,0x2F,0x5A,0x8A,0x88,0x00,OLED上温度湿度光照强度都能显示汉字,为什么土壤显示的是乱码

int main(void) { /*模块初始化*/ OLED_Init(); //OLED初始化 LightSensor_Init(); //光敏传感器初始化 DHT11_Init(); //DHT11初始化 USART2_Init(115200);//初始化串口 int light; uint8_t temp = 0; uint8_t humi = 0; char temp_str[10] = {0}; char humi_str[10] = {0}; char lux_str[10] = {0}; // 新增光照强度字符串 DHT11_Init();//再次初始化DHT11 while (1) { // 读取温湿度 DHT11_Read_Data(&temp, &humi); sprintf(temp_str, "Temp:%d C", temp); sprintf(humi_str, "Humi:%d %RH", humi); OLED_ShowString(2, 1, temp_str); OLED_ShowString(3, 1, humi_str); // 读取光照强度并显示 float lux = LightSensor_GetLux(); sprintf(lux_str, "Lux:%.1f", lux); OLED_ShowString(1, 1, lux_str); Delay_s(1); // 1. 配置ESP8266为STA模式 ESP8266_SendCmd("AT+CWMODE=1\r\n"); // 2. 连接Wi-Fi ESP8266_SendCmd("AT+CWJAP=\"t-Magic\",\"zhw890000\"\r\n"); // 3. 配置MQTT参数 ESP8266_SendCmd("AT+MQTTUSERCFG=0,1,\"67ceedd88e04aa0690bc1fe3_000001_0_1_2025031206\",\"67ceedd88e04aa0690bc1fe3_000001\",\"f674952c905f16e8cb83ff7e40f11a041220391d6bca3098ba41e76b1878d2cb\",0,0,\"\"\r\n"); // 4. 连接华为云MQTT服务器 ESP8266_SendCmd("AT+MQTTCONN=0,\"529d6c98f1.st1.iotda-device.cn-north-4.myhuaweicloud.com\",1883,1\r\n"); // 5. 订阅主题(例如属性上报) ESP8266_SendCmd("AT+MQTTSUB=0,\"$oc/devices/deviceId/sys/properties/report\",1\r\n"); sprintf(temp, "{\"services\":[{\"agriculture\":\"basic\",\"properties\":{\"temperature\":25}}]}"); ESP8266_SendCmd("AT+MQTTPUB=0,\"$oc/devices/67ceedd88e04aa0690bc1fe3_000001/sys/properties/report\",\"%s\",1,0\r\n", temp); Delay_ms(5); } }请依据下方的报错修改User\main.c(80): error: #167: argument of type "uint8_t" is incompatible with parameter of type "char *restrict" sprintf(temp, "{\"services\":[{\"agriculture\":\"basic\",\"properties\":{\"temperature\":25}}]}");

/**************************************************************************** * drivers/sensors/sensor.c * * SPDX-License-Identifier: Apache-2.0 * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include <nuttx/config.h> #include <sys/types.h> #include <stdbool.h> #include <stdio.h> #include <string.h> #include <assert.h> #include <errno.h> #include <debug.h> #include #include <fcntl.h> #include <nuttx/list.h> #include <nuttx/kmalloc.h> #include <nuttx/circbuf.h> #include <nuttx/mutex.h> #include <nuttx/sensors/sensor.h> #include <nuttx/lib/lib.h> /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ /* Device naming ************************************************************/ #define ROUND_DOWN(x, y) (((x) / (y)) * (y)) #define DEVNAME_FMT "/dev/uorb/sensor_%s%s%d" #define DEVNAME_UNCAL "_uncal" #define TIMING_BUF_ESIZE (sizeof(uint32_t)) /**************************************************************************** * Private Types ****************************************************************************/ struct sensor_axis_map_s { int8_t src_x; int8_t src_y; int8_t src_z; int8_t sign_x; int8_t sign_y; int8_t sign_z; }; /* This structure describes sensor meta */ struct sensor_meta_s { size_t esize; FAR char *name; }; typedef enum sensor_role_e { SENSOR_ROLE_NONE, SENSOR_ROLE_WR, SENSOR_ROLE_RD, SENSOR_ROLE_RDWR, } sensor_role_t; /* This structure describes user info of sensor, the user may be * advertiser or subscriber */ struct sensor_user_s { /* The common info */ struct list_node node; /* Node of users list */ struct pollfd *fds; /* The poll structure of thread waiting events */ sensor_role_t role; /* The is used to indicate user's role based on open flags */ bool changed; /* This is used to indicate event happens and need to * asynchronous notify other users */ unsigned int event; /* The event of this sensor, eg: SENSOR_EVENT_FLUSH_COMPLETE. */ bool flushing; /* The is used to indicate user is flushing */ sem_t buffersem; /* Wakeup user waiting for data in circular buffer */ size_t bufferpos; /* The index of user generation in buffer */ /* The subscriber info * Support multi advertisers to subscribe their own data when they * appear in dual role */ struct sensor_ustate_s state; }; /* This structure describes the state of the upper half driver */ struct sensor_upperhalf_s { FAR struct sensor_lowerhalf_s *lower; /* The handle of lower half driver */ struct sensor_state_s state; /* The state of sensor device */ struct circbuf_s timing; /* The circular buffer of generation */ struct circbuf_s buffer; /* The circular buffer of data */ rmutex_t lock; /* Manages exclusive access to file operations */ struct list_node userlist; /* List of users */ }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ static void sensor_pollnotify(FAR struct sensor_upperhalf_s *upper, pollevent_t eventset, sensor_role_t role); static int sensor_open(FAR struct file *filep); static int sensor_close(FAR struct file *filep); static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer, size_t buflen); static ssize_t sensor_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg); static int sensor_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); static ssize_t sensor_push_event(FAR void *priv, FAR const void *data, size_t bytes); /**************************************************************************** * Private Data ****************************************************************************/ static const struct sensor_axis_map_s g_remap_tbl[] = { { 0, 1, 2, 1, 1, 1 }, /* P0 */ { 1, 0, 2, 1, -1, 1 }, /* P1 */ { 0, 1, 2, -1, -1, 1 }, /* P2 */ { 1, 0, 2, -1, 1, 1 }, /* P3 */ { 0, 1, 2, -1, 1, -1 }, /* P4 */ { 1, 0, 2, -1, -1, -1 }, /* P5 */ { 0, 1, 2, 1, -1, -1 }, /* P6 */ { 1, 0, 2, 1, 1, -1 }, /* P7 */ }; static const struct sensor_meta_s g_sensor_meta[] = { {0, NULL}, {sizeof(struct sensor_accel), "accel"}, {sizeof(struct sensor_mag), "mag"}, {sizeof(struct sensor_orientation), "orientation"}, {sizeof(struct sensor_gyro), "gyro"}, {sizeof(struct sensor_light), "light"}, {sizeof(struct sensor_baro), "baro"}, {sizeof(struct sensor_noise), "noise"}, {sizeof(struct sensor_prox), "prox"}, {sizeof(struct sensor_rgb), "rgb"}, {sizeof(struct sensor_accel), "linear_accel"}, {sizeof(struct sensor_rotation), "rotation"}, {sizeof(struct sensor_humi), "humi"}, {sizeof(struct sensor_temp), "temp"}, {sizeof(struct sensor_pm25), "pm25"}, {sizeof(struct sensor_pm1p0), "pm1p0"}, {sizeof(struct sensor_pm10), "pm10"}, {sizeof(struct sensor_event), "motion_detect"}, {sizeof(struct sensor_event), "step_detector"}, {sizeof(struct sensor_step_counter), "step_counter"}, {sizeof(struct sensor_ph), "ph"}, {sizeof(struct sensor_hrate), "hrate"}, {sizeof(struct sensor_event), "tilt_detector"}, {sizeof(struct sensor_event), "wake_gesture"}, {sizeof(struct sensor_event), "glance_gesture"}, {sizeof(struct sensor_event), "pickup_gesture"}, {sizeof(struct sensor_event), "wrist_tilt"}, {sizeof(struct sensor_orientation), "device_orientation"}, {sizeof(struct sensor_pose_6dof), "pose_6dof"}, {sizeof(struct sensor_gas), "gas"}, {sizeof(struct sensor_event), "significant_motion"}, {sizeof(struct sensor_hbeat), "hbeat"}, {sizeof(struct sensor_force), "force"}, {sizeof(struct sensor_hall), "hall"}, {sizeof(struct sensor_event), "offbody_detector"}, {sizeof(struct sensor_uv), "uv"}, {sizeof(struct sensor_angle), "hinge_angle"}, {sizeof(struct sensor_ir), "ir"}, {sizeof(struct sensor_hcho), "hcho"}, {sizeof(struct sensor_tvoc), "tvoc"}, {sizeof(struct sensor_dust), "dust"}, {sizeof(struct sensor_ecg), "ecg"}, {sizeof(struct sensor_ppgd), "ppgd"}, {sizeof(struct sensor_ppgq), "ppgq"}, {sizeof(struct sensor_impd), "impd"}, {sizeof(struct sensor_ots), "ots"}, {sizeof(struct sensor_co2), "co2"}, {sizeof(struct sensor_cap), "cap"}, {sizeof(struct sensor_eng), "eng"}, {sizeof(struct sensor_gnss), "gnss"}, {sizeof(struct sensor_gnss_satellite), "gnss_satellite"}, {sizeof(struct sensor_gnss_measurement), "gnss_measurement"}, {sizeof(struct sensor_gnss_clock), "gnss_clock"}, {sizeof(struct sensor_gnss_geofence_event), "gnss_geofence_event"}, }; static const struct file_operations g_sensor_fops = { sensor_open, /* open */ sensor_close, /* close */ sensor_read, /* read */ sensor_write, /* write */ NULL, /* seek */ sensor_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* truncate */ sensor_poll /* poll */ }; /**************************************************************************** * Private Functions ****************************************************************************/ static void sensor_lock(FAR void *priv) { FAR struct sensor_upperhalf_s *upper = priv; nxrmutex_lock(&upper->lock); } static void sensor_unlock(FAR void *priv) { FAR struct sensor_upperhalf_s *upper = priv; nxrmutex_unlock(&upper->lock); } static int sensor_update_interval(FAR struct file *filep, FAR struct sensor_upperhalf_s *upper, FAR struct sensor_user_s *user, uint32_t interval) { FAR struct sensor_lowerhalf_s *lower = upper->lower; FAR struct sensor_user_s *tmp; uint32_t min_interval = interval; uint32_t min_latency = interval != UINT32_MAX ? user->state.latency : UINT32_MAX; int ret = 0; if (interval == user->state.interval) { return 0; } list_for_every_entry(&upper->userlist, tmp, struct sensor_user_s, node) { if (tmp == user || tmp->state.interval == UINT32_MAX) { continue; } if (min_interval > tmp->state.interval) { min_interval = tmp->state.interval; } if (min_latency > tmp->state.latency) { min_latency = tmp->state.latency; } } if (lower->ops->set_interval) { if (min_interval != UINT32_MAX && min_interval != upper->state.min_interval) { uint32_t expected_interval = min_interval; ret = lower->ops->set_interval(lower, filep, &min_interval); if (ret < 0) { return ret; } else if (min_interval > expected_interval) { return -EINVAL; } } if (min_latency == UINT32_MAX) { min_latency = 0; } if (lower->ops->batch && (min_latency != upper->state.min_latency || (min_interval != upper->state.min_interval && min_latency))) { ret = lower->ops->batch(lower, filep, &min_latency); if (ret >= 0) { upper->state.min_latency = min_latency; } } } upper->state.min_interval = min_interval; user->state.interval = interval; sensor_pollnotify(upper, POLLPRI, SENSOR_ROLE_WR); return ret; } static int sensor_update_latency(FAR struct file *filep, FAR struct sensor_upperhalf_s *upper, FAR struct sensor_user_s *user, uint32_t latency) { FAR struct sensor_lowerhalf_s *lower = upper->lower; FAR struct sensor_user_s *tmp; uint32_t min_latency = latency; int ret = 0; if (latency == user->state.latency) { return 0; } if (user->state.interval == UINT32_MAX) { user->state.latency = latency; return 0; } if (latency <= upper->state.min_latency) { goto update; } list_for_every_entry(&upper->userlist, tmp, struct sensor_user_s, node) { if (tmp == user || tmp->state.interval == UINT32_MAX) { continue; } if (min_latency > tmp->state.latency) { min_latency = tmp->state.latency; } } update: if (min_latency == UINT32_MAX) { min_latency = 0; } if (min_latency == upper->state.min_latency) { user->state.latency = latency; return ret; } if (lower->ops->batch) { ret = lower->ops->batch(lower, filep, &min_latency); if (ret < 0) { return ret; } } upper->state.min_latency = min_latency; user->state.latency = latency; sensor_pollnotify(upper, POLLPRI, SENSOR_ROLE_WR); return ret; } static void sensor_generate_timing(FAR struct sensor_upperhalf_s *upper, unsigned long nums) { uint32_t interval = upper->state.min_interval != UINT32_MAX ? upper->state.min_interval : 1; while (nums-- > 0) { upper->state.generation += interval; circbuf_overwrite(&upper->timing, &upper->state.generation, TIMING_BUF_ESIZE); } } static bool sensor_is_updated(FAR struct sensor_upperhalf_s *upper, FAR struct sensor_user_s *user) { long delta = (long long)upper->state.generation - user->state.generation; if (delta <= 0) { return false; } else if (user->state.interval == UINT32_MAX) { return true; } else { /* Check whether next generation user want in buffer. * generation next generation(not published yet) * ____v_____________v * ////|//////^ | * ^ middle point * next generation user want */ return delta >= user->state.interval - (upper->state.min_interval >> 1); } } static void sensor_catch_up(FAR struct sensor_upperhalf_s *upper, FAR struct sensor_user_s *user) { uint32_t generation; long delta; circbuf_peek(&upper->timing, &generation, TIMING_BUF_ESIZE); delta = (long long)generation - user->state.generation; if (delta > 0) { user->bufferpos = upper->timing.tail / TIMING_BUF_ESIZE; if (user->state.interval == UINT32_MAX) { user->state.generation = generation - 1; } else { delta -= upper->state.min_interval >> 1; user->state.generation += ROUND_DOWN(delta, user->state.interval); } } } static ssize_t sensor_do_samples(FAR struct sensor_upperhalf_s *upper, FAR struct sensor_user_s *user, FAR char *buffer, size_t len) { uint32_t generation; ssize_t ret = 0; size_t nums; size_t pos; size_t end; sensor_catch_up(upper, user); nums = upper->timing.head / TIMING_BUF_ESIZE - user->bufferpos; if (len < nums * upper->state.esize) { nums = len / upper->state.esize; } len = nums * upper->state.esize; /* Take samples continuously */ if (user->state.interval == UINT32_MAX) { if (buffer != NULL) { ret = circbuf_peekat(&upper->buffer, user->bufferpos * upper->state.esize, buffer, len); } else { ret = len; } user->bufferpos += nums; circbuf_peekat(&upper->timing, (user->bufferpos - 1) * TIMING_BUF_ESIZE, &user->state.generation, TIMING_BUF_ESIZE); return ret; } /* Take samples one-bye-one, to determine whether a sample needed: * * If user's next generation is on the left side of middle point, * we should copy this sample for user. * next_generation(or end) * ________________v____ * timing buffer: //|//////. | * ^ middle * generation * next sample(or end) * ________________v____ * data buffer: | | * ^ * sample */ pos = user->bufferpos; end = upper->timing.head / TIMING_BUF_ESIZE; circbuf_peekat(&upper->timing, pos * TIMING_BUF_ESIZE, &generation, TIMING_BUF_ESIZE); while (pos++ != end) { uint32_t next_generation; long delta; if (pos * TIMING_BUF_ESIZE == upper->timing.head) { next_generation = upper->state.generation + upper->state.min_interval; } else { circbuf_peekat(&upper->timing, pos * TIMING_BUF_ESIZE, &next_generation, TIMING_BUF_ESIZE); } delta = next_generation + generation - ((user->state.generation + user->state.interval) << 1); if (delta >= 0) { if (buffer != NULL) { ret += circbuf_peekat(&upper->buffer, (pos - 1) * upper->state.esize, buffer + ret, upper->state.esize); } else { ret += upper->state.esize; } user->bufferpos = pos; user->state.generation += user->state.interval; if (ret >= len) { break; } } generation = next_generation; } if (pos - 1 == end && sensor_is_updated(upper, user)) { generation = upper->state.generation - user->state.generation + (upper->state.min_interval >> 1); user->state.generation += ROUND_DOWN(generation, user->state.interval); } return ret; } static void sensor_pollnotify_one(FAR struct sensor_user_s *user, pollevent_t eventset, sensor_role_t role) { if (!(user->role & role)) { return; } if (eventset == POLLPRI) { user->changed = true; } poll_notify(&user->fds, 1, eventset); } static void sensor_pollnotify(FAR struct sensor_upperhalf_s *upper, pollevent_t eventset, sensor_role_t role) { FAR struct sensor_user_s *user; list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node) { sensor_pollnotify_one(user, eventset, role); } } static int sensor_open(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; FAR struct sensor_upperhalf_s *upper = inode->i_private; FAR struct sensor_lowerhalf_s *lower = upper->lower; FAR struct sensor_user_s *user; int ret = 0; nxrmutex_lock(&upper->lock); user = kmm_zalloc(sizeof(struct sensor_user_s)); if (user == NULL) { ret = -ENOMEM; goto errout_with_lock; } if (lower->ops->open) { ret = lower->ops->open(lower, filep); if (ret < 0) { goto errout_with_user; } } if ((filep->f_oflags & O_DIRECT) == 0) { if (filep->f_oflags & O_RDOK) { if (upper->state.nsubscribers == 0 && lower->ops->activate) { ret = lower->ops->activate(lower, filep, true); if (ret < 0) { goto errout_with_open; } } user->role |= SENSOR_ROLE_RD; upper->state.nsubscribers++; } if (filep->f_oflags & O_WROK) { user->role |= SENSOR_ROLE_WR; upper->state.nadvertisers++; if (filep->f_oflags & SENSOR_PERSIST) { lower->persist = true; } } } if (upper->state.generation && lower->persist) { user->state.generation = upper->state.generation - 1; user->bufferpos = upper->timing.head / TIMING_BUF_ESIZE - 1; } else { user->state.generation = upper->state.generation; user->bufferpos = upper->timing.head / TIMING_BUF_ESIZE; } user->state.interval = UINT32_MAX; user->state.esize = upper->state.esize; nxsem_init(&user->buffersem, 0, 0); list_add_tail(&upper->userlist, &user->node); /* The new user generation, notify to other users */ sensor_pollnotify(upper, POLLPRI, SENSOR_ROLE_WR); filep->f_priv = user; goto errout_with_lock; errout_with_open: if (lower->ops->close) { lower->ops->close(lower, filep); } errout_with_user: kmm_free(user); errout_with_lock: nxrmutex_unlock(&upper->lock); return ret; } static int sensor_close(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; FAR struct sensor_upperhalf_s *upper = inode->i_private; FAR struct sensor_lowerhalf_s *lower = upper->lower; FAR struct sensor_user_s *user = filep->f_priv; int ret = 0; nxrmutex_lock(&upper->lock); if (lower->ops->close) { ret = lower->ops->close(lower, filep); if (ret < 0) { nxrmutex_unlock(&upper->lock); return ret; } } if ((filep->f_oflags & O_DIRECT) == 0) { if (filep->f_oflags & O_RDOK) { upper->state.nsubscribers--; if (upper->state.nsubscribers == 0 && lower->ops->activate) { lower->ops->activate(lower, filep, false); } } if (filep->f_oflags & O_WROK) { upper->state.nadvertisers--; } } list_delete(&user->node); sensor_update_latency(filep, upper, user, UINT32_MAX); sensor_update_interval(filep, upper, user, UINT32_MAX); nxsem_destroy(&user->buffersem); /* The user is closed, notify to other users */ sensor_pollnotify(upper, POLLPRI, SENSOR_ROLE_WR); nxrmutex_unlock(&upper->lock); kmm_free(user); return ret; } static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer, size_t len) { FAR struct inode *inode = filep->f_inode; FAR struct sensor_upperhalf_s *upper = inode->i_private; FAR struct sensor_lowerhalf_s *lower = upper->lower; FAR struct sensor_user_s *user = filep->f_priv; ssize_t ret; if (!len) { return -EINVAL; } nxrmutex_lock(&upper->lock); if (lower->ops->fetch) { if (buffer == NULL) { return -EINVAL; } if (!(filep->f_oflags & O_NONBLOCK)) { nxrmutex_unlock(&upper->lock); ret = nxsem_wait_uninterruptible(&user->buffersem); if (ret < 0) { return ret; } nxrmutex_lock(&upper->lock); } else if (!upper->state.nsubscribers) { ret = -EAGAIN; goto out; } ret = lower->ops->fetch(lower, filep, buffer, len); } else if (circbuf_is_empty(&upper->buffer)) { ret = -ENODATA; } else if (sensor_is_updated(upper, user)) { ret = sensor_do_samples(upper, user, buffer, len); } else if (lower->persist) { if (buffer == NULL) { ret = upper->state.esize; } else { /* Persistent device can get latest old data if not updated. */ ret = circbuf_peekat(&upper->buffer, (user->bufferpos - 1) * upper->state.esize, buffer, upper->state.esize); } } else { ret = -ENODATA; } out: nxrmutex_unlock(&upper->lock); return ret; } static ssize_t sensor_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) { FAR struct inode *inode = filep->f_inode; FAR struct sensor_upperhalf_s *upper = inode->i_private; FAR struct sensor_lowerhalf_s *lower = upper->lower; return lower->push_event(lower->priv, buffer, buflen); } static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { FAR struct inode *inode = filep->f_inode; FAR struct sensor_upperhalf_s *upper = inode->i_private; FAR struct sensor_lowerhalf_s *lower = upper->lower; FAR struct sensor_user_s *user = filep->f_priv; uint32_t arg1 = (uint32_t)arg; int ret = 0; switch (cmd) { case SNIOC_GET_STATE: { nxrmutex_lock(&upper->lock); memcpy((FAR void *)(uintptr_t)arg, &upper->state, sizeof(upper->state)); user->changed = false; nxrmutex_unlock(&upper->lock); } break; case SNIOC_GET_USTATE: { nxrmutex_lock(&upper->lock); memcpy((FAR void *)(uintptr_t)arg, &user->state, sizeof(user->state)); nxrmutex_unlock(&upper->lock); } break; case SNIOC_SET_INTERVAL: { nxrmutex_lock(&upper->lock); ret = sensor_update_interval(filep, upper, user, arg1 ? arg1 : UINT32_MAX); nxrmutex_unlock(&upper->lock); } break; case SNIOC_BATCH: { nxrmutex_lock(&upper->lock); ret = sensor_update_latency(filep, upper, user, arg1); nxrmutex_unlock(&upper->lock); } break; case SNIOC_SELFTEST: { if (lower->ops->selftest == NULL) { ret = -ENOTSUP; break; } ret = lower->ops->selftest(lower, filep, arg); } break; case SNIOC_SET_CALIBVALUE: { if (lower->ops->set_calibvalue == NULL) { ret = -ENOTSUP; break; } ret = lower->ops->set_calibvalue(lower, filep, arg); } break; case SNIOC_CALIBRATE: { if (lower->ops->calibrate == NULL) { ret = -ENOTSUP; break; } ret = lower->ops->calibrate(lower, filep, arg); } break; case SNIOC_SET_USERPRIV: { nxrmutex_lock(&upper->lock); upper->state.priv = (uint64_t)arg; nxrmutex_unlock(&upper->lock); } break; case SNIOC_SET_BUFFER_NUMBER: { nxrmutex_lock(&upper->lock); if (!circbuf_is_init(&upper->buffer)) { if (arg1 >= lower->nbuffer) { lower->nbuffer = arg1; upper->state.nbuffer = arg1; } else { ret = -ERANGE; } } else { ret = -EBUSY; } nxrmutex_unlock(&upper->lock); } break; case SNIOC_UPDATED: { nxrmutex_lock(&upper->lock); *(FAR bool *)(uintptr_t)arg = sensor_is_updated(upper, user); nxrmutex_unlock(&upper->lock); } break; case SNIOC_GET_INFO: { if (lower->ops->get_info == NULL) { ret = -ENOTSUP; break; } ret = lower->ops->get_info(lower, filep, (FAR struct sensor_device_info_s *)(uintptr_t)arg); } break; case SNIOC_GET_EVENTS: { nxrmutex_lock(&upper->lock); *(FAR unsigned int *)(uintptr_t)arg = user->event; user->event = 0; user->changed = false; nxrmutex_unlock(&upper->lock); } break; case SNIOC_FLUSH: { nxrmutex_lock(&upper->lock); /* If the sensor is not activated, return -EINVAL. */ if (upper->state.nsubscribers == 0) { nxrmutex_unlock(&upper->lock); return -EINVAL; } if (lower->ops->flush != NULL) { /* Lower half driver will do flush in asynchronous mode, * flush will be completed until push event happened with * bytes is zero. */ ret = lower->ops->flush(lower, filep); if (ret >= 0) { user->flushing = true; } } else { /* If flush is not supported, complete immediately */ user->event |= SENSOR_EVENT_FLUSH_COMPLETE; sensor_pollnotify_one(user, POLLPRI, user->role); } nxrmutex_unlock(&upper->lock); } break; default: /* Lowerhalf driver process other cmd. */ if (lower->ops->control) { ret = lower->ops->control(lower, filep, cmd, arg); } else { ret = -ENOTTY; } break; } return ret; } static int sensor_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) { FAR struct inode *inode = filep->f_inode; FAR struct sensor_upperhalf_s *upper = inode->i_private; FAR struct sensor_lowerhalf_s *lower = upper->lower; FAR struct sensor_user_s *user = filep->f_priv; pollevent_t eventset = 0; int semcount; int ret = 0; nxrmutex_lock(&upper->lock); if (setup) { /* Don't have enough space to store fds */ if (user->fds) { ret = -ENOSPC; goto errout; } user->fds = fds; fds->priv = filep; if (lower->ops->fetch) { /* Always return POLLIN for fetch data directly(non-block) */ if (filep->f_oflags & O_NONBLOCK) { eventset |= POLLIN; } else { nxsem_get_value(&user->buffersem, &semcount); if (semcount > 0) { eventset |= POLLIN; } } } else if (sensor_is_updated(upper, user)) { eventset |= POLLIN; } if (user->changed) { eventset |= POLLPRI; } poll_notify(&fds, 1, eventset); } else { user->fds = NULL; fds->priv = NULL; } errout: nxrmutex_unlock(&upper->lock); return ret; } static ssize_t sensor_push_event(FAR void *priv, FAR const void *data, size_t bytes) { FAR struct sensor_upperhalf_s *upper = priv; FAR struct sensor_lowerhalf_s *lower = upper->lower; FAR struct sensor_user_s *user; unsigned long envcount; int semcount; int ret; nxrmutex_lock(&upper->lock); if (bytes == 0) { list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node) { if (user->flushing) { user->flushing = false; user->event |= SENSOR_EVENT_FLUSH_COMPLETE; sensor_pollnotify_one(user, POLLPRI, user->role); } } nxrmutex_unlock(&upper->lock); return 0; } envcount = bytes / upper->state.esize; if (bytes != envcount * upper->state.esize) { nxrmutex_unlock(&upper->lock); return -EINVAL; } if (!circbuf_is_init(&upper->buffer)) { /* Initialize sensor buffer when data is first generated */ ret = circbuf_init(&upper->buffer, NULL, lower->nbuffer * upper->state.esize); if (ret < 0) { nxrmutex_unlock(&upper->lock); return ret; } ret = circbuf_init(&upper->timing, NULL, lower->nbuffer * TIMING_BUF_ESIZE); if (ret < 0) { circbuf_uninit(&upper->buffer); nxrmutex_unlock(&upper->lock); return ret; } } circbuf_overwrite(&upper->buffer, data, bytes); sensor_generate_timing(upper, envcount); list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node) { if (sensor_is_updated(upper, user)) { nxsem_get_value(&user->buffersem, &semcount); if (semcount < 1) { nxsem_post(&user->buffersem); } sensor_pollnotify_one(user, POLLIN, SENSOR_ROLE_RD); } } nxrmutex_unlock(&upper->lock); return bytes; } static void sensor_notify_event(FAR void *priv) { FAR struct sensor_upperhalf_s *upper = priv; FAR struct sensor_user_s *user; int semcount; nxrmutex_lock(&upper->lock); list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node) { nxsem_get_value(&user->buffersem, &semcount); if (semcount < 1) { nxsem_post(&user->buffersem); } sensor_pollnotify_one(user, POLLIN, SENSOR_ROLE_RD); } nxrmutex_unlock(&upper->lock); } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: sensor_remap_vector_raw16 * * Description: * This function remap the sensor data according to the place position on * board. The value of place is determined base on g_remap_tbl. * * Input Parameters: * in - A pointer to input data need remap. * out - A pointer to output data. * place - The place position of sensor on board, * ex:SENSOR_BODY_COORDINATE_PX * ****************************************************************************/ void sensor_remap_vector_raw16(FAR const int16_t *in, FAR int16_t *out, int place) { FAR const struct sensor_axis_map_s *remap; int16_t tmp[3]; DEBUGASSERT(place < (sizeof(g_remap_tbl) / sizeof(g_remap_tbl[0]))); remap = &g_remap_tbl[place]; tmp[0] = in[remap->src_x] * remap->sign_x; tmp[1] = in[remap->src_y] * remap->sign_y; tmp[2] = in[remap->src_z] * remap->sign_z; memcpy(out, tmp, sizeof(tmp)); } /**************************************************************************** * Name: sensor_register * * Description: * This function binds an instance of a "lower half" Sensor driver with the * "upper half" Sensor device and registers that device so that can be used * by application code. * * We will register the chararter device by node name format based on the * type of sensor. Multiple types of the same type are distinguished by * numbers. eg: accel0, accel1 * * Input Parameters: * dev - A pointer to an instance of lower half sensor driver. This * instance is bound to the sensor driver and must persists as long * as the driver persists. * devno - The user specifies which device of this type, from 0. If the * devno alerady exists, -EEXIST will be returned. * * Returned Value: * OK if the driver was successfully register; A negated errno value is * returned on any failure. * ****************************************************************************/ int sensor_register(FAR struct sensor_lowerhalf_s *lower, int devno) { FAR char *path; int ret; DEBUGASSERT(lower != NULL); path = lib_get_pathbuffer(); if (path == NULL) { return -ENOMEM; } snprintf(path, PATH_MAX, DEVNAME_FMT, g_sensor_meta[lower->type].name, lower->uncalibrated ? DEVNAME_UNCAL : "", devno); ret = sensor_custom_register(lower, path, g_sensor_meta[lower->type].esize); lib_put_pathbuffer(path); return ret; } /**************************************************************************** * Name: sensor_custom_register * * Description: * This function binds an instance of a "lower half" Sensor driver with the * "upper half" Sensor device and registers that device so that can be used * by application code. * * You can register the character device type by specific path and esize. * This API corresponds to the sensor_custom_unregister. * * Input Parameters: * dev - A pointer to an instance of lower half sensor driver. This * instance is bound to the sensor driver and must persists as long * as the driver persists. * path - The user specifies path of device. ex: /dev/uorb/xxx. * esize - The element size of intermediate circular buffer. * * Returned Value: * OK if the driver was successfully register; A negated errno value is * returned on any failure. * ****************************************************************************/ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower, FAR const char *path, size_t esize) { FAR struct sensor_upperhalf_s *upper; int ret = -EINVAL; DEBUGASSERT(lower != NULL); if (lower->type >= SENSOR_TYPE_COUNT || !esize) { snerr("ERROR: type is invalid\n"); return ret; } /* Allocate the upper-half data structure */ upper = kmm_zalloc(sizeof(struct sensor_upperhalf_s)); if (!upper) { snerr("ERROR: Allocation failed\n"); return -ENOMEM; } /* Initialize the upper-half data structure */ list_initialize(&upper->userlist); upper->state.esize = esize; upper->state.min_interval = UINT32_MAX; if (lower->ops->activate) { upper->state.nadvertisers = 1; } nxrmutex_init(&upper->lock); /* Bind the lower half data structure member */ lower->priv = upper; lower->sensor_lock = sensor_lock; lower->sensor_unlock = sensor_unlock; if (!lower->ops->fetch) { if (!lower->nbuffer) { lower->nbuffer = 1; } lower->push_event = sensor_push_event; } else { lower->notify_event = sensor_notify_event; lower->nbuffer = 0; } #ifdef CONFIG_SENSORS_RPMSG lower = sensor_rpmsg_register(lower, path); if (lower == NULL) { ret = -EIO; goto rpmsg_err; } #endif upper->state.nbuffer = lower->nbuffer; upper->lower = lower; sninfo("Registering %s\n", path); ret = register_driver(path, &g_sensor_fops, 0666, upper); if (ret) { goto drv_err; } return ret; drv_err: #ifdef CONFIG_SENSORS_RPMSG sensor_rpmsg_unregister(lower); rpmsg_err: #endif nxrmutex_destroy(&upper->lock); kmm_free(upper); return ret; } /**************************************************************************** * Name: sensor_unregister * * Description: * This function unregister character node and release all resource about * upper half driver. * * Input Parameters: * dev - A pointer to an instance of lower half sensor driver. This * instance is bound to the sensor driver and must persists as long * as the driver persists. * devno - The user specifies which device of this type, from 0. ****************************************************************************/ void sensor_unregister(FAR struct sensor_lowerhalf_s *lower, int devno) { FAR char *path; path = lib_get_pathbuffer(); if (path == NULL) { return; } snprintf(path, PATH_MAX, DEVNAME_FMT, g_sensor_meta[lower->type].name, lower->uncalibrated ? DEVNAME_UNCAL : "", devno); sensor_custom_unregister(lower, path); lib_put_pathbuffer(path); } /**************************************************************************** * Name: sensor_custom_unregister * * Description: * This function unregister character node and release all resource about * upper half driver. This API corresponds to the sensor_custom_register. * * Input Parameters: * dev - A pointer to an instance of lower half sensor driver. This * instance is bound to the sensor driver and must persists as long * as the driver persists. * path - The user specifies path of device, ex: /dev/uorb/xxx ****************************************************************************/ void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *lower, FAR const char *path) { FAR struct sensor_upperhalf_s *upper; DEBUGASSERT(lower != NULL); DEBUGASSERT(lower->priv != NULL); upper = lower->priv; sninfo("UnRegistering %s\n", path); unregister_driver(path); #ifdef CONFIG_SENSORS_RPMSG sensor_rpmsg_unregister(lower); #endif nxrmutex_destroy(&upper->lock); if (circbuf_is_init(&upper->buffer)) { circbuf_uninit(&upper->buffer); circbuf_uninit(&upper->timing); } kmm_free(upper); }

#include "ADC_Config.h" #define ADCIP_CTRL (*(uint32_t*)(0x40020800+0x60)) /* ADC时钟: 14MHZ 声音范围:20Hz~20KHz TIME触发ADC:TIM频率 128K ADC采样时间 = (71.5 +12.5)/14 采样频率:128K 采样个数: 125ms=8HZ 128K/8Hz=16000次, 512K/8HZ=64000 64000/256=250 BUFF0大小256 BUFF1大小128,DMA HT中断,即要中断16000/128=125次 每125次求和 PA1:ADC_IN1 30-70DB PA2: ADC_IN2 70-100DB PA3:ADC_IN3 100-130DB 采样125ms: 共要计算 16000组数据 采样1s: 共要计算 16000*8=128000组数据 设置DMA BUFF大小 256组 HT中断 中断时间1ms 中断程序耗费8.8us 那么 采样125ms就需要中断 125000/1=125次 9K的信号能采样14组 那么 采样1s就需要中断 125*8=1000次 DMA_MEM 从开始到计算结束 用时140us 不会超过一次ADC DMA中断时间 数据不会被覆盖 */ ADC_BUFF Noise_Data; DMA_InitType DMA_InitStructure, DMA_InitStructure_MEM; u8 USB_Busy ; ADC_InitType ADC_InitStructure; extern uint16_t DMA_Test_Value[5], DMA_Test_Value1[5]; void TIM2_ETR_Config(void) { TIM_TimeBaseInitType TIM_TimeBaseStructure; OCInitType TIM_OCInitStructure; RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE); TIM_TimeBaseStructure.Period = TRG_FREQ_USER - 1; //64k TIM_TimeBaseStructure.Prescaler = 0; TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1; TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP; TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure); TIM_OCInitStructure.OcMode = TIM_OCMODE_PWM1; TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE; TIM_OCInitStructure.Pulse = TRG_FREQ_USER / 2 - 1; TIM_OCInitStructure.OcPolarity = TIM_OC_POLARITY_LOW; TIM_InitOc2(TIM2, &TIM_OCInitStructure); TIM_ConfigInt(TIM2, TIM_INT_CC2, ENABLE); /* TIM2 enable counter */ TIM_Enable(TIM2, ENABLE); TIM_EnableCtrlPwmOutputs(TIM2, ENABLE); } /** * @brief Configures the different system clocks. */ void RCC_Configuration(void) { /* Enable peripheral clocks ------------------------------------------------*/ /* Enable DMA clocks */ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE); /* Enable GPIOC clocks */ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); /* Enable ADC clocks */ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE); /* RCC_ADCHCLK_DIV16*/ ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV2);//96/2=48M RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE, RCC_ADC1MCLK_DIV12); //selsect HSE as RCC ADC1M CLK Source } /** * @brief Configures the different GPIO ports. */ void GPIO_Configuration(void) { GPIO_InitType GPIO_InitStructure; GPIO_InitStruct(&GPIO_InitStructure); /* Configure GPIO_PIN_WIFI_RST GPIO_PIN_WIFI_CEN GPIO_PIN_WIFI_RX GPIO_PIN_WIFI_TX as analog input ---------*/ GPIO_InitStructure.Pin = GPIO_PIN_WIFI_RST | GPIO_PIN_WIFI_CEN | GPIO_PIN_WIFI_RX | GPIO_PIN_WIFI_TX | GPIO_PIN_BATT; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Analog; GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); } //配置DMA中断 void NVIC_DMA_Config(void) { NVIC_InitType NVIC_InitStructure; //DMA通道6中断设置 NVIC_InitStructure.NVIC_IRQChannel = DMA_Channel1_IRQn;// DMA1_Channel2_3_IRQn NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能 NVIC_Init(&NVIC_InitStructure); } void Change_Addr_MEM(MEA_GROUP_TypeDef MeaGroup) { DMA_EnableChannel(DMA_CH6, DISABLE); switch(MeaGroup) { case GROUP0: DMA_InitStructure_MEM.PeriphAddr = (uint32_t)Noise_Data.Buff0; break; case GROUP1: DMA_InitStructure_MEM.PeriphAddr = (uint32_t)(&Noise_Data.Buff0[DMA_BUFF_SIZE / 2]); break; } DMA_Init(DMA_CH6, &DMA_InitStructure_MEM); if(USB_Busy == 0) //对EEPROM数据进行释放锁后才去打开DMA3 { DMA_EnableChannel(DMA_CH6, ENABLE ); } else { DMA_EnableChannel(DMA_CH6, DISABLE ); } } void ADC_DMA_Cfg(void) { SysData.DMA_Group = 0; /* System clocks configuration ---------------------------------------------*/ RCC_Configuration(); /* GPIO configuration ------------------------------------------------------*/ GPIO_Configuration(); NVIC_DMA_Config(); /* DMA channel1 configuration ----------------------------------------------*/ DMA_DeInit(DMA_CH1); DMA_InitStructure.PeriphAddr = (uint32_t)&ADC->DAT; DMA_InitStructure.MemAddr = (uint32_t)Noise_Data.Buff0; DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC; DMA_InitStructure.BufSize = DMA_BUFF_SIZE; DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE; DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE; DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD; DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;//DMA_MODE_CIRCULAR; DMA_InitStructure.Priority = DMA_PRIORITY_HIGH; DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE; DMA_Init(DMA_CH1, &DMA_InitStructure); DMA_RequestRemap(DMA_REMAP_ADC1, DMA, DMA_CH1, ENABLE); DMA_ClrIntPendingBit(DMA_INT_TXC1, DMA); // DMA_ClrIntPendingBit(DMA_INT_HTX1,DMA); DMA_ConfigInt(DMA_CH1, DMA_INT_TXC, ENABLE); // DMA_ConfigInt(DMA_CH1,DMA_INT_HTX,ENABLE); /* Enable DMA channel1 */ DMA_EnableChannel(DMA_CH1, ENABLE); ADC_DeInit(ADC); /* ADC1 configuration ------------------------------------------------------*/ ADC_InitStructure.MultiChEn = ENABLE; ADC_InitStructure.ContinueConvEn = DISABLE; ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_T2_CC2; ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R; ADC_InitStructure.ChsNumber = 4; ADC_Init(ADC, &ADC_InitStructure); ADCIP_CTRL = 0x28; //在ADC使能前配置这个 ADC_EnableTempSensorVrefint( ENABLE); /* ADC1 regular channel13 configuration */ ADC_ConfigRegularChannel(ADC, ADC_CH_1_PA0, 1, ADC_SampleTime_User);//WIFI_RST ADC_ConfigRegularChannel(ADC, ADC_CH_2_PA1, 2, ADC_SampleTime_User);//WIFI_CEN ADC_ConfigRegularChannel(ADC, ADC_CH_3_PA2, 3, ADC_SampleTime_User);//WIFI_RX ADC_ConfigRegularChannel(ADC, ADC_CH_4_PA3, 4, ADC_SampleTime_User);//WIFI_TX ADC_EnableExternalTrigConv(ADC, ENABLE); ADC_ConfigInt(ADC, ADC_INT_ENDC, ENABLE); /* Enable ADC DMA */ ADC_EnableDMA(ADC, ENABLE); /* Enable ADC */ ADC_Enable(ADC, ENABLE); /* Check ADC Ready */ while(ADC_GetFlagStatusNew(ADC, ADC_FLAG_RDY) == RESET); /* Start ADC1 calibration */ ADC_StartCalibration(ADC); /* Check the end of ADC1 calibration */ while (ADC_GetCalibrationStatus(ADC)); } #ifndef __ADC_CONFIG_H #define __ADC_CONFIG_H #include "main.h" #define ADC1_DR_Address 0x40012440 #define TRG_FREQ_1M 72 #define TRG_FREQ_500K 144 #define TRG_FREQ_600K 120 #define TRG_FREQ_300K 240 #define TRG_FREQ_50K 1440 //#define TRG_FREQ_64K 1125 //#define TRG_FREQ_32K 1125*2 #define TRG_FREQ_128K 1125 #define TRG_FREQ_64K 750 #define TRG_FREQ_USER TRG_FREQ_64K #define ADC_SampleTime_User ADC_SAMP_TIME_71CYCLES5 //要求大于 64*4=256K 48/(71.5+12.5+16)=480K >256K #define DMA_CAL_BUFF_SIZE 3200 //125ms*64*4=32000=3200*10= DMA_CAL_BUFF_SIZE*SMP_DMA_CNT 3200/64=50ms 中断一次 #define DMA_BUFF_SIZE DMA_CAL_BUFF_SIZE typedef enum { GROUP0 = 0x00, GROUP1 = 0x01, } MEA_GROUP_TypeDef; typedef struct { //ADC DMA 用 u16 Buff0[DMA_CAL_BUFF_SIZE]; u16 Buff1[DMA_CAL_BUFF_SIZE]; } ADC_BUFF; extern ADC_BUFF Noise_Data; void ADC_Config(MEA_RANGE_TypeDef MeaRange); void DMA_Config(void); void NVIC_DMA_Config(void); void DMA_Config_MEM(void); void TIM2_ETR_Config(void); void Change_Addr_MEM(MEA_GROUP_TypeDef MeaGroup); void ADC_DMA_Cfg(void); #endif /***************************************************************************** * Copyright (c) 2022, Nations Technologies Inc. * * All rights reserved. * **************************************************************************** * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the disclaimer below. * * Nations' name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /** * @file n32g43x_it.c * @author Nations * @version v1.2.0 * * @copyright Copyright (c) 2022, Nations Technologies Inc. All rights reserved. */ #include "n32g43x_it.h" #include "n32g43x.h" #include "main.h" #include "usb_istr.h" /** @addtogroup N32G43X_StdPeriph_Template * @{ */ extern __IO uint32_t CurrDataCounterEnd; /******************************************************************************/ /* Cortex-M4 Processor Exceptions Handlers */ /******************************************************************************/ /** * @brief This function handles NMI exception. */ void NMI_Handler(void) { } /** * @brief This function handles Hard Fault exception. */ void HardFault_Handler(void) { /* Go to infinite loop when Hard Fault exception occurs */ while (1) { } } /** * @brief This function handles Memory Manage exception. */ void MemManage_Handler(void) { /* Go to infinite loop when Memory Manage exception occurs */ while (1) { } } /** * @brief This function handles Bus Fault exception. */ void BusFault_Handler(void) { /* Go to infinite loop when Bus Fault exception occurs */ while (1) { } } /** * @brief This function handles Usage Fault exception. */ void UsageFault_Handler(void) { /* Go to infinite loop when Usage Fault exception occurs */ while (1) { } } /** * @brief This function handles SVCall exception. */ void SVC_Handler(void) { } /** * @brief This function handles Debug Monitor exception. */ void DebugMon_Handler(void) { } /** * @brief This function handles DMA interrupt request defined in main.h . */ void DMA_IRQ_HANDLER(void) { } /** * @brief This function handles USB_LP_IRQHandler Handler. */ void USB_LP_IRQHandler(void) { USB_Istr(); } /** * @brief This function handles USB WakeUp interrupt request. */ void USBWakeUp_IRQHandler(void) { EXTI_ClrITPendBit(EXTI_LINE17); } void DMA_Channel1_IRQHandler(void) { //国民芯片在一个DMA通道里面 配置另一个DMA通道会导致当前通道顺序异常 //这里配置 2us完成 ADC 一次的时间是15.4us 足够赶上下一次ADC完成 if(DMA_GetIntStatus(DMA_INT_TXC1, DMA) != RESET) //全传输完 { DMA_ClrIntPendingBit(DMA_INT_TXC1, DMA); //国民芯片 建议传输完成 重新配置TXNUM 否则可能出现顺序错乱 DMA_CH1->CHCFG &= (uint16_t)(~DMA_CHCFG1_CHEN); DMA_CH1->TXNUM = DMA_BUFF_SIZE; SysData.DMA_Group = !SysData.DMA_Group; DMA_CH1->MADDR = (uint32_t)Noise_Data.Buff0; if(SysData.DMA_Group != 0) { DMA_CH1->MADDR = (uint32_t)Noise_Data.Buff1; } DMA_CH1->CHCFG |= DMA_CHCFG1_CHEN; SysFlag.DMA_OK = 1; } } void DMA_Channel6_IRQHandler(void) { if(DMA_GetIntStatus(DMA_INT_TXC6, DMA) != RESET) { DMA_ClrIntPendingBit(DMA_INT_TXC6, DMA); // Get_AD_SUM(); } } void ADC_IRQHandler(void) { if(ADC_GetIntStatus(ADC, ADC_INT_ENDC) != RESET) { ADC_ClearIntPendingBit(ADC, ADC_INT_ENDC); // LED1_Turn(); } } void TIM2_IRQHandler(void) { if(TIM_GetFlagStatus(TIM2, TIM_FLAG_CC2) == SET) { TIM_ClearFlag(TIM2, TIM_FLAG_CC2); // LED1_Turn(); // test1++; } } void TIM3_IRQHandler(void) { if(TIM_GetFlagStatus(TIM3, TIM_FLAG_UPDATE) == SET) { TIM_ClearFlag(TIM3, TIM_FLAG_UPDATE); // Clock_150++; // Clock_500++; // Clock_750++; // SysClock++; // // Buzzer_Process(); } } void TIM4_IRQHandler(void) { if(TIM_GetFlagStatus(TIM4, TIM_FLAG_UPDATE) == SET) { TIM_ClearFlag(TIM4, TIM_FLAG_UPDATE); Clock_150++; Clock_500++; Clock_750++; SysClock++; LED1_Turn(); Buzzer_Process(); } } void EXTI9_5_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_LINE8) != RESET) { EXTI_ClrITPendBit(EXTI_LINE8); SysFlag.PWD = 1; Clock_500 = 0; if((SysFlag.EraseDoing) && (SysInfo.PWRON_Erase == 0)) { SysInfo.PWRON_Erase = 1; Save_Param(&SysInfo.PWRON_Erase, sizeof(SysInfo.PWRON_Erase)); } } } /** * @brief This function handles SysTick Handler. */ u32 Time_1ms = 0; void SysTick_Handler(void) { Time_1ms++; } /******************************************************************************/ /* N32G43X Peripherals Interrupt Handlers */ /* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ /* available peripheral interrupt handler's name please refer to the startup */ /* file (startup_n32g43x.s). */ /******************************************************************************/ /** * @brief This function handles PPP interrupt request. */ /*void PPP_IRQHandler(void) { }*/ /** * @} */ void Get_AD_SUM(void) { uint64_t Sum[3] = {0, 0, 0}; //这里有3种计算,分别是sum[0],sum[1],sum[2] u8 Ratio; u16 loopi, *Data; u32 Temp; Data = Noise_Data.Buff1;//将DMA移过来的地址给Data if(SysData.DMA_Group != 0) Data = Noise_Data.Buff0;//将DMA移过来的地址给Data SysData.BattCnt = 0; //sum[0] for(loopi = 0; loopi < DMA_CAL_BUFF_SIZE; loopi += 4) //循环480/3=150次 { Temp = (u32)(*Data); //将Noise_Data.Buff1的值给Temp Data++;//地址++ if(Temp > ADC_HLimit) SysData.OverCntt[0]++; //如果Temp>2482,数据溢出的标志位++,这个数据溢出的标志位也有3种,用数组来表示 Temp = Temp + (s32)SysInfo.Cal_Adc[0];// 这个应该是存放校准后的ADC if(Temp > 0x80000000)Temp = 0; Temp = Temp * Temp; //不知道平方一次是用来干啥的 Sum[0] += (uint64_t)Temp; //计算总和,存到sum[0] //sum[1] Temp = (u32)(*Data); Data++; if(Temp > ADC_HLimit_H) SysData.OverCntt[1]++; Temp = Temp + (s32)SysInfo.Cal_Adc[1]; if(Temp > 0x80000000)Temp = 0; Temp = Temp * Temp; Sum[1] += (uint64_t)Temp; //计算总和,存到sum[1] //sum[2] Temp = (u32)(*Data); Data++; Temp = Temp + (s32)SysInfo.Cal_Adc[2]; if(Temp > 0x80000000) Temp = 0; Temp = Temp * Temp; Sum[2] += (uint64_t)Temp; //计算总和,存到sum[2] if(SysData.BattCnt < 64) { SysData.BattBuff[SysData.BattCnt++] = *Data; } Data++; } SysData.Batt = 0; for(loopi = 0; loopi < 64; loopi++) { SysData.Batt += SysData.BattBuff[loopi]; } SysData.Batt = SysData.Batt / 64; // //报警时低于3.3V不关机问题,电源检测这里添加关机 // if(SysData.Batt < BattSHUT) // { // Shut_Down(); // } //将计算的总和,存到SysData.ADC_VALUE SysData.ADC_VALUE[0] += (double)Sum[0]; SysData.ADC_VALUE[1] += (double)Sum[1]; SysData.ADC_VALUE[2] += (double)Sum[2]; SysData.ADC_CNT++; Ratio = SysData.Freq_Resp * 7 + 1; //不知道这2句是干嘛的 if(SysData.ADC_CNT >= (SMP_DMA_CNT * Ratio)) { SysData.ADC_CNT = 0; // if(SysData.Cal_Mode == 0) // { // if(SysData.OverCntt[0] < MIN_OVER_CNT) //溢出计数判断 // { // SysData.Adc_Range = RANG_70DB; // } // else if(SysData.OverCntt[1] < MIN_OVER_CNT) // { // SysData.Adc_Range = RANG_100DB; // } // else // { // SysData.Adc_Range = RANG_130DB; // } // } SysData.ADC_Sum_Value = (SysData.ADC_VALUE[SysData.Adc_Range] / (float)Ratio) + SysInfo.Cal_Adc_Squ[SysData.Adc_Range]; if(SysData.ADC_Sum_Value < 0) { ; } else { // Get_Noise_Data(); } SysData.ADC_VALUE[0] = 0; SysData.ADC_VALUE[1] = 0; SysData.ADC_VALUE[2] = 0; SysData.OverCntt[0] = 0; SysData.OverCntt[1] = 0; SysData.OverCntt[2] = 0; } } void Get_Noise_Data(void) { Phasea = SysData.ADC_Sum_Value; /* 523公式:10*log10(SysData.ADC_Sum_Value) *10 //是为了扩大10倍 用于获取小数部分,来显示 */ Phasea = log10(Phasea); Phasea = Phasea * 1000; Phaseb = (u32)Phasea; SysData.CAL_INT_Value = Phaseb + SysInfo.Cal_DB[SysData.Adc_Range]; SysData.ADC_INT_Value = SysData.CAL_INT_Value / 10; if(SysData.Cal_Mode == 0) { if(SysData.ADC_TAB_CNT == 0) { SysData.ADC_TAB_CNT = 1; SysData.ADC_INT_Value_TAB[1] = SysData.ADC_INT_Value; SysData.ADC_INT_Value_TAB[2] = SysData.ADC_INT_Value; SysData.ADC_INT_Value_TAB[3] = SysData.ADC_INT_Value; } else { SysData.ADC_INT_Value_TAB[3] = SysData.ADC_INT_Value_TAB[2]; SysData.ADC_INT_Value_TAB[2] = SysData.ADC_INT_Value_TAB[1]; SysData.ADC_INT_Value_TAB[1] = SysData.ADC_INT_Value_TAB[0]; } SysData.ADC_INT_Value_TAB[0] = SysData.ADC_INT_Value; } else { SysData.CalEn = 1; if(SysData.Adc_Range == RANG_130DB) { if(SysData.ADC_INT_Value == 1300) { SysFlag.FlickEn = 1; } else { SysFlag.FlickEn = 0; } } } } 保留温湿度和电压,去除噪音

完成一个仓储环境监测的模拟系统。具体要求如下: 1. DHT11模块完成温湿度测量,5s更新,数值显示于数码管,同时打印到串口。温度超过阈值触发蜂鸣器短鸣,同时启动风扇小马达; 2. LDR模块完成环境照度测量,4s更新,数值显示于数码管,同时打印到串口。照度超过阈值启动PWM调光(高、中、低三级调光)。 3. 按键循环切换显示模式,按第1下固定显示温度,按第二下固定显示照度,按第三下恢复默认的自动显示模式。按键用外部中断实现 int main(void) { systick_init(72); led_init(); usart1_init(115200); display_init(); tim4_init(1000,72); // 1ms的定时间隔 TIM3_CH2_PWM_Init(500-1,72-1); dht11_init(); ldr_init(); //key_init(); while(1) { // 轮询DHT11的状态 if(dht11.state == WORK) { if(dht11.getData(&dht11.temp, &dht11.humi) == SUCCESS) // DHT11温湿度数据更新 { printf("temperature:%d℃ humidity(RH):%d \r\n", dht11.temp, dht11.humi); dsp.interface = TEMP; dht11.onTempChange(dht11.temp_threshold); // 温度超过阈值的处理 } dht11.state = STANDBY; } // 轮询LDR的状态 if(ldr.state == WORK) { ldr.light = ldr.getData(); printf("light intensity:%d \r\n", ldr.light); dsp.interface = LIGHT; ldr.onLightChange(ldr.high_threshold,ldr.low_threshold); // 照度超过阈值的处理 ldr.state = STANDBY; } // 轮询数码管界面状态 switch(dsp.interface) { case LIGHT: setLightValue(&dsp,1); break; case TEMP: setTempValue(&dsp,1); break; case HUMI: setHumiValue(&dsp,1); break; default: break; } } }#include "systick.h" static u8 fac_us=0; //us延时倍乘数 static u16 fac_ms=0; //ms延时倍乘数 //初始化延迟函数 //SYSTICK的时钟固定为AHB时钟的1/8 //SYSCLK:系统时钟频率 void systick_init(u8 SYSCLK) { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); fac_us = SYSCLK/8; fac_ms = (u16)fac_us * 1000; } //延时nus //nus为要延时的us数. void delay_us(u32 nus) { u32 temp; SysTick->LOAD=nus*fac_us; //时间加载 SysTick->VAL=0x00; //清空计数器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } //延时nms //注意nms的范围 //SysTick->LOAD为24位寄存器,所以,最大延时为: //nms<=0xffffff*8*1000/SYSCLK //SYSCLK单位为Hz,nms单位为ms //对72M条件下,nms<=1864 void delay_ms(u16 nms) { u32 temp; SysTick->LOAD = (u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit) SysTick->VAL = 0x00; //清空计数器 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; } while((temp&0x01) && !(temp&(1<<16))); //等待时间到达 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL = 0x00; //清空计数器 } #include "display.h" DisplayStruct dsp; void segDisplay(void); // 共阴极数码管,阴极位选(0有效),阳极段选(1有效) const u16 segCode[11] = { /* 0 1 2 3 4 5 6 7 */ 0x003F, 0x0006, 0x005B, 0x004F, 0x0066, 0x006D, 0x007D, 0x0007, /* 8 9 off */ 0x007F, 0x006F, 0x0000 }; /******************************************************************************* * @brief 初始化数码管用到的GPIO端口和dsp结构体 * @param None * @retval None *******************************************************************************/ void display_init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); // PA0~PA7: 段选(分别连接引脚A~G); // PB12~PB15:位选(分别连接引脚D1~D4) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); dsp.currDigit = 1; // dsp结构体的初始化 dsp.SegDisplay = segDisplay; } /*********************************************************************************** * @brief 设置数码管要显示的4位数值。 * @param dsp:数码管结构体指针;value[4]:4位数值;dotBit:小数点位置(没有小数点则置0) * @retval None ***********************************************************************************/ void setValue(DisplayStruct *dsp, u8 value[4], u8 dotBit) { dsp->digit[0] = value[0]; dsp->digit[1] = value[1]; dsp->digit[2] = value[2]; dsp->digit[3] = value[3]; dsp->dotDigit = dotBit; } void setLightValue(DisplayStruct *dsp, u8 dotBit) { dsp->digit[0] = 1; // 参数编号 dsp->digit[1] = 10; // 第二位空缺 dsp->digit[2] = ldr.light/10; dsp->digit[3] = ldr.light%10; // dsp->dotDigit = dotBit; // 小数点位置 } void setTempValue(DisplayStruct *dsp, u8 dotBit) { dsp->digit[0] = 2; dsp->digit[1] = 10; dsp->digit[2] = dht11.temp/10; dsp->digit[3] = dht11.temp%10; dsp->dotDigit = dotBit; } void setHumiValue(DisplayStruct *dsp, u8 dotBit) { dsp->digit[0] = 3; dsp->digit[1] = 10; dsp->digit[2] = dht11.humi/10; dsp->digit[3] = dht11.humi%10; dsp->dotDigit = dotBit; } /******************************************************************************* * @简 介 段选,让某一位数码管显示指定的数字 * @输入参数 value:段码数组的序号(0~9),代表要显示的数字 * @retval * 备注:只操作PA的低8位,不要影响高8位。 ********************************************************************************/ void seg(uint8_t value) { if(value < sizeof(segCode)) // 避免数组溢出 { GPIOA->ODR &= 0xFF00; GPIOA->ODR |= segCode[value]; } } /******************************************************************************** * 简 介 位选,一次只能选一位。 * 输入参数 com:位数(取值1~4,从左到右) * 返回值 无 * 备注:只操作PB的高4位(置0),不要影响其他位。 ********************************************************************************/ void com(uint8_t currDigit) { // 数码管位选(0有效) GPIOB->ODR |= 0xF000; GPIOB->ODR &= ~(0x1000<<(currDigit-1)); } /******************************************************************************** * 简介 在数码管上逐位显示其段码(由Timer中断服务函数调用) * 参数 无 * 返回值 无 ********************************************************************************/ void segDisplay(void) { seg(10); // 消隐之前的显示内容 com(dsp.currDigit); // 位选,从COM1到COM4逐次移位,实现动态显示 if(dsp.currDigit != dsp.dotDigit) // 当前位不显示小数点 seg(dsp.digit[dsp.currDigit-1]); else // 当前位要显示小数点 { GPIO_Write(GPIOA, segCode[dsp.digit[dsp.currDigit-1]]| 0x0080); //GPIOA->ODR &= 0xFF00; //GPIOA->ODR |= (segCode[dsp.currDigit-1]|0x0080); } if(++dsp.currDigit > DSP_DIGIT) // 从当前位右移到下一位 dsp.currDigit = 1; } #include "usart.h" int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用 { USART_SendData(USART1,(u8)ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); return ch; } //串口1中断服务程序 //注意,读取USARTx->SR能避免莫名其妙的错误 u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART1_RX_STA=0; //接收状态标记 /******************************************************************************* * 函 数 名 : USART1_Init * 函数功能 : USART1初始化函数 * 输 入 : bound:波特率 * 输 出 : 无 *******************************************************************************/ void usart1_init(u32 baud) { //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); /* 配置GPIO的模式和IO口 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //串口输出TX:PA9 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; //串口输入RX:PA10 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //模拟输入 GPIO_Init(GPIOA,&GPIO_InitStructure); //USART1 初始化设置 USART_InitStructure.USART_BaudRate = baud; //波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_Cmd(USART1, ENABLE); //使能串口1 USART_ClearFlag(USART1, USART_FLAG_TC); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、 } /******************************************************************************* * 函 数 名 : USART1_IRQHandler * 函数功能 : USART1中断函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void USART1_IRQHandler(void) //串口1中断服务程序 { u8 r; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断 { r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据 if((USART1_RX_STA&0x8000)==0)//接收未完成 { if(USART1_RX_STA&0x4000)//接收到了0x0d { if(r!=0x0a)USART1_RX_STA=0;//接收错误,重新开始 else USART1_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(r==0x0d)USART1_RX_STA|=0x4000; else { USART1_RX_BUF[USART1_RX_STA&0X3FFF]=r; USART1_RX_STA++; if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收 } } } } } #include "timer.h" #include "beep.h" volatile uint16_t beep_time; /******************************************************************************* * 函 数 名 : tim4_init * 函数功能 : TIM4初始化函数 * 输 入 : per:重装载值 psc:分频系数 * 输 出 : 无 *******************************************************************************/ void tim4_init(u16 per,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); // 使能TIM4的时钟 // 配置TIM的时基参数 TIM_TimeBaseInitStructure.TIM_Period = per; // 自动装载值 TIM_TimeBaseInitStructure.TIM_Prescaler = psc; // 分频系数 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; // 设置向上计数模式 TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure); // 设置参数生效 // 配置中断参数 TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); // 开启定时器的更新中断 TIM_ClearITPendingBit(TIM4,TIM_IT_Update); // 中断标志位清零 // 配置NVIC NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 中断优先级分组(组2) NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; // 定时器4的中断通道(30号通道) NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 响应优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 中断通道使能 NVIC_Init(&NVIC_InitStructure); // NVIC设置参数生效 TIM_Cmd(TIM4,ENABLE); // 使能Timer4 } /******************************************************************************* * 函 数 名 : TIM4_IRQHandler * 函数功能 : TIM4中断函数 * 输 入 : 无 * 输 出 : 无 * 备 注 : 定时间隔1ms ** *****************************************************************************/ void TIM4_IRQHandler(void) { static u16 cnt_dht11; static u16 cnt_ldr; // 蜂鸣器时间处理 if(beep_time > 0) { beep_time--; if(beep_time == 0) { BEEP_OFF(); } } if(TIM_GetITStatus(TIM4,TIM_IT_Update)) // 检查更新中断是否产生 { // 处理定时任务 if(++cnt_dht11 == dht11.period) { if(dht11.state == STANDBY) { dht11.state = WORK; // DHT11状态从STANDBY切换到WORK } cnt_dht11 = 0; } if(++cnt_ldr == ldr.period) { if (ldr.state == STANDBY) { ldr.state = WORK; // LDR状态从STANDBY切换到WORK } cnt_ldr = 0; } // 刷新数码管显示 dsp.SegDisplay(); } TIM_ClearITPendingBit(TIM4,TIM_IT_Update); // 手动清除中断标志位 } #include "dht11.h" #include "relay.h" #include "beep.h" Dht11Struct dht11 = {0}; void SET_DHT11_IO_OUT(void); void SET_DHT11_IO_IN(void); void DHT11_RequestData(void); u8 DHT11_RespondRequest(void); u8 DHT11_Read_Data(u8 *temp, u8 *humi); void DHT11_OnTempChange(u8 temp_threshold); // DHT11_PIN初始化 // 返回值: 无 extern void dht11_init() { GPIO_InitTypeDef GPIO_InitStructure; // 数据引脚初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 数据引脚 GPIO_InitStructure.GPIO_Pin = DHT11_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(DHT11_PORT, &GPIO_InitStructure); GPIO_SetBits(DHT11_PORT, DHT11_PIN); // 初始输出状态:高电平 // 结构体初始化 dht11.period = DHT11_PERIOD; dht11.temp_threshold = TEMP_THRESHOLD; dht11.getData = DHT11_Read_Data; // 获取温湿度数据的函数 dht11.onTempChange = DHT11_OnTempChange; // 温度超过阈值的处理函数 // 做一次数据请求测试,检查设备状态 DHT11_RequestData(); if (DHT11_RespondRequest() == SUCCESS) { dht11.state = STANDBY; printf("DHT11 Init OK!\r\n"); } else { dht11.state = FAIL; printf("DHT11 Check Error!\r\n"); } } // 复位DHT11,单片机向DHT11发起数据采集请求 // 时序图的黑线部分 static void DHT11_RequestData() { SET_DHT11_IO_OUT(); // 数据引脚配置为输出模式 DHT11_DQ_OUT = 0; delay_ms(20); // 低电平持续至少18ms DHT11_DQ_OUT = 1; delay_us(30); // 高电平持续20~40us } // DHT11响应单片机的数据请求 // 返回值:SUCCESS or FAILURE static u8 DHT11_RespondRequest() { u8 retry=0; SET_DHT11_IO_IN(); // 数据引脚设为输入模式,接收DHT11的响应 while (DHT11_DQ_IN && retry<100) // 等待输入由高变低 { retry++; if(retry >= 100) return FAILURE; // 等待时间过长,返回异常。 delay_us(1); } retry=0; while (!DHT11_DQ_IN && retry<100) // 低电平持续时间80us { retry++; if(retry >= 100) return FAILURE; // 低电平持续时间过长,返回异常。 delay_us(1); } return SUCCESS; } //DHT11输出模式配置 static void SET_DHT11_IO_OUT() { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(DHT11_PORT,&GPIO_InitStructure); } //DHT11输入模式配置 static void SET_DHT11_IO_IN() { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入模式,最小系统板和DHT11之间并未接上拉电阻 GPIO_Init(DHT11_PORT,&GPIO_InitStructure); } //从DHT11读取一位 //返回值:bit 1或0 //注:此函数处并未做高低电平持续时间异常的处理,因DHT11自身有校验和,即便读错1位也不会造成最终数据的错误。 // 严格来讲,除了正常情况下返回“1”或“0”,还应增加异常情况的返回值(比如“2”)。 static u8 DHT11_Read_Bit(void) { u8 retry=0; while(DHT11_DQ_IN && retry<100) // 等待输入电平由高变低(低电平持续50us) { retry++; delay_us(1); } retry=0; while(!DHT11_DQ_IN && retry<100) // 等待输入电平由低变高 { retry++; delay_us(1); } delay_us(40); // 等待40us(高电平持续26~28us表示0,持续70us表示1) if(DHT11_DQ_IN) return 1; // 40us后如果输入仍为高电平,则表示读入1;否则表示读入0。 else return 0; } //从DHT11读取一个字节 //返回值:读到的8位数据 static u8 DHT11_Read_Byte(void) { u8 i,byte; byte = 0; for (i=0;i<8;i++) { byte <<= 1; // 先前读取的数据(不足8位)全部左移一位 byte |= DHT11_Read_Bit(); // 最低位填入新读取的1位 } return byte; } //从DHT11读取一次完整的数据 //temp:温度值(整数,范围:0~50°) //humi:湿度值(整数,范围:20%~90%) //返回值:0,正常; 1,失败 static u8 DHT11_Read_Data(u8 *temp, u8 *humi) { u8 buf[5]; u8 i; DHT11_RequestData(); if(DHT11_RespondRequest() == SUCCESS) { for(i=0;i<5;i++) // 读取5组共40位数据 { buf[i] = DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3]) == buf[4]) // 数据校验 { *humi = buf[0]; // 湿度整数部分 *temp = buf[2]; // 温度整数部分 return SUCCESS; } } return FAILURE; } // 采集DHT11数据并打印至串口 void dht11DataCollect() { u8 temp; u8 humi; if (DHT11_Read_Data(&temp, &humi) == SUCCESS) printf("temperature:%d℃ humidity(RH):%d \r\n", temp, humi); // 输出到串口(重定向) else printf("DHT11 data error! \r\n"); } // 温度阈值处理 void DHT11_OnTempChange(u8 temp_threshold) { if (dht11.temp > temp_threshold) { // 启动风扇(继电器低电平触发) Relay_Low(); // 蜂鸣器短鸣(100ms) BEEP_ON(); beep_time = 100; // 100ms } else { // 关闭风扇 Relay_High(); } } #include "ldr.h" LdrStruct ldr; static u8 getLightIntensity(void); static void OnLightChange(u8 hiLight, u8 loLight); /******************************************************************************* * 函 数 名 : adc_init * 函数功能 : ADC外设的初始化 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ static void adc_init(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; // 1.打开相关外设的总线时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE); // 2.信号引脚的参数配置 GPIO_InitStructure.GPIO_Pin=LDR_PIN; // 信号引脚:PB0 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; // 设置模拟输入模式 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; // 设置传输速率 GPIO_Init(LDR_PORT,&GPIO_InitStructure); // 3. 输入时钟降频(<14MHz) RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 分频因子6,输入时钟为72M/6=12MHz // 4. 初始化ADC参数 ADC_InitStructure.ADC_Mode=ADC_Mode_Independent; //独立模式 ADC_InitStructure.ADC_ScanConvMode=DISABLE; //单次扫描 ADC_InitStructure.ADC_ContinuousConvMode=DISABLE; //单次转换 ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None; //软件触发 ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right; //数据右对齐 ADC_InitStructure.ADC_NbrOfChannel=1; //只有1个通道 ADC_Init(ADC1,&ADC_InitStructure); // 5. 使能ADC ADC_Cmd(ADC1,ENABLE); // 6. ADC校准 ADC_ResetCalibration(ADC1); //复位校准 while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); //开启并完成校准 while(ADC_GetCalibrationStatus(ADC1)); } // LDR的设备初始化 extern void ldr_init() { adc_init(); ldr.period = LDR_PERIOD; ldr.high_threshold = HI_THRESHOLD; ldr.low_threshold = LO_THRESHOLD; ldr.getData = getLightIntensity; ldr.onLightChange = OnLightChange; ldr.state = STANDBY; } /******************************************************************************* * 函 数 名 : GET_ADC_Value * 函数功能 : 获取通道ch的转换值,测量times次,取平均值 * 输 入 : ch:通道编号,Rank:规则序列中的第几个转换,取值1~16; times:测量次数 * 输 出 : 通道ch的times次转换结果的平均值 *******************************************************************************/ static u16 Get_ADC_Value(u8 ch, u8 times) //获取ADC1通道ch的转换值 { u8 i; u32 Temp_val=0; ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5); for(i=0;i<times;i++) { ADC_SoftwareStartConvCmd(ADC1,ENABLE); // 开始转换 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); // 等待至单次转换结束 Temp_val += ADC_GetConversionValue(ADC1); delay_ms(10); } return Temp_val/times; } /******************************************************************************* * 函 数 名 : getLightIntensity * 函数功能 : 将ADC转换值解读为光照强度 * 输 入 : 无 * 输 出 : 光照照度值(0~100, 0:照度最低;100:照度最高) *******************************************************************************/ static u8 getLightIntensity(void) //通过ADC1 通道0的值获取亮度值 { u16 value = 0; u8 lightvalue = 0; value = Get_ADC_Value(ADC_Channel_8,20); lightvalue = 100 - (u16)(value/40.95); return lightvalue; } // 添加PWM控制LED功能 static void set_led_brightness(u8 level) { switch(level) { case 0: // 低档 TIM_SetCompare2(TIM3, 125); // 25%占空比 break; case 1: // 中档 TIM_SetCompare2(TIM3, 250); // 50%占空比 break; case 2: // 高档 TIM_SetCompare2(TIM3, 375); // 75%占空比 break; } } /******************************************************************************* * 函 数 名 : OnLightChange * 函数功能 : 照度超过阈值(高阈值和低阈值)的处理措施 * 输 入 : hiLight-高阈值; loLight-低阈值 * 输 出 : 无 *******************************************************************************/ static void OnLightChange(u8 hiLight, u8 loLight) { if (ldr.light > hiLight) { set_led_brightness(0);// 照度过高,降低亮度 } else if (ldr.light < loLight) { set_led_brightness(2); // 照度过低,提升亮度 } else // 正常范围 { set_led_brightness(1); // 中等亮度 } } #include "key.h" #include "pwm.h" /******************************************************************************* * 函 数 名 : TIM3_CH2_PWM_Init * 函数功能 : TIM3通道2 PWM初始化函数 * 输 入 : per:重装载值 * psc:分频系数 * 输 出 : 无 *******************************************************************************/ void TIM3_CH2_PWM_Init(u16 per,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* 开启时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE); // PB5引脚启用复用模式 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); // 选择TIM3部分重映射 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); /* PB5作为PWM的输出引脚 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOB,&GPIO_InitStructure); // 初始化TIM3 TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值 TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数 TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); // 设置TIM3_CH2的PWM模式,使能CH2输出,呈现出PPT展示的PWM波形 // PWM1即mode1,先输出有效电平,再输出无效电平;PWM2即mode2则正好相反。 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; // 设置有效电平为低电平(此案例中低电平点亮D2) TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; TIM_OC2Init(TIM3,&TIM_OCInitStructure); //输出比较通道2初始化 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIM3在 CCR2 上的预装载寄存器 TIM_Cmd(TIM3,ENABLE); //使能定时器 } #include "relay.h" void Relay_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStruct); //默认输出低电平 } void Relay_High(void) { GPIO_SetBits(GPIOA, GPIO_Pin_11); } void Relay_Low(void) { GPIO_ResetBits(GPIOA, GPIO_Pin_11); } #ifndef _RELAY_H_ #define _RELAY_H_ #include "main.h" #define RELAY_HIGH 1 #define RELAY_LOW 0 void Relay_Init(void); void Relay_High(void); void Relay_Low(void); #endif #ifndef __PWM_H #define __PWM_H #include "main.h" void TIM3_CH2_PWM_Init(u16 per,u16 psc); #endif #ifndef __LDR_H #define __LDR_H #include "main.h" #define LDR_PIN GPIO_Pin_0 #define LDR_PORT GPIOB #define LDR_PERIOD 4000 // ADC转换周期:4000ms #define HI_THRESHOLD 70 // 照度高阈值 #define LO_THRESHOLD 30 // 照度低阈值 typedef struct{ u8 light; // 光照强度(相对强度:0~100) u16 period; // 重复测量周期(s) u8 high_threshold; // 高亮阈值 u8 low_threshold; // 低亮阈值 SensorState state; // 工作状态 u8 (*getData)(void); // 获取光照强度数据 void (*onLightChange)(u8 hiLight, u8 loLight); // 亮度变化的响应操作 } LdrStruct; void ldr_init(void); extern LdrStruct ldr; #endif #ifndef __DHT11_H #define __DHT11_H #include "main.h" #define DHT11_PIN GPIO_Pin_12 #define DHT11_PORT GPIOA #define DHT11_DQ_IN PCin(12) // 输入 #define DHT11_DQ_OUT PCout(12) // 输出 #define SUCCESS 0 #define FAILURE 1 #define DHT11_PERIOD 5000 // 数据采集周期:5000ms #define TEMP_THRESHOLD 28 // 温度阈值(℃) // 定义DHT11结构体 typedef struct{ u8 temp; // 温度值 u8 humi; // 湿度值 u16 period; // 重复测量周期(s) u8 temp_threshold; // 温度阈值 u8 humi_threshold; // 湿度阈值 SensorState state; // 设备状态 u8 (*getData)(u8 *temp, u8 *humi); // 获取温湿度数据 void (*onTempChange)(u8 temp_threshold); // 高温的响应操作 } Dht11Struct; void dht11_init(void); extern Dht11Struct dht11; #endif #ifndef _usart_H #define _usart_H #include "main.h" #define USART1_REC_LEN 200 //定义最大接收字节数 200 extern u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 extern u16 USART1_RX_STA; //接收状态标记 void usart1_init(u32 baud); #endif #ifndef __TIM_H #define __TIM_H #include "main.h" //#include "stm32f10x.h" void tim4_init(u16 per,u16 psc); #endif #ifndef __DISPLAY_H #define __DISPLAY_H #include "main.h" #define DSP_DIGIT 4 // 4位数码管 typedef enum{LIGHT, TEMP, HUMI} DSP_Interface; // 数码管界面 typedef struct { u16 digit[DSP_DIGIT]; // 数码管的4位数字 u8 currDigit; // 当前显示位(1~4) u8 dotDigit; // 小数点位置(0~4,0代表不显示小数点) DSP_Interface interface; // 界面显示哪个测量值 void(*SegDisplay)(void); }DisplayStruct; void display_init(void); void segDisplay(void); //void setValue(DisplayStruct *dsp, u8 value[4], u8 dotBit); void setLightValue(DisplayStruct *dsp, u8 dotBit); void setTempValue(DisplayStruct *dsp, u8 dotBit); void setHumiValue(DisplayStruct *dsp, u8 dotBit); extern DisplayStruct dsp; #endif 在已有代码上完善该任务,STM32F103C8t6,用标准库

rbWrite ERR: Failed to rbWrite ERR: Failed to rbWrite ERR: Failed to rbWrite ERR: Failed to rbWrite DHT11 OK: T=29, H=62DHT11 OK: T=29, H=62valuehumi Changedvaluelight Changedchanged, report data?? >~鬌HT11 OK: T=29, H=62Warning:gizProtocolResendData 29156 28102 0Warning: timeout, resend data ?? >~鬌HT11 OK: T=29, H=62Warning:gizProtocolResendData 30218 29164 1Warning: timeout, resend data ?? >~鬌HT11 OK: T=29, H=62DHT11 OK: T=29, H=62DHT11 OK: T=29, H=62DHT11 OK: T=29, H=62valuelight Changedchanged, report data?? >| /** ************************************************************ * @file ringbuffer.c * @brief Loop buffer processing * @author Gizwits * @date 2017-07-19 * @version V03030000 * @copyright Gizwits * * @note Gizwits is only for smart hardware * Gizwits Smart Cloud for Smart Products * Links | Value Added | Open | Neutral | Safety | Own | Free | Ecology * www.gizwits.com * ***********************************************************/ #include "ringBuffer.h" #include "common.h" int8_t ICACHE_FLASH_ATTR rbCreate(rb_t* rb) { if(NULL == rb) { return -1; } rb->rbHead = rb->rbBuff; rb->rbTail = rb->rbBuff; return 0; } int8_t ICACHE_FLASH_ATTR rbDelete(rb_t* rb) { if(NULL == rb) { return -1; } rb->rbBuff = NULL; rb->rbHead = NULL; rb->rbTail = NULL; rb->rbCapacity = 0; return 0; } int32_t ICACHE_FLASH_ATTR rbCapacity(rb_t *rb) { if(NULL == rb) { return -1; } return rb->rbCapacity; } int32_t ICACHE_FLASH_ATTR rbCanRead(rb_t *rb) { if(NULL == rb) { return -1; } if (rb->rbHead == rb->rbTail) { return 0; } if (rb->rbHead < rb->rbTail) { return rb->rbTail - rb->rbHead; } return rbCapacity(rb) - (rb->rbHead - rb->rbTail); } int32_t ICACHE_FLASH_ATTR rbCanWrite(rb_t *rb) { if(NULL == rb) { return -1; } return rbCapacity(rb) - rbCanRead(rb); } int32_t ICACHE_FLASH_ATTR rbRead(rb_t *rb, void *data, size_t count) { int32_t copySz = 0; if(NULL == rb) { return -1; } if(NULL == data) { return -1; } if (rb->rbHead < rb->rbTail) { copySz = min(count, rbCanRead(rb)); memcpy(data, rb->rbHead, copySz); rb->rbHead += copySz; return copySz; } else { if (count < rbCapacity(rb)-(rb->rbHead - rb->rbBuff)) { copySz = count; memcpy(data, rb->rbHead, copySz); rb->rbHead += copySz; return copySz; } else { copySz = rbCapacity(rb) - (rb->rbHead - rb->rbBuff); memcpy(data, rb->rbHead, copySz); rb->rbHead = rb->rbBuff; copySz += rbRead(rb, (char*)data+copySz, count-copySz); return copySz; } } } int32_t ICACHE_FLASH_ATTR rbWrite(rb_t *rb, const void *data, size_t count) { int32_t tailAvailSz = 0; if((NULL == rb)||(NULL == data)) { return -1; } if (count >= rbCanWrite(rb)) { return -2; } if (rb->rbHead <= rb->rbTail) { tailAvailSz = rbCapacity(rb) - (rb->rbTail - rb->rbBuff); if (count <= tailAvailSz) { memcpy(rb->rbTail, data, count); rb->rbTail += count; if (rb->rbTail == rb->rbBuff+rbCapacity(rb)) { rb->rbTail = rb->rbBuff; } return count; } else { memcpy(rb->rbTail, data, tailAvailSz); rb->rbTail = rb->rbBuff; return tailAvailSz + rbWrite(rb, (char*)data+tailAvailSz, count-tailAvailSz); } } else { memcpy(rb->rbTail, data, count); rb->rbTail += count; return count; } } #include "sys.h" #include "usart.h" #include "gizwits_product.h" #if 1 #pragma import(__use_no_semihosting) //Ҫ׼ࠢѨҪք֧Ԗگ˽ struct __FILE { int handle; }; FILE __stdout; //֨ӥ_sys_exit()ӔҜĢʹԃѫ׷ܺģʽ void _sys_exit(int x) { x = x; } //ט֨ӥfputcگ˽ int fputc(int ch, FILE *f) { while((USART1->SR&0X40)==0);//ѭ۷ע̍,ֱսע̍Ϊҏ USART1->DR = (u8) ch; return ch; } #endif #if EN_USART1_RX //ɧڻʹŜ‹ޓ˕ //Ԯࠚ1א׏ؾϱԌѲ //עӢ,ׁȡUSARTx->SRŜҜĢĪĻǤĮքխϳ u8 USART_RX_BUF[USART_REC_LEN]; //ޓ˕ۺԥ,خճUSART_REC_LENٶؖޚ. //ޓ˕״̬ //bit15ì ޓ˕ΪԉҪ־ //bit14ì ޓ˕ս0x0d //bit13~0ì ޓ˕սքԐЧؖޚ˽Ŀ u16 USART_RX_STA=0; //ޓ˕״̬Ҫ݇ void uart1_init(u32 bound){ //GPIO׋ࠚʨ׃ GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //ʹŜUSART1ìGPIOAʱד //USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //شԃΆάˤԶ GPIO_Init(GPIOA, &GPIO_InitStructure);//ԵʼۯGPIOA.9 //USART1_RX GPIOA.10Եʼۯ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//ءࠕˤɫ GPIO_Init(GPIOA, &GPIO_InitStructure);//ԵʼۯGPIOA.10 //Usart1 NVIC Ƥ׃ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//ȀռԅЈܶ3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //ؓԅЈܶ3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨրʹŜ NVIC_Init(&NVIC_InitStructure); //ٹߝָ֨քӎ˽ԵʼۯVIC݄զǷ //USART Եʼۯʨ׃ USART_InitStructure.USART_BaudRate = bound;//ԮࠚҨ͘Ê USART_InitStructure.USART_WordLength = USART_WordLength_8b;//ؖӤΪ8λ˽ߝٱʽ USART_InitStructure.USART_StopBits = USART_StopBits_1;//һٶֹͣλ USART_InitStructure.USART_Parity = USART_Parity_No;//ϞǦżУҩλ USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//ϞӲݾ˽ߝ·࠘׆ USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //˕עģʽ USART_Init(USART1, &USART_InitStructure); //ԵʼۯԮࠚ1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//ߪǴԮࠚޓ˜א׏ USART_Cmd(USART1, ENABLE); //ʹŜԮࠚ1 } void uart2_init(u32 bound){ //GPIO׋ࠚʨ׃ GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //ʹŜUSART2ìGPIOAʱד RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //شԃΆάˤԶ GPIO_Init(GPIOA, &GPIO_InitStructure);//ԵʼۯGPIOA.9 //USART1_RX GPIOA.10Եʼۯ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//ءࠕˤɫ GPIO_Init(GPIOA, &GPIO_InitStructure);//ԵʼۯGPIOA.10 //Usart1 NVIC Ƥ׃ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//ȀռԅЈܶ3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //ؓԅЈܶ3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨրʹŜ NVIC_Init(&NVIC_InitStructure); //ٹߝָ֨քӎ˽ԵʼۯVIC݄զǷ //USART Եʼۯʨ׃ USART_InitStructure.USART_BaudRate = bound;//ԮࠚҨ͘Ê USART_InitStructure.USART_WordLength = USART_WordLength_8b;//ؖӤΪ8λ˽ߝٱʽ USART_InitStructure.USART_StopBits = USART_StopBits_1;//һٶֹͣλ USART_InitStructure.USART_Parity = USART_Parity_No;//ϞǦżУҩλ USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//ϞӲݾ˽ߝ·࠘׆ USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //˕עģʽ USART_Init(USART2, &USART_InitStructure); //ԵʼۯԮࠚ1 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//ߪǴԮࠚޓ˜א׏ USART_Cmd(USART2, ENABLE); //ʹŜԮࠚ1 } void USART1_IRQHandler(void) //Ԯࠚ1א׏ؾϱԌѲ { u8 Res; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //ޓ˕א׏(ޓ˕սք˽ߝҘѫˇ0x0d 0x0aޡβ) { USART_ClearITPendingBit(USART1,USART_IT_RXNE); Res =USART_ReceiveData(USART1); //ׁȡޓ˕սք˽ߝ } } void USART2_IRQHandler(void) //Ԯࠚ2א׏ؾϱԌѲ { u8 Res; if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //ޓ˕א׏(ޓ˕սք˽ߝҘѫˇ0x0d 0x0aޡβ) { USART_ClearITPendingBit(USART2,USART_IT_RXNE); Res =USART_ReceiveData(USART2); //ׁȡޓ˕սք˽ߝ gizPutData(&Res,1); } } #endif #include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "DHT11.h" #include "LED.h" #include "Light_Sensor.h" // 光敏电阻驱动(PA7) #include "Fan.h" #include "Buzzer.h" #include "TIM3.h" // TIM3定时器(1ms中断) #include "usart.h" // 串口通信(含机智云数据传输) #include "gizwits_product.h" // 机智云SDK #include "gizwits_protocol.h" // 阈值定义 #define TEMP_THRESHOLD 29 // 温度阈值(℃) #define LIGHT_THRESHOLD 128 // 光照阈值(0-255) extern uint8_t temp; extern uint8_t humi; extern dataPoint_t currentDataPoint; // 全局变量 uint8_t light_intensity; // 光照强度 void controlPeripherals(void) { // 温度控制风扇 if (temp > TEMP_THRESHOLD) { Control_Fan(1); // 风扇开启 currentDataPoint.valueFan_OnOff = 1; // 更新机智云风扇状态 OLED_ShowString(4, 1, "Fan: ON "); } else { Control_Fan(0); // 风扇关闭 currentDataPoint.valueFan_OnOff = 0; // 更新机智云风扇状态 OLED_ShowString(4, 1, "Fan: OFF"); } // 光照控制LED if (light_intensity < LIGHT_THRESHOLD) { Control_Light(1); // 光照不足,开灯 currentDataPoint.valueLED_OnOff = 1; } else { Control_Light(0); // 光照充足,关灯 currentDataPoint.valueLED_OnOff = 0; } // 超阈值报警(温度+湿度) if (temp > TEMP_THRESHOLD) { Buzzer_ON(); // 蜂鸣器报警 } else { Buzzer_OFF(); // 停止报警 } } // OLED显示更新 void updateOLED(void) { // 光照显示 OLED_ShowString(1, 1, "Light:"); OLED_ShowNum(1, 7, light_intensity, 3); OLED_ShowString(1, 10, "/255"); // 温度显示 OLED_ShowString(2, 1, "Temp:"); if(temp == 0xFF) { // 0xFF表示读取错误 OLED_ShowString(2, 6, "ERR"); } else { OLED_ShowNum(2, 6, temp, 2); OLED_ShowCC_F16x16(2, 8, 0); // 显示℃ } // 湿度显示 OLED_ShowString(3, 1, "Humi:"); OLED_ShowNum(3, 6, humi, 2); OLED_ShowCC_F16x16(3, 8, 1); // %显示 } int main(void) { // 初始化外设(按依赖顺序) NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); Delay_Init(); uart1_init(115200); // 初始化USART1,用于printf输出 uart2_init(115200); printf("UART1 and UART2 initialized.\r\n"); // 现在应该可以输出 OLED_Init(); // OLED显示屏 OLED_ShowString(1, 1, "System Start"); Delay_ms(1000); OLED_Clear(); LED_Init(); // LED初始化 LightSensor_Init(); // 光敏电阻初始化(PA7) ADC1_Init(); // ADC初始化(读取光敏电阻) DHT11_UserConfig(); // DHT11温湿度传感器初始化 Fan_Init(); // 风扇初始化 Buzzer_Init(); // 蜂鸣器初始化 GENERAL_TIM_Init(); // TIM3初始化(1ms中断,机智云定时) userInit(); // 机智云用户初始化 gizwitsInit(); gizwitsSetMode(WIFI_AIRLINK_MODE); // 机智云设备初始化 Delay_ms(500); OLED_Clear(); // 清屏准备正式显示 while (1) { light_intensity = Get_Light_Intensity(); // 1. 采集传感器数据 collectSensorData(); // 2. 更新机智云数据点(供云端读取) currentDataPoint.valuetemp = temp; // 温度数据 currentDataPoint.valuehumi = humi; // 湿度数据 currentDataPoint.valuelight = light_intensity;// 光照数据 // 3. 控制外设(风扇、LED、蜂鸣器) controlPeripherals(); // 4. 更新OLED显示 updateOLED(); // 5. 机智云任务处理(数据上报/指令接收) userHandle(); // 用户自定义处理 gizwitsHandle(¤tDataPoint); // 机智云核心处理 // 6. 延时,降低CPU占用 Delay_ms(1000); } }

大家在看

recommend-type

商品条形码及生产日期识别数据集

商品条形码及生产日期识别数据集,数据集样本数量为2156,所有图片已标注为YOLO txt格式,划分为训练集、验证集和测试集,能直接用于YOLO算法的训练。可用于跟本识别目标相关的蓝桥杯比赛项目
recommend-type

7.0 root.rar

Android 7.0 MTK MT8167 user 版本root权限修改,super权限修改,当第三方APP想要获取root权限时,会弹出窗口访问是否给与改APP root权限,同意后该APP可以得到root权限,并操作相关内容
recommend-type

RK3308开发资料

RK3308全套资料,《06 RK3308 硬件设计介绍》《07 RK3308 软件方案介绍》《08 RK3308 Audio开发介绍》《09 RK3308 WIFI-BT功能及开发介绍》
recommend-type

即时记截图精灵 v2.00.rar

即时记截图精灵是一款方便易用,功能强大的专业截图软件。   软件当前版本提供以下功能:   1. 可以通过鼠标选择截图区域,选择区域后仍可通过鼠标进行边缘拉动或拖拽来调整所选区域的大小和位置。   2. 可以将截图复制到剪切板,或者保存为图片文件,或者自动打开windows画图程序进行编辑。   3. 保存文件支持bmp,jpg,png,gif和tif等图片类型。   4. 新增新浪分享按钮。
recommend-type

WinUSB4NuVCOM_NUC970+NuWriter.rar

NUC970 USB启动所需的USB驱动,已经下载工具NuWriter,可以用于裸机启动NUC970调试,将USB接电脑后需要先安装WinUSB4NuVCOM_NUC970驱动,然后使用NuWriter初始化硬件,之后就可以使用jlink或者ulink调试。

最新推荐

recommend-type

C#类库封装:简化SDK调用实现多功能集成,构建地磅无人值守系统

内容概要:本文介绍了利用C#类库封装多个硬件设备的SDK接口,实现一系列复杂功能的一键式调用。具体功能包括身份证信息读取、人证识别、车牌识别(支持臻识和海康摄像头)、LED显示屏文字输出、称重数据读取、二维码扫描以及语音播报。所有功能均被封装为简单的API,极大降低了开发者的工作量和技术门槛。文中详细展示了各个功能的具体实现方式及其应用场景,如身份证读取、人证核验、车牌识别等,并最终将这些功能整合到一起,形成了一套完整的地磅称重无人值守系统解决方案。 适合人群:具有一定C#编程经验的技术人员,尤其是需要快速集成多种硬件设备SDK的应用开发者。 使用场景及目标:适用于需要高效集成多种硬件设备SDK的项目,特别是那些涉及身份验证、车辆管理、物流仓储等领域的企业级应用。通过使用这些封装好的API,可以大大缩短开发周期,降低维护成本,提高系统的稳定性和易用性。 其他说明:虽然封装后的API极大地简化了开发流程,但对于一些特殊的业务需求,仍然可能需要深入研究底层SDK。此外,在实际部署过程中,还需考虑网络环境、硬件兼容性等因素的影响。
recommend-type

Teleport Pro教程:轻松复制网站内容

标题中提到的“复制别人网站的软件”指向的是一种能够下载整个网站或者网站的特定部分,然后在本地或者另一个服务器上重建该网站的技术或工具。这类软件通常被称作网站克隆工具或者网站镜像工具。 描述中提到了一个具体的教程网址,并提到了“天天给力信誉店”,这可能意味着有相关的教程或资源可以在这个网店中获取。但是这里并没有提供实际的教程内容,仅给出了网店的链接。需要注意的是,根据互联网法律法规,复制他人网站内容并用于自己的商业目的可能构成侵权,因此在此类工具的使用中需要谨慎,并确保遵守相关法律法规。 标签“复制 别人 网站 软件”明确指出了这个工具的主要功能,即复制他人网站的软件。 文件名称列表中列出了“Teleport Pro”,这是一款具体的网站下载工具。Teleport Pro是由Tennyson Maxwell公司开发的网站镜像工具,允许用户下载一个网站的本地副本,包括HTML页面、图片和其他资源文件。用户可以通过指定开始的URL,并设置各种选项来决定下载网站的哪些部分。该工具能够帮助开发者、设计师或内容分析人员在没有互联网连接的情况下对网站进行离线浏览和分析。 从知识点的角度来看,Teleport Pro作为一个网站克隆工具,具备以下功能和知识点: 1. 网站下载:Teleport Pro可以下载整个网站或特定网页。用户可以设定下载的深度,例如仅下载首页及其链接的页面,或者下载所有可访问的页面。 2. 断点续传:如果在下载过程中发生中断,Teleport Pro可以从中断的地方继续下载,无需重新开始。 3. 过滤器设置:用户可以根据特定的规则过滤下载内容,如排除某些文件类型或域名。 4. 网站结构分析:Teleport Pro可以分析网站的链接结构,并允许用户查看网站的结构图。 5. 自定义下载:用户可以自定义下载任务,例如仅下载图片、视频或其他特定类型的文件。 6. 多任务处理:Teleport Pro支持多线程下载,用户可以同时启动多个下载任务来提高效率。 7. 编辑和管理下载内容:Teleport Pro具备编辑网站镜像的能力,并可以查看、修改下载的文件。 8. 离线浏览:下载的网站可以在离线状态下浏览,这对于需要测试网站在不同环境下的表现的情况十分有用。 9. 备份功能:Teleport Pro可以用来备份网站,确保重要数据的安全。 在实际使用此类工具时,需要注意以下几点: - 著作权法:复制网站内容可能侵犯原作者的版权,因此在使用此类工具时,必须确保有合法权利去下载和使用目标网站的内容。 - 服务条款:许多网站的服务条款明确禁止未经授权的网站克隆。因此,在使用此类软件之前,应当仔细阅读并遵守目标网站的服务条款。 - 数据隐私:下载含有个人数据的网站可能触及隐私保护法律,特别是在欧洲通用数据保护条例(GDPR)等法规的环境下。 - 网络安全:随意下载网站可能导致恶意软件和病毒的传播,用户应当使用最新的反病毒软件,并在安全的环境中进行操作。 综上所述,虽然“复制别人网站的软件”在技术上是可行的,且可以用于多种正当目的,但在使用此类工具时,必须遵守法律法规和道德规范,不可侵犯他人的合法权益。
recommend-type

【跨平台开发者的必读】:解决Qt5Widgetsd.lib目标计算机类型冲突终极指南

# 1. 跨平台开发与Qt框架简介 跨平台开发已经成为现代软件开发中不可或缺的一部分,它使得开发者能够构建出能够在多种操作系统上运行的应用程序,从而触及更广泛的用户群体。在这其中,Qt框架作为一套成熟的跨平台应用程序和用户界面框架,扮演着关键角色。Qt不仅仅是一个跨平台的工具集,它的设计哲学还包含了模块化和可扩展性,使其能够适应各种规模和复杂度的项目。本章节我们将简要介绍
recommend-type

普通RNN结构和特点

<think>首先,用户的问题是:“我想了解普通RNN的结构及其特点请问RNN循环神经网络结构特点工作原理”。这涉及到RNN的结构、特点和工作原理。根据系统级指令:-所有行内数学表达式必须使用$...$格式。-独立公式必须使用$$...$$格式并单独成段。-LaTeX语法正确。-使用中文回答。-生成相关问题。-回答中引用的段落末尾自然地添加引用标识。用户可见层指令:-回答结构清晰,帮助用户逐步解决问题。-保证回答真实可靠。参考站内引用:-引用[1]:关于RNN的基本介绍,为什么需要RNN。-引用[2]:关于RNN的工作原理、结构图,以及与其他网络的比较。用户上一次的问题和我的回答:用户是第一次
recommend-type

探讨通用数据连接池的核心机制与应用

根据给定的信息,我们能够推断出讨论的主题是“通用数据连接池”,这是一个在软件开发和数据库管理中经常用到的重要概念。在这个主题下,我们可以详细阐述以下几个知识点: 1. **连接池的定义**: 连接池是一种用于管理数据库连接的技术,通过维护一定数量的数据库连接,使得连接的创建和销毁操作更加高效。开发者可以在应用程序启动时预先创建一定数量的连接,并将它们保存在一个池中,当需要数据库连接时,可以直接从池中获取,从而降低数据库连接的开销。 2. **通用数据连接池的概念**: 当提到“通用数据连接池”时,它意味着这种连接池不仅支持单一类型的数据库(如MySQL、Oracle等),而且能够适应多种不同数据库系统。设计一个通用的数据连接池通常需要抽象出一套通用的接口和协议,使得连接池可以兼容不同的数据库驱动和连接方式。 3. **连接池的优点**: - **提升性能**:由于数据库连接创建是一个耗时的操作,连接池能够减少应用程序建立新连接的时间,从而提高性能。 - **资源复用**:数据库连接是昂贵的资源,通过连接池,可以最大化现有连接的使用,避免了连接频繁创建和销毁导致的资源浪费。 - **控制并发连接数**:连接池可以限制对数据库的并发访问,防止过载,确保数据库系统的稳定运行。 4. **连接池的关键参数**: - **最大连接数**:池中能够创建的最大连接数。 - **最小空闲连接数**:池中保持的最小空闲连接数,以应对突发的连接请求。 - **连接超时时间**:连接在池中保持空闲的最大时间。 - **事务处理**:连接池需要能够管理不同事务的上下文,保证事务的正确执行。 5. **实现通用数据连接池的挑战**: 实现一个通用的连接池需要考虑到不同数据库的连接协议和操作差异。例如,不同的数据库可能有不同的SQL方言、认证机制、连接属性设置等。因此,通用连接池需要能够提供足够的灵活性,允许用户配置特定数据库的参数。 6. **数据连接池的应用场景**: - **Web应用**:在Web应用中,为了处理大量的用户请求,数据库连接池可以保证数据库连接的快速复用。 - **批处理应用**:在需要大量读写数据库的批处理作业中,连接池有助于提高整体作业的效率。 - **微服务架构**:在微服务架构中,每个服务可能都需要与数据库进行交互,通用连接池能够帮助简化服务的数据库连接管理。 7. **常见的通用数据连接池技术**: - **Apache DBCP**:Apache的一个Java数据库连接池库。 - **C3P0**:一个提供数据库连接池和控制工具的开源Java框架。 - **HikariCP**:目前性能最好的开源Java数据库连接池之一。 - **BoneCP**:一个高性能的开源Java数据库连接池。 - **Druid**:阿里巴巴开源的一个数据库连接池,提供了对性能监控的高级特性。 8. **连接池的管理与监控**: 为了保证连接池的稳定运行,开发者需要对连接池的状态进行监控,并对其进行适当的管理。监控指标可能包括当前活动的连接数、空闲的连接数、等待获取连接的请求队列长度等。一些连接池提供了监控工具或与监控系统集成的能力。 9. **连接池的配置和优化**: 连接池的性能与连接池的配置密切相关。需要根据实际的应用负载和数据库性能来调整连接池的参数。例如,在高并发的场景下,可能需要增加连接池中连接的数量。另外,适当的线程池策略也可以帮助连接池更好地服务于多线程环境。 10. **连接池的应用案例**: 一个典型的案例是电商平台在大型促销活动期间,用户访问量激增,此时通用数据连接池能够保证数据库操作的快速响应,减少因数据库连接问题导致的系统瓶颈。 总结来说,通用数据连接池是现代软件架构中的重要组件,它通过提供高效的数据库连接管理,增强了软件系统的性能和稳定性。了解和掌握连接池的原理及实践,对于任何涉及数据库交互的应用开发都至关重要。在实现和应用连接池时,需要关注其设计的通用性、配置的合理性以及管理的有效性,确保在不同的应用场景下都能发挥出最大的效能。
recommend-type

【LabVIEW网络通讯终极指南】:7个技巧提升UDP性能和安全性

# 摘要 本文系统介绍了LabVIEW在网络通讯中的应用,尤其是针对UDP协议的研究与优化。首先,阐述了UDP的原理、特点及其在LabVIEW中的基础应用。随后,本文深入探讨了通过调整数据包大小、实现并发通信及优化缓冲区管理等技巧来优化UDP性能的LabVIEW方法。接着,文章聚焦于提升UDP通信安全性,介绍了加密技术和认证授权机制在LabVIEW中的实现,以及防御网络攻击的策略。最后,通过具体案例展示了LabVIEW在实时数据采集和远程控制系统中的高级应用,并展望了LabVIEW与UDP通讯技术的未来发展趋势及新兴技术的影响。 # 关键字 LabVIEW;UDP网络通讯;性能优化;安全性;
recommend-type

简要介绍cnn卷积神经网络

<think>首先,用户的问题是:“我想了解卷积神经网络的基本概念和原理 请问CNN卷积神经网络简介及其工作原理”。所以,我需要基于提供的引用材料,构建一个清晰的回答。 引用材料总结: - [^1]: CNN的核心思想是局部感受野、权值共享和时间或空间亚采样,提供位移、尺度、形变不变性。三大特色:局部感知、权重共享和多卷积核。 - [^2]: CNN是一种前馈神经网络,由卷积层和池化层组成,特别在图像处理方面出色。与传统多层神经网络相比,CNN加入了卷积层和池化层,使特征学习更有效。 - [^3]: CNN与全连接神经网络的区别:至少有一个卷积层提取特征;神经元局部连接和权值共享,减少参数数
recommend-type

基于ASP的深度学习网站导航系统功能详解

从给定文件中我们可以提取以下IT知识点: ### 标题知识点 #### "ASP系统篇" - **ASP技术介绍**:ASP(Active Server Pages)是一种服务器端的脚本环境,用于创建动态交互式网页。ASP允许开发者将HTML网页与服务器端脚本结合,使用VBScript或JavaScript等语言编写代码,以实现网页内容的动态生成。 - **ASP技术特点**:ASP适用于小型到中型的项目开发,它可以与数据库紧密集成,如Microsoft的Access和SQL Server。ASP支持多种组件和COM(Component Object Model)对象,使得开发者能够实现复杂的业务逻辑。 #### "深度学习网址导航系统" - **深度学习概念**:深度学习是机器学习的一个分支,通过构建深层的神经网络来模拟人类大脑的工作方式,以实现对数据的高级抽象和学习。 - **系统功能与深度学习的关系**:该标题可能意味着系统在进行网站分类、搜索优化、内容审核等方面采用了深度学习技术,以提供更智能、自动化的服务。然而,根据描述内容,实际上系统并没有直接使用深度学习技术,而是提供了一个传统的网址导航服务,可能是命名上的噱头。 ### 描述知识点 #### "全后台化管理,操作简单" - **后台管理系统的功能**:后台管理系统允许网站管理员通过Web界面执行管理任务,如内容更新、用户管理等。它通常要求界面友好,操作简便,以适应不同技术水平的用户。 #### "栏目无限分类,自由添加,排序,设定是否前台显示" - **动态网站结构设计**:这意味着网站结构具有高度的灵活性,支持创建无限层级的分类,允许管理员自由地添加、排序和设置分类的显示属性。这种设计通常需要数据库支持动态生成内容。 #### "各大搜索和站内搜索随意切换" - **搜索引擎集成**:网站可能集成了外部搜索引擎(如Google、Bing)和内部搜索引擎功能,让用户能够方便地从不同来源获取信息。 #### "网站在线提交、审阅、编辑、删除" - **内容管理系统的功能**:该系统提供了一个内容管理平台,允许用户在线提交内容,由管理员进行审阅、编辑和删除操作。 #### "站点相关信息后台动态配置" - **动态配置机制**:网站允许管理员通过后台系统动态调整各种配置信息,如网站设置、参数调整等,从而实现快速的网站维护和更新。 #### "自助网站收录,后台审阅" - **网站收录和审核机制**:该系统提供了一套自助收录流程,允许其他网站提交申请,由管理员进行后台审核,决定是否收录。 #### "网站广告在线发布" - **广告管理功能**:网站允许管理员在线发布和管理网站广告位,以实现商业变现。 #### "自动生成静态页 ver2.4.5" - **动态与静态内容**:系统支持动态内容的生成,同时也提供了静态页面的生成机制,这可能有助于提高网站加载速度和搜索引擎优化。 #### "重写后台网址分类管理" - **系统优化与重构**:提到了后台网址分类管理功能的重写,这可能意味着系统进行了一次重要的更新,以修复前一个版本的错误,并提高性能。 ### 标签知识点 #### "ASP web 源代码 源码" - **ASP程序开发**:标签表明这是一个ASP语言编写的网站源代码,可能是一个开源项目,供开发者下载、研究或部署到自己的服务器上。 ### 压缩包子文件名称列表知识点 #### "深度学习(asp)网址导航程序" - **文件内容和类型**:文件列表中提到的“深度学习(asp)网址导航程序”表明这是一个ASP语言编写的网址导航系统程序,可能包含了系统安装和配置需要的所有源文件。 通过以上分析,我们可以得出这个ASP系统是一个传统的网址导航系统,以后台管理为核心功能,并没有实际运用到深度学习技术。系统的主要功能包括对网站内容、分类、搜索引擎、广告位、以及其他网站相关信息的管理。它可能还提供了一个平台,供用户提交网址,供管理员审核并收录到导航中。源代码可能以ASP语言编写,并在文件中包含了所有必要的程序文件。
recommend-type

【Oracle数据泵进阶技巧】:避免ORA-31634和ORA-31664错误的终极策略

# 1. Oracle数据泵技术概述 ## Oracle数据泵技术简介 Oracle数据泵(Data Pump)是一种用于高效地在Oracle数据库之间传输数据和元数据的工具。它从Oracle 10g版本开始引入,提供了快速且灵活的数据导入导出功能。数据泵技术优于旧版的`imp`和`exp`工具,因为它支持多线程,可以在导入和导出过程中显著提高性能。 ## 数据泵的核心优势 数据泵的核心优势在于它能并行处理数据,支持大对象(LOBs)和网络传输。它还允许用户自定义数据和对象的传输方式,以及可以控制传输过程中的各种细节,如过滤对象、调整数据缓冲区大小、并行度和网络数据包大小等。 ## 数据
recommend-type

多头注意力机制的时间复杂度

<think>首先,用户的问题是:“我想计算多头注意力机制的时间复杂度 请问多头注意力机制的时间复杂度计算方法”。我需要基于提供的引用和系统级指令来回答。 关键引用: - 引用[1]:提到Transformer模型的计算时间复杂度主要由自注意力机制的O(n²·d)决定。 - 引用[2]:详细解释了注意力机制的计算复杂度,包括QK转置的复杂度为O(N²d),内存需求为N² + Nd。 - 引用[3]:提到原始注意力机制的时间复杂度为O(n²d),并讨论了优化方法如稀疏注意力和线性注意力。 - 引用[4]:涉及多头注意力的未来趋势,但没有直接给出计算方法。 用户的问题是计算多头注意力机制的时间