我研究的Marlin是1.0版本的.想用在的地方是stm32

Marlin关于接收Gcode命令最主要的函数就是: get_command()

get_command()函数说实话对于我这样的学生来说程度还是挺复杂的.
为了节省大家理清代码和阅读文章的时间, 我全文用字力求精简, 别人已经写了的知识我就不会写

先上函数全文:

void get_command(void)
{ int16_t n;char time[30];unsigned long t;int hours, minutes;while( MYSERIAL_available() > 0  && buflen < BUFSIZE){   //  LCD_ShowString(5,5,240,320,12, ".1.");    serial_char = MYSERIAL_read();
//      printf(" serial_char: %c\n\r",serial_char);if(serial_char == '\n' ||serial_char == '\r' ||(serial_char == ':' && comment_mode == false) ||serial_count >= (MAX_CMD_SIZE - 1) )//sanse 冒号{if(!serial_count)  //if empty line{comment_mode = false; //for new commandreturn;}cmdbuffer[bufindw][serial_count] = 0; //terminate stringif(!comment_mode){comment_mode = false; //for new commandfromsd[bufindw] = false;if(strchr(cmdbuffer[bufindw], 'N') != NULL)                                                                      {strchr_pointer = strchr(cmdbuffer[bufindw], 'N');gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10));if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], PSTR("M110")) == NULL) )  {                                                                          SERIAL_ERROR_START;printf(MSG_ERR_LINE_NO);printf("%ld",gcode_LastN);//Serial.println(gcode_N);FlushSerialRequestResend();serial_count = 0;return;}if(strchr(cmdbuffer[bufindw], '*') != NULL){u8 checksum = 0;u8 count = 0;while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++];strchr_pointer = strchr(cmdbuffer[bufindw], '*');if( (u8)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum){                                                                 SERIAL_ERROR_START;printf(MSG_ERR_CHECKSUM_MISMATCH);printf(" checksum: %d\n\r",checksum);count = 0;printf(" '");while(cmdbuffer[bufindw][count] != '*'){printf("%c",cmdbuffer[bufindw][count++]);}printf(" '\n\r ");checksum = 0;count = 0;while(cmdbuffer[bufindw][count] != '*'){ printf("cmdbuffer:%d;",cmdbuffer[bufindw][count]);checksum = checksum^cmdbuffer[bufindw][count++];printf(" checksum:%d \n\r",checksum);}/// printf("\n\r ");printf("%ld",gcode_LastN);FlushSerialRequestResend();serial_count = 0;return;}//if no errors, continue parsing}else{SERIAL_ERROR_START;printf(MSG_ERR_NO_CHECKSUM);printf("%ld",gcode_LastN);FlushSerialRequestResend();serial_count = 0;return;}gcode_LastN = gcode_N;//if no errors, continue parsing}else  // if we don't receive 'N' but still see '*'{if((strchr(cmdbuffer[bufindw], '*') != NULL))                                                            {SERIAL_ERROR_START;printf(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM);printf("%ld",gcode_LastN);serial_count = 0;return;}}if((strchr(cmdbuffer[bufindw], 'G') != NULL))                                                                {strchr_pointer = strchr(cmdbuffer[bufindw], 'G');switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){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.#ifdef SDSUPPORTif(card.saving)break;#endif //SDSUPPORTprintf(MSG_OK);printf("\n");}else {printf(MSG_ERR_STOPPED);// LCD_MESSAGEPGM(MSG_STOPPED);}break;default:break;}}bufindw = (bufindw + 1)%BUFSIZE;buflen += 1;//sanse}serial_count = 0; //clear buffer}else{if(serial_char == ';') comment_mode = true;if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;}}#ifdef SDSUPPORT   //sanseif(!card.sdprinting || serial_count!=0){ //    LCD_ShowString(20,5,240,320,12, ".2.");return;}while( !card_eof()  && buflen < BUFSIZE) {  //LCD_ShowString(50,5,240,320,12, ".3.");n=card_get();serial_char = (BYTE)n;if(serial_char == '\n' ||serial_char == '\r' ||(serial_char == ':' && comment_mode == false) ||serial_count >= (MAX_CMD_SIZE - 1)||n==-1){ if(card_eof())//sanse{printf(MSG_FILE_PRINTED);printf("\n");stoptime=millis();t=(stoptime-starttime)/1000;minutes=(t/60)%60;hours=t/60/60;sprintf(time, PSTR("%i hours %i minutes"),hours, minutes);SERIAL_ECHO_START;printf("%s",time);//   lcd_setstatus(time);card_printingHasFinished();// card_checkautostart(true);}if(!serial_count){comment_mode = false; //for new commandreturn; //if empty line}cmdbuffer[bufindw][serial_count] = 0; //terminate string
//      if(!comment_mode){fromsd[bufindw] = true;//sansebuflen += 1;bufindw = (bufindw + 1)%BUFSIZE;
//      }comment_mode = false; //for new commandserial_count = 0; //clear buffer}else{if(serial_char == ';') comment_mode = true;if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;}}#endif //SDSUPPORT}

get_command()牵涉到的主要变量为: serial_char, cmdbuffer, bufindw, serial_count, comment_mode

static char serial_char: 相当于串口数据的中转站, 依靠MYSERIAL_read()读取 从串口中断中得到的rx_buffer 来获取命令数据

static char cmdbuffer[8] [128]:存储命令的功能, 从serial_char获取命令数据

static int bufindw: 全名buffer_index_write, 指示作用, 作为cmdbuffer的下标, 在代码中会 +1

static int serial_count: 指示作用, 作为cmdbuffer的下标, 在代码中会自+

static bool comment_mode = false: 判断模式(判断为动词), 为false就执行get_command函数, 为true就结束get_command()

static int buflen:计算缓冲区字节数量的功能, 在代码中会+1

再讲个结构体, 下面有用

typedef struct ring_buffer
{unsigned char buffer[RX_BUFFER_SIZE]; //RX_BUFFER_SIZE=128int head;int tail;
}ring_buffer;
extern  ring_buffer rx_buffer;  ring_buffer rx_buffer  =  { { 0 }, 0, 0 };

我们例如要将" G1 X1000 Y1000 Z250 "录入command_buffer中, 他是这样变的:

" G1 X1000 Y1000 Z250 "先由串口进入rx_buffer, rx_buffer的结构体中的第一位unsigned char buffer[RX_BUFFER_SIZE]中,结构体的第二,三位起下标作用.

再由get_command()函数使得: cmdbuffer[0]为G1 , cmdbuffer[1]为X1000, 以此类推, 以Z250为例, 那么
cmdbuffer[3] [2]就为5了

代码结构一张思维导图即可理清 (如有纰漏, 还望不吝赐教, 在评论区提出改正):
我只画了关于串口的读取Gcode的那一段, 如果想研究从SD卡读Gcode, 道理是一样的, 不做过多解释


温馨提示: 别看左边那一列有那么多, 其实执行最多的是右面一列:

我再送上我做过注释的, 根据思维导图截取了部分的代码:

while( MYSERIAL_available() > 0  && buflen < BUFSIZE){ //  LCD_ShowString(5,5,240,320,12, ".1.");    serial_char = MYSERIAL_read();
//      printf(" serial_char: %c\n\r",serial_char);if(serial_char == '\n' ||serial_char == '\r' ||(serial_char == ':' && comment_mode == false) ||serial_count >= (MAX_CMD_SIZE - 1) )//sanse 冒号{if(!serial_count)  //if empty line{comment_mode = false; //for new commandreturn;}cmdbuffer[bufindw][serial_count] = 0; //terminate stringif(!comment_mode){comment_mode = false; //for new command     确保处于读模式, 避免执行命令模式fromsd[bufindw] = false;  // 避免从SD卡读取if(strchr(cmdbuffer[bufindw], 'N') != NULL)                                                                       {strchr_pointer = strchr(cmdbuffer[bufindw], 'N');       // strchr函数功能为在一个串中查找给定字符的第一个匹配之处   gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10));   // strtol函数会将参数nptr字符串根据参数base来转换成长整型数,参数类型范围从2至36。if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], PSTR("M110")) == NULL) ) // strstr(str1,str2) 返回字符串中首次出现子串的地址    pstr表示一个指向字符串的指针变量{                                                                          SERIAL_ERROR_START;   // 报错printf(MSG_ERR_LINE_NO);printf("%ld",gcode_LastN);    // %ld: long int//Serial.println(gcode_N);FlushSerialRequestResend();serial_count = 0;return;}if(strchr(cmdbuffer[bufindw], '*') != NULL){u8 checksum = 0;u8 count = 0;while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++]; // 计算从字符串起始位到'*'的checksum, cheaksum用^运算是为了尽可能地大strchr_pointer = strchr(cmdbuffer[bufindw], '*');if( (u8)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum)    // strtod:将字符串转换成浮点数    一般来说checksum为0, "strchr_pointer - cmdbuffer[bufindw] + 1"为1, 不等于说明内存出问题了 呼应 ↑{                                                                 SERIAL_ERROR_START;printf(MSG_ERR_CHECKSUM_MISMATCH);printf(" checksum: %d\n\r",checksum);count = 0;printf(" '");while(cmdbuffer[bufindw][count] != '*'){printf("%c",cmdbuffer[bufindw][count++]);}printf(" '\n\r ");checksum = 0;count = 0;while(cmdbuffer[bufindw][count] != '*'){ printf("cmdbuffer:%d;",cmdbuffer[bufindw][count]);checksum = checksum^cmdbuffer[bufindw][count++];printf(" checksum:%d \n\r",checksum);}///  printf("\n\r ");printf("%ld",gcode_LastN);FlushSerialRequestResend();serial_count = 0;return;}//if no errors, continue parsing}else{SERIAL_ERROR_START;printf(MSG_ERR_NO_CHECKSUM);printf("%ld",gcode_LastN);FlushSerialRequestResend();serial_count = 0;return;}gcode_LastN = gcode_N;//if no errors, continue parsing}else  // if we don't receive 'N' but still see '*'{if((strchr(cmdbuffer[bufindw], '*') != NULL))                                                            {SERIAL_ERROR_START;printf(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM);printf("%ld",gcode_LastN);serial_count = 0;return;}}if((strchr(cmdbuffer[bufindw], 'G') != NULL))                                                                {strchr_pointer = strchr(cmdbuffer[bufindw], 'G');switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){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.#ifdef SDSUPPORTif(card.saving)break;#endif //SDSUPPORTprintf(MSG_OK);printf("\n");}else {printf(MSG_ERR_STOPPED);// LCD_MESSAGEPGM(MSG_STOPPED);}break;default:break;}}bufindw = (bufindw + 1)%BUFSIZE;buflen += 1;//sanse}serial_count = 0; //clear buffer}else{if(serial_char == ';') comment_mode = true;if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; //注意serial_count自加}}

Marlin关于如何接收Gcode指令的详解相关推荐

  1. python接收邮件内容启动程序_Python实现发送与接收邮件的方法详解

    本文实例讲述了Python实现发送与接收邮件的方法.分享给大家供大家参考,具体如下: 一.发送邮件 这里实现给网易邮箱发送邮件功能: import smtplib import tkinter cla ...

  2. ARM指令CMP详解

    ARM指令CMP详解                                                                     1.加减指令     add  r1, r ...

  3. Nginx SSI指令配置详解

    这篇文章主要介绍了Nginx SSI指令配置详解,本文讲解了什么是SSI.为什么要用SSI.nginx配置SSI.页面上配置.配置示例等内容,需要的朋友可以参考下 什么是SSI Server Side ...

  4. c语言 recv_sin,C++_C语言中经socket接收数据的相关函数详解,recv()函数: 头文件:#incl - phpStudy...

    C语言中经socket接收数据的相关函数详解 recv()函数:头文件: #include #include 定义函数: int recv(int s, void *buf, int len, uns ...

  5. route指令使用详解

    参考:route指令使用详解 1.观察路由表信息: route [-nee] -n :不要使用通讯协定或主机名称,直接使用 IP 或 port number: -ee :使用更详细的资讯来显示 2.输 ...

  6. at指令 meid_AT指令大全详解完整版

    file:///F|/学习资料/AT指令大全/AT指令大全详解完整版.txt[2012-03-12 09:50:51] 一.    一般命令 1.    AT+CGMI 给出模块厂商的标识. 2.   ...

  7. 【参考】Android wm指令用法详解

    我就放些我自己大概率会用到的指令在这儿,详细的看原文地址. 原文地址:Android wm指令用法详解 - 走看看 adb shell SE:/ $ wm size        //查看当前分辨率 ...

  8. linux下top指令参数详解及用法

    一.命令介绍 Linux top命令用于实时显示 process (进程)的动态. 它用于监控正在运行系统负荷的信息,包括系统负载.CPU利用分布情况.内存使用.每个进程的资源占用情况等. 使用权限: ...

  9. Mac terminal find 指令常用详解

    Find 详解 逻辑运算符 -o 或者 !非 如果使用该命令时,不设置任何参数,则find命令将在当前目录下查找子目录与文件 文件名 find . -name "*.rmvb" 正 ...

  10. 计算机操作指令arp,详解在win7电脑中操作ARP命令的详细步骤

    在我们的电脑中很多的设置都是需要一定的技巧来实现的,那在操作不同的设置的时候使用命令的形式是最快的方法,可以实现操作的命令也是很多的,那需要使用到ARP命令的小伙伴在网络上提问怎么实现使用的呢,其实A ...

最新文章

  1. AI一分钟 | 妈呀!连地铁都开始无人驾驶了,飞机还远吗;北京无人驾驶新规出台,终于知道李彦宏该不该被罚了(12月19日)
  2. div+css多浏览器测试方法
  3. 如何丢弃Git中未进行的变更?
  4. python增删改查的框架layui_spring+springMvc+mybatis+layui实现数据表格的增删改查(纯layui实现)...
  5. Spring框架知识复习之二
  6. ModelArts黑科技揭秘|模型智能评估、诊断,让模型来个“体检
  7. 归一化方法 Normalization Method
  8. WCF 安全性 之 None
  9. 《Using OpenRefine》翻译~2
  10. php 输出git fetch,git fetch
  11. linux怎么看本机ip,linux下查看本机IP的两种方法
  12. games101 作业1
  13. PHP实现时间轴函数(个性化时间)
  14. 批量将jpg格式图像改为png格式
  15. scrapy--Rule()与LinkExtractor()函数理解
  16. 应用MapX编程两例
  17. Python调用R出现“UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xb2” 问题
  18. python中括号的作用_浅析python 中大括号中括号小括号的区分
  19. orchard文档之-orchard工作原理
  20. 2022-2027年中国现代通信网络行业市场调研及未来发展趋势预测报告

热门文章

  1. segnet运行记录
  2. php opendir 不能用,php opendir()函数讲解及遍历目录实例
  3. spring源码分析AOP原理图文详解
  4. Cp与Cpk了解与计算
  5. 无法通过百度联盟申请的常见原因
  6. 墨刀可以导入文件吗_墨刀和Sketch擦出的火花
  7. nbu备份社区版mysql_mysql数据备份之NBU
  8. SONY α系列(A6000A7)数码微单相机APP破解免付费安装教程
  9. 更改Servlet需要重启Tomcat
  10. 关于linux打包以及解压到指定目录的简单操作demo