【正点原子STM32连载】 第二十六章 USMART调试组件实验摘自【正点原子】STM32F103 战舰开发指南V1.2

news2024/12/20 0:56:06

1)实验平台:正点原子stm32f103战舰开发板V4
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html

第二十六章 USMART调试组件实验

本章,我们将向大家介绍一个十分重要的辅助调试工具:USMART调试组件。该组件由正点原子开发提供,功能类似linux的shell(RTT的finsh也属于此类)。USMART最主要的功能就是通过串口调用单片机里面的函数,并执行,对我们调试代码是很有帮助的。
本章分为如下几个小节:
26.1 USMART调试组件简介
26.2 硬件设计
26.3 程序设计
26.4 下载验证

26.1 USMART调试组件简介

USMART是由正点原子开发的一个灵巧的串口调试互交组件,通过它你可以通过串口助手调用程序里面的任何函数,并执行。因此,你可以随意更改函数的输入参数(支持数字(10/16进制,支持负数)、字符串、函数入口地址等作为参数),单个函数最多支持10个输入参数,并支持函数返回值显示,目前最新版本为V3.5。
USMART的特点如下:
1,可以调用绝大部分用户直接编写的函数。
2,资源占用极少(最少情况:FLASH:4K;SRAM:72B)。
3,支持参数类型多(数字(包含10/16进制,支持负数)、字符串、函数指针等)。
4,支持函数返回值显示。
5,支持参数及返回值格式设置。
6,支持函数执行时间计算(V3.1及以后的版本新特性)。
7,使用方便。
有了USMART,你可以轻易的修改函数参数、查看函数运行结果,从而快速解决问题。比如你调试一个摄像头模块,需要修改其中的几个参数来得到最佳的效果,普通的做法:写函数修改参数下载看结果不满意修改参数下载看结果不满意….不停的循环,直到满意为止。这样做很麻烦不说,单片机也是有寿命的啊,老这样不停的刷,很折寿的。而利用USMART,则只需要在串口调试助手里面输入函数及参数,然后直接串口发送给单片机,就执行了一次参数调整,不满意的话,你在串口调试助手修改参数在发送就可以了,直到你满意为止。这样,修改参数十分方便,不需要编译、不需要下载、不会让单片机折寿。
USMART支持的参数类型基本满足任何调试了,支持的类型有:10或者16进制数字、字符串指针(如果该参数是用作参数返回的话,可能会有问题!)、函数指针等。因此绝大部分函数,可以直接被USMART调用,对于不能直接调用的,你只需要重写一个函数,把影响调用的参数去掉即可,这个重写后的函数,即可以被USMART调用了。
USMART的实现流程简单概括就是:第一步,添加需要调用的函数(在usmart_config.c里面的usmart_nametab数组里面添加);第二步,初始化串口;第三步,初始化USMART(通过usmart_init函数实现);第四步,轮询usmart_scan函数,处理串口数据。
接下来我们看下USMART的组成,USMART组件总共包含8个文件,如图26.1.1.所示:
在这里插入图片描述

图26.1.1 USMART组件代码
USMART每个文件的作用如表26.1.1所示:
在这里插入图片描述

表26.1.1 USMART文件介绍
经过以上简单介绍,我们对USMART有了个大概了解,接下来我们将在下一小节给大家介绍USMART组件的移植和使用。
26.2 硬件设计

  1. 例程功能
    本实验通过usmart调用单片机里面的函数,实现对LCD显示和LED以及延时的控制。LED0闪烁用于提示程序正在运行。
  2. 硬件资源
    1)LED灯
    LED0 – PB5
    LED1 – PE5
    1)串口1(PA9/PA10连接在板载USB转串口芯片CH340上面)
    2)定时器4
    3)正点原子2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
    26.3 程序设计
    26.3.1 程序流程图
    在这里插入图片描述

图26.3.1.1 USMART调试组件实验程序流程图
26.3.2 程序解析

  1. USMART驱动代码
    要使用USMART,我们先得进行代码移植,USMART的移植非常简单,我们只需要修改usmart_port.c里面的5个函数即可完成移植。
    第一个函数,USMART输入数据流获取函数,该函数的实现代码如下:
