源代码在 https://github.com/grblHal 目前日期2024/07/09
或许几年以后代码会做变更. 仅供参考.

grbl是个很好的库. grblHAL是在grbl的基础上改进来的.
grbl的板子通过串口或者SD卡或网络与上位机进行通信, 上位机负责查看和人机交互.
上位机把CAM软件生成的代码读入以后,转换成grbl的通信代码.
grblHAL目前支持的G代码如下

- 非模态命令: G4, G10L2, G10L20, G28, G30, G28.1, G30.1, G53, G65*****, G92, G92.1
  - 额外非模态命令: G10L1*, G10L10*, G10L11*
  - 运动模式: G0, G1, G2****, G3****, G5, G5.1, G38.2, G38.3, G38.4, G38.5, G80, G33*
  - 可编程循环: G73, G81, G82, G83, G85, G86, G89, G98, G99
  - 重复循环: G76*
  - 进制速率模式: G93, G94, G95*, G96*, G97*
  - 单位模式: G20, G21
  - 缩放模式: G50, G51
  - Lat 模式: G7*, G8*
  - 距离模式: G90, G91
  - IJK距离模式: G91.1
  - 平面选择模式: G17, G18, G19
  - 工具长度偏移模式: G43*, G43.1, G43.2*, G49
  - 刀具补偿模式: G40
  - 坐标系模式: G54, G55, G56, G57, G58, G59, G59.1, G59.2, G59.3
  - 控制模式: G61
  - 程序流程: M0, M1, M2, M30, M60
  - 冷却剂控制: M7, M8, M9
  - 转子控制: M3, M4, M5
  - 工具更换: M6* (两种可能:手动** - 支持 jogging, ATC), M61
  - 开关: M48, M49, M50, M51, M53
  - 输入/输出控制***: M62, M63, M64, M65, M66, M67, M68
  - 模态状态处理*: M70, M71, M72, M73
  - 从宏返回*****: M99
  - 有效的非命令词: A*, B*, C*, D, E*, F, H*, I, J, K, L, N, O*, P, Q*, R, S, T, U*, V*, W*, X, Y, Z
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

上位机与下位机板子之间的通信格式如下:
  https://github.com/gnea/grbl/wiki/Grbl-v1.1-Interface

如何衔接grbl核心层和具体设备驱动层

对于驱动开发人员来讲, 最重要的莫过于理解grblHAL的内部代码结构.
grblHAL把核心的代码解析和运动规划等抽象成了HAL层. 代码在项目
core中. 编译的时候需要把core代码复制到你的项目中.
core代码和驱动之间的连接使用的是全局变量. hal
hal的定义在hal.h中.

extern grbl_hal_t hal; //!< Global HAL struct.
  • 1.

下面的电机和外部设备的驱动实现设备代码, 通过全局变量hal 来调用和获取其它信息.

对设备的特性配置

编译开关应在具体实现的代码 my_machine.h 中定义.
例如:

https://github.com/grblHAL/STM32F4xx/tree/master/Inc/my_machine.h
  • 1.

C语言中的函数指针

typedef void (*spindle_update_pwm_ptr)(uint_fast16_t pwm);
  • 1.

在这个例子中,我们定义了一个函数指针spindle_update_pwm_ptr,它接受一个无符号整数(uint_fast16_t)参数pwm,并将其传递给一个名为update_pwm的函数。这个函数的指针类型是void (*)(uint_fast16_t pwm)。

要使用这个函数指针,首先需要定义一个函数,该函数具有与函数指针类型匹配的参数列表和返回类型。例如,我们可以定义一个名为update_pwm的函数:

void update_pwm(uint_fast16_t pwm) {
    // 在这里实现您的代码
}
  • 1.
  • 2.
  • 3.

然后,您可以将update_pwm函数的地址分配给spindle_update_pwm_ptr类型的变量。例如:

spindle_update_pwm_ptr spindle_update_pwm = update_pwm;
  • 1.

现在,您可以像使用普通函数一样使用spindle_update_pwm变量。当您调用spindle_update_pwm时,它会自动调用update_pwm函数。例如:

spindle_update_pwm(100); // 调用 update_pwm 函数,传递参数 100
  • 1.

请注意,函数指针可以指向任何类型的函数,包括函数声明。因此,您可以根据需要使用不同的函数类