Marlin关于如何接收Gcode指令的详解
我研究的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指令的详解相关推荐
- python接收邮件内容启动程序_Python实现发送与接收邮件的方法详解
本文实例讲述了Python实现发送与接收邮件的方法.分享给大家供大家参考,具体如下: 一.发送邮件 这里实现给网易邮箱发送邮件功能: import smtplib import tkinter cla ...
- ARM指令CMP详解
ARM指令CMP详解 1.加减指令 add r1, r ...
- Nginx SSI指令配置详解
这篇文章主要介绍了Nginx SSI指令配置详解,本文讲解了什么是SSI.为什么要用SSI.nginx配置SSI.页面上配置.配置示例等内容,需要的朋友可以参考下 什么是SSI Server Side ...
- c语言 recv_sin,C++_C语言中经socket接收数据的相关函数详解,recv()函数:
头文件:#incl - phpStudy...
C语言中经socket接收数据的相关函数详解 recv()函数:头文件: #include #include 定义函数: int recv(int s, void *buf, int len, uns ...
- route指令使用详解
参考:route指令使用详解 1.观察路由表信息: route [-nee] -n :不要使用通讯协定或主机名称,直接使用 IP 或 port number: -ee :使用更详细的资讯来显示 2.输 ...
- at指令 meid_AT指令大全详解完整版
file:///F|/学习资料/AT指令大全/AT指令大全详解完整版.txt[2012-03-12 09:50:51] 一. 一般命令 1. AT+CGMI 给出模块厂商的标识. 2. ...
- 【参考】Android wm指令用法详解
我就放些我自己大概率会用到的指令在这儿,详细的看原文地址. 原文地址:Android wm指令用法详解 - 走看看 adb shell SE:/ $ wm size //查看当前分辨率 ...
- linux下top指令参数详解及用法
一.命令介绍 Linux top命令用于实时显示 process (进程)的动态. 它用于监控正在运行系统负荷的信息,包括系统负载.CPU利用分布情况.内存使用.每个进程的资源占用情况等. 使用权限: ...
- Mac terminal find 指令常用详解
Find 详解 逻辑运算符 -o 或者 !非 如果使用该命令时,不设置任何参数,则find命令将在当前目录下查找子目录与文件 文件名 find . -name "*.rmvb" 正 ...
- 计算机操作指令arp,详解在win7电脑中操作ARP命令的详细步骤
在我们的电脑中很多的设置都是需要一定的技巧来实现的,那在操作不同的设置的时候使用命令的形式是最快的方法,可以实现操作的命令也是很多的,那需要使用到ARP命令的小伙伴在网络上提问怎么实现使用的呢,其实A ...
最新文章
- AI一分钟 | 妈呀!连地铁都开始无人驾驶了,飞机还远吗;北京无人驾驶新规出台,终于知道李彦宏该不该被罚了(12月19日)
- div+css多浏览器测试方法
- 如何丢弃Git中未进行的变更?
- python增删改查的框架layui_spring+springMvc+mybatis+layui实现数据表格的增删改查(纯layui实现)...
- Spring框架知识复习之二
- ModelArts黑科技揭秘|模型智能评估、诊断,让模型来个“体检
- 归一化方法 Normalization Method
- WCF 安全性 之 None
- 《Using OpenRefine》翻译~2
- php 输出git fetch,git fetch
- linux怎么看本机ip,linux下查看本机IP的两种方法
- games101 作业1
- PHP实现时间轴函数(个性化时间)
- 批量将jpg格式图像改为png格式
- scrapy--Rule()与LinkExtractor()函数理解
- 应用MapX编程两例
- Python调用R出现“UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xb2” 问题
- python中括号的作用_浅析python 中大括号中括号小括号的区分
- orchard文档之-orchard工作原理
- 2022-2027年中国现代通信网络行业市场调研及未来发展趋势预测报告