/**
 * @brief     	获取输入数据流(字符串)
 *   @note    	USMART通过解析该函数返回的字符串以获取函数名及参数等信息
 * @param      	无
 * @retval
 *   @arg      	0,  没有接收到数据
 *   @arg     	其他,数据流首地址(不能是0)
 */
char *usmart_get_input_string(void)
{
    uint8_t len;
    char *pbuf = 0;

    if (g_usart_rx_sta & 0x8000)        	/* 串口接收完成? */
    {
        len = g_usart_rx_sta & 0x3fff;  	/* 得到此次接收到的数据长度 */
        g_usart_rx_buf[len] = '\0';     	/* 在末尾加入结束符. */
        pbuf = (char*)g_usart_rx_buf;
        g_usart_rx_sta = 0;             	/* 开启下一次接收 */
    }

    return pbuf;
}
该函数通过SYSTEM文件夹默认的串口接收来实现输入数据流获取。SYSTEM文件夹里面的串口接收函数,最大可以一次接收200字节,用于从串口接收函数名和参数等。大家如果在其他平台移植,请参考SYSTEM文件夹串口接收的实现方式进行移植(详细接收原理请参考:串口通信实验)。

第二个是usmart_timx_init函数,该函数的实现代码如下:

/**
 * @brief       定时器初始化函数
 * @param       arr:自动重装载值
 *              psc:定时器分频系数
 * @retval      无
 */ 
void usmart_timx_init(uint16_t arr, uint16_t psc)
{ 
    USMART_TIMX_CLK_ENABLE();
    
    g_timx_usmart_handle.Instance = USMART_TIMX;		/* 通用定时器4 */
    g_timx_usmart_handle.Init.Prescaler = psc;        	/* 分频系数 */
    g_timx_usmart_handle.Init.CounterMode = TIM_COUNTERMODE_UP;  /* 向上计数器 */
    g_timx_usmart_handle.Init.Period = arr;           	/* 自动装载值 */
    g_timx_usmart_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_Base_Init(&g_timx_usmart_handle);
    HAL_TIM_Base_Start_IT(&g_timx_usmart_handle);     	/* 使能定时器和定时器中断 */
    HAL_NVIC_SetPriority(USMART_TIMX_IRQn, 3, 3);    	/* 抢占优先级3,子优先级3 */
    HAL_NVIC_EnableIRQ(USMART_TIMX_IRQn);             	/* 开启TIM中断 */ 
}

该函数只有在:USMART_ENTIMX_SCAN值为1时,才需要实现,用于定时器初始化,利用定时器完成对usmart_scan函数的周期性调用,并实现函数运行时间计时(runtime)功能。该函数里面的:USMART_TIMX_CLK_ENABLE、USMART_TIMX和USMART_TIMX_IRQn等定时器相关宏定义我们在usmart_prot.h里面定义,方便大家修改。本实验我们用的TIM4。
注意:usmart_timx_init函数是在usmart.c里面,被usmart_init调用,usmart_init源码如下:

/**
 * @brief     	初始化USMART
 * @param     	tclk: 定时器的工作频率(单位:Mhz)
 * @retval     	无
 */
void usmart_init(uint16_t tclk)
{
#if USMART_ENTIMX_SCAN == 1
    usmart_timx_init(1000, tclk * 100 - 1);
#endif
    usmart_dev.sptype = 1;  	/* 十六进制显示参数 */
}

该函数有一个参数tclk,就是用于定时器初始化。注意:这里的tclk是指所选TIM的时钟频率,而非系统主频!这里我们用的TIM4,对于STM32F103来说,TIM4的时钟源来自2倍的APB1,频率为:72Mhz。
另外,USMART_ENTIMX_SCAN是在usmart_port.h里面定义的一个是否使能定时器中断扫描的宏定义。如果为1,就初始化定时器中断,并在中断里面调用usmart_scan函数。如果为0,那么需要用户需要自行间隔一定时间(100ms左右为宜)调用一次usmart_scan函数,以实现串口数据处理。注意:如果要使用函数执行时间统计功能(runtime 1),则必须设置USMART_ENTIMX_SCAN为1。另外,为了让统计时间精确到0.1ms,定时器的计数时钟频率必须设置为10Khz,否则时间就不是0.1ms了。
第三和第四个函数仅用于服务USMART的函数执行时间统计功能(串口指令:runtime 1),分别是:usmart_timx_reset_time和usmart_timx_get_time,这两个函数代码如下:

