搜索
bottom↓
12
返回列表 发新帖
楼主: 落叶知秋

GRBL源码简单分析[源码+图片+xmind文档]

  [复制链接]

出0入79汤圆

发表于 2018-11-10 11:42:38 | 显示全部楼层
感谢LZ。

出0入0汤圆

发表于 2018-11-10 21:56:52 | 显示全部楼层
正在研究,强烈关注!

出0入0汤圆

发表于 2018-11-12 11:39:57 | 显示全部楼层
好东西。谢谢分享!

出0入0汤圆

发表于 2018-11-12 13:11:45 | 显示全部楼层

谢谢分享~~~~~~~

出0入0汤圆

发表于 2018-11-13 09:43:50 | 显示全部楼层
楼主很有毅力。

出0入0汤圆

发表于 2018-11-13 10:36:18 | 显示全部楼层
有机会的拜读一下

出0入0汤圆

发表于 2018-11-13 11:03:49 | 显示全部楼层
楼主用一年时间断断续续整理出来的学习笔记和心得,有心了,谢谢

出0入0汤圆

发表于 2018-11-13 21:10:28 | 显示全部楼层
楼主神人啊,佩服佩服!

出0入0汤圆

发表于 2019-5-15 14:47:48 | 显示全部楼层
楼主您好,我现在设置脉冲输出12.5KHZ, 系统就无法运行了,是不是不能产生这么高频率的脉冲?如果可以的话,该怎样设置一下呢,希望能够指点一下,谢谢!

出40入42汤圆

 楼主| 发表于 2019-5-15 15:46:24 | 显示全部楼层
浪子怀海 发表于 2019-5-15 14:47
楼主您好,我现在设置脉冲输出12.5KHZ, 系统就无法运行了,是不是不能产生这么高频率的脉冲?如果可以的话, ...

说一下你的硬件平台,用的代码版本,以及系统无法运行的描述
按照grbl的官方配置,脉冲频率应该是可以达到33KHz左右的

出0入0汤圆

发表于 2019-5-15 16:22:13 | 显示全部楼层
硬件平台:Arduino UNO ;
代码版本:Grbl v1.1

驱动器:2500 Pulse/r
高微步值:4
设置速度:3000 mm/min
运行轨迹:200*200mm 的正方形

出现以下问题

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出40入42汤圆

 楼主| 发表于 2019-5-15 17:01:31 | 显示全部楼层
浪子怀海 发表于 2019-5-15 16:22
硬件平台:Arduino UNO ;
代码版本:Grbl v1.1

轴的电子齿轮比设的太大了,根据实际的电机驱动参数来设置吧
就是$100以上的参数,先了解一些这些参数是什么意思

出0入0汤圆

发表于 2019-6-3 17:55:26 来自手机 | 显示全部楼层
谢谢楼主,非常有用!

出0入0汤圆

发表于 2019-6-3 22:38:00 | 显示全部楼层
谢谢分享~~~~~~~

出0入4汤圆

发表于 2019-6-4 15:52:56 来自手机 | 显示全部楼层
谢谢分享,收藏备用

出0入0汤圆

发表于 2019-10-9 17:22:53 | 显示全部楼层
谢谢楼主,注册会员就是为了看到你这个啊

出40入42汤圆

 楼主| 发表于 2019-10-9 17:40:53 | 显示全部楼层
fengfengcloud 发表于 2019-10-9 17:22
谢谢楼主,注册会员就是为了看到你这个啊

你这么说,楼主有压力的……总之,帖子对你有用就好

出0入0汤圆

发表于 2019-10-31 21:26:36 | 显示全部楼层
谢谢,正想学习

出0入45汤圆

发表于 2019-11-25 14:40:48 | 显示全部楼层
谢谢楼主!有空研究一下

出0入0汤圆

发表于 2019-12-23 21:05:14 | 显示全部楼层
谢谢分享!

出0入0汤圆

发表于 2020-1-26 21:37:31 | 显示全部楼层
落叶知秋 发表于 2018-5-20 10:05
st.counter_x = st.counter_y = st.counter_z = (st.exec_block->step_event_count >> 1);
这个是给计数 ...

