STM32F103C8T6平台实现GRBL移植与G代码解析
一、系统架构设计
核心模块划分
- 通信模块:USART1(波特率115200)接收G代码
- 运动控制模块:4路PWM输出(使用TIM1高级定时器)
- 解析引擎:GRBL 1.1f源码适配
- 存储模块:SPI Flash存储G代码缓存
二、硬件配置实现
2.1 时钟配置(SystemClock_Config)
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 72MHz
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
}
2.2 定时器配置(TIM1 PWM生成)
void MX_TIM1_Init(void)
{
TIM_HandleTypeDef htim1;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 20000; // 1MHz计数频率
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
HAL_TIM_PWM_Init(&htim1);
// 配置4路通道
TIM_OC_InitTypeDef sConfigOC = {0};
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 1000; // 初始占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1); // X轴
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2); // Y轴
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3); // Z轴
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_ALL);
}
三、GRBL源码移植
3.1 关键修改点
// 修改grbl.h硬件抽象层
#define STEPPER_TIMER TIM1
#define STEP_PORT GPIOA
#define STEP_PIN_X GPIO_PIN_8
#define STEP_PIN_Y GPIO_PIN_9
#define STEP_PIN_Z GPIO_PIN_10
// 重写步进脉冲生成函数
void step_pulse_generate(uint8_t axis) {
switch(axis) {
case X_AXIS: HAL_GPIO_TogglePin(STEP_PORT, STEP_PIN_X); break;
case Y_AXIS: HAL_GPIO_TogglePin(STEP_PORT, STEP_PIN_Y); break;
case Z_AXIS: HAL_GPIO_TogglePin(STEP_PORT, STEP_PIN_Z); break;
}
}
3.2 通信协议适配
// USART1中断处理
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE)) {
char c = USART_ReceiveData(USART1);
grbl_rx_buffer[rx_index++] = c;
if(c == '\n' || rx_index >= RX_BUFFER_SIZE) {
grbl_parse_command(grbl_rx_buffer); // 调用GRBL解析器
rx_index = 0;
}
}
}
四、G代码解析实现
4.1 解析器核心逻辑
typedef struct {
float x, y, z;
float feedrate;
uint8_t command;
} GCodeCommand;
void grbl_parse_command(char* buffer) {
GCodeCommand cmd = {0};
char* token = strtok(buffer, " ");
while(token != NULL) {
if(strncmp(token, "G", 1) == 0) {
cmd.command = atoi(token+1);
parse_gcode_parameters(token+2, &cmd);
}
token = strtok(NULL, " ");
}
execute_gcode_command(&cmd); // 执行解析后的指令
}
void parse_gcode_parameters(char* str, GCodeCommand* cmd) {
char* param = strtok(str, " ");
while(param != NULL) {
if(strncmp(param, "X", 1) == 0) cmd->x = atof(param+1);
if(strncmp(param, "Y", 1) == 0) cmd->y = atof(param+1);
if(strncmp(param, "F", 1) == 0) cmd->feedrate = atof(param+1);
param = strtok(NULL, " ");
}
}
五、运动控制算法
5.1 加减速控制(Trapezoidal Profile)
void motion_control(GCodeCommand* cmd) {
static float current_feedrate = 0;
// 加速阶段
while(current_feedrate < cmd->feedrate) {
current_feedrate += ACCELERATION * STEP_INTERVAL;
if(current_feedrate > cmd->feedrate) current_feedrate = cmd->feedrate;
set_motor_speed(current_feedrate);
}
// 匀速阶段
while(distance_remaining > MIN_SEGMENT_LENGTH) {
step_motor();
update_position();
}
// 减速阶段
while(current_feedrate > 0) {
current_feedrate -= DECELERATION * STEP_INTERVAL;
if(current_feedrate < 0) current_feedrate = 0;
set_motor_speed(current_feedrate);
}
}
5.2 步进电机驱动
void set_motor_speed(float speed) {
uint16_t pulse_width = (uint16_t)(1000000 / speed); // 1MHz基准频率
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pulse_width);
}
参考代码 gcode解析、运动控制代码grbl移植于stm32f103c8t6平台 www.youwenfan.com/contentcnh/56183.html
六、调试与优化
6.1 性能监控
// 在main.c中添加性能统计
volatile uint32_t step_count = 0;
volatile uint32_t overflow_count = 0;
void TIM1_UP_TIM10_IRQHandler(void) {
if(TIM_GetITStatus(TIM1, TIM_IT_UPDATE)) {
step_count++;
overflow_count++;
}
}
// 计算实际运行速度
float calculate_speed() {
float elapsed = (overflow_count * 0xFFFF + step_count) * TIMER_INTERVAL;
return (float)step_count / elapsed;
}
6.2 常见问题解决
| 现象 | 解决方案 |
|---|---|
| 电机丢步 | 增加细分设置(TIM_CtrlPWMOutputs) |
| 通信丢包 | 启用USART硬件流控(RTS/CTS) |
| 解析延迟 | 优化字符串处理算法(状态机) |
| 运动不平滑 | 实现前瞻算法(Look-ahead) |
七、完整工程结构
├── Core/
│ ├── Inc/
│ │ ├── grbl.h
│ │ └── stm32f1xx_hal_conf.h
│ └── Src/
│ ├── main.c
│ └── tim.c
├── Drivers/
│ ├── CMSIS/
│ └── STM32F1xx_HAL_Driver/
├── Middlewares/
│ └── USB_Device/
└── Projects/
└── STM32F103C8T6/
└── GRBL_Config.h
八、测试用例
; 测试文件test.gcode
G21 ; 单位毫米
G90 ; 绝对坐标
G0 X10 Y10 F1000 ; 快速定位
G1 Z-5 F500 ; 切削进给
G0 Z50 ; 抬刀
M30 ; 程序结束
通过上述方案,开发者可在STM32F103C8T6平台上实现稳定可靠的GRBL系统。建议优先使用HAL库进行开发,并针对具体硬件特性调整中断优先级和定时器参数。

浙公网安备 33010602011771号