/**
 * @brief     	复位runtime
 *   @note    	需要根据所移植到的MCU的定时器参数进行修改
 * @param      	无
 * @retval    	无
 */
void usmart_timx_reset_time(void)
{
    __HAL_TIM_CLEAR_FLAG(&g_timx_usmart_handle, TIM_FLAG_UPDATE);/* 清中断标志 */
    __HAL_TIM_SET_AUTORELOAD(&g_timx_usmart_handle, 0XFFFF);	/* 重载值设置最大 */
    __HAL_TIM_SET_COUNTER(&g_timx_usmart_handle, 0);        		/* 清定时器CNT */
    usmart_dev.runtime = 0;
}

/**
 * @brief     	获得runtime时间
 *   @note      	需要根据所移植到的MCU的定时器参数进行修改
 * @param       	无
 * @retval      	执行时间,单位:0.1ms,最大延时时间为定时器CNT值的2倍*0.1ms
 */
uint32_t usmart_timx_get_time(void)
{
	/* 在运行期间,产生了定时器溢出 */
    if (__HAL_TIM_GET_FLAG(&g_timx_usmart_handle, TIM_FLAG_UPDATE) == SET)  
    {
        usmart_dev.runtime += 0XFFFF;
    }
    usmart_dev.runtime += __HAL_TIM_GET_COUNTER(&g_timx_usmart_handle);
    return usmart_dev.runtime;		/* 返回计数值 */
}

usmart_timx_reset_time函数在每次USMART调用函数之前执行,清除定时器的计数器,然后在函数执行完之后,调用usmart_timx_get_time获取计数器值,从而得到整个函数的运行时间。由于usmart调用的函数,都是在中断里面执行的,所以我们不太方便再用定时器的中断功能来实现定时器溢出统计,因此,USMART的函数执行时间统计功能,最多可以统计定时器溢出1次的时间,对STM32F103的TIM4来说,该定时器是16位的,最大计数是65535,而由于我们定时器设置的是0.1ms一个计时周期(10Khz),所以最长计时时间是:
65535 * 2 * 0.1ms = 13.1秒
也就是说,如果函数执行时间超过13.1秒,那么计时将不准确。
最后一个是USMART_TIMX_IRQHandler函数,该函数的实现代码如下:

/**
 * @brief     	USMART定时器中断服务函数
 * @param      	无
 * @retval    	无
 */
void USMART_TIMX_IRQHandler(void)
{
/* 溢出中断 */
    if(__HAL_TIM_GET_IT_SOURCE(&g_timx_usmart_handle,TIM_IT_UPDATE)==SET)
    {
        usmart_dev.scan();                                   			/* usmart扫描 */
        __HAL_TIM_SET_COUNTER(&g_timx_usmart_handle, 0);;    	/* 清定时器CNT */
        __HAL_TIM_SET_AUTORELOAD(&g_timx_usmart_handle, 100);	/* 恢复原来的设置 */
    }
    
    __HAL_TIM_CLEAR_IT(&g_timx_usmart_handle, TIM_IT_UPDATE);	/* 清除中断标志位 */
}

该函数是定时器TIMX的中断服务函数,也是一个宏定义函数,同样是在usmart_port.h里面定义,方便大家修改。该函数主要用于周期性调用usmart扫描函数(实际函数:usmart_scan),完成对输入数据流的处理。同时,清除定时器的CNT值,并设置自动重装载值。
完成这几个函数的移植,就可以使用USMART了。不过,需要注意的是,usmart同外部的互交,一般是通过usmart_dev结构体实现,所以usmart_init和usmart_scan的调用分别是通过:usmart_dev.init和usmart_dev.scan实现的。
外我们还需要在usmart_config.c文件里面添加想要被USMART调用的函数。打开usmart_config.c文件,如图26.3.2.1所示:
在这里插入图片描述

