优化远程配置驱动--目前支持全部读取和单个写入,上个版本问题未解决
This commit is contained in:
parent
857a4b434d
commit
ccd6ea6432
|
@ -10,6 +10,8 @@
|
|||
//#define TX_DMA_BUFFER_SIZE 800
|
||||
|
||||
extern uint8_t dma_tx_buffer[];
|
||||
extern volatile uint8_t dma_tx_busy;
|
||||
extern volatile uint8_t current_buffer;
|
||||
|
||||
const GpioArray io_array[kGpioType_End] =
|
||||
{
|
||||
|
@ -97,6 +99,14 @@ const GpioArray io_array[kGpioType_End] =
|
|||
kGpioMode_Input_Floating, kGpioStatus_High, GPIO_PORT_PIN(kGpioPort_G, 15), kGpioPort_G, kGpioPin_15 , //W5500_INT
|
||||
};
|
||||
|
||||
void reset_dma_tx_state(void)
|
||||
{
|
||||
__disable_irq();
|
||||
dma_tx_busy = 0;
|
||||
current_buffer = 0;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void drv_wireless_dma_init(void)
|
||||
{
|
||||
// 使能 DMA1 和 USART2 的时钟
|
||||
|
@ -122,6 +132,11 @@ void drv_wireless_dma_init(void)
|
|||
DMA_SxCR_TEIE | // 建议添加传输错误中断
|
||||
(0 << 16); // 优先级
|
||||
|
||||
reset_dma_tx_state();
|
||||
|
||||
DMA1_Stream6->CR |= (1 << 0); // 启用FIFO
|
||||
DMA1_Stream6->FCR = (0x3 << 0); // 全FIFO模式
|
||||
|
||||
NVIC_EnableIRQ(DMA1_Stream6_IRQn);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<InvalidFlash>1</InvalidFlash>
|
||||
</TargetStatus>
|
||||
<OutputDirectory>.\Objects\</OutputDirectory>
|
||||
<OutputName>BCU10</OutputName>
|
||||
<OutputName>BCU11</OutputName>
|
||||
<CreateExecutable>1</CreateExecutable>
|
||||
<CreateLib>0</CreateLib>
|
||||
<CreateHexFile>1</CreateHexFile>
|
||||
|
@ -83,7 +83,7 @@
|
|||
<AfterMake>
|
||||
<RunUserProg1>0</RunUserProg1>
|
||||
<RunUserProg2>0</RunUserProg2>
|
||||
<UserProg1Name>D:\CodeHvStack\BCU\app\stm32fxxx_app\hex2bin.exe D:\CodeHvStack\BCU\app\stm32fxxx_app\prj\Objects\BCU10.hex</UserProg1Name>
|
||||
<UserProg1Name>D:\CodeHvStack\BCU\app\stm32fxxx_app\hex2bin.exe D:\CodeHvStack\BCU\app\stm32fxxx_app\prj\Objects\BCU11.hex</UserProg1Name>
|
||||
<UserProg2Name></UserProg2Name>
|
||||
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
|
||||
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -834,6 +834,20 @@ BspMdExCode bcu_modbus_485_0x04_fun(uint16_t start_addr, uint16_t reg_num, uint8
|
|||
}
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
这是modbus读取数据接口和读取并发送单个数据到mqtt的代码,现在需要根据
|
||||
3000 3
|
||||
3010 1
|
||||
3017 1
|
||||
3041 1
|
||||
3068 2
|
||||
3092 1
|
||||
3156 1
|
||||
4000 72
|
||||
4198 72
|
||||
来进行多段读取数据和发送,每组前面的字段是首地址,后面的字段是每组连续读取的数量,因为所需数据不连续,所以分段读取。发送的字符中每个数据中间用+号连接。
|
||||
*/
|
||||
|
||||
|
||||
void bcu_data_set_0x06_msg(uint16_t address,uint16_t data)
|
||||
{
|
||||
|
@ -1206,7 +1220,7 @@ BspMdExCode bcu_modbus_485_0x06_fun(uint16_t start_addr, uint16_t reg_num, uint8
|
|||
data = (buf[0] << 8) + buf[1];
|
||||
|
||||
//kit_time_dly_ms(50);
|
||||
if((start_addr >= 3000) && (start_addr <= 3169))
|
||||
if((start_addr >= 3000) && (start_addr <= 3149))
|
||||
{
|
||||
bcu_data_set_0x06_msg(start_addr, data);
|
||||
*len = reg_num << 1;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,9 +30,26 @@ WifiBleItem qfc41dItem = {
|
|||
.sendCall = NULL,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16_t start_addr;
|
||||
uint16_t reg_num;
|
||||
} RegSegment;
|
||||
|
||||
RegSegment segments[] = {
|
||||
{3000, 3}, //BMU个数,电芯总数,温感总数
|
||||
{3010, 1}, //Can通讯协议
|
||||
{3017, 1}, //设备地址
|
||||
{3041, 1}, //SOC
|
||||
{3068, 2}, //SOC满放校准电压,满充校准电压
|
||||
{3092, 1}, //充电末端降流电压
|
||||
{4000, 72}, //放电欠压值
|
||||
{4198, 72} //充电过压值
|
||||
};
|
||||
const uint8_t segment_count = sizeof(segments) / sizeof(segments[0]);
|
||||
|
||||
void parse_mqtt_message(char* message)
|
||||
{
|
||||
// 示例消息: +QMTRECV: 0,31,"bluesun/bms/control/123",11,"MQ3156+1MQ"
|
||||
// +QMTRECV: 0,31,"bluesun/bms/control/123",11,"MQ3156+1MQ"
|
||||
uint16_t first = 0;
|
||||
uint16_t second = 0;
|
||||
uint8_t buffer[5];
|
||||
|
@ -95,7 +112,6 @@ void parse_mqtt_message(char* message)
|
|||
first = atoi(processed);
|
||||
second = atoi(plus_pos + 1);
|
||||
|
||||
current_buffer = 1;
|
||||
if(strstr(message, "control") != NULL)
|
||||
{
|
||||
buffer[0] = (second >> 8) & 0xFF;
|
||||
|
@ -118,17 +134,49 @@ void parse_mqtt_message(char* message)
|
|||
}
|
||||
else if (strstr(message, "read") != NULL)
|
||||
{
|
||||
data = bcu_modbus_485_0x03_fun(first, 1, buffer, &length);
|
||||
|
||||
if (data == 0 && length >= 2)
|
||||
char data_str[650] = {0};
|
||||
uint8_t is_first_data = 1; // 标记是否为第一个数据
|
||||
uint8_t read_success = 1;
|
||||
|
||||
for (uint8_t i = 0; i < segment_count; i++)
|
||||
{
|
||||
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));
|
||||
}
|
||||
uint16_t start_addr = segments[i].start_addr;
|
||||
uint16_t reg_num = segments[i].reg_num;
|
||||
uint16_t length = 0;
|
||||
uint8_t read_buffer[150] = {0};
|
||||
|
||||
uint8_t err = bcu_modbus_485_0x03_fun(start_addr, reg_num, read_buffer, &length);
|
||||
|
||||
if (err != 0 || length != (reg_num << 1))
|
||||
{
|
||||
read_success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint16_t j = 0; j < reg_num; j++)
|
||||
{
|
||||
uint16_t value = (read_buffer[j * 2] << 8) | read_buffer[j * 2 + 1];
|
||||
|
||||
if (!is_first_data)
|
||||
{
|
||||
strcat(data_str, "+");
|
||||
}
|
||||
else
|
||||
{
|
||||
is_first_data = 0;
|
||||
}
|
||||
|
||||
char val_str[6];
|
||||
snprintf(val_str, sizeof(val_str), "%u", value);
|
||||
strcat(data_str, val_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (read_success && strlen(data_str) > 0)
|
||||
{
|
||||
drv_mqtt_publish_read_no_respose(data_str, strlen(data_str));
|
||||
}
|
||||
}
|
||||
current_buffer = 0;
|
||||
}
|
||||
|
||||
static void drv_qfc41d_push_data(WifiBleItem* item, uint8_t *buf, uint16_t len)
|
||||
|
@ -179,35 +227,37 @@ void drv_wireless_send_string(const char *str)
|
|||
|
||||
void drv_wireless_send_string_dma_high_priority(const char *str)
|
||||
{
|
||||
uint32_t timeout = 0;
|
||||
uint32_t start_time = kit_time_get_tick();
|
||||
|
||||
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++;
|
||||
if (kit_time_get_tick() - start_time > 180)
|
||||
{
|
||||
__disable_irq();
|
||||
if (DMA1_Stream6->CR & DMA_SxCR_EN)
|
||||
{
|
||||
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;
|
||||
__enable_irq();
|
||||
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 参数并启动
|
||||
__disable_irq();
|
||||
// 确保DMA已停止
|
||||
DMA1_Stream6->CR &= ~DMA_SxCR_EN;
|
||||
while (DMA1_Stream6->CR & DMA_SxCR_EN);
|
||||
|
||||
|
@ -217,25 +267,37 @@ void drv_wireless_send_string_dma_high_priority(const char *str)
|
|||
dma_tx_busy = 1;
|
||||
current_buffer = 1;
|
||||
DMA1_Stream6->CR |= DMA_SxCR_EN;
|
||||
USART2->CR3 |= USART_CR3_DMAT; // 开启 DMA 发送
|
||||
USART2->CR3 |= USART_CR3_DMAT;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
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;
|
||||
__disable_irq();
|
||||
if (dma_tx_busy || current_buffer == 1)
|
||||
{
|
||||
__enable_irq();
|
||||
return;
|
||||
}
|
||||
__enable_irq();
|
||||
|
||||
// 拷贝数据到 DMA 缓冲区
|
||||
bsp_task_delay_ms(250);
|
||||
|
||||
uint16_t len = 0;
|
||||
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 参数并启动
|
||||
__disable_irq();
|
||||
if (dma_tx_busy || current_buffer == 1)
|
||||
{
|
||||
__enable_irq();
|
||||
return;
|
||||
}
|
||||
|
||||
DMA1_Stream6->CR &= ~DMA_SxCR_EN;
|
||||
while (DMA1_Stream6->CR & DMA_SxCR_EN);
|
||||
|
||||
|
@ -245,7 +307,8 @@ void drv_wireless_send_string_dma(const char *str)
|
|||
dma_tx_busy = 1;
|
||||
current_buffer = 0;
|
||||
DMA1_Stream6->CR |= DMA_SxCR_EN;
|
||||
USART2->CR3 |= USART_CR3_DMAT; // 开启 DMA 发送
|
||||
USART2->CR3 |= USART_CR3_DMAT;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -279,13 +279,14 @@ void DMA1_Stream5_IRQHandler(void)
|
|||
|
||||
void DMA1_Stream6_IRQHandler(void)
|
||||
{
|
||||
__disable_irq();
|
||||
|
||||
if (DMA1->HISR & DMA_HISR_TCIF6)
|
||||
{
|
||||
DMA1->HIFCR |= DMA_HIFCR_CTCIF6;
|
||||
dma_tx_busy = 0;
|
||||
USART2->CR3 &= ~USART_CR3_DMAT; // 传输完成后关闭DMA请求
|
||||
USART2->CR3 &= ~USART_CR3_DMAT;
|
||||
|
||||
// 如果是高优先级缓冲区发送完成,切换回正常缓冲区
|
||||
if (current_buffer == 1)
|
||||
{
|
||||
current_buffer = 0;
|
||||
|
@ -295,8 +296,10 @@ void DMA1_Stream6_IRQHandler(void)
|
|||
{
|
||||
DMA1->HIFCR |= DMA_HIFCR_CTEIF6;
|
||||
dma_tx_busy = 0;
|
||||
current_buffer = 0; // 发生错误也切换回正常缓冲区
|
||||
current_buffer = 0;
|
||||
}
|
||||
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void DMA1_Channel6_IRQHandler(void)
|
||||
|
|
Loading…
Reference in New Issue