forked from gary/BCU
2
0
Fork 0
BCU/library/drv_peripheral/drv_qfc41d.c

356 lines
8.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
* @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;
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);
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)
{
//需要解决发送过程中与实时值DMA上传的冲突问题可以尝试标志位或者队列的方式
drv_mqtt_publish_read_no_respose("1", 1);
}
}
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;
}