图26.3.2.1 添加需要被USMART调用的函数
这里的添加函数很简单,只要把函数所在头文件添加进来,并把函数名按上图所示的方式增加即可,默认我们添加了两个函数:delay_ms和delay_us。另外,read_addr和write_addr属于usmart自带的函数,用于读写指定地址的数据,通过配置USMART_USE_WRFUNS宏定义,可以使能或者禁止这两个函数。
这里我们根据自己的需要按上图的格式添加其他函数,usmart_config.c文件中我们已经添加了LCD的相关函数,大家可以查看本实验的usmart_config.c文件,并可在串口助手中调用。具体的调用方法26.4小节有具体讲解。
2. main.c代码
在main函数之前,我们添加了led_set和test_fun两个函数,代码如下:

/* LED状态设置函数 */
void led_set(uint8_t sta)
{
    LED1(sta);
}

/* 函数参数调用测试函数 */
void test_fun(void(*ledset)(uint8_t), uint8_t sta)
{
    ledset(sta);
}
led_set函数,用于设置LED1的状态,而第二个函数test_fun则是测试USMART对函数参数的支持的,test_fun的第一个参数是函数,在USMART里面也是可以被调用的。
main函数代码如下: 
int main(void)
{
    HAL_Init();                            		/* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);		/* 设置时钟, 72Mhz */
    delay_init(72);                        		/* 延时初始化 */
    usart_init(115200);                    	/* 串口初始化为115200 */
    usmart_dev.init(72);                  		/* 初始化USMART */
    led_init();                              	/* 初始化LED */
lcd_init();                              	/* 初始化LCD */

    lcd_show_string(30,50,200,16,16,"STM32", RED);
    lcd_show_string(30,70,200,16,16,"USMART TEST", RED);
lcd_show_string(30,90,200,16,16,"ATOM@ALIENTEK", RED);

    while(1) 
    {
        LED0_TOGGLE();  /* LED0(RED) 闪烁 */
        delay_ms(500);
    }
}

此部分代码功能如下:经过一系列初始化,显示使用信息后,就是在无限循环中LED0翻转延时,并等待串口数据。
26.4 下载验证
将程序下载到开发板后,可以看到LED0不停的闪烁,提示程序已经在运行了。同时,屏幕上显示了一些字符(就是主函数里面要显示的字符)。
我们打开串口调试助手XCOM,选择正确的串口号多条发送勾选发送新行(即发送回车键)选项,然后发送list指令,即可打印所有usmart可调用函数。如下图所示:
在这里插入图片描述

图26.4.1 驱动串口调试助手
上图中list、id、help、hex、dec、?和runtime都属于usmart自带的系统命令,点击后方的数字按钮,即可发送对应的指令。下面我们简单介绍下这几个命令:
list,该命令用于打印所有usmart可调用函数。发送该命令后,串口将受到所有能被usmart调用得到函数,如图26.4.1所示。
id,该指令用于获取各个函数的入口地址。比如前面写的test_fun函数,就有一个函数参数,我们需要先通过id指令,获取led_set函数的id(即入口地址),然后将这个id作为函数参数,传递给test_fun。
help(或者‘?’也可以),发送该指令后,串口将打印usmart使用的帮助信息。
hex和dec,这两个指令可以带参数,也可以不带参数。当不带参数的时候,hex和dec分别用于设置串口显示数据格式为16进制/10进制。当带参数的时候,hex和dec就执行进制转换,比如输入:hex 1234,串口将打印:HEX:0X4D2,也就是将1234转换为16进制打印出来。又比如输入:dec 0X1234,串口将打印:DEC:4660,就是将0X1234转换为10进制打印出来。
runtime指令,用于函数执行时间统计功能的开启和关闭,发送:runtime 1,可以开启函数执行时间统计功能;发送:runtime 0,可以关闭函数执行时间统计功能。函数执行时间统计功能,默认是关闭的。
大家可以亲自体验下这几个系统指令,不过要注意,所有的指令都是大小写敏感的,不要写错哦。
接下来,我们将介绍如何调用list所打印的这些函数,先来看一个简单的delay_ms的调用,我们分别输入delay_ms(1000)和delay_ms(0x3E8),如图26.4.2所示:
在这里插入图片描述

