GRBL分析:protocol文件

說明

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代碼還是其他指令,之後執行相關的函數即可。

(後面的其他函數等之後分析完成之後再進行更新)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章