说明
protocol文件中存在多个函数,目前根据主函数的流程,暂时分析这其中的部分函数,剩余的部分函数,再进行更新。
分析
2020-4-8更新
1、首先分析是的GRBL初始化完成之后的主循环,该循环再GRBL中的作用主要是接收串口的数据,并分析串口数据,形成完成的G代码,交给gcode解释器处理后面的工作。(这里将去除一些没有意义的宏定义)
void protocol_main_loop()
{
// 判断是否开启硬件限位,如果开启,判断限位是否正常
#ifdef CHECK_LIMITS_AT_INIT
if (bit_istrue(settings.flags, BITFLAG_HARD_LIMIT_ENABLE)) {
if (limits_get_state()) {
sys.state = STATE_ALARM; // Ensure alarm state is active.
report_feedback_message(MESSAGE_CHECK_LIMITS);
}
}
#endif
// Check for and report alarm state after a reset, error, or an initial power up.
// NOTE: Sleep mode disables the stepper drivers and position can't be guaranteed.
// Re-initialize the sleep state as an ALARM mode to ensure user homes or acknowledges.
//插件当前的状态是否处于IDLE
if (sys.state & (STATE_ALARM | STATE_SLEEP)) {
report_feedback_message(MESSAGE_ALARM_LOCK);
sys.state = STATE_ALARM; // Ensure alarm state is set.
} else {
// Check if the safety door is open.
sys.state = STATE_IDLE;
if (system_check_safety_door_ajar()) {
bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR);
protocol_execute_realtime(); // Enter safety door mode. Should return as IDLE state.
}
// All systems go!
//执行启动块,该函数时先读取,如果没有则结束,如果有则执行
system_execute_startup(line); //这里的line是设置的启动块,也就是上电执行的部分
}
// ---------------------------------------------------------------------------------
// Primary loop! Upon a system abort, this exits back to main() to reset the system.
// This is also where Grbl idles while waiting for something to do.
// ---------------------------------------------------------------------------------
uint8_t line_flags = 0; //记录部分特殊的字符的意义,以及相关的标志位
uint8_t char_counter = 0; //记录字符的个数
uint8_t c;
for (;;) {
// Process one line of incoming serial data, as the data becomes available. Performs an
// initial filtering by removing spaces and comments and capitalizing all letters.
while((c = serial_read()) != SERIAL_NO_DATA) {
if ((c == '\n') || (c == '\r')) { // End of line reached //上位机发送的G代码都是以 '\n'结尾的,因此可以判断出G代码是否结束
protocol_execute_realtime(); // 检查实时程序,处于循环中,通过这样检查相关的实时控制,防止再循环中无法响应,这样也可以使得相关的指令最快的时间得以响应
if (sys.abort) { return; } // Bail to calling function upon system abort
line[char_counter] = 0; // Set string termination character.
// Direct and execute one line of formatted input, and report status of execution.
if (line_flags & LINE_FLAG_OVERFLOW) { //判断这个G码是都是长度过长的
// Report line overflow error.
report_status_message(STATUS_OVERFLOW);
} else if (line[0] == 0) { //是否为空
// Empty or comment line. For syncing purposes.
report_status_message(STATUS_OK);
} else if (line[0] == '$') { //是否为系统设置命令
// Grbl '$' system command
report_status_message(system_execute_line(line));
} else if (sys.state & (STATE_ALARM | STATE_JOG)) { //系统是否处于运动或者报警状态
// Everything else is gcode. Block if in alarm or jog mode.
report_status_message(STATUS_SYSTEM_GC_LOCK);
} else {
// Parse and execute g-code block.
report_status_message(gc_execute_line(line)); //没有问题说明这是一个完成的G代码,开始解析
}
// 开始下一个新的G代码.
line_flags = 0;
char_counter = 0;
} else {
if (line_flags) {
// Throw away all (except EOL) comment characters and overflow characters.
if (c == ')') {
// End of '()' comment. Resume line allowed.
if (line_flags & LINE_FLAG_COMMENT_PARENTHESES) { line_flags &= ~(LINE_FLAG_COMMENT_PARENTHESES); }
}
} else {
if (c <= ' ') {
// ASCII码小于空格(32)的字符都丢弃
} else if (c == '/') {
// Block delete NOT SUPPORTED. Ignore character. 丢弃
// NOTE: If supported, would simply need to check the system if block delete is enabled.
} else if (c == '(') {
// Enable comments flag and ignore all characters until ')' or EOL.
// NOTE: This doesn't follow the NIST definition exactly, but is good enough for now.
// In the future, we could simply remove the items within the comments, but retain the
// comment control characters, so that the g-code parser can error-check it.
line_flags |= LINE_FLAG_COMMENT_PARENTHESES;
} else if (c == ';') {
// NOTE: ';' comment to EOL is a LinuxCNC definition. Not NIST.
line_flags |= LINE_FLAG_COMMENT_SEMICOLON;
// TODO: Install '%' feature
// } else if (c == '%') {
// Program start-end percent sign NOT SUPPORTED.
// NOTE: This maybe installed to tell Grbl when a program is running vs manual input,
// where, during a program, the system auto-cycle start will continue to execute
// everything until the next '%' sign. This will help fix resuming issues with certain
// functions that empty the planner buffer to execute its task on-time.
} else if (char_counter >= (LINE_BUFFER_SIZE-1)) { //判断是都超出了每条的最大长度
// Detect line buffer overflow and set flag.
line_flags |= LINE_FLAG_OVERFLOW;
} else if (c >= 'a' && c <= 'z') { // 大小写转换,将接收到的单个字符加入到数组中
line[char_counter++] = c-'a'+'A';
} else {
line[char_counter++] = c;
}
}
}
}
// If there are no more characters in the serial read buffer to be processed and executed,
// this indicates that g-code streaming has either filled the planner buffer or has
// completed. In either case, auto-cycle start, if enabled, any queued moves.
protocol_auto_cycle_start();
protocol_execute_realtime(); // Runtime command check point.
if (sys.abort) { return; } // Bail to main() program loop to reset system.
}
return; /* Never reached */
}
整体上主循环部分比较简单,主要就是接收相关的字符,判断是不是G代码还是其他指令,之后执行相关的函数即可。
(后面的其他函数等之后分析完成之后再进行更新)