一个定时器怎么可以同时控制4个轴?每一个轴的脉冲呢?

出0入0汤圆

发表于 2020-1-26 21:38:26 | 显示全部楼层
落叶知秋 发表于 2019-10-9 17:40
你这么说,楼主有压力的……总之,帖子对你有用就好

一个定时器怎么控制4个轴的输出连接IO呢?

出40入42汤圆

 楼主| 发表于 2020-1-26 21:44:08 来自手机 | 显示全部楼层
13434222211 发表于 2020-1-26 21:38
一个定时器怎么控制4个轴的输出连接IO呢?

定时器用来计算脉冲频率,输出还是直接操作寄存器翻转电平,grbl是用了两个定时器,另外一个是用来统一拉低电平

出0入0汤圆

发表于 2020-1-26 23:02:42 | 显示全部楼层
落叶知秋 发表于 2020-1-26 21:44
定时器用来计算脉冲频率,输出还是直接操作寄存器翻转电平,grbl是用了两个定时器,另外一个是用来统一拉 ...

一个拉高一个拉低,GPIO设置时高阻态吗?

出0入0汤圆

发表于 2020-1-26 23:03:49 | 显示全部楼层
落叶知秋 发表于 2020-1-26 21:44
定时器用来计算脉冲频率,输出还是直接操作寄存器翻转电平,grbl是用了两个定时器,另外一个是用来统一拉 ...

四个轴的单独管脚设置文件在哪?

出0入0汤圆

发表于 2020-2-20 00:26:38 | 显示全部楼层
楼主,这个GRBL你真的厉害了,我现在也在看。
st_prep_buffer 这个函数,我看了好几遍一直没弄明白,他到底是怎么按照DT_SEGMENT来划分的。比如一个有加速/匀速/减速的Block过程,到底会分成多少个segment呢。
do
{}while(mm_remaining > prep.mm_complete)  里面的prep.mm_complete一直没看懂。

楼主还在关注的话,不吝赐教。

出0入0汤圆

发表于 2020-2-20 10:53:30 | 显示全部楼层
我补充一下,这里主要问题体现在加/减速位置。
根据我的理解应该是DT间隔来细分这个加/减速过程(一个Segment就是一个DT时间),但是我看代码似乎不是这么个意思,所以非常难受,还望楼主救救。

出0入0汤圆

发表于 2020-2-20 11:00:34 | 显示全部楼层
牛比的啊。。叼炸天啊。。

出40入42汤圆

 楼主| 发表于 2020-2-20 17:13:16 | 显示全部楼层
本帖最后由 落叶知秋 于 2020-2-20 17:16 编辑
byron1784 发表于 2020-2-20 00:26
楼主,这个GRBL你真的厉害了,我现在也在看。
st_prep_buffer 这个函数,我看了好几遍一直没弄明白,他到底 ...


st_prep_buffer这个函数主要是grbl中planner和stepper之间的过渡计算,也就是将block按照梯型加减速来分配成segment,时间单位是DT_SEGMENT

你看到代码感到困惑,应该是看到timer_var变量初始赋值是DT_SEGMENT,但在计算过程中又会变化吧?

如果是这个的话,其实很简单,
在do{}while(mm_remaining > prep.mm_complete)这部分代码上面的流程里,
在取planner的block的时候已经对block进行了一次规划,
算出了prep.accelerate_until和prep.decelerate_after,

这两个就是block的加速段和减速段的位置点,
下面在分割成segment的时候,默认是按照DT_SEGMENT的时间单位来的,
但有些情况是prep.accelerate_until和规划的位置点不重合,要对时间进行了处理来重合这两个点,
所以才会有timer_var的重计算步骤,而且一般情况下do{}while(mm_remaining > prep.mm_complete)这个流程只运行一次,
然后重复运行st_prep_buffer(),重复运行do{}while(mm_remaining > prep.mm_complete)这个流程

编辑:把内容进行分行处理

