智能车菜单

使用简单的索引菜单实现基本智能车调参 - 知乎 (zhihu.com)

参考这个博主的,在tc377实现了复刻并加上了flash,如果有更好的可以交流


/*****************************************************************/
// /* Menu.c
//  *
//  *  Created on: 2023/3/7
//  *  Author: WHJ
//  *
//  >>本菜单适用于较为简单的基本调参,存在部分情况未充分考量的情况
//  >>但是由于适用场景为智能车项目,提供显示的物理载体为IPS200,因
//  >>此部分可能导致数组越界的情况可以忽略。
/*****************************************************************/
#include "zf_common_headfile.h"

float a = 10;
int key1_flag,key2_flag,key3_flag,key4_flag;

#define FLASH_SECTION_INDEX       (0)                                 // 存储数据用的扇区
#define FLASH_PAGE_INDEX          (11)                                // 存储数据用的页码 倒数第一个页码注意tc264与377的区别

typedef struct
{
    int menu_id;                                        // 菜单索引号
    char menu_name[30];                                 // 菜单显示名称
    void (*menu_action)(float32 *param, char name[30]); // 子菜单执行函数
    float32 *param;                                     // 需要传入处理的参数
} menu_item;
// 由于IPS200 屏幕大小为240X180,逐飞提供默认字库大小为8X16,因此屏幕横向无法显示超过30个字符

menu_item *current_menu_item;

int key_switch()
{
    int key_state = 0;
    if(key_get_state(KEY_1) == KEY_SHORT_PRESS) key1_flag = 1;
    else if(key_get_state(KEY_2) == KEY_SHORT_PRESS) key2_flag = 1;
    else if(key_get_state(KEY_3) == KEY_SHORT_PRESS) key3_flag = 1;
    else if(key_get_state(KEY_4) == KEY_SHORT_PRESS) key4_flag = 1;
    key_state = ((key1_flag || key2_flag || key3_flag || key4_flag) == 1) ?  1 : 0;
    return key_state;
}


void key_flag_clear()
{
    key1_flag = 0,key2_flag = 0,key3_flag = 0,key4_flag = 0;
}


void menu_tuning(float32 *tuning, char name[30]) // 调参界面菜单
{
    char buf[30]; // 由于IPS200 屏幕大小为240X180,逐飞提供默认字库大小为8X16,因此屏幕横向无法显示超过30个字符
    char *menu_name = name;
    float32 level[4] = {0.01, 0.1, 1, 10};
    int current_level = 0;

    ips200_clear();
    ips200_show_string(1, 0, "Change_level:");
    sprintf(buf, "X%5.2f: ", level[current_level]);
    ips200_show_string(1, 30, buf);
    key_flag_clear();

    while (1)
    {
        if (key_switch())
        {
            if (key1_flag && current_level < 4)
            {
                current_level += 1;
            }
            else if (key2_flag && current_level > 0)
            {
                current_level -= 1;
            }
            else if (key3_flag)
            {
                ips200_clear();
                sprintf(buf, "%s: ", menu_name);
                ips200_show_string(1, 0, buf);
                sprintf(buf, "%5.2f", *tuning);
                ips200_show_string(1, 30, buf);
                key_flag_clear();
                while (1)
                {
                    if (key_switch())
                    {
                        if (key1_flag)
                        {
                            *tuning += level[current_level];
                        }
                        else if (key2_flag)
                        {
                            *tuning -= level[current_level];
                        }
                        else if (key3_flag)
                        {
                            return;
                        }
                        else if (key4_flag)
                        {
                            flah_storage();
                        }
                        ips200_clear();
                        sprintf(buf, "%s: ", menu_name);
                        ips200_show_string(1, 0, buf);
                        sprintf(buf, "%5.2f", *tuning);
                        ips200_show_string(1, 30, buf);
                        key_flag_clear();
                    }
                }
            }

            ips200_clear();
            ips200_show_string(1, 0, "Change_level:");
            sprintf(buf, "X %5.2f: ", level[current_level]);
            ips200_show_string(1, 30, buf);
            key_flag_clear();
        }
    }
}

menu_item menu[] = {
        {1, "Tuning Mode", NULL, NULL},                                        // 调参模式
        {11, "Motor", NULL, NULL},                                              // 电机参数调整
        {111, "Motor_L", NULL, NULL},                                       // 电机参数调整——变积分
        {1111,"P", menu_tuning, &pid_i_L.Kp},
        {1112,"I", menu_tuning, &pid_i_L.Ki},
        {1114, "Back to Main", NULL, NULL},                                   // 回到主菜单

        {112, "Motor_R", NULL, NULL},                                       // 电机参数调整——变积分
        {1121,"P", menu_tuning, &pid_i_R.Kp},
        {1122,"I", menu_tuning, &pid_i_R.Ki},
        {1123, "Back to Main", NULL, NULL},                                   // 回到主菜单

//        {3, "Departure Mode", NULL, NULL}                                      // 发车模式

};

