/* * @Author: wangxujie wangxujie@wuxismart.com * @Date: 2025-03-10 15:05:20 * @LastEditors: wangxujie wangxujie@wuxismart.com * @LastEditTime: 2025-07-30 17:01:28 * @FilePath: \signal_generator\User\driver\uart_lcd.c * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ #include "uart_lcd.h" #include "usart.h" #include "lwip.h" #include "tim.h" extern ip4_addr_t ipaddr; uart_lcd_t uart_lcd_state = {0}; lcd_makecurve_t lcd_makecurve_data = {0}; lcd_set_button_t lcd_set_button1_data = {0}; // 输出通道文本按钮,界面ID 0,控件ID 1 lcd_set_button_t lcd_set_button2_data = {0}; // 第一路AO输出箭头按钮,界面ID 0,控件ID 2 lcd_set_button_t lcd_set_button3_data = {0}; // 第二路AO输出箭头按钮,界面ID 0,控件ID 3 lcd_set_button_t lcd_set_button4_data = {0}; // SW1状态按钮,界面ID 1,控件ID 1 lcd_set_button_t lcd_set_button5_data = {0}; // SW2状态按钮,界面ID 1,控件ID 2 lcd_set_txt_t lcd_set_txt_data = {0}; // 文本设置数据 lcd_set_progress_t lcd_set_progress_data = {0}; // 进度条设置数据 lcd_switchscreen_t lcd_switchscreen_data = {0}; // 切换画面数据 extern float current_buff[2]; static void uart_lcd_page_init(lcd_switchscreen_t *screen_data); static void uart_lcd_button_init(lcd_set_button_t *button_data, uint16_t screen_id, uint16_t ctrl_id); static void uart_lcd_current_channel1(void); static void uart_lcd_current_channel2(void); static void uart_lcd_page_init(lcd_switchscreen_t *screen_data) { screen_data->cmd_head = LCD_CMD_HEAD; screen_data->cmd_type = LCD_CMD_TYPE; screen_data->cmd_ctrl_type = LCD_CMD_CTRL_TYPE_SWITCH_SCREEN; screen_data->cmd_screen_id = 0x0000; // 默认切换到主界面 screen_data->cmd_tail = LCD_CMD_TAIL; } static void uart_lcd_button_init(lcd_set_button_t *button_data, uint16_t screen_id, uint16_t ctrl_id) { button_data->cmd_head = LCD_CMD_HEAD; button_data->cmd_type = LCD_CMD_TYPE; button_data->cmd_ctrl_type = LCD_CMD_CTRL_TYPE_SET_BUTTON; button_data->cmd_screen_id = screen_id; button_data->cmd_ctrl_id = ctrl_id; button_data->cmd_button_status = 0; // 默认按钮状态为未按下 button_data->cmd_tail = LCD_CMD_TAIL; } /** * @brief 设置LCD按钮状态 * * 该函数用于设置LCD上的按钮状态。 * * @param button_data 按钮数据指针,指向包含按钮设置信息的结构体 */ static void uart_lcd_set_button_status(lcd_set_button_t *button_data, uint8_t status) { if (button_data == NULL) { return; } while (uart_lcd_state.lcd_flag != 0) { } button_data->cmd_button_status = status; // 设置按钮状态 static uint8_t uart_lcd_button_data[sizeof(lcd_set_button_t)] = {0}; uart_lcd_button_data[0] = button_data->cmd_head; // 帧头 uart_lcd_button_data[1] = button_data->cmd_type; // 命令类型 uart_lcd_button_data[2] = button_data->cmd_ctrl_type; // 控制类型 uart_lcd_button_data[3] = (button_data->cmd_screen_id >> 8) & 0xFF; // 画面ID高位 uart_lcd_button_data[4] = button_data->cmd_screen_id & 0xFF; // 画面ID低位 uart_lcd_button_data[5] = (button_data->cmd_ctrl_id >> 8) & 0xFF; // 控件ID高位 uart_lcd_button_data[6] = button_data->cmd_ctrl_id & 0xFF; // 控件ID低位 uart_lcd_button_data[7] = button_data->cmd_button_status; // 按钮状态 uart_lcd_button_data[8] = (button_data->cmd_tail >> 24) & 0xFF; // 帧尾 uart_lcd_button_data[9] = (button_data->cmd_tail >> 16) & 0xFF; // 帧尾 uart_lcd_button_data[10] = (button_data->cmd_tail >> 8) & 0xFF; // 帧尾 uart_lcd_button_data[11] = button_data->cmd_tail & 0xFF; // 帧尾 // 大小端转换 dma_usart_send(&huart4, uart_lcd_button_data, sizeof(lcd_set_button_t)); } static void uart_lcd_current_channel1(void) { // 输出文本按钮状态0,第一路AO状态1,第二路AO状态0 // lcd_set_button1_data.cmd_button_status = 0; // 第一路AO输出文本按钮状态为未按下 uart_lcd_set_button_status(&lcd_set_button1_data, 0); // lcd_set_button2_data.cmd_button_status = 1; // 第一路AO输出箭头按钮状态为按下 uart_lcd_set_button_status(&lcd_set_button2_data, 1); // lcd_set_button3_data.cmd_button_status = 0; // 第二路AO输出箭头按钮状态为未按下 uart_lcd_set_button_status(&lcd_set_button3_data, 0); } static void uart_lcd_current_channel2(void) { // 输出文本按钮状态1,第一路AO状态0,第二路AO状态1 // lcd_set_button1_data.cmd_button_status = 1; uart_lcd_set_button_status(&lcd_set_button1_data, 1); // lcd_set_button2_data.cmd_button_status = 0; uart_lcd_set_button_status(&lcd_set_button2_data, 0); // lcd_set_button3_data.cmd_button_status = 1; uart_lcd_set_button_status(&lcd_set_button3_data, 1); } /** * @brief 通过UART向LCD屏幕绘制IP地址 * * 此函数通过UART接口向LCD屏幕发送IP地址,以便在屏幕上显示。 * * @note 此函数假定已经正确初始化了UART接口,并且LCD屏幕已经正确连接到UART接口。 */ void uart_lcd_draw_ipaddr(void) { uint8_t ip_addr[24] = {0}; // 串口发送的固定值为串口屏指令指定的帧头帧尾 ip_addr[0] = 0xEE; // 帧头 ip_addr[1] = 0xB1; ip_addr[2] = 0x10; // 命令码,此处为文本控件文本设置指令 ip_addr[3] = 0x00; // 画面ID高位地址 ip_addr[4] = 0x00; // 画面ID低位地址 ip_addr[5] = 0x00; // 控件ID高位地址 ip_addr[6] = 0x03; // 控件ID低位地址 char *ip_addr_str = ipaddr_ntoa(&ipaddr); MEMCPY(ip_addr + 7, (uint8_t *)ip_addr_str, strlen(ip_addr_str)); ip_addr[7 + strlen(ip_addr_str)] = 0xFF; // 帧尾,下列都为帧尾 ip_addr[8 + strlen(ip_addr_str)] = 0xFC; ip_addr[9 + strlen(ip_addr_str)] = 0xFF; ip_addr[10 + strlen(ip_addr_str)] = 0xFF; dma_usart_send(&huart4, ip_addr, ARRAY_LEN(ip_addr)); } void uart_lcd_init(void) { // 初始化屏幕 uart_lcd_state.page_num = 0; uart_lcd_page_init(&lcd_switchscreen_data); // 初始化页面数据 uart_lcd_page_switch(uart_lcd_state.page_num); // 切换到第一个页面 // 初始化按钮 uart_lcd_button_init(&lcd_set_button1_data, 0, 1); uart_lcd_button_init(&lcd_set_button2_data, 0, 2); uart_lcd_button_init(&lcd_set_button3_data, 0, 3); uart_lcd_button_init(&lcd_set_button4_data, 1, 1); uart_lcd_button_init(&lcd_set_button5_data, 1, 2); uart_lcd_state.current_out_channel = 0; uart_lcd_state.current_value[0] = 0; uart_lcd_state.current_value[1] = 0; uart_lcd_channel_switch(uart_lcd_state.current_out_channel); HAL_Delay(10); uart_lcd_current_out(0); HAL_Delay(10); uart_lcd_current_out(1); lcd_makecurve_data.cmd_head = 0xEE; // 帧头 lcd_makecurve_data.cmd_type = 0xB1; // 命令类型 lcd_makecurve_data.cmd_ctrl_type = 0x32; // 写曲线数据 lcd_makecurve_data.cmd_screen_id = 0x01; // 画面ID lcd_makecurve_data.cmd_ctrl_id = 0x0E; // 控件ID lcd_makecurve_data.cmd_curve_channel = 0x00; // 曲线通道 lcd_makecurve_data.cmd_tail = 0xFFFCFFFF; // 帧尾 } uint8_t lcd_channel[15] = {0xEE, 0xB1, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF}; void uart_lcd_current_out(uint8_t channel) { if (channel == 0) { lcd_channel[6] = 0x04; lcd_channel[10] = uart_lcd_state.current_value[0]; dma_usart_send(&huart4, lcd_channel, ARRAY_LEN(lcd_channel)); } else if (channel == 1) { lcd_channel[6] = 0x05; lcd_channel[10] = uart_lcd_state.current_value[1]; dma_usart_send(&huart4, lcd_channel, ARRAY_LEN(lcd_channel)); } } void uart_lcd_channel_switch(uint8_t channel) { switch (channel) { case 0: uart_lcd_current_channel1(); break; case 1: uart_lcd_current_channel2(); break; default: uart_lcd_current_channel1(); break; } } void uart_lcd_page_switch(uint8_t page) { while (uart_lcd_state.lcd_flag != 0) { } static uint8_t uart_switchscreen_data[sizeof(lcd_switchscreen_t)] = {0}; lcd_switchscreen_data.cmd_screen_id = (uint16_t)page; // 更新当前页面状态 uart_switchscreen_data[0] = lcd_switchscreen_data.cmd_head; // 帧头 uart_switchscreen_data[1] = lcd_switchscreen_data.cmd_type; // 命令类型 uart_switchscreen_data[2] = lcd_switchscreen_data.cmd_ctrl_type; // 控制类型 uart_switchscreen_data[3] = (lcd_switchscreen_data.cmd_screen_id >> 8) & 0xFF; // 画面ID高位地址 uart_switchscreen_data[4] = lcd_switchscreen_data.cmd_screen_id & 0xFF; // 画面ID低位地址 uart_switchscreen_data[5] = (lcd_switchscreen_data.cmd_tail >> 24) & 0xFF; // 帧尾 uart_switchscreen_data[6] = (lcd_switchscreen_data.cmd_tail >> 16) & 0xFF; // 帧尾 uart_switchscreen_data[7] = (lcd_switchscreen_data.cmd_tail >> 8) & 0xFF; // 帧尾 uart_switchscreen_data[8] = lcd_switchscreen_data.cmd_tail & 0xFF; // 帧尾 dma_usart_send(&huart4, uart_switchscreen_data, sizeof(lcd_switchscreen_t)); // 发送切换画面数据 } void uart_lcd_ecll_control_current_out(void) { if (ec11_data.confirm_key_flag == 0) { } else if (ec11_data.confirm_key_flag == 1) // Confirm button - confirms current output { ec11_data.confirm_key_flag_last++; if (ec11_data.confirm_key_flag_last > 2) { current_buff[0] = (float)uart_lcd_state.current_value[0]; current_buff[1] = (float)uart_lcd_state.current_value[1]; ec11_data.confirm_key_flag_last = 0; ec11_data.confirm_key_flag = 0; } } else if (ec11_data.confirm_key_flag == 2) // Switch the current output channel { ec11_data.confirm_key_flag_last++; if (ec11_data.confirm_key_flag_last > 2) { if (uart_lcd_state.current_out_channel == 1) { uart_lcd_state.current_out_channel = 0; } else if (uart_lcd_state.current_out_channel == 0) { uart_lcd_state.current_out_channel = 1; } ec11_data.confirm_key_flag_last = 0; ec11_data.confirm_key_flag = 0; uart_lcd_channel_switch(uart_lcd_state.current_out_channel); } } else if (ec11_data.confirm_key_flag == 3) // 切换界面 { if (uart_lcd_state.page_num == 0) { uart_lcd_state.page_num = 1; } else if (uart_lcd_state.page_num == 1) { uart_lcd_state.page_num = 0; } ec11_data.confirm_key_flag_last = 0; ec11_data.confirm_key_flag = 0; uart_lcd_page_switch(uart_lcd_state.page_num); } } void uart_lcd_ec11_control_current(void) { if (uart_lcd_state.page_num == 0) // 当前页面为电流调节页面时,才对EC11编码器进行计数处理 { ec11_data.direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim1); ec11_data.encode_num = (short)__HAL_TIM_GET_COUNTER(&htim1); if ((ec11_data.direction == 0) && (ec11_data.encode_num > ec11_data.encode_num_last)) { if (uart_lcd_state.current_out_channel == 0) { uart_lcd_state.current_value[0] += 1; if (uart_lcd_state.current_value[0] > 20) { uart_lcd_state.current_value[0] = 20; } } else if (uart_lcd_state.current_out_channel == 1) { uart_lcd_state.current_value[1] += 1; if (uart_lcd_state.current_value[1] > 20) { uart_lcd_state.current_value[1] = 20; } } uart_lcd_current_out(uart_lcd_state.current_out_channel); } if ((ec11_data.direction == 1) && (ec11_data.encode_num < ec11_data.encode_num_last)) { if (uart_lcd_state.current_out_channel == 0) { if (uart_lcd_state.current_value[0] < 2) { uart_lcd_state.current_value[0] = 0; } else { uart_lcd_state.current_value[0] -= 1; } } else if (uart_lcd_state.current_out_channel == 1) { if (uart_lcd_state.current_value[1] < 2) { uart_lcd_state.current_value[1] = 0; } else { uart_lcd_state.current_value[1] -= 1; } } uart_lcd_current_out(uart_lcd_state.current_out_channel); } ec11_data.encode_num_last = ec11_data.encode_num; } } void uart_lcd_makecurvet(lcd_makecurve_t *makecurve_data) { static uint8_t uart_makecurve_data[256] = {0}; // 发送数据缓冲区,最大长度为256字节 uart_makecurve_data[0] = makecurve_data->cmd_head; // 帧头 uart_makecurve_data[1] = makecurve_data->cmd_type; // 命令类型 uart_makecurve_data[2] = makecurve_data->cmd_ctrl_type; // 控制类型 uart_makecurve_data[3] = (makecurve_data->cmd_screen_id >> 8) & 0xFF; // 画面ID高位地址 uart_makecurve_data[4] = makecurve_data->cmd_screen_id & 0xFF; // 画面ID低位地址 uart_makecurve_data[5] = (makecurve_data->cmd_ctrl_id >> 8) & 0xFF; // 控件ID高位地址 uart_makecurve_data[6] = makecurve_data->cmd_ctrl_id & 0xFF; // 控件ID低位地址 uart_makecurve_data[7] = makecurve_data->cmd_curve_channel; // 曲线通道 uart_makecurve_data[8] = (makecurve_data->cmd_data_len >> 8) & 0xFF; // 数据长度高位地址 uart_makecurve_data[9] = makecurve_data->cmd_data_len & 0xFF; // 数据长度低位地址 MEMCPY(uart_makecurve_data + 10, makecurve_data->cmd_data, makecurve_data->cmd_data_len); // 数据内容 uart_makecurve_data[10 + makecurve_data->cmd_data_len] = (makecurve_data->cmd_tail >> 24) & 0xFF; // 帧尾 uart_makecurve_data[11 + makecurve_data->cmd_data_len] = (makecurve_data->cmd_tail >> 16) & 0xFF; // 帧尾 uart_makecurve_data[12 + makecurve_data->cmd_data_len] = (makecurve_data->cmd_tail >> 8) & 0xFF; // 帧尾 uart_makecurve_data[13 + makecurve_data->cmd_data_len] = makecurve_data->cmd_tail & 0xFF; // 帧尾 dma_usart_send(&huart4, uart_makecurve_data, makecurve_data->cmd_data_len + 14); } void uart_lcd_makecurve_test(void) { lcd_makecurve_data.cmd_data_len = 1; // 假设数据长度为1 // if (uart_lcd_state.page_num == 1) { lcd_makecurve_data.cmd_data[0] = (current_buff[1] - 4) * 100 / 16; // 填充数据内容 uart_lcd_makecurvet(&lcd_makecurve_data); // 调用函数发送数据 } }