出0入0汤圆

发表于 2020-2-28 16:51:14 | 显示全部楼层
落叶知秋 发表于 2020-2-20 17:13
st_prep_buffer这个函数主要是grbl中planner和stepper之间的过渡计算,也就是将block按照梯型加减速来分 ...

非常感谢楼主的耐心解答。
余下的时间我去把TinyG看了一下,确实思路很相似。

他们的思想都是把运行过程细分为一个个小段来插补,比如TinyG是5ms一个小段。 使用更好的硬件比如Zynq,就是可以把这个细分做到很小,比如250us,DDA的输出用FPGA来做,时基可以提到1MHz甚至更高。   那么我问题是要借用这套规划方式,还有更好的方式么。楼主不吝赐教。

出40入42汤圆

 楼主| 发表于 2020-2-28 17:23:46 | 显示全部楼层
byron1784 发表于 2020-2-28 16:51
非常感谢楼主的耐心解答。
余下的时间我去把TinyG看了一下,确实思路很相似。
那么我问题是要借用这套规划方式,还有更好的方式么


不太理解你说的更好的方式是什么意思
但无非运动控制的规划大致上可以分为 planner、buffer和stepper几个步骤,
不同的硬件和平台可能实现起来不一样,比如grbl,planner是在循环里面做的,而stepper用了芯片的定时器功能,
buffer作为planner和stepper之间的过渡,为了实现变速平滑以及数据保护

如果是用zynq这种多架构的芯片,其实就是ARM+FPGA的模式,抽象的步骤也就是planner、buffer和stepper,
但实现起来可以自己定义,主要是实时这块的处理,一般都是ARM进行路径的分解和速度规划,而FPGA实现stepper功能,两者用总线或是其他方式来传递数据,
甚至如果FPGA功能做得更强大些,完全可以兼顾所有的运动控制步骤,ARM对路径进行解析分解后,可以直接丢给FPGA来进行planner和stepper。
主要还是要了解运动控制的步骤流程是怎样的,具体怎么实现可以根据情况来划分给硬件实现

出0入0汤圆

发表于 2020-3-10 05:55:59 | 显示全部楼层
楼主,你好,我想请教一下,关于中断的问题:脉冲和串口通信都受中断控制,而且串口中断的抢占优先级还不能低于发生脉冲的那个定时器的抢占优先级(否则串口控制不了下位机),这样一来,串口中断是否会对脉冲宽度有影响?比如原本再过5us就要产生一个脉冲(高电平),但是到第4us的时候,来了一次串口中断,这个串口中断服务函数运行耗时3us,这是不是就造成了这个脉冲高电平延后2us(4+3-5 = 2)?

出40入42汤圆

 楼主| 发表于 2020-3-10 08:38:09 | 显示全部楼层
ixiaoimi 发表于 2020-3-10 05:55
楼主,你好,我想请教一下,关于中断的问题:脉冲和串口通信都受中断控制,而且串口中断的抢占优先级还不能 ...

这个也就是中断优先级的判断问题,直接查芯片的架构是怎么处理的就行了。
一般来说,同级别的优先级不会相互打断,高优先级的会打断低优先级的
其实只要脉冲的运算耗时有余量的话,串口就算不设置中断也能够进行通信的

出0入0汤圆

发表于 2020-3-10 15:11:56 | 显示全部楼层
落叶知秋 发表于 2020-3-10 08:38
这个也就是中断优先级的判断问题,直接查芯片的架构是怎么处理的就行了。
一般来说,同级别的优先级不会 ...


感谢!
之前把脉冲定时器的抢占优先级设定为0,串口中断的抢占优先级设定为1,结果导致上位机频繁接收到各种异常字符串,
而且上位机发送立即指令的时候,下位机要经过一段时间才能做出响应,
当时简单的下结论说是串口通信被脉冲频繁打断造成的。

今天又试了一下上述的抢占优先级设定,又没出任何问题,估计当时问题原因并非出在中断优先级上。

出95入100汤圆

