signal_generator/User/driver/uart_lcd.c

360 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.

/*
* @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); // 调用函数发送数据
}
}