Marlin固件获取G代码部分分析

余生长醉 提交于 2019-11-30 06:12:53

Marlin固件获取G代码部分分析

Marlin固件用到的C语言字符串操作函数:

函数原型: char *strchr(const char *str,int c)
参数说明:str为一个字符串的指针,c为一个待查找字符。
函数功能:从字符串str中寻找字符c第一次出现的位置。
返回说明:返回指向第一次出现字符c位置的指针,如果没找到则返回NULL

函数原型: long int strtol (const char* str, char** endptr, int base);
参数说明:str 为要转换的字符串,endstr 为第一个不能转换的字符的指针,base 为字符串 str 所采用的进制。
函数功能: 将字符串转换为长整型数(long) ,一开始strtol()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时(’\0’)结束转换,并将结果返回。若参数endptr不为NULL,则会将遇到不合条件而终止的nptr中的字符指针由endptr返回;若参数endptr为NULL,则会不返回非法字符串
返回说明:返回转换后的长整型数;如果不能转换或者 str 为空字符串,那么返回 0(0L);

函数原型: char *strstr(char *str1, const char *str2);
参数说明:str1: 被查找目标 str2: 要查找对象
函数功能:函数用于判断字符串str2是否是str1的子串
返回说明:若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL。

函数原型: double strtod(const char *nptr,char **endptr);
参数说明: nptr:为要转换的字符串,endstr 为第一个不能转换的字符的指针。
函数功能:将字符串转化为浮点型数。strtod()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,到出现非数字或字符串结束时(’\0’)才结束转换,并将结果返回。
若endptr不为NULL,则会将遇到不合条件而终止的nptr中的字符指针由endptr传回。参数nptr字符串可包含正负号、小数点或E(e)来表示指数部分。如123.456或123e-2。
返回说明:返回转换后的浮点型数

代码分析

在读取串口信息部分定义了一个环形缓冲区(指令缓冲区),用于存储完整的单条Gcode指令 。
cmdbuffer的二维数组可以存储多条Gcode指令,一维指向整条Gcode指令,二维指向单条Gcode指令中的具体内容 。

static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE];
volatile static bool fromsd[BUFSIZE];
static int bufindr = 0; //环形缓冲区的读取位置(buffer_index_read)
static int bufindw = 0; //环形缓冲区的写入位置(buffer_index_write)
static int buflen = 0; //环形缓冲区中命令的个数

void get_command(void)  //读取串口信息
{ 
  // char i;
  // int16_t n;
  // char time[30];
  // unsigned long t;
  // int hours, minutes;

  /* 当串口收到值且cmdbuffer有空间是时,Gcode命令会被读取到cmdbuffer */
  while( MYSERIAL_available() > 0  && buflen < BUFSIZE)
  {	
    serial_char = MYSERIAL_read(); //从串口缓冲区中读取字符
	/* 如果读取到‘\n’ 或 '\r' 或 ':'且不是注释 或是超过MAX_CMD_SIZE字节数,即表示一条Gcode指令结束 */
    if(serial_char == '\n' ||serial_char == '\r' ||(serial_char == ':' && comment_mode == false) ||serial_count >= (MAX_CMD_SIZE - 1) )
    {
      /* 如果串口计数为0说明当前行为空行,清除注释标记,退出函数,准备读取新行 */
	  if(!serial_count) //if empty line
	  {
        comment_mode = false; //for new command
        return;
      }
	  /* 结束字符串,为存储下一条指令做准备 */
      cmdbuffer[bufindw][serial_count] = 0; //terminate string
	  /* 当前命令行不是注释 */
      if(!comment_mode)  //comment_mode 注释,如果不是注释
	  {
        comment_mode = false; //for new command
        fromsd[bufindw] = false;
		/*
		   删除了读取标记代码并校对部分的代码,此处为非必要代码
		*/   
		/* 当cmdbuffer读取到G0,G1,G2,G3的指令时,如果系统是停止运作的状态,发送错误信息。如果正常运作则打印0k */
        if((strchr(cmdbuffer[bufindw], 'G') != NULL)) //当前字符串中有字符“G”
		{
          strchr_pointer = strchr(cmdbuffer[bufindw], 'G');  //返回字符G所在位置的指针
          switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL))))  //读取字符G后面的数字 
		  {
			case 0:
			case 1:
			case 2:
			case 3:
			  if(Stopped == false) { // If printer is stopped by an error the G[0-3] codes are ignored. //如果打印机由于错误停止,G[0-3]代码被忽略掉。
			    #ifdef SDSUPPORT
				  if(card.saving)
					break;
			    #endif //SDSUPPORT
				printf(MSG_OK);  //打印“OK”
				printf("\n");
			  }
			  else {
			    printf(MSG_ERR_STOPPED);  //打印 由于错误停止的信息 "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)"
			  }
			  break;
			default:
		      break;
          }
        }
        /* 读取一个指令结束,载入下一个cmdbuffer空间 */
		bufindw = (bufindw + 1)%BUFSIZE;
        buflen += 1;
      }
      serial_count = 0; //clear buffer  //清除缓冲区
    }
    else
    {
      if(serial_char == ';') comment_mode = true; //如果串口读取到;号,说明后面为注释
      if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; //如果不是注释内容,将串口信息存储到缓冲区
    }
  }
  /*
    删除了支持SD卡接收部分的代码
  */
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!