发表于 2020-3-10 18:12:21 | 显示全部楼层
3D打印,G代码解析的

出0入0汤圆

发表于 2020-4-29 16:11:55 | 显示全部楼层
大赞楼主!特地注册了一下
楼主了解过Marlin吗?和GRBL比如何?

出0入0汤圆

发表于 2020-4-29 16:22:43 | 显示全部楼层
学习了 运动控制也可以看看

出40入42汤圆

 楼主| 发表于 2020-4-29 16:32:27 来自手机 | 显示全部楼层
aidyaish 发表于 2020-4-29 16:11
大赞楼主!特地注册了一下
楼主了解过Marlin吗?和GRBL比如何?

我另外有个帖子是有marlin的源码分析的

出0入0汤圆

发表于 2020-4-29 19:33:30 | 显示全部楼层
顶一下

出20入0汤圆

发表于 2020-4-29 19:56:50 | 显示全部楼层
楼主很强,学习了

出0入0汤圆

发表于 2020-4-30 08:13:04 | 显示全部楼层
收藏,   

出0入0汤圆

发表于 2020-4-30 15:50:52 | 显示全部楼层
落叶知秋 发表于 2020-4-29 16:32
我另外有个帖子是有marlin的源码分析的

小白想请教一下楼主方案问题。做一个龙门式的大行程水泥3D打印机,X/Y1/Y2/Z1/Z2/挤出电机E,一共6个伺服电机,用stm32h750配合grbl可行吗?stm32通过定时器直接输出6路脉冲到伺服驱动器可以吗?

出40入42汤圆

 楼主| 发表于 2020-4-30 17:30:51 来自手机 | 显示全部楼层
aidyaish 发表于 2020-4-30 15:50
小白想请教一下楼主方案问题。做一个龙门式的大行程水泥3D打印机,X/Y1/Y2/Z1/Z2/挤出电机E,一共6个伺服 ...

理论上应该没什么问题,如果是用定时器的pwm功能的话,要改下脉冲模块吧,3D打印推荐用marlin框架,功能比grbl全一些

出0入0汤圆

发表于 2020-7-15 10:09:50 | 显示全部楼层
太专业了,多谢楼主分享!

出0入4汤圆

发表于 2020-7-18 15:54:17 | 显示全部楼层
谢谢分享,下次可能用得到

出0入0汤圆

发表于 2020-7-19 21:04:51 | 显示全部楼层
mark,高手

出0入0汤圆

发表于 2020-9-14 23:11:55 | 显示全部楼层
谢谢楼主的贡献,最近在玩grbl-mega-5x,可惜资料很少,我先从grbl源码入手吧!

出100入101汤圆

发表于 2020-9-14 23:25:32 来自手机 | 显示全部楼层
lz做这个研究,是工作需要,还是兴趣爱好?

出40入42汤圆

 楼主| 发表于 2020-9-15 08:32:00 | 显示全部楼层
fengyunyu 发表于 2020-9-14 23:25
lz做这个研究,是工作需要,还是兴趣爱好?

两者皆有

出0入0汤圆

发表于 2020-11-2 19:04:43 | 显示全部楼层
牛牛牛,真心不错,个人认为精华帖

出0入0汤圆

发表于 2021-1-31 22:26:46 | 显示全部楼层
拜读了大神的帖子!这种钻研的精神值得学习!另外请教下采用grbl来做桁架机械手或者点胶机等方案是否可行呢?请大神给予指教,谢谢!

出5入0汤圆

发表于 2021-1-31 22:29:52 来自手机 | 显示全部楼层
这个搞个要是弄个像盖个计一样开原,大家一起玩。多好

出40入42汤圆

 楼主| 发表于 2021-2-1 08:40:35 | 显示全部楼层
yubobo0622 发表于 2021-1-31 22:26
拜读了大神的帖子!这种钻研的精神值得学习!另外请教下采用grbl来做桁架机械手或者点胶机等方案是否可行呢 ...

跟G代码相关的设备,理论上都可以用grbl框架的板去控制,如果有些特殊M代码,可以自己实现