图26.4.2 串口调用delay_ms函数
从上图可以看出,delay_ms(1000)和delay_ms(0x3E8)的调用结果是一样的,都是延时1000ms,因为usmart默认设置的是hex显示,所以看到串口打印的参数都是16进制格式的,大家可以通过发送dec指令切换为十进制显示。另外,由于USMART对调用函数的参数大小写不敏感,所以参数写成:0X3E8或者0x3e8都是正确的。另外,发送:runtime 1,开启运行时间统计功能,从测试结果看,USMART的函数运行时间统计功能,是相当准确的。
我们再看另外一个函数,lcd_show_string函数,该函数用于显示字符串,我们通过串口输入:lcd_show_string(30,200,200,16,16," This is a test for usmart!!", 0xF800),如图26.4.3所示:
在这里插入图片描述

图26.4.3 串口调用lcd_show_string函数
该函数用于在指定区域,显示指定字符串,发送给开发板后,我们可以看到LCD在我们指定的地方显示了:This is a test for usmart!! 这个字符串。
其他函数的调用,也都是一样的方法,这里我们就不多介绍了,最后说一下带有函数参数的函数的调用。我们将led_set函数作为 test_fun的参数,通过在test_fun里面调用led_set函数,实现对LED1的控制。前面说过,我们要调用带有函数参数的函数,就必须先得到函数参数的入口地址(id),通过输入id指令,我们可以得到led_set的函数入口地址是:0X0800321D,所以,我们在串口输入:test_fun(0X0800321D,0),就可以控制LED1亮了。如图26.4.4所示:
在这里插入图片描述

图26.4.4 串口调用test_fun函数
在开发板上,我们可以看到,收到串口发送的test_fun(0X0800321D,0)后,开发板的LED1亮了,然后大家可以通过发送test_fun(0X0800321D,1),来关闭LED1。说明我们成功的通过test_fun函数调用led_set,实现了对LED1的控制。也就验证了USMART对函数参数的支持。
USMART调试组件的使用,就为大家介绍到这里。USMART是一个非常不错的调试组件,希望大家能学会使用,可以达到事半功倍的效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/612401.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录搭建hadoop集群的过程

Linux(CentOS-7.6-x64位)基础配置, 虚拟机平台VmWare15 CentOS-7.6-x64镜像下载: https://www.aliyundrive.com/s/72Xg449t6i8 提取码: 32rm VmVare15安装包下载带序列号:VmVare15安装包下载带激活序列号资源-CSDN文库 点击关闭,点击完成&…

NineData,稳定、高效的Redis数据同步解决方案

在 DB-Engines 网站的排名中,Redis 在 Key-value 存储的NoSQL领域连续霸榜多年,是目前最流行的键值对存储数据库,被广泛用于缓存、队列、实时分析等多种高并发的场景中。在生产环境中,我们会遇到对Redis进行版本升级和架构的扩缩容…

vue 自定义el-table穿梭框功能

一、需求描述:前段时间接到一个需求是点击做一个类似穿梭框的表格点击选中功能,弹框的左边是全部数据展示,点击表格行数据可以选中自动增加到右边的已选框,并且可以手动删除、重置选中数据。点击确定后到展示到主页面,…

深入理解Linux虚拟内存管理(四)

