极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 138607|回复: 59

Arduino机械坊学习笔记04( 开始理解GRBL下位机)_2014_3_16

[复制链接]
发表于 2014-3-16 13:20:07 | 显示全部楼层 |阅读模式
本帖最后由 oldbeginner 于 2014-3-16 13:21 编辑

因为在研究 成品 激光雕刻机 时, 发现 GRBL 代码基本上都改了,主要是 通讯接通 和上位机 界面。

本节笔记开始学习下位机,希望能够理解其控制基本原理。

下载winavr(http://sourceforge.net/projects/winavr/files/),是一个编译器,
打开软件如下,



把GRBL下位机源文件中的 *.h 和 *.c 文件加入,再加入 makefile 文件, 点击 make all



即可生成 hex 文件。

*************************************************

GRBL 自带文档 的介绍,大致结构如下,



'protocol'        : Accepts command lines from the serial port and passes them to 'gcode' for execution.  Provides status responses for each command. Also manages run-time commands set by the serial interrupt.

'gcode'           : Recieves gcode from 'protocol', parses it according to the current state
                    of the parser and issues commands via '..._control' modules


'spindle_control' : Commands for controlling the spindle.

'motion_control'  : Accepts motion commands from 'gcode' and passes them to the 'planner'. This module
                    represents the public interface of the planner/stepper duo.

'planner'         : Receives linear motion commands from 'motion_control' and adds them to the plan of
                    prepared motions. It takes care of continuously optimizing the acceleration profile
                    as motions are added.

'stepper'         : Executes the motions by stepping the steppers according to the plan.


本帖子中包含更多资源

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

x
回复

使用道具 举报

 楼主| 发表于 2014-3-17 07:32:39 | 显示全部楼层
*****************************
对 serial.h 的理解

定义串口通讯底层函数
*****************************


#ifndef serial_h
#define serial_h

内容

#endif

标志头文件格式,防止 头文件 被重复引用。

******************************

内容1
#include "nuts_bolts.h"

包含头文件 nuts_bolts.h

nuts_bolts.h - Header file for shared definitions, variables, and functions.
共享 定义、变量和函数

************************

内容2
#ifndef RX_BUFFER_SIZE
  #define RX_BUFFER_SIZE 128
#endif


从字面意思可以看出,定义接收缓存 为 128。

同理,
#ifndef TX_BUFFER_SIZE
  #define TX_BUFFER_SIZE 64
#endif


***********************

内容3
#define SERIAL_NO_DATA 0xff

从字面意思,串口无数据
不知道要用在哪里?

***********************

内容4

#ifdef ENABLE_XONXOFF
  #define RX_BUFFER_FULL 96 // XOFF high watermark
  #define RX_BUFFER_LOW 64 // XON low watermark
  #define SEND_XOFF 1
  #define SEND_XON 2
  #define XOFF_SENT 3
  #define XON_SENT 4
  #define XOFF_CHAR 0x13
  #define XON_CHAR 0x11
#endif


不知道怎么用? 也不知道 watermark 水印 是什么意思?

************************

内容5

void serial_init();


字面理解,串口初始化函数。

************************

内容6

void serial_write(uint8_t data);

字面理解,将数据 data 写入串口。

************************

内容7

uint8_t serial_read();

字面理解, 从串口读出数据。

***********************

内容8

void serial_reset_read_buffer();

Reset and empty data in read buffer.
Used by e-stop and reset.

清空读缓存。

***************************************************

winavr编程提示,
uint8_t 在 stdint.h 被定义,typedef unsigned char uint8_t

从 serial.h 上看, serial.h 定义了 串口通讯的底层函数,即使不理解如何实现关系也不大,只需记住函数功能就可以了,如何实现已经被 serial.c 封装了。


回复 支持 1 反对 0

使用道具 举报

发表于 2014-3-16 17:15:04 | 显示全部楼层
机架到手没,你图里面的那款机架就不错
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-17 08:56:24 | 显示全部楼层
oldbeginner 发表于 2014-3-17 07:32
*****************************
对 serial.h 的理解

**************************
serial.c 的理解 上

只需要理解功能,怎样实现可以暂时简单了解
low level functions for sending and recieving bytes via the serial port
***************************


内容1

#include <avr/interrupt.h>
#include "serial.h"
#include "config.h"
#include "motion_control.h"
#include "protocol.h"


需要的头文件,
1、<avr/interrupt.h> 定义中断 ISR,

2、serial.h 好理解

3、config.h 该文件 compile time configuration

This file contains compile-time configurations for Grbl's internal system.
For the most part, users will not need to directly modify these, but they are here for specific needs, i.e. performance tuning or adjusting to non-typical machines.

这个文件很特殊,90%的内容是解释,只有10%是代码。
需要专门一篇文章来学习。

4、motion_control.h   

- high level interface for issuing motion commands

会另外开一篇文章学习

5、protocol.h

- the serial protocol master control unit

也会另外开一篇文章学习。

*****************************************


内容2

uint8_t rx_buffer[RX_BUFFER_SIZE];

uint8_t rx_buffer_head = 0;

uint8_t rx_buffer_tail = 0;

uint8_t tx_buffer[TX_BUFFER_SIZE];

uint8_t tx_buffer_head = 0;

volatile uint8_t tx_buffer_tail = 0;



目测是环形队列格式,输出 和 接收 都是 采用环形队列,感觉会有一定难度



tx_buffer_tail 前 加了一个 volatile 声明,说明 tx_buffer_tail 可能会被 几个 子程序 共享。

*******************************************

内容3

#ifdef ENABLE_XONXOFF
  volatile uint8_t flow_ctrl = XON_SENT; // Flow control state variable
  
  static uint8_t get_rx_buffer_count()
  {
    if (rx_buffer_head == rx_buffer_tail)
               { return(0); }

    if (rx_buffer_head < rx_buffer_tail)
              { return(rx_buffer_tail-rx_buffer_head); }

    return (RX_BUFFER_SIZE - (rx_buffer_head-rx_buffer_tail));
  }
#endif


Returns the number of bytes in the RX buffer.
This replaces a typical byte counter to prevent  the interrupt and main programs from writing to the counter at the same time.



用来判断 缓存的字节数量。

*****************************

内容4

void serial_init()
{

Set baud rate();

enable rx and tx();

enable interrupt on complete reception of a byte();

          
}


利用伪代码来理解整体结构,

然后,细化,
**************************

1、Set baud rate();

  #if BAUD_RATE < 57600
    uint16_t UBRR0_value = ((F_CPU / (8L * BAUD_RATE)) - 1)/2 ;
    UCSR0A &= ~(1 << U2X0); // baud doubler off  - Only needed on Uno XXX
  #else
    uint16_t UBRR0_value = ((F_CPU / (4L * BAUD_RATE)) - 1)/2;
    UCSR0A |= (1 << U2X0);  // baud doubler on for high baud rates, i.e. 115200
  #endif

  UBRR0H = UBRR0_value >> 8;
  UBRR0L = UBRR0_value;


这里需要查看 avr 串口设置资料,涉及到寄存器配置,我不是很熟悉,感觉和找到的代码有些区别,暂时先继续。


2、enable rx and tx();

  UCSR0B |= 1<<RXEN0;
  UCSR0B |= 1<<TXEN0;

通过寄存器赋值实现,RXEN0 和 TXEN0 是寄存器。


3、enable interrupt on complete reception of a byte();

UCSR0B |= 1<<RXCIE0;

如果对 avr 串口编程很熟悉的话,上面的代码应该是 格式化的,就是遇到类似情况,copy paste 就可以了。

****************************************

内容5

void serial_write(uint8_t data)
{
  Calculate next head();

  Wait until there is space in the buffer();

  Store data and advance head();
  
  Enable Data Register Empty Interrupt to make sure tx-streaming is running();
}


同样利用伪代码 熟悉结构,然后细化


1、Calculate next head();

  uint8_t next_head = tx_buffer_head + 1;

  if (next_head == TX_BUFFER_SIZE)
           { next_head = 0; }


当next_head == TX_BUFFER_SIZE 时,表面走了一圈了,要再 从 0 开始。

2、 Wait until there is space in the buffer();

  while (next_head == tx_buffer_tail)
{
    if (sys.execute & EXEC_RESET)
                { return; } // Only check for abort to avoid an endless loop.
  }


当next_head == tx_buffer_tail 时,说明环形队列中已经没有空间了,在这里循环等待。循环内部判断 sys状态,避免死循环。


3、Store data and advance head();

  tx_buffer[tx_buffer_head] = data;
  tx_buffer_head = next_head;


好理解


4、 Enable Data Register Empty Interrupt to make sure tx-streaming is running();

  UCSR0B |=  (1 << UDRIE0);

需要看avr 串口方面资料。

***************************************

内容太多了,将 serial.c 理解 分为 两部分。

本帖子中包含更多资源

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

x
回复 支持 反对

使用道具 举报

发表于 2014-3-17 20:49:13 | 显示全部楼层
好教程,谢谢分享。。。。。。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-18 08:52:51 | 显示全部楼层
本帖最后由 oldbeginner 于 2014-3-18 09:26 编辑
oldbeginner 发表于 2014-3-17 08:56
**************************
serial.c 的理解 上


**************************
serial.c 的理解 下

只需要理解功能,怎样实现可以暂时简单了解
low level functions for sending and recieving bytes via the serial port
***************************


内容6

ISR(SERIAL_UDRE)
{
  Temporary tx_buffer_tail();
  
   Send a byte from the buffer();

   Update tail position();
  
  Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer();

}


这是AVR的中断,//USART0接收中断 // Data Register Empty Interrupt handler

其中, #define SERIAL_UDRE USART_UDRE_vect (pin_map.h 中)
http://blog.sina.com.cn/s/blog_55c3ae71010005d8.html
可以参考http://blog.sina.com.cn/s/blog_694edd930100z24y.html

// 数据从发送寄存器完整移动到移位寄存器
// 中断或轮询模式,均是写数据清零
// 每一个字符character发生一次


Temporary tx_buffer_tail()

  uint8_t tail = tx_buffer_tail;

  #ifdef ENABLE_XONXOFF

    if (flow_ctrl == SEND_XOFF) {
      UDR0 = XOFF_CHAR;
      flow_ctrl = XOFF_SENT;

    } else if (flow_ctrl == SEND_XON) {
      UDR0 = XON_CHAR;
      flow_ctrl = XON_SENT;

    } else

  #endif
  {


#ifdef 和 #endif 之间的代码暂时不理解。


   Send a byte from the buffer();

    UDR0 = tx_buffer[tail];

UDR0是数据寄存器,用来放置缓存。


   Update tail position();

    tail++;
    if (tail == TX_BUFFER_SIZE)
              { tail = 0; }
  
    tx_buffer_tail = tail;
  }


好理解


  Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer();


if (tail == tx_buffer_head)
          { UCSR0B &= ~(1 << UDRIE0); }


  没有数据了,设置寄存器(下面为通用的,这里 n 为0,参考 http://www.amobbs.com/archiver/tid-3415797.html),
    //UCSRnB USART控制和状态寄存器B
    // -----------------------------------------------------------------
    // | RXCIEn| TXCIEn| UDRIEn| RXENn | TXENn | UCSZn2| RXB8n | TXB8n |
    // -----------------------------------------------------------------
    // RXCIEn:接收结束中断使能
    // TXCIEn:发送结束中断使能
    // UDRIEn:USART数据寄存器空中使能
    // RXENn:接收使能
    // TXENn:发送使能
    // UCSZn2:字符长度,具体见下面
    // RXB8n:接收数据位8
    // TXB8n:发送数据位8

可以看出,禁止了 USART数据寄存器空中使能。

理解程度不是很详细,因为暂时不需要,不影响 理解 整体。

***********************************************

内容7

uint8_t serial_read()
{
  if (rx_buffer_head == rx_buffer_tail)
{
    return SERIAL_NO_DATA;
  }

  else {
    uint8_t data = rx_buffer[rx_buffer_tail];
    rx_buffer_tail++;

    if (rx_buffer_tail == RX_BUFFER_SIZE)
         { rx_buffer_tail = 0; }

    #ifdef ENABLE_XONXOFF
      if ((get_rx_buffer_count() < RX_BUFFER_LOW) && flow_ctrl == XOFF_SENT)
{
        flow_ctrl = SEND_XON;
        UCSR0B |=  (1 << UDRIE0); // Force TX
      }
    #endif
   
    return data;
  }
}


从缓存中读出数据。


*******************************

内容8

ISR(SERIAL_RX)
{

  uint8_t data = UDR0;
  uint8_t next_head;

  Pick off runtime command characters directly from the serial stream. These characters are not passed into the buffer, but these set system state flag bits for runtime execution();

Write character to buffer();

Write data to buffer unless it is full();
}


其中,#define SERIAL_RX USART_RX_vect
中断接受函数

1、Pick off runtime command characters directly from the serial stream. These characters are not passed into the buffer, but these set system state flag bits for runtime execution();

  switch (data) {
    case CMD_STATUS_REPORT: sys.execute |= EXEC_STATUS_REPORT; break; // Set as true
    case CMD_CYCLE_START:   sys.execute |= EXEC_CYCLE_START; break; // Set as true
    case CMD_FEED_HOLD:     sys.execute |= EXEC_FEED_HOLD; break; // Set as true
    case CMD_RESET:         mc_reset(); break; // Call motion control reset routine.

   
设置执行系统状态标志。


2、Write character to buffer();

    default: // Write character to buffer   
      next_head = rx_buffer_head + 1;

      if (next_head == RX_BUFFER_SIZE)
            { next_head = 0; }



3、Write data to buffer unless it is full()

      if (next_head != rx_buffer_tail) {
        rx_buffer[rx_buffer_head] = data;
        rx_buffer_head = next_head;   
        
        #ifdef ENABLE_XONXOFF
          if ((get_rx_buffer_count() >= RX_BUFFER_FULL) && flow_ctrl == XON_SENT) {
            flow_ctrl = SEND_XOFF;
            UCSR0B |=  (1 << UDRIE0); // Force TX
          }
        #endif
        
      }
  }


看来 XONXOFF的很碍事,去掉就简洁很多了。

*****************************************

内容9

void serial_reset_read_buffer()
{
  rx_buffer_tail = rx_buffer_head;

  #ifdef ENABLE_XONXOFF
    flow_ctrl = XON_SENT;
  #endif
}


复位。


************************************

总体上,需要理解环形队列(这里没有分析,head 是用来写入数据的index,tail 是用来导出数据的index),就能理解50% 了,另外 对AVR 串口寄存器如果熟悉的话,就又能理解30%了。

剩下的20% 就是 XONXOFF 还没理解。


摘录AVR 串口寄存器

void init_uart(void)
{
    //UDRn USART I/O数据寄存器, 不可用读修改写命令操作, 否则会改变FIFO状态

    //UCSRnA USART控制和状态寄存器A
    // -----------------------------------------------------------------
    // |RXCn |TXCn | UDREn |FEn|DORn |UPEn |U2Xn | MPCMn |
    // -----------------------------------------------------------------
    // RXCn:USART接收结束标志
    // TXCn:USART发送结束标志,写1可清除
    // UDREn:USART数据寄存器为空标志,只有该标志为1才数据才可写入UDR0
    // FEn:帧错误,未正确收到停止位
    // DORn:数据过速
    // UPEn:奇偶效验错误
    // U2Xn:倍速发送,仅对异步操作有影响
    // MPCMn:多处理器通讯模式

    //UCSRnB USART控制和状态寄存器B
    // -----------------------------------------------------------------
    // | RXCIEn| TXCIEn| UDRIEn| RXENn | TXENn | UCSZn2| RXB8n | TXB8n |
    // -----------------------------------------------------------------
    // RXCIEn:接收结束中断使能
    // TXCIEn:发送结束中断使能
    // UDRIEn:USART数据寄存器空中使能
    // RXENn:接收使能
    // TXENn:发送使能
    // UCSZn2:字符长度,具体见下面
    // RXB8n:接收数据位8
    // TXB8n:发送数据位8

    //UCSRxC USART控制和状态寄存器C
    // -----------------------------------------------------------------
    // |   -   | UMSELn| UPMn1 | UPMn0 | USBSn | UCSZn1| UCXZn0| UCPOLn|
    // -----------------------------------------------------------------
    // UMSELn:模式选择,0为异步操作,1为同步操作
    // UPMn1,UPMn0:奇偶效验模式,00禁止,01保留,10偶效验,11奇校验
    // USBSn:停止位选择,0为1位停止位,1为2位停止位
    // UCSZn2,UCSZn0:字符长度,000为5位, 001为 6位,010为7位, 011为8位
    //                         100为保留,101为保留,110为保留,111为9位
    // UCPOLn:时钟极性,(异步模式应清零)
    //                              UCPOL0   发送数据位置   接收数据位置
    //                              0      XCK0上升沿    XCK0下降沿
    //                              1      XCK0下降沿    XCK0上升沿

    //UBRRnL和UBRRnH USART波特率寄存器, UBRRnH15:12为保留位:
    // -----------------------------------------------------------------
    // |   -   |   -   |   -   |   -   | BIT11 | BIT10 | BIT09 | BIT08 |
    // -----------------------------------------------------------------
    // -----------------------------------------------------------------
    // | BIT07 | BIT06 | BIT05 | BIT04 | BIT03 | BIT02 | BIT01 | BIT00 |
    // -----------------------------------------------------------------

}   

回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-18 11:03:16 | 显示全部楼层
oldbeginner 发表于 2014-3-18 08:52
**************************
serial.c 的理解 下


************************************
serial 中 环形队列

简化后
************************************


去除了 如果 队列 满了 或者 空了 等判断;
也忽略了 读入的是 某种命令;
也忽略 XONXOFF

哇~~~~,这个世界清净了,现在大家知道,





TX 队列
*****************************





RX 队列

本帖子中包含更多资源

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

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-19 08:13:51 | 显示全部楼层
本帖最后由 oldbeginner 于 2014-3-19 08:16 编辑
oldbeginner 发表于 2014-3-18 11:03
************************************
serial 中 环形队列


******************************
config.h  上

几乎全是注释的文件
******************************


This file contains compile-time configurations for Grbl's internal system.

For the most part,users will not need to directly modify these, but they are here for specific needs, i.e. performance tuning or adjusting to non-typical machines.

说明了这个文件的用途。

1、 Default settings. Used when resetting EEPROM. Change to desired name in defaults.h

#define DEFAULTS_GENERIC

保存在 EEPROM 中的参数,默认值。

2、Serial baud rate

#define BAUD_RATE 9600

3、Default pin mappings. Grbl officially supports the Arduino Uno only. Other processor typesmay exist from user-supplied templates or directly user-defined in pin_map.h

#define PIN_MAP_ARDUINO_UNO

默认端口配置。

4、Define runtime command special characters. These characters are 'picked-off' directly from the serial read data stream and are not passed to the grbl line execution parser.
Select characters that do not and must not exist in the streamed g-code program. ASCII control characters may be used, if they are available per user setup.
Also, extended ASCII codes (>127), which are never in  g-code programs, maybe selected for interface programs.
NOTE: If changed, manually update help message in report.c.

#define CMD_STATUS_REPORT '?'
#define CMD_FEED_HOLD '!'
#define CMD_CYCLE_START '~'
#define CMD_RESET 0x18 // ctrl-x


命令符,区别 G CODE,用来控制程序。

5、The temporal resolution of the acceleration management subsystem. Higher number give smoother acceleration but may impact performance.
NOTE: Increasing this parameter will help any resolution related issues, especially with machines requiring very high accelerations and/or very fast feedrates.
In general, this will reduce the error between how the planner plans the motions and how the stepper program actually performs them.
However, at some point, the resolution can be high enough, where the errors related to numerical round-off can be great enough to cause problems and/or it's too fast for the Arduino.
The correct value for this parameter is machine dependent, so it's advised to set this only as high as needed.
Approximate successful values can range from 30L to 100L or more.

#define ACCELERATION_TICKS_PER_SECOND 50L

工作原理还不清楚,作用注释已经解释很清楚了。

6、Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end of the buffer and all stops. This should not be much greater than zero and should only be changed if unwanted behavior is observed on a user's machine when running at very slow speeds.

#define MINIMUM_PLANNER_SPEED 0.0 // (mm/min)

不清楚工作机理,看起来很厉害。

7、Minimum stepper rate. Sets the absolute minimum stepper rate in the stepper program and never runs slower than this value, except when sleeping. This parameter overrides the minimum planner speed.
This is primarily used to guarantee that the end of a movement is always reached and not stop to never reach its target. This parameter should always be greater than zero.

#define MINIMUM_STEPS_PER_MINUTE 800 // (steps/min) - Integer value only

8、Time delay increments performed during a dwell. The default value is set at 50ms, which provides a maximum time delay of roughly 55 minutes, more than enough for most any application.
Increasing this delay will increase the maximum dwell time linearly, but also reduces the responsiveness of run-time command executions, like status reports, since these are performed between each dwell time step.
Also, keep in mind that the Arduino delay timer is not very accurate for long delays.

define DWELL_TIME_STEP 50 // Integer (1-255) (milliseconds)

9、If homing is enabled, homing init lock sets Grbl into an alarm state upon power up.
This forces the user to perform the homing cycle (or override the locks) before doing anything else. This is mainly a safety feature to remind the user to home, since position is unknown to Grbl.

#define HOMING_INIT_LOCK // Comment to disable

不理解,用到时再来理解。

10、The homing cycle seek and feed rates will adjust so all axes independently move at the homing seek and feed rates regardless of how many axes are in motion simultaneously.
If disabled, rates are point-to-point rates, as done in normal operation. For example in an XY diagonal motion, the diagonal motion moves at the intended rate, but the individual axes move at 70% speed.
This option just moves them all at 100% speed.

#define HOMING_RATE_ADJUST // Comment to disable

11、Define the homing cycle search patterns with bitmasks. The homing cycle first performs a search to engage the limit switches.
HOMING_SEARCH_CYCLE_x are executed in order starting with suffix 0 and searches the enabled axes in the bitmask.
This allows for users with non-standard cartesian machines, such as a lathe (x then z), to configure the homing cycle behavior to their needs.
Search cycle 0 is required, but cycles 1 and 2 are both optional and may be commented to disable.
After the search cycle, homing then performs a series of locating about the limit switches to hone in on machine zero, followed by a pull-off maneuver. HOMING_LOCATE_CYCLE governs these final moves, and this mask must contain all axes in the search.
NOTE: Later versions may have this installed in settings.

#define HOMING_SEARCH_CYCLE_0 (1<<Z_AXIS)                // First move Z to clear workspace.
#define HOMING_SEARCH_CYCLE_1 ((1<<X_AXIS)|(1<<Y_AXIS)) // Then move X,Y at the same time.
// #define HOMING_SEARCH_CYCLE_2                         // Uncomment and add axes mask to enable
#define HOMING_LOCATE_CYCLE   ((1<<X_AXIS)|(1<<Y_AXIS)|(1<<Z_AXIS)) // Must contain ALL search axes

12、Number of homing cycles performed after when the machine initially jogs to limit switches.
This help in preventing overshoot and should improve repeatability. This value should be one or greater.

#define N_HOMING_LOCATE_CYCLE 2 // Integer (1-128)

13、Number of blocks Grbl executes upon startup.
These blocks are stored in EEPROM, where the size and addresses are defined in settings.h. With the current settings, up to 5 startup blocks may be stored and executed in order.
These startup blocks would typically be used to set the g-code parser state depending on user preferences.

#define N_STARTUP_LINE 2 // Integer (1-5)


******************************************

感觉设置很复杂,大多数都不理解,先混个脸熟。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-19 09:09:39 | 显示全部楼层
oldbeginner 发表于 2014-3-19 08:13
******************************
config.h  上

**********************
config.h  下

advanced users only
**********************


The number of linear motions in the planner buffer to be planned at any give time.
The vast majority of RAM that Grbl uses is based on this buffer size.
Only increase if there is extra available RAM, like when re-compiling for a Teensy or Sanguino. Or decrease if the Arduino begins to crash due to the lack of available RAM or if the CPU is having trouble keeping up with planning new incoming motions as they are executed.

// #define BLOCK_BUFFER_SIZE 18  // Uncomment to override default in planner.h.

默认 是注释掉的

Line buffer size from the serial input stream to be executed.
Also, governs the size of each of the startup blocks, as they are each stored as a string of this size.
Make sure to account for the available EEPROM at the defined memory address in settings.h and for the number of desired startup blocks.
NOTE: 70 characters is not a problem except for extreme cases, but the line buffer size can be too small and g-code blocks can get truncated.
Officially, the g-code standards support up to 256 characters. In future versions, this default will be increased, when we know how much extra memory space we can re-invest into this.

// #define LINE_BUFFER_SIZE 70  // Uncomment to override default in protocol.h


Serial send and receive buffer size.
The receive buffer is often used as another streaming buffer to store incoming blocks to be processed by Grbl when its ready. Most streaming interfaces will character count and track each block send to each block response.
So, increase the receive buffer if a deeper receive buffer is needed for streaming and avaiable memory allows. The send buffer primarily handles messages in Grbl.
Only increase if large messages are sent and Grbl begins to stall, waiting to send the rest of the message.

// #define RX_BUFFER_SIZE 128 // Uncomment to override defaults in serial.h
// #define TX_BUFFER_SIZE 64

这个已经在 serial.c 中理解过了。

Toggles XON/XOFF software flow control for serial communications.
Not officially supported due to problems involving the Atmega8U2 USB-to-serial chips on current Arduinos.
The firmware on these chips do not support XON/XOFF flow control characters and the intermediate buffer in the chips cause latency and overflow problems with standard terminal programs.
However, using specifically-programmed UI's to manage this latency problem has been confirmed to work.
As well as, older FTDI FT232RL-based Arduinos(Duemilanove) are known to work with standard terminal programs since their firmware correctly manage these XON/XOFF characters.

// #define ENABLE_XONXOFF // Default disabled. Uncomment to enable.


Creates a delay between the direction pin setting and corresponding step pulse by creating another interrupt (Timer2 compare) to manage it.
The main Grbl interrupt (Timer1 compare)  sets the direction pins, and does not immediately set the stepper pins, as it would in normal operation.
The Timer2 compare fires next to set the stepper pins after the step pulse delay time, and Timer2 overflow will complete the step pulse, except now delayed by the step pulse time plus the step pulse delay. (Thanks langwadt for the idea!)
This is an experimental feature that should only be used if your setup requires a longer delay between direction and step pin settings (some opto coupler based drivers), as it may adversely effect Grbl's high-end performance (>10kHz).
However, we suggest to first try our direction delay hack/solution posted in the Wiki involving inverting the stepper pin mask.
NOTE: Uncomment to enable. The recommended delay must be > 3us and the total step pulse time, which includes the Grbl settings pulse microseconds, must not exceed 127us.
Reported successful values for certain setups have ranged from 10 to 20us.

// #define STEP_PULSE_DELAY 10 // Step pulse delay in microseconds. Default disabled.


******************************

感觉 和 电机 加速度算法 之类的有关系。还没有找到适合的资料 来 帮助理解。

回复 支持 反对

使用道具 举报

发表于 2014-3-19 09:25:44 | 显示全部楼层
不错不错,继续跟进,顶一下!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-19 11:25:39 | 显示全部楼层
oldbeginner 发表于 2014-3-19 09:09
**********************
config.h  下

**********************
defaults.h 上

默认参数设置
**********************



通讯一建立,这些参数就会显示出来

幸好有帮助文档,https://github.com/grbl/grbl/wiki/Configuring-Grbl-v0.8

The defaults.h file serves as a central default settings file for different machine  types, from DIY CNC mills to CNC conversions of off-the-shelf machines.
The settings  here are supplied by users, so your results may vary.
However, this should give you  a good starting point as you get to know your machine and tweak the settings for your our nefarious needs.

#ifdef DEFAULTS_GENERIC

参数设置

#endif

只理解默认的,

参数设置0、1、2
#define DEFAULT_X_STEPS_PER_MM 250.0


Grbl needs to know how far each step will take the tool in reality. To calculate steps/mm for an axis of your machine you need to know:

    The mm per revolution of the lead screw
    The full steps per revolution of your steppers (typically 200)
    The microsteps per step of your controller (typically 1, 2, 4, 8, or 16). Tip: Using high microstep values (e.g 16) can reduce your stepper motor torque, so use the lowest that gives you the desired axes resolution and comfortable running properties.

The steps/mm can then be calculated like this: steps_per_mm = (steps_per_revolution*microsteps)/mm_per_rev

Compute this value for every axis and write these settings to Grbl.

计算方法实例,
     Motor 200 steps/rev
    Driver 2 microsteps/step
    Screw 1.25 rev/mm

The resolution is: 2 microsteps/step * 200 step/rev * 1/1.25 rev/mm = 320 microstep/mm.

同理,
#define DEFAULT_Y_STEPS_PER_MM 250.0
  #define DEFAULT_Z_STEPS_PER_MM 250.0


应该丝杆尺寸不一致,这个数字基本更改。

*************************************

参数设置3
#define DEFAULT_STEP_PULSE_MICROSECONDS 10


Step pulse, microseconds

Stepper drivers are rated for a certain minimum step pulse length. Check the data sheet or just try some numbers. You want as short pulses as the stepper drivers can reliably recognize. If the pulses are too long you might run into trouble running the system at high feed rates. Generally something between 5 and 50 microseconds works fine.

*************************************

参数设置4、5

  #define DEFAULT_RAPID_FEEDRATE 500.0 // mm/min
  #define DEFAULT_FEEDRATE 250.0


Default feed and seek rates, mm/min

This setting sets the default seek(G0) and feed rates(G1,G2,G3) after Grbl powers on and initializes. The seek rate (aka rapids) is used for moving from point A to point B as quickly as possible, usually for traversing into position. The seek rate should be set at the maximum speed your machine can go in any axes movement. The default feed rate usually does not enter into the picture as feed rates will generally be specified in the g-code program, but if not, this default feed rate will be used.

*************************************

参数设置6

#define DEFAULT_JUNCTION_DEVIATION 0.05 // mm

  
Step port invert mask, int:binary

Some cnc-stepper controllers needs its high-low inputs inverted for both direction and steps.
Signal lines are normally held high or low to signal direction or held high and goes low for a couple of microseconds to signal a step event. To achieve this, Grbl can invert the output bits to accomodate particular needs.
The invert mask value is a byte that is xored with the step and direction data before it is sent down the stepping port. That way you can use this both to invert step pulses or to invert one or more of the directions of the axes.
The bits in this byte corresponds to the pins assigned to stepping in config.h. Note that bits 0 and 1 are not used for inversion. Per default bits are assigned like this:

  1. #define X_STEP_BIT 2
  2. #define Y_STEP_BIT 3
  3. #define Z_STEP_BIT 4
  4. #define X_DIRECTION_BIT 5
  5. #define Y_DIRECTION_BIT 6
  6. #define Z_DIRECTION_BIT 7
复制代码


If you wanted to invert the X and Y direction in this setup you would calculate a value by bitshifting like this (in your favorite calculating environment):

> (1<<X_DIRECTION_BIT)|(1<<Y_DIRECTION_BIT)

Which is equal to 96, so issuing this command would invert them:

$6=96

Now when you view the current settings, you should now see this in your invert mask line with the binary representation of the number (bits 5 and 6 should now show a 1 to indicate inversion.)

$6=96 (step port invert mask. int:1100000)

*****************************************


参数设置7

  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)


Step idle delay, msec

Every time your steppers complete a motion and come to a stop, Grbl will disable the steppers by default.
The stepper idle lock time is the time length Grbl will keep the steppers locked before disabling.
Depending on the system, you can set this to zero and disable it. On others, you may need 25-50 milliseconds to make sure your axes come to complete stop before disabling. (My machine tends to drift just slightly if I don't have this enabled.) OR, you can always keep your axes enabled at all times by setting this value to the maximum 255 milliseconds. Again, just to repeat, you can keep all axes always enabled by setting $7=255.

*******************************************

参数设置8

  #define DEFAULT_ACCELERATION (10.0*60*60) // 10 mm/min^2


Acceleration, mm/sec^2

This is the acceleration in mm/second/second.
You don’t have to understand what that means, suffice it to say that a lower value gives smooooother acceleration while a higher value yields tighter moves and reach the desired feedrates much quicker.
In technical terms, this is the point to point acceleration of your machine, independent of axes. Set this acceleration value as high as your most limiting axes can let you without losing ANY steps.
Usually you'd like to give yourself a little buffer, because if you lose steps, Grbl has no idea this has happened (steppers are open-loop control) and will keep going.

**********************************************

参数设置9

  #define DEFAULT_JUNCTION_DEVIATION 0.05 // mm

  Junction deviation, mm

Cornering junction deviation is used by the acceleration manager to determine how fast it can move through a path.
The math is a bit complicated but in general, higher values gives generally faster, possibly jerkier motion. Lower values makes the acceleration manager more careful and will lead to careful and slower cornering.
So if you run into problems where your machine tries to take a corner too fast, decrease this value to make it slow down.
If you want your machine to move faster through junctions, increase this value to speed it up.
For technical people, hit this link to read about Grbl's cornering algorithm, which accounts for both velocity and junction angle with a very simple, efficient, and robust method.

*********************************************

本帖子中包含更多资源

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

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-20 08:37:38 | 显示全部楼层
oldbeginner 发表于 2014-3-19 11:25
**********************
defaults.h 上

***********************
defaults.h 下

************************


参数设置10

  #define DEFAULT_MM_PER_ARC_SEGMENT 0.1


Arc, mm/segment

Grbl renders circles and arcs by subdividing them into teeny tiny lines. You will probably never need to adjust this value – but if you find that your circles are too crude (really? one tenth of a millimeter is not precise enough for you? Are you in nanotech?) you may adjust this. Lower values gives higher precision but may lead to performance issues.

***************************

参数设置11

  #define DEFAULT_N_ARC_CORRECTION 25


N-arc correction, int

This is an advanced setting that shouldn't be changed unless there are circumstances that you need to. To make G02/03 arcs possible in Grbl, Grbl approximates the location of the next arc segment by a small angle approximation. N-arc correction is the number of approximate arc segments performed before Grbl computes an exact arc segment to correct for the approximation error drift. Computing these exact locations are computationally expensive, but there are some extreme cases where the small angle approximations can introduce enough error to be noticeable, like very very small arcs with a large arc segment length. Change this setting only if find strange problems with arcs, but it's not recommended to go below 3 because this may lead to buffer starvation, where the axes slow down and hiccup. But, results can vary.

****************************

参数设置12

  #define DEFAULT_DECIMAL_PLACES 3


N-decimal, int

Set how many decimal places all of the floating point values Grbl reports. Not much more complicated than that.

****************************

参数设置13

#define DEFAULT_REPORT_INCHES 0 // false


Report inches, bool

Grbl v0.8 has a real-time positioning reporting feature to provide a user feedback on where the machine is exactly at that time. By default it is set to report in mm, but by sending a $13=1 command, you send this boolean flag to true and the status reporting feature will now report in inches. $13=0 to set back to mm.

名字 是 report inches,真 时,单位 inch,假时 单位 mm。

******************************

参数设置14

  #define DEFAULT_AUTO_START 1 // true


Auto start, bool

In a more professional CNC environment, pros start a job by loading up their program and then pressing the 'cycle start' button on their machine. It begins the job. Grbl does the same thing, but not by default. As a learning tool, we 'auto-cycle start' any g-code command that user sends to Grbl, for just jogging the machine to see if move in the direction they think it should go, or just seeing with what their machine can do. This makes it easier to load up your machine with Grbl and pick up on how it works, rather than having to diligently hit 'cycle start' anytime you want to move any your axes. Once you learn your machine and get a good handle on g-code, you can disable the 'auto cycle-start' feature by sending Grbl $14=0 command. (May need a soft-reset or power cycle to load the change.)

Another way of saying that might be:

If $14=0 then some gcode commands like Xn, Yn etc. won't happen when you enter them at a serial terminal. If $14=1 then the gcode motion commands will happen.

Apparently big cnc's won't execute gcode until the operator presses a 'cycle start' button. The gcode commands were received but queued and awaiting the 'cycle start' button. Makes sense yes? When $14=0 then that's how grbl acts too. You need the button! (in which case attach the feed-hold button too!).

When $14=1 then the grbl software automatically presses a software version of the 'cycle start' for you each time you 'enter' a gcode command line via a serial terminal. This is done to make it more convenient for you to enter commands and see something happen without having to push the button.




*********************************

参数设置15

  #define DEFAULT_INVERT_ST_ENABLE 0 // false


Invert step enable, bool

By default, the stepper enable pin is high to disable and low to enable. If your setup needs the opposite, just invert the stepper enable pin by typing $15=1. Disable with $15=0. (May need a power cycle to load the change.)

**********************************

参数设置16

  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false


Hard limits, bool

Hard limit switches are a safety feature to help prevent your machine from traveling way too far off the ends of travel and crashing or breaking something expensive. Basically you wire up some switches (mechanical or optical) near the end of travel of each axes, or where ever you feel like there might be trouble if your program moves too far to where it shouldn't. When the switch triggers, it will immediately stop all motion, shutdown the coolant and spindle (if connected), and go into alarm mode, which forces you to check your machine and reset everything.

To use hard limits with Grbl, the limit pins are held high with an internal pull-up resistor, so all you have to do is wire in a normally-open switch with the pin and ground and enable hard limits with $16=1. That's it. (Disable with $16=0) If you want a limit for both ends of travel of one axes, just wire in two switches in parallel with the pin and ground, so if either one of them trips, it triggers the hard limit.

Just know, that a hard limit event is considered to be critical event, where steppers immediately stop and will have likely lost steps. Grbl doesn't have any feedback on position, so it can't guarantee it has any idea where it is. So, if a hard limit is triggered, Grbl will go into an infinite loop ALARM mode, giving you a chance to check your machine and forcing you to reset Grbl. Remember it's a purely a safety feature.

If you have issues with the hard limit switch constantly triggering after you reset, a soft-reset will reset Grbl into an alarm state, where you can access the settings and Grbl commands, but all g-codes and startup blocks will be locked out. So you can disable the hard limits setting and then $X unlock the alarm. Or, you can wire in a normally-closed switch in series with ground to all the limit switches to disconnect the switches temporarily so you can have Grbl move your axes off the switches.

******************************

参数设置17

  #define DEFAULT_HOMING_ENABLE 0  // false


Homing cycle, bool

Ahh, homing. Something that has been sorely needed in Grbl for a long time. It's now fully supported in v0.8. For those just initiated into CNC, the homing cycle is used to accurately and precisely locate position zero on a machine (aka machine zero) everytime you startup your Grbl between sessions. In other words, you know exactly where you are at any given time, every time. Say you start machining something or are about to start the next step in a job and the power goes out, you re-start Grbl and Grbl has no idea where it is. You're left with the task of figuring out where you are. If you have homing, you always have the machine zero reference point to locate from, so all you have to do is run the homing cycle and resume where you left off.

To set up the homing cycle for Grbl, you need to have limit switches in a fixed position that won't get bumped or moved, or else your reference point gets messed up. Usually they are setup in the farthest point in +x, +y, +z of each axes. Wire your limit switches in with the limit pins and ground, just like with the hard limits, and enable homing. If you're curious, you can use your limit switches for both hard limits AND homing. They play nice with each other.

By default, Grbl's homing cycle moves the Z-axis positive first to clear the workspace and then moves both the X and Y-axes at the same time in the positive direction. To set up how your homing cycle behaves, there are more Grbl settings down the page describing what they do (and compile-time options as well.)

Also, one more thing to note, when homing is enabled. Grbl will lock out all g-code commands until you perform a homing cycle. Meaning no axes motions, unless the lock is disabled ($X) but more on that later. Most, if not all CNC controllers, do something similar, as it mostly a safety feature to help users from making positioning mistake, which is very easy to do and be saddening when a mistake ruins a part. If you find this annoying or find any weird bugs, please let us know and we'll try to work on it so everyone is happy.

NOTE: Check out config.h for more homing options for advanced users. You can disable the homing lockout at startup, configure which axes move first during a homing cycle and in what order, and more.

***********************

参数设置18

#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir


Homing dir invert mask, int:binary

By default, Grbl assumes your homing limit switches are in the positive direction, first moving the z-axis positive, then the x-y axes positive before trying to precisely locate machine zero by going back and forth slowly around the switch. If your machine has a limit switch in the negative direction, the homing direction mask can invert the axes direction. It works just like the invert stepper mask, where all you have to do set the axis direction pins to 1 that you want to invert and that axes will now search for the limit pin in the negative direction.

***************************

参数设置19

  #define DEFAULT_HOMING_FEEDRATE 25.0 // mm/min


Homing feed, mm/min

The homing cycle first searches for the limit switches at a higher seek rate, and after it finds them, it moves at a slower feed rate to hone into the precise location of machine zero. Homing feed rate is that slower feed rate. Set this to whatever rate value that provides repeatable and precise machine zero locating.

**************************

参数设置20

  #define DEFAULT_HOMING_RAPID_FEEDRATE 250.0 // mm/min


Homing seek, mm/min

Homing seek rate is the homing cycle search rate, or the rate at which it first tries to find the limit switches. Adjust to whatever rate gets to the limit switches in a short enough time without crashing into your limit switches if they come in too fast. This seek rate behaves a little differently than the main stepper driver. Instead of the rate from point to point, it just moves all of the axes at the same individual rate, regardless of how many axes are moving at the same time. So, the XY seek move will seem to move about 41% faster than if you would move it with a G1 command. (You can disable this in config.h if it bothers you. It's there to speed up the homing cycle.)

*******************************

参数设置21

  #define DEFAULT_HOMING_DEBOUNCE_DELAY 100 // msec (0-65k)


Homing debounce, ms

Whenever a switch triggers, some of them can have electrical/mechanical noise that actually 'bounce' the signal high and low for a few milliseconds before settling in. To solve this, you need to debounce the signal, either by hardware with some kind of signal conditioner or by software with a short delay to let the signal finish bouncing. Grbl performs a short delay only homing when locating machine zero. Set this delay value to whatever your switch needs to get repeatable homing. In most cases, 5-25 milliseconds is fine.

类似单片机中 常见的 键盘 消抖

*******************************

参数设置22

  #define DEFAULT_HOMING_PULLOFF 1.0 // mm


Homing pull-off, mm

To play nice with the hard limits feature, where homing can share the same limit switches, the homing cycle will move off the all of the limit switches by this pull-off travel after it completes. In other words, it helps to prevent accidental triggering of the hard limit after a homing cycle.

The homing seek rate setting controls how quickly the pull-off maneuver moves, like a G1 command.


******************************************

总共 22 个参数设置,对我这样第一次接触,内容量还是很大的。

本帖子中包含更多资源

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

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-20 11:51:21 | 显示全部楼层
本帖最后由 oldbeginner 于 2014-3-20 11:52 编辑
oldbeginner 发表于 2014-3-20 08:37
***********************
defaults.h 下


*******************************
protocol.h

the serial protocol master control unit
*******************************




serial 收到 gcode 后,要通过 protocal 来处理,

****************************

内容1

#include <avr/sleep.h>


睡眠模式,难道要省电?

****************************

内容2

#ifndef LINE_BUFFER_SIZE
  #define LINE_BUFFER_SIZE 70
#endif


Line buffer size from the serial input stream to be executed.
NOTE: Not a problem except for extreme cases, but the line buffer size can be too small and g-code blocks can get truncated. Officially, the g-code standards support up to 256 characters. In future versions, this will be increased, when we know how much extra memory space we can invest into here or we re-write the g-code parser not to have his buffer.

在 config.h 中 也有定义,不过默认 是 // 的

*****************************

内容3

void protocol_init();


Initialize the serial protocol
放在 这里 的函数 都可以 被 其它文件调用。

******************************

内容4

void protocol_process();


Read command lines from the serial port and execute them as they come in. Blocks until the serial buffer is emptied.

********************************

内容5

uint8_t protocol_execute_line(char *line);


Executes one line of input according to protocol

*******************************

内容6

void protocol_execute_runtime();


Checks and executes a runtime command at various stop points in main program

*********************************

内容7

void protocol_execute_startup();


Execute the startup script lines stored in EEPROM upon initialization

*******************************

函数数量不多,功能明确,下一步理解 .c 文件,理解如何实现。

本帖子中包含更多资源

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

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-21 07:14:24 | 显示全部楼层
oldbeginner 发表于 2014-3-20 11:51
*******************************
protocol.h

************************
protocol.c  上

the serial protocol master control unit
************************


内容1 包含的头文件

#include <avr/io.h>

#include <avr/interrupt.h>

#include "protocol.h"

#include "gcode.h"

#include "serial.h"

#include "print.h"

#include "settings.h"

#include "config.h"

#include "nuts_bolts.h"

#include "stepper.h"

#include "report.h"

#include "motion_control.h"


理解所需的头文件

<avr/io.h> 和 <avr/interrupt.h> 是标准文件,输入输出 和 中断。

已经理解过的头文件:protocol.h 是 声明文件,serial.h 声明通讯函数,config.h —— compile time configuration

还没有接触的头文件
gcode.h —— rs274/ngc parser

print.h —— Functions for formatting output strings

settings.h —— eeprom configuration handling

nuts_bolts.h —— Header file for shared definitions, variables, and functions

stepper.h —— stepper motor driver: executes motion plans of planner.c using the stepper motors

report.h —— reporting and messaging methods

motion_control.h —— high level interface for issuing motion commands

这些头文件 被用到时再理解。

*****************************************

内容2 定义静态变量 数组

static char line[LINE_BUFFER_SIZE];

static uint8_t char_counter;

static uint8_t iscomment;


Line to be executed. Zero-terminated.  line[LINE_BUFFER_SIZE],复习一下,
在 protocol.h 中
#ifndef LINE_BUFFER_SIZE
  #define LINE_BUFFER_SIZE 70
#endif

Last character counter in line variable. char_counter

Comment/block delete flag for processor to ignore comment characters. iscomment

*****************************************

内容4 静态 函数

static void protocol_reset_line_buffer()
{
  char_counter = 0; // Reset line input
  iscomment = false;
}


为什么 静态? http://bbs.csdn.net/topics/350238100 7楼
定义静态函数的好处:
<1> 其他文件中可以定义相同名字的函数,不会发生冲突
<2> 静态函数不能被其他文件所用。

同样也可以理解 为什么 char_counter 静态变量

由于static变量的以上特性,可实现一些特定功能。
1. 统计次数功能
声明函数的一个局部变量,并设为static类型,作为一个计数器,这样函数每次被调用的时候就可以进行计数。这是统计函数被调用次数的最好的办法,因为这个变量是和函数息息相关的,而函数可能在多个不同的地方被调用,所以从调用者的角度来统计比较困难。

************************************************

内容 4 初始化 protocol

void protocol_init()
{
  复位();

  欢迎信息();

  设置端口();
}


利用伪代码理解结构,然后细化,

1、复位();

protocol_reset_line_buffer();

直接调用刚才定义的静态函数就可以了。


2、欢迎信息();

report_init_message();

就是输出欢迎的信息,声明在 report.h 中。非常简单。


3、设置端口();

PINOUT_DDR &= ~(PINOUT_MASK);

PINOUT_PORT |= PINOUT_MASK;

PINOUT_PCMSK |= PINOUT_MASK;

PCICR |= (1 << PINOUT_INT);


首先 需要看一下定义,

  #define PINOUT_DDR       DDRC
  #define PINOUT_PORT      PORTC
  #define PINOUT_PCMSK     PCMSK1
  #define PINOUT_MASK ((1<<PIN_RESET)|(1<<PIN_FEED_HOLD)|(1<<PIN_CYCLE_START))
  #define PINOUT_INT       PCIE1

  #define PIN_RESET        0
  #define PIN_FEED_HOLD    1
  #define PIN_CYCLE_START  2

上面的定义 位于  pin_map.h 中,而被 nuts_bolts.h 引用,再被该文件引用

这里可能需要花些精力来确认 哪个是哪个端口?

首先 看具体定义端口的

  #define PIN_RESET        0  // Uno Analog Pin 0
  #define PIN_FEED_HOLD    1  // Uno Analog Pin 1
  #define PIN_CYCLE_START  2  // Uno Analog Pin 2

然后,看一张总图,



然后,具体 到 上面 三个端口



然后,看

  #define PINOUT_MASK ((1<<PIN_RESET)|(1<<PIN_FEED_HOLD)|(1<<PIN_CYCLE_START))

意思 就是 arduino上 A0 A1 A2 端口取1。(即 AVR PC0 PC1 PC2 端口 取1)

再来理解AVR中DDRC、PORTC什么意思?
http://zhidao.baidu.com/link?url=PMQMGvu0zO61NNsNeiHfEBNCIjP0B6A41mflcZT26KBwbVkZFbc9tAGeWnoL6xIAsnGSrQj_v1w1OLQYAnoMJq

AVR单片机的IO是3态门DDRC是C口的方向寄存器,PORTC是C口的数据寄存器,
DDRC为0时,C口为输入,IO的高低从PORTC可以读出
DDRC为1时,c为输出,输出高低有PORTC控制。

然后,再理解中断
PCMSK1 为引脚变化屏蔽寄存器 即决定某一I/O引脚变化中断是否使能。

再回到
PINOUT_DDR &= ~(PINOUT_MASK);

Set as input pins. 对 PINOUT_MASK 取反,就是 arduino上 A0 A1 A2 端口取0。

  PINOUT_PORT |= PINOUT_MASK;

Enable internal pull-up resistors. Normal high operation.

  PINOUT_PCMSK |= PINOUT_MASK;

Enable specific pins of the Pin Change Interrupt. A0 A1 A2 端口可以中断。

  PCICR |= (1 << PINOUT_INT);

Enable Pin Change Interrupt

这里需要 理解 AVR 中断机制。暂时理解为 设置哪些引脚可以中断。

***********************************************

可能还需要 找些 AVR 中断方面的资料。

本帖子中包含更多资源

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

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-22 08:30:58 | 显示全部楼层
oldbeginner 发表于 2014-3-21 07:14
************************
protocol.c  上

***************************
protocol.c 中

****************************


内容5

Executes user startup script, if stored.


void protocol_execute_startup()
{
  uint8_t n;
  for (n=0; n < N_STARTUP_LINE; n++) {
     内容5A();
  }  
}


复习,
N_STARTUP_LINE 定义 在 config.h 中, #define N_STARTUP_LINE 2
These startup blocks would typically be used to set the g-code parser state depending on user preferences.
blocks :程序块?

内容5A();


if (!(settings_read_startup_line(n, line))) {
      report_status_message(STATUS_SETTING_READ_FAIL);
    } else {
      if (line[0] != 0) {
        printString(line); // Echo startup line to indicate execution.
        report_status_message(gc_execute_line(line));
      }
    }


其中,settings_read_startup_line 函数, 定义在 setting.c 文件中,
Reads startup line from EEPROM. Updated pointed line string data.
没有成功,返回 false

report_status_messages 函数 根据名字 就理解意思。

在 protocol.c 文件中,static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated.
只要不是零,就执行,
printString 函数 定义在print.c 中,串口写入
gc_execute_line 函数 定义在 gcode.c 中,执行命令

**************************************

内容6

Pin change interrupt for pin-out commands


ISR(PINOUT_INT_vect)
{
  // Enter only if any pinout pin is actively low.
内容6A();
}


首先,  #define PINOUT_INT_vect  PCINT1_vect
这里要再 学习 一下 AVR 的中断,



PC0 through PC6 trigger PCINT1.

we’ll need to tell the AVR which pins we’d like for it to watch specifically.
This is done through the pin mask, which is just a normal 8-bit byte where the corresponding bit is set for each pin we’d like to be able to trigger the interrupt.

映射端口已经理解过,arduino上 A0 A1 A2 端口。(即 AVR上 PC0 PC1 PC2 端口)

内容 6A();

Enter only if any pinout pin is actively low.


if ((PINOUT_PIN & PINOUT_MASK) ^ PINOUT_MASK) {
            内容6B();
}


判断条件感觉有点复杂,PINOUT_PIN 先和  PINOUT_MASK 按位与,然后再 按位 异或。
只有 PINOUT_PIN 是 低电平,才能为真

然后,

内容6B();

    if (bit_isfalse(PINOUT_PIN,bit(PIN_RESET))) {
      mc_reset();
    } else if (bit_isfalse(PINOUT_PIN,bit(PIN_FEED_HOLD))) {
      sys.execute |= EXEC_FEED_HOLD;
    } else if (bit_isfalse(PINOUT_PIN,bit(PIN_CYCLE_START))) {
      sys.execute |= EXEC_CYCLE_START;
    }


首先,
bit_isfalse 是 个宏,定义在 nuts_bolts.h 中,
#define bit_isfalse(x,mask) ((x & mask) == 0)

mc_reset 定义在 motion_control.c 中,system reset。

sys 一个复杂的结构体,
// Define global system variables
typedef struct {
  uint8_t abort;                 // System abort flag. Forces exit back to main loop for reset.
  uint8_t state;                 // Tracks the current state of Grbl.
  volatile uint8_t execute;      // Global system runtime executor bitflag variable. See EXEC bitmasks.
  int32_t position[N_AXIS];      // Real-time machine (aka home) position vector in steps.
                                 // NOTE: This may need to be a volatile variable, if problems arise.   
  uint8_t auto_start;            // Planner auto-start flag. Toggled off during feed hold. Defaulted by settings.
} system_t;


本帖子中包含更多资源

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

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-29 15:35 , Processed in 0.063160 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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