出40入42汤圆

 楼主| 发表于 2021-2-1 08:43:33 | 显示全部楼层
NM2012 发表于 2021-1-31 22:29
这个搞个要是弄个像盖个计一样开原,大家一起玩。多好

这个要是搞成DIY项目的话,成本可不算低的,除了硬件板子,还要买机械设备的,不然没啥意思

现在TB上也可以买到grbl的硬件板子,感觉没什么好做的了

出0入0汤圆

发表于 2021-2-1 19:47:05 | 显示全部楼层
落叶知秋 发表于 2021-2-1 08:40
跟G代码相关的设备,理论上都可以用grbl框架的板去控制,如果有些特殊M代码,可以自己实现 ...

再请教下,是否有方案或者移植路径分享下,我是想把grbl中涉及的算法和gcode部分移植出来,作为独立的模块加入到我的其他硬件平台上,不在依赖于grbl中使用到的pin map和中断。谢谢啊!

出40入42汤圆

 楼主| 发表于 2021-2-1 20:07:58 | 显示全部楼层
yubobo0622 发表于 2021-2-1 19:47
再请教下,是否有方案或者移植路径分享下,我是想把grbl中涉及的算法和gcode部分移植出来,作为独立的模 ...

插补算法、速度规划和G代码解释器都是纯C写的,把一些硬件相关的东西,如脉冲的IO映射操作,定时器中断,flash之类的替换就好了
下面的是grbl官方人员移植到arm平台的工程(LPC系列),可以参考一下
https://github.com/gnea/grbl-LPC

出0入0汤圆

发表于 2021-2-1 20:26:48 | 显示全部楼层
落叶知秋 发表于 2021-2-1 20:07
插补算法、速度规划和G代码解释器都是纯C写的,把一些硬件相关的东西,如脉冲的IO映射操作,定时器中断, ...

谢谢,我正在考虑对grbl的移植工作,如果你觉得有更好的方案可以替代grbl框架的话请推荐给我!

出0入0汤圆

发表于 2021-2-2 13:13:22 | 显示全部楼层
浪子怀海 发表于 2019-5-15 16:22
硬件平台:Arduino UNO ;
代码版本:Grbl v1.1

请问你这个laserGRBL 仿真软件是否连续下位机吗?能否在不连接下位机的情况下仿真呢?

出0入0汤圆

发表于 2021-4-10 21:28:25 | 显示全部楼层
让我消化一下,再与你们讨论

出0入0汤圆

发表于 2021-8-2 08:26:08 | 显示全部楼层
多谢楼主分享

出0入0汤圆

发表于 2021-8-11 11:04:13 | 显示全部楼层
感谢楼主无私分享

出0入0汤圆

发表于 2021-11-10 20:51:11 | 显示全部楼层
楼主,请问,grbl支持螺旋线插补吗?看代码里面好像没有是吧。

出40入42汤圆

 楼主| 发表于 2021-11-11 08:32:47 | 显示全部楼层
sddzycnq 发表于 2021-11-10 20:51
楼主,请问,grbl支持螺旋线插补吗?看代码里面好像没有是吧。

目前GRBL不支持螺旋线插补

出0入0汤圆

发表于 2021-11-11 09:12:57 | 显示全部楼层
落叶知秋 发表于 2021-11-11 08:32
目前GRBL不支持螺旋线插补

有其它开源方案支持螺旋插补的吗?想看一下算法实现。

出40入42汤圆

 楼主| 发表于 2021-11-11 09:28:41 | 显示全部楼层
sddzycnq 发表于 2021-11-11 09:12
有其它开源方案支持螺旋插补的吗?想看一下算法实现。

目前没有看到有开源项目支持螺旋线插补的,了解算法的话,可以看一下论文

出0入0汤圆

发表于 2021-11-11 14:05:15 | 显示全部楼层
落叶知秋 发表于 2021-11-11 09:28
目前没有看到有开源项目支持螺旋线插补的,了解算法的话,可以看一下论文 ...

非常感谢。

出0入0汤圆

