关于GRBL解析比较好的说明
输入输出管脚定义的标准指令
在Arduino中一般用pinmode指令进行输入输出管脚设定,如下所示
void setup() {
int led=13;
pinMode(led, OUTPUT);
}
void loop() {
digitalWrite(led, HIGH); // 打开led (高电平输出)
delay(1000); // wait for a second
digitalWrite(led, LOW); // 关闭led (低电平输出)
delay(1000); // wait for a second
}
但是查看了从GitHub下载的grbl源码,却通篇找不到pinmode指令,仔细研发发现采用AVR定义管脚的方式实现,后面会有详细说明。
关于Arduino的一些基本说明:
Arduino是一款便捷灵活、方便上手的开源电子原型平台。包含硬件(各种型号的Arduino板)和软件(Arduino IDE)。Arduino核心板使用的是AVR单片机,AVR是ATMEL系列的微控制器。可以理解为,Arduino是基于AVR单片机搭建的一个平台。
Arduino UNO的主控芯片为ATmega328P,下面是Arduino UNO板的管脚图,其中左上角就是ATmega328P单片机管脚图。
下面是Arduino UNO管脚与AVR单片机管脚的对应关系
AVR单片机关于管脚输入输出等的定义方式
AVR单片机要实现一个端口的输入输出功能,需要三个方面
方向数据寄存器DDRx,用来定义端口是输入还是输出,设为1代表为输出,0代表输入;
端口数据寄存器PORTx(输出值),当DDRx为输出时,管脚的电平随PORTx变化而变化;
端口输入引脚地址PINx(输入值),当DDRx为输入时,PINx的值随管脚的电平变化而变化;
注意:每一个方向数据寄存器并不单单针对一个pin引脚而是针对该端口相对应的数个引脚,这里我们用DDRD来举例说明。DDRD其对应了PD7~PD0 8个引脚,若我们在程序中将DDRD设置为0xFF时,则表示将D端口所对应的8个引脚均被设置为输出,若我们将DDRD设置为0xF0时,则表示将D端口对应的低4位的4个引脚(PD0~PD3)设置为输入。
GRBL中关于管脚的定义
首先在grbl.h文件中,有对avr头文件的引用
#include <avr/io.h> //IO操作,用于定义DDRx/PORTx/PINx
#include <avr/pgmspace.h> //flash,常用PROGMEM定义,pgm_read_byte,pgm_write_byte
#include <avr/interrupt.h> //中断,中断向量定义,中断宏定义
#include <avr/wdt.h>
上面这些头文件在下面文件夹中
GRBL中关于管脚的定义在cpu_map.h文件中,摘录部分如下
输出管脚的设定
说明:相当于把所有需要设为输出的管脚,通过左移指令置为1,如下面的1<<X_STEP_BIT,然后再把所有管脚取“或”操作
#define STEP_DDR DDRD
#define STEP_PORT PORTD
#define X_STEP_BIT 2 // Uno Digital Pin 2
#define Y_STEP_BIT 3 // Uno Digital Pin 3
#define Z_STEP_BIT 4 // Uno Digital Pin 4
#define STEP_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)) // All step bits
…
STEP_DDR |= STEP_MASK;//相关指令还有很多
输入管脚的设定
与上面类似,就是最后采用的取反操作,同时注意,下面代码是从grbl v1.1中摘抄的,在该版本的代码中,默认采用模拟主轴,即下面的VARIABLE_SPINDLE,注意控制主轴输出的管脚为11管脚
#define LIMIT_DDR DDRB
#define LIMIT_PIN PINB
#define LIMIT_PORT PORTB
#define X_LIMIT_BIT 1 // Uno Digital Pin 9
#define Y_LIMIT_BIT 2 // Uno Digital Pin 10
#ifdef VARIABLE_SPINDLE // Z Limit pin and spindle enabled swapped to access hardware PWM on Pin 11.
#define Z_LIMIT_BIT 4 // Uno Digital Pin 12
#else
#define Z_LIMIT_BIT 3 // Uno Digital Pin 11
#endif
#if !defined(ENABLE_DUAL_AXIS)
#define LIMIT_MASK ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT)) // All limit bits
#endif
…
LIMIT_DDR &= ~(LIMIT_MASK); // Set as input pins