/****************************************************************************** * @file drv_qfc41d.c * @brief drv_qfc41d driver * @version V1.0 * @author Gary * @copyright ******************************************************************************/ #include "drv_qfc41d.h" uint8_t rev_buff[QFC41D_MAX_RECV_SIZE] = {0}; uint8_t send_buff[QFC41D_MAX_SEND_SIZE] = {0}; #define MAX_PAYLOAD_LEN 128 char cmd[1000] = {0}; //降低栈空间使用 #define TX_DMA_BUFFER_SIZE 2000 volatile uint8_t dma_tx_busy = 0; uint8_t dma_tx_buffer[2][TX_DMA_BUFFER_SIZE]; volatile uint8_t current_buffer = 0; // 0表示正常缓冲区,1表示高优先级缓冲区 //定义 WifiBleItem qfc41dItem = { .dev = QFC41D_UART_PORT, .buf_pos = 0, .buf_size = QFC41D_MAX_RECV_SIZE, .buf = rev_buff, .sendCall = NULL, }; void parse_mqtt_message(char* message) { // 示例消息: +QMTRECV: 0,31,"bluesun/bms/control/123",11,"MQ3156+1MQ" uint16_t first = 0; uint16_t second = 0; uint8_t buffer[256]; // 存储Modbus响应的缓冲区 uint16_t length; // 响应数据长度 uint8_t data; // 函数返回值 char data_str[6] = {0}; char* quotes[4] = {0}; int quote_count = 0; for(char* p = message; *p && quote_count < 4; p++) { if(*p == '\"') { quotes[quote_count++] = p; } } if(quote_count < 4) { return; } char* payload_start = quotes[2] + 1; char* payload_end = quotes[3]; size_t payload_len = payload_end - payload_start; if(payload_len >= MAX_PAYLOAD_LEN) { return; } char payload[MAX_PAYLOAD_LEN]; strncpy(payload, payload_start, payload_len); payload[payload_len] = '\0'; char* processed = payload; size_t len = strlen(processed); // 去除开头"MQ" if(len >= 2 && strncmp(processed, "MQ", 2) == 0) { processed += 2; len -= 2; } // 去除结尾"MQ" if(len >= 2 && strcmp(processed + len - 2, "MQ") == 0) { processed[len - 2] = '\0'; len -= 2; } char* plus_pos = strchr(processed, '+'); if(!plus_pos) { return; } *plus_pos = '\0'; first = atoi(processed); second = atoi(plus_pos + 1); current_buffer = 1; if(strstr(message, "control") != NULL) { if((first >= 3000) && (first <= 3168)) { bcu_data_set_0x06_msg(first, second); } else if ((first >= 4000) && (first <= 4999)) { hmi_write_modbus_cfg(first - 4000, second); } drv_mqtt_publish_control_no_respose("ok", 2); } else if (strstr(message, "read") != NULL) { data = bcu_modbus_485_0x03_fun(first, 1, buffer, &length); if (data == 0 && length >= 2) { //解析16位寄存器值 uint16_t value = (buffer[0] << 8) | buffer[1]; snprintf(data_str, sizeof(data_str), "%u", value); drv_mqtt_publish_read_no_respose(data_str, strlen(data_str)); memset(data_str, 0, sizeof(data_str)); } } current_buffer = 0; } static void drv_qfc41d_push_data(WifiBleItem* item, uint8_t *buf, uint16_t len) { uint16_t i = 0; if((item != NULL) && (item->buf_pos + len < item->buf_size)) { item->buf[item->buf_pos++] = buf[i]; // 处理换行符,表示一条完整的 AT 指令返回 if (buf[i] == '\n') { item->buf[item->buf_pos] = '\0'; // 添加结束符 if (item->buf_pos < 100) { parse_mqtt_message(item->buf); // 解析消息 } item->buf_pos = 0; // 重置索引,准备下一条数据 } } } static void drv_qf41d_uart_rx_it_call(kit_ret_e res, void *data) { OS_TRACE_ISR_ENTER(); drv_qfc41d_push_data(&qfc41dItem, data, 1); OS_TRACE_ISR_EXIT(); } // 发送单个字符 void drv_wireless_send_char(char c) { while (!(USART2->SR & USART_SR_TXE)); // 等待发送缓冲区空 USART2->DR = c; } // 发送字符串 void drv_wireless_send_string(const char *str) { while (*str) { drv_wireless_send_char(*str++); } drv_wireless_send_char('\r'); // 发送 CR drv_wireless_send_char('\n'); // 发送 LF } void drv_wireless_send_string_dma_high_priority(const char *str) { uint32_t timeout = 0; uint32_t start_time = kit_time_get_tick(); while (dma_tx_busy && current_buffer == 0) { if (kit_time_get_tick() - start_time > 100) { DMA1_Stream6->CR &= ~DMA_SxCR_EN; while (DMA1_Stream6->CR & DMA_SxCR_EN); // 清除可能的中断标志 DMA1->HIFCR |= DMA_HIFCR_CTCIF6 | DMA_HIFCR_CTEIF6; dma_tx_busy = 0; current_buffer = 0; USART2->CR3 &= ~USART_CR3_DMAT; break; } } uint16_t len = 0; while (*str && len < TX_DMA_BUFFER_SIZE - 2) { dma_tx_buffer[1][len++] = *str++; } dma_tx_buffer[1][len++] = '\r'; dma_tx_buffer[1][len++] = '\n'; // 设置 DMA 参数并启动 DMA1_Stream6->CR &= ~DMA_SxCR_EN; while (DMA1_Stream6->CR & DMA_SxCR_EN); DMA1_Stream6->M0AR = (uint32_t)dma_tx_buffer[1]; DMA1_Stream6->NDTR = len; dma_tx_busy = 1; current_buffer = 1; DMA1_Stream6->CR |= DMA_SxCR_EN; USART2->CR3 |= USART_CR3_DMAT; // 开启 DMA 发送 } void drv_wireless_send_string_dma(const char *str) { if (dma_tx_busy || current_buffer == 1) return; // 正在发送或高优先级发送中,丢弃 bsp_task_delay_ms(250); uint16_t len = 0; // 拷贝数据到 DMA 缓冲区 while (*str && len < TX_DMA_BUFFER_SIZE - 2) { dma_tx_buffer[0][len++] = *str++; } dma_tx_buffer[0][len++] = '\r'; dma_tx_buffer[0][len++] = '\n'; // 设置 DMA 参数并启动 DMA1_Stream6->CR &= ~DMA_SxCR_EN; while (DMA1_Stream6->CR & DMA_SxCR_EN); DMA1_Stream6->M0AR = (uint32_t)dma_tx_buffer[0]; DMA1_Stream6->NDTR = len; dma_tx_busy = 1; current_buffer = 0; DMA1_Stream6->CR |= DMA_SxCR_EN; USART2->CR3 |= USART_CR3_DMAT; // 开启 DMA 发送 } // 发送 AT 指令并等待返回值 int drv_at_send_cmd(const char *cmd, const char *response, uint32_t timeout) { memset(qfc41dItem.buf, 0, QFC41D_MAX_RECV_SIZE); qfc41dItem.buf_pos = 0; // 清空接收缓冲区索引 drv_wireless_send_string(cmd); uint32_t start_time = kit_time_get_tick(); // 获取当前时间 while (kit_time_get_tick() - start_time < timeout) { if (strstr((char *)qfc41dItem.buf, response)) { return 1; // 成功匹配返回值 } } return 0; // 超时未收到期望数据 } static uint8_t drv_wifi_init() { if (!drv_at_send_cmd("AT", "OK", WIFI_TIMEOUT)) { return 1 ; } if (!drv_at_send_cmd("AT+QSTASTOP", "OK", WIFI_TIMEOUT)) { return 1; } if (!drv_at_send_cmd("AT+QSOFTAPSTOP", "OK", WIFI_TIMEOUT)) { return 1; } return 0; } uint8_t drv_ble_init() { if (!drv_at_send_cmd("AT+QBLEINIT=3", "OK", WIFI_TIMEOUT)) { return 1; } //设置wifi名称,必须以BSM开头,后缀可以加sn码 if (!drv_at_send_cmd("AT+QBLENAME=BSM11223344", "OK", WIFI_TIMEOUT)) { return 1; } return 0; } uint8_t drv_qfc41d_init(void) { //初始化串口 drv_uart_init((UartDev)qfc41dItem.dev, 115200, 0 | UART_CFG_STOP_BIT_1, kGpioType_WIRELESSUart_Tx, kGpioType_WIRELESSUart_Rx); USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | USART_CR1_UE; //设置接收回调函数 drv_uart_set_interrupt(QFC41D_UART_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, drv_qf41d_uart_rx_it_call);//#define SIM_UART_PORT kUartDev_2 //初始化蓝牙(BLE) if (drv_ble_init() != 0) { return 1; } return 0; } #define MQTT_BROKER "47.120.14.45" // 你的 MQTT 服务器地址 #define MQTT_PORT 3011 // MQTT 端口 #define MQTT_CLIENT_ID "fc41d_client" // 客户端 ID #define MQTT_USER "user" // MQTT 用户名 #define MQTT_PASSWORD "password" // MQTT 密码 #define MQTT_TOPIC "bluesun/bms/period/11223344" #define MQTT_TOPIC_control "bluesun/bms/control/reply/11223344" #define MQTT_TOPIC_read "bluesun/bms/read/reply/11223344" static uint8_t drv_mqtt_subscribe() { snprintf(cmd, sizeof(cmd), "AT+MQTTSUB=0,1,\"%s\",2", MQTT_TOPIC); drv_wireless_send_string(cmd); return 0; } uint8_t drv_mqtt_publish(char* str,uint16_t length) { snprintf(cmd, sizeof(cmd), "AT+QMTPUB=1,1,2,0,%s,%d,%s",MQTT_TOPIC, length, str); if (!drv_at_send_cmd(cmd, "OK\0", WIFI_TIMEOUT)) { return 1; } return 0; } uint8_t drv_mqtt_publish_no_respose(char* str,uint16_t length) { // snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,%s,%d,%s",MQTT_TOPIC, length, str); snprintf(cmd, sizeof(cmd), "AT+QMTPUB=1,1,2,0,\"%s\",%d,\"%s\"", MQTT_TOPIC, length, str); // drv_wireless_send_string(cmd); // 未使用DMA drv_wireless_send_string_dma(cmd); // 使用DMA return 0; } uint8_t drv_mqtt_publish_control_no_respose(char* str,uint16_t length) { snprintf(cmd, sizeof(cmd), "AT+QMTPUB=1,1,2,0,\"%s\",%d,\"%s\"", MQTT_TOPIC_control, length, str); drv_wireless_send_string_dma_high_priority(cmd); return 0; } uint8_t drv_mqtt_publish_read_no_respose(char* str,uint16_t length) { snprintf(cmd, sizeof(cmd), "AT+QMTPUB=1,1,2,0,\"%s\",%d,\"%s\"", MQTT_TOPIC_read, length, str); drv_wireless_send_string_dma_high_priority(cmd); return 0; }