发表于 2021-11-11 16:43:20 | 显示全部楼层
谢谢楼主无私分享

出0入0汤圆

发表于 2021-11-15 21:07:14 | 显示全部楼层
  1. // NOTE: Segment end points are on the arc, which can lead to the arc diameter being smaller by up to
  2.   // (2x) settings.arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit
  3.   // is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation.
  4.   // For the intended uses of Grbl, this value shouldn't exceed 2000 for the strictest of cases.
  5.   uint16_t segments = floor(fabs(0.5*angular_travel*radius)/
  6.                           sqrt(settings.arc_tolerance*(2*radius - settings.arc_tolerance)) );
复制代码


楼主,请教一下,mc_arc函数中,这个计算段数的公式怎么理解,没看明白。

出0入0汤圆

发表于 2021-11-16 09:21:13 | 显示全部楼层
sddzycnq 发表于 2021-11-15 21:07
楼主,请教一下,mc_arc函数中,这个计算段数的公式怎么理解,没看明白。 ...

哦。明白了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2021-12-9 11:08:17 | 显示全部楼层
落叶知秋 发表于 2021-11-11 09:28
目前没有看到有开源项目支持螺旋线插补的,了解算法的话,可以看一下论文 ...


楼主,这个G代码在grbl上能跑,这个是不是就是螺旋线。
抑或是说,grbl只支持一个圆周的螺旋线?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出40入42汤圆

 楼主| 发表于 2021-12-9 14:07:46 | 显示全部楼层
sddzycnq 发表于 2021-12-9 11:08
楼主,这个G代码在grbl上能跑,这个是不是就是螺旋线。
抑或是说,grbl只支持一个圆周的螺旋线? ...

G02/03是圆弧插补指令,后面带个Z是可以做出这种圆柱型的螺旋线插补轨迹,但受限于圆弧指令,Z轴只能是跟随圆弧的长度进行离散化
但是更为复杂的螺旋线,如圆锥型的,就不支持了

出0入0汤圆

发表于 2021-12-10 08:04:29 | 显示全部楼层
落叶知秋 发表于 2021-12-9 14:07
G02/03是圆弧插补指令,后面带个Z是可以做出这种圆柱型的螺旋线插补轨迹,但受限于圆弧指令,Z轴只能是跟 ...

谢谢楼主回复。明白了。
最近一直在研究grbl源码,结合你写的文档,以及在本帖中你给别人的回复。收获很多。
非常感谢你的无私分享。

出0入0汤圆

发表于 2021-12-10 09:18:28 | 显示全部楼层
顶一个 Thank you !!!

出0入0汤圆

发表于 2022-3-25 13:05:34 | 显示全部楼层
很用心的资料

出0入0汤圆

发表于 2022-3-25 23:10:24 来自手机 | 显示全部楼层
厉害了,解释的很用心

出0入0汤圆

发表于 2022-3-27 00:04:10 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2022-4-25 15:56:40 | 显示全部楼层
压缩包中的keilkill批处理文件,什么用途呢?字面意思吗?

出0入0汤圆

发表于 2022-4-25 16:16:22 | 显示全部楼层
王涛 发表于 2018-5-20 11:56
对了误差counter_y本来应该是0的。这里给赋了个初值0.5*event_count。
谢谢了我明白了。
这个问题我迷糊 ...
(引用自92楼)

bresenham算法_360百科  https://baike.so.com/doc/6839653-7056924.html

出0入0汤圆

发表于 2023-10-25 14:37:02 | 显示全部楼层
楼主好,看了你grbl的帖子,敬佩不已。 我们现在用的ZYNQ,没有开放定时器,也就不可能在定时器的中断函数里,实现IO翻转。我们现在要使用FPGA实现脉冲发送,请指导一下,我该怎么做呢

出0入0汤圆

发表于 2023-12-7 17:48:04 | 显示全部楼层
大虾好,我看了你分享的grbl分析,有一个问题想请教一下,不知是否可以。 我的mail 是 5452634#qq.com
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-11 00:32

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表