系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核(一) 深入理解 Linux 内核(二) Linux 设备驱动程序(一) Linux 设备驱动程序(二) Linux 设备驱动程序(三&#xf…

精选一线企业最佳生产实践,《Apache Doris 用户案例集》重磅发布!

过去的一年势必是 Apache Doris 在发展历程中有着浓墨重彩的一年,凭借对技术创新的执着与用户体验的追求,Apache Doris 已俘获全球范围内超过 2000 家企业的认可,拥有了极为广泛的用户规模、在企业实时数据分析的多种场景中得到广泛应用&…

热门AI通用大模型对比盘点(附论文)

今天我来和大家聊聊通用大模型,垂直领域大模型等整理完了再和大家分享。大家可以先关注一下我,有更新可以立马看见。 本文文末有整理好的通用大模型论文,都是各个大模型的原始论文,强烈建议大模型方向的同学,或者对大…

突破软件交付不可能三角,企业级无代码如何实现卓越交付?

一、VUCA时代下项目交付面临的困境 软件开发或软件项目交付一直以来都存在着“不可能三角”,即成本、效率和质量三者难以兼得。 交付周期长、成本高、满意度低等一直是行业内长期存在的现象,甚至软件交付双方都习以为常。传统项目管理与软件实施过程难…

Niagara—— Texture Sample 与 Particle Subuv 区别

一,Texture Sample 此节点是最基本的采样节点,依据UV坐标来采样Texture; MipValueMode,设置采样的Mipmap Level; None,根据当前Texture大小和物理缩放,自动选择合适的 Mipmap Level &#xff1b…

行为型设计模式03-观察者模式

🧑‍💻作者:猫十二懿 🏡账号:CSDN 、个人博客 、Github 🎊公众号:猫十二懿 观察者模式 1、观察者模式介绍 观察者模式是一种行为型设计模式,也被称为发布-订阅模式,它定…

Hive学习---4、函数(单行函数、高级聚合函数、炸裂函数、窗口函数)

1、函数 1.1 函数简介 Hive会将常用的逻辑封装成函数给用户进行使用,类似java中的函数。 好处:避免用户反复写逻辑,可以直接拿来使用 重点:用户需要知道函数叫什么,能做什么 Hive提供了大量的内置函数,按…

《相信》读后感

近日阅读了蔡磊的《相信》一书,蔡磊先生曾是京东集团副总裁,中国电子发票的推动者。上天给了他优越的智商条件,从上学到工作,前半生几乎顺风顺水、获誉无数,却在初为人父、本该享受家庭幸福的时候,接到突患…

Python字典及用法详解

Python中的字典(Dictionary)是一种无序、可变的数据类型,用于存储键(Key)和值(Value)之间的映射关系。字典是一种高效的数据结构,可以用于快速查找和检索数据。 1.创建字典 可以使…

MobileViT详解:轻型,通用,移动友好的视觉变压器

MobileViT详解:轻型,通用,移动友好的视觉变压器 0. 引言1. 网络结构2. 模型详解2.1 MobileViT Block2.1.1 Local representations2.1.2 Transformers as Convolutions (global representations)2.1.3 Fusion 2.2 MV2 3. 简化版理解4. 总结 0.…

Ubuntu系统搭建FTP服务器

Ubuntu 系统版本:Ubuntu 22.04.2 LTS 安装 vsftpd 软件包 sudo apt-get update sudo apt-get install vsftpd查看版本,验证是否安装成功:vsftpd -v 配置文件 以下是我翻译后的默认配置文件(地址 /etc/vsftpd.conf)&a…

[NOI2009] 描边

题目描述 小 Z 是一位杰出的数学家。聪明的他特别喜欢研究一些数学小问题。 有一天,他在一张纸上选择了 n 个点,并用铅笔将它们两两连接起来,构成 (�−1)22n(n−1)​ 条线段。由于铅笔很细,可以认为这些线段的宽度为…

ROS:参数的使用与编程方法

目录 一、参数模型二、 创建功能包三、参数命令行的使用(rosparam)四、使用程序来使用参数(C)4.1创建代码4.2编译4.3运行 一、参数模型 在ROS Master中,存在一个参数服务器(Parameter Server),它是一个全局…

Python高光谱遥感数据处理与机器学习实践技术丨Matlab高光谱遥感数据处理与混合像元分解

目录 Python高光谱遥感数据处理与机器学习实践技术 第一章 高光谱基础 第二章 高光谱开发基础(Python) 第三章 高光谱机器学习技术(python) 第四章 典型案例操作实践 Matlab 高光谱遥感数据处理与混合像元分解 第一章 理论…

java SSM 互助旅游管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM 互助旅游管理系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采…

预制菜进击万亿市场,谁能更快上桌“吃菜”?

文 | 螳螂观察 作者 | 图霖 消费行业很少有可持续的风口,这两年的预制菜算其中一个。 艾媒咨询发布的行业预测显示,2026年我国预制菜市场规模有望达到10720亿元。 过去这一年,武汉、大同等地已相继召开了预制菜相关的产业峰会。峰会规模有…

gismo-3维IGA

文章目录 前言一、简单示例二、gismo-3维IGA3维程序中的几何模型 三、xml文件的理解1、xml文件示例2、gismo中二维示例文件-一个曲面(简单) 四、三维程序中xml文件的理解三维几何模型边界信息 五、三维程序运行细化四次细化5次 总结 #pic_center 前言 只…