bool have_sub_menu(int menu_id) // 查看是否存在子菜单
{
    for (int i = 0; i < sizeof(menu) / sizeof(menu[0]); i++)
    {
        if (menu[i].menu_id / 10 == menu_id)
        {
            return true;
        }
    }
    return false;
}

int show_sub_menu(int parent_id, int highlight_col) // 显示子菜单,以及当前高亮菜单
{
    ips200_clear();
    int item_idx = 0;
    for (int i = 0; i < sizeof(menu) / sizeof(menu[0]); i++)
    {
        if (menu[i].menu_id / 10 == parent_id)
        {
            if (item_idx == highlight_col)
            {
                current_menu_item = &menu[i];
                ips200_set_color(RGB565_RED, RGB565_BLACK);
            }
            else
            {
                ips200_set_color(RGB565_GREEN, RGB565_BLACK);
            }
            ips200_show_string(1, 30 * item_idx, menu[i].menu_name);
            item_idx++;
        }
    }
    return item_idx;
}

void Menu_Switch(void)
{

    int parent_menu_id = 0;
    int highlight_col = 0; // 设定高亮行号
    int menu_item_count = show_sub_menu(parent_menu_id, highlight_col);
    while (1)
    {
        if (key_switch()) // 读取按键函数
        {
            if (key1_flag && highlight_col > 0) // 按下按键1减少当前行数
            {
                highlight_col--;
            }
            else if (key2_flag && highlight_col < menu_item_count - 1) // 按下按键2增加当前行数
            {
                highlight_col++;
            }
            else if (key3_flag)
            {
                if (have_sub_menu(current_menu_item->menu_id))
                {
                    highlight_col = 0;
                    parent_menu_id = current_menu_item->menu_id;
                }
                else if (strcmp(current_menu_item->menu_name, "Back to Main") == 0) // 如果当前菜单为“Back to Main”,则返回主界面
                {
                    highlight_col = 0;
                    parent_menu_id = 0;
                }
                else if (current_menu_item->menu_action)
                {
                    current_menu_item->menu_action(current_menu_item->param, current_menu_item->menu_name);
                }
            }

            menu_item_count = show_sub_menu(parent_menu_id, highlight_col);
            key_flag_clear();
        }
    }
}

void flah_storage()
{
    if(flash_check(FLASH_SECTION_INDEX, FLASH_PAGE_INDEX))                      // 判断是否有数据
        flash_erase_page(FLASH_SECTION_INDEX, FLASH_PAGE_INDEX);                // 擦除这一页

    flash_buffer_clear();                                                       // 清空缓冲区

    flash_union_buffer[0].float_type  = pid_i_L.Kp;                              // 向缓冲区第 0 个位置写入 float  数据
    flash_union_buffer[1].float_type  = pid_i_L.Ki;
    flash_union_buffer[2].float_type  = pid_i_R.Kp;
    flash_union_buffer[3].float_type  = pid_i_R.Ki;

    flash_write_page_from_buffer(FLASH_SECTION_INDEX, FLASH_PAGE_INDEX);        // 向指定 Flash 扇区的页码写入缓冲区数据
    flash_buffer_clear();                                                       // 清空缓冲区

    system_delay_ms(200);

}

void flash_read()
{
    flash_read_page_to_buffer(FLASH_SECTION_INDEX, FLASH_PAGE_INDEX);           // 将数据从 flash 读取到缓冲区

    pid_i_L.Kp = flash_union_buffer[0].float_type;
    pid_i_L.Ki = flash_union_buffer[1].float_type;
    pid_i_R.Kp = flash_union_buffer[2].float_type;
    pid_i_R.Ki = flash_union_buffer[3].float_type;

    flash_buffer_clear();
}
 

主函数为

int core0_main(void)
{
    clock_init();                               // 获取时钟频率<务必保留>
    debug_init();                               // 初始化默认调试串口
    reset_pid_increase(&pid_i_L,64,8);          //设置速度环的PI
    reset_pid_increase(&pid_i_R,56,7.1);        //设置速度环的PI20

    reset_pid_position(&pid_p_angular_velocity,40,0.0002,0.01);//设置角速度环的PID ,响应有点慢,注意转圈的bug,后期修正一下,reset_pid_position(&pid_p_angular_velocity,28,0001,5.2);
    reset_pid_position(&pid_p_angle,4,0,0.1);     //设置方向环的PID  6.5,0,0


    car_Init();
    flash_read();                               //***如果有新变量必需先存一次再读取
    Menu_Switch();

    cpu_wait_event_ready();

    while (TRUE)
    {

    }
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值