FluxDC/components/FluxUart/FluxUart.c

467 lines
15 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 FluxUart.c
* @brief 串口通讯实现源文件
*
* 用于串口通讯实现
*
* @author wang xiang en
* @date 2025-04-19
* @version 版本号
* @copyright 版权声明((C)2025, YUWELL MEDTECH Co.ltd
*/
#include <stdio.h>
#include "FluxUart.h"
#include "ui.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "FluxSD.h"
static const char *TAG = "UART TEST";
/* 通讯使用到的结构体 */
struct FluxMachineData FluxMachineData;
struct ModbusRTU_Frame flux_frame;
struct ModbusRTU_Frame breath_frame;
struct ModbusRTU_Frame flux_frame_start;
struct ModbusRTU_Frame2Reg flux_frame2Reg;
/*创建用于记录开始测量事件的事件组*/
EventGroupHandle_t start_state_event_group;
/* 用于进行CRC校验的数组 */
const unsigned char chCRCHTalbe[] =
{
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40
};
/* 用于进行CRC校验的数组 */
const unsigned char chCRCLTalbe[] =
{
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
0x41, 0x81, 0x80, 0x40
};
/**
* @brief CRC16 校验函数
*
* @param[in] pchMsg 输入的数据
* @param[in] wDataLen 数据长度
*
*/
unsigned short CRC16(unsigned char* pchMsg, unsigned short wDataLen)
{
unsigned char chCRCHi = 0xFF;
unsigned char chCRCLo = 0xFF;
unsigned short wIndex;
while(wDataLen--)
{
wIndex = chCRCLo ^ *pchMsg++ ;
chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];
chCRCHi = chCRCLTalbe[wIndex] ;
}
#if BIG_ENDIAN_USED
return((chCRCHi << 8) | chCRCLo) ;
#else
return((chCRCLo << 8) | chCRCHi) ;
#endif
}
/**
* @brief 串口1收发任务 (流量计服务函数)
*
* @param[in] arg not used
*
*/
void uart1_echoTask(void* arg)
{
/* Configure parameters of an UART driver,
* communication pins and install the driver */
uart_config_t uart_config = {
.baud_rate = ECHO_UART_BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
int intr_alloc_flags = 0;
ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM1, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM1, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM1, ECHO_TEST_TXD1, ECHO_TEST_RXD1, ECHO_TEST_RTS, ECHO_TEST_CTS));
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
unsigned short crc;
flux_frame.ADDR = FLUX_ADDR;
flux_frame.FUNC = FLUX_FUNC_READ;
flux_frame.DATA[0] = 0x00;
flux_frame.DATA[1] = 0x01;
flux_frame.DATA[2] = 0x00;
flux_frame.DATA[3] = 0x02;
/*初始化启动命令帧内容*/
flux_frame_start.ADDR = FLUX_ADDR;
flux_frame_start.FUNC = FLUX_FUNC_SET_SINGLE;
flux_frame_start.DATA[0] = 0x00;
flux_frame_start.DATA[1] = 0x01;
flux_frame_start.DATA[2] = 0x00;
flux_frame_start.DATA[3] = 0x01;
float time = 0;
uint8_t bytes[4];
#if LOG_RECORD_ENABLE
example_write_log("uart1_echoTask 流量计任务初始化完毕");
#endif
while (1)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
// Read data from the UART
/*更新data*/
int len = uart_read_bytes(ECHO_UART_PORT_NUM1, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
// Write data back to the UART
//uart_write_bytes(ECHO_UART_PORT_NUM1, (const char *) data, len);
if (len)
{
data[len] = '\0';
for(int i=0;i<len;i++)
ESP_LOGI(TAG, "data[%d]:%02X", i, data[i]);
/*检查测试是否完成*/
if ((data[20] == 0x01)&&(data[1]==0x03)&&data[4]==FLUX_MODE_TIMER)
{
/*测试已完成*/
lv_obj_add_state(ui_pageFluxRead_checkboxUnfinished,LV_STATE_CHECKED);
/*获取定时模式的时间*/
bytes[0] = data[10];
bytes[1] = data[9];
bytes[2] = data[8];
bytes[3] = data[7];
memcpy(&FluxMachineData.time, bytes, 4);
lv_label_set_text_fmt(ui_pageFluxRead_labelTimerPeriod,"%.2f",FluxMachineData.time);
/*获取积分流量值*/
bytes[0] = data[46];
bytes[1] = data[45];
bytes[2] = data[44];
bytes[3] = data[43];
/*获取积分流量值将单位转化为mL*/
memcpy(&FluxMachineData.cumulativeVolume, bytes, 4);
FluxMachineData.cumulativeVolume = FluxMachineData.cumulativeVolume*1000;
lv_label_set_text_fmt(ui_pageFluxRead_labelCumulativeVolume,"%.2f",FluxMachineData.cumulativeVolume);
#if LOG_RECORD_ENABLE
example_write_log("uart1_echoTask 收到有效流量计数据,解析成功。");
#endif
/* 获取测试结果并写入到SD卡中 */
switch (lv_dropdown_get_selected(ui_pageFluxRead_dropdownPulseTimes))
{
case 0:
sdData.flux_test_result.current_test_result = FluxMachineData.cumulativeVolume/10.0;
break;
default:
break;
}
sd_testData_write();
RefreshResult();
/*获取当前液温*/
bytes[0] = data[66];
bytes[1] = data[65];
bytes[2] = data[64];
bytes[3] = data[63];
memcpy(&FluxMachineData.liquidTemperature, bytes, 4);
lv_label_set_text_fmt(ui_pageFluxRead_labelLiquidTemperature,"%.2f",FluxMachineData.liquidTemperature);
}else{
lv_obj_clear_state(ui_pageFluxRead_checkboxUnfinished,LV_STATE_CHECKED);
}
}
}
}
/**
* @brief 测试用任务函数
*
* @param[in] arg not used
*
*/
void test_task(void *arg)
{
start_state_event_group = xEventGroupCreate();
/*事件初始化*/
xEventGroupClearBits(start_state_event_group,START_TEST_EVENT_BIT);
int32_t timeS = 0;
while (1)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
if (xEventGroupGetBits(start_state_event_group)&START_TEST_EVENT_BIT)
{
/*开始测试*/
timeS = lv_spinbox_get_value(ui_pageFluxRead_spinboxTime);
/*下发启动测试指令*/
FLUX_TEST_START;
lv_label_set_text(ui_pageHome_labelStartTest,"Testing...");
vTaskDelay(timeS*1000/portTICK_PERIOD_MS);
lv_event_send(ui_pageFluxRead_buttonReadFlux,LV_EVENT_CLICKED,NULL);
lv_label_set_text(ui_pageHome_labelStartTest,"Test Complete!");
/*测试完毕后清空事件*/
xEventGroupClearBits(start_state_event_group,START_TEST_EVENT_BIT);
}
}
}
/**
* @brief 串口2收发任务 (呼吸模拟器)
*
* @param[in] arg not used
*
*/
void uart2_echoTask(void* arg)
{
/* Configure parameters of an UART driver,
* communication pins and install the driver */
uart_config_t uart_config = {
.baud_rate = ECHO_UART_BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
int intr_alloc_flags = 0;
ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM2, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM2, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM2, ECHO_TEST_TXD2, ECHO_TEST_RXD2, ECHO_TEST_RTS, ECHO_TEST_CTS));
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
#if LOG_RECORD_ENABLE
example_write_log("uart2_echoTask 呼吸模拟器消息处理任务初始化完毕");
#endif
while (1)
{
// Read data from the UART
int len = uart_read_bytes(ECHO_UART_PORT_NUM2, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
// Write data back to the UART
uart_write_bytes(ECHO_UART_PORT_NUM2, (const char *) data, len);
if (len)
{
data[len] = '\0';
lv_textarea_add_char(ui_pageFluxDebug_textAreaContent,'\n');
lv_textarea_add_text(ui_pageFluxDebug_textAreaContent, (char *) data);
}
}
}
/**
* @brief 封装03 06指令函数 单寄存器写、多寄存器读
*
* @param[in] uart_num 串口号
* @param[in] frame 需要发送的数据帧
*
*/
esp_err_t ModbusRTU_Send_0306(uart_port_t uart_num, struct ModbusRTU_Frame *frame)
{
unsigned short crc;
char text[64];
int res=0;
crc = CRC16((unsigned char *)frame, sizeof(frame->ADDR) + sizeof(frame->FUNC) + sizeof(frame->DATA));
frame->CRC[1] = (crc & 0xFF);
frame->CRC[0] = (crc >> 8);
res = uart_write_bytes(uart_num, (const char *)frame, sizeof(struct ModbusRTU_Frame)/sizeof(unsigned char));
if (res == -1)
{
return ESP_FAIL;
}
#if 1
sprintf(text,"%02X %02X %02X %02X %02X %02X %02X %02X \n",frame->ADDR,frame->FUNC,frame->DATA[0],frame->DATA[1],frame->DATA[2],frame->DATA[3],frame->CRC[0],frame->CRC[1]);
lv_textarea_add_char(ui_pageFluxDebug_textAreaContent,'\n');
lv_textarea_add_text(ui_pageFluxDebug_textAreaContent,"Send:");
lv_textarea_add_text(ui_pageFluxDebug_textAreaContent,(char*)text);
#if LOG_RECORD_ENABLE
example_write_log("ModbusRTU_Send_0306 数据发送成功。");
example_write_log(text);
#endif
#endif
return ESP_OK;
}
/**
* @brief 封装多寄存器写函数 0x10指令
*
* @param[in] uart_num 串口号
* @param[in] frame 需要发送的数据帧
*
*/
esp_err_t ModbusRTU_Send_0x10(uart_port_t uart_num, struct ModbusRTU_Frame2Reg *frame)
{
unsigned short crc;
//char text[64];
int res=0;
crc = CRC16((unsigned char *)frame, sizeof(frame->ADDR) + sizeof(frame->FUNC) + sizeof(frame->DATA)+\
sizeof(frame->regAddr) + sizeof(frame->regNum)+sizeof(frame->ByteNum));
frame->CRC[1] = (crc & 0xFF);
frame->CRC[0] = (crc >> 8);
ESP_LOGI("uart_write_bytes", "%02X %02X %02X %02X %02X %02X %02X %02X \n",\
frame->ADDR,frame->FUNC,frame->DATA[0],frame->DATA[1],frame->DATA[2],frame->DATA[3],frame->CRC[0],frame->CRC[1]);
res = uart_write_bytes(uart_num, (const char *)frame, sizeof(struct ModbusRTU_Frame2Reg)/sizeof(unsigned char));
if (res == -1)
{
return ESP_FAIL;
ESP_LOGI("uart_write_bytes", "uart_write_bytes fail");
}
ESP_LOGI("uart_write_bytes", "uart_write_bytes success");
return ESP_OK;
}
/**
* @brief 根据主界面内容刷新测试结果
*
*/
esp_err_t RefreshResult(void)
{
/* 获取当前测试次数 */
switch (lv_dropdown_get_selected(ui_pageFluxRead_dropdownPulseTimes))
{
case 0:
FluxMachineData.breathTimes = 10;
break;
case 1:
FluxMachineData.breathTimes = 20;
break;
case 2:
FluxMachineData.breathTimes = 30;
break;
default:
break;
}
/* 获取当前测试流量 */
float breathVolume = FluxMachineData.cumulativeVolume/FluxMachineData.breathTimes;
lv_label_set_text_fmt(ui_pageHome_labelTestVolume,"%.2f",breathVolume);
#if 0
sdData.flux_test_result.current_test_result = breathVolume;
sd_testData_write();
#endif
/*获取测试体积上下限*/
float testVolumeUpper = atoff(lv_label_get_text(ui_pageHome_labelNominalVolumeMax));
float testVolumeLower = atoff(lv_label_get_text(ui_pageHome_labelNominalVolumeMin));
/*根据测试结果判断是否合格*/
if (breathVolume > testVolumeUpper || breathVolume < testVolumeLower)
{
RESULT_FAULT;
if (breathVolume > testVolumeUpper )
{
lv_label_set_text(ui_pageHome_labelResultCompare,"High");
}else if (breathVolume < testVolumeLower)
{
lv_label_set_text(ui_pageHome_labelResultCompare,"Low");
}
}else{
RESULT_RIGHT;
lv_label_set_text(ui_pageHome_labelResultCompare,"Pass!");
}
#if LOG_RECORD_ENABLE
example_write_log("RefreshResult 结果刷新完毕");
#endif
return ESP_OK;
}