grbl移植日志第二天移植串口数据接收

zynq的串口发送中断总是不能进入中断函数 . . . 看了好几天. 找不到原因了. 后来用了官方的串口中断示例代码也不行…
后来终于找到原因了…我的妈呀. 卡了我好几天, 原来是中断函数里面有个函数指针指向了Null.

if(rec_data == CMD_TOOL_ACK ) {   // If tool change acknowledged
	 hal.stream.read = serialGetC;                    // and restore normal input.
}
else if (!hal.stream.enqueue_rt_command((char)rec_data)) 
{
	fifo_push(&rxbuffer, (char)rec_data);
}

这个hal.stream.enqueue_rt_command 因为没有初始化, 导致指向的是Null. 执行过后就停止了.中断也不再进入了. C语言真的是要命啊.这种也不报异常,全靠人工逐行排查…
不知道C++能不能补货到这种异常.

zynq的串口中断示例中, 有些bug. 提供的库也不是很好用. 因为封装好的库里面内置了一些固定的逻辑, 里面默认进行了中断的开启和关闭. 用起来并不是很顺手.

因为grbl 有一个循环缓冲队列, 为了实现此数据的上传, 需要在中断中修改此队列的指针.
索性摸索了一下zynq的的uart库, 直接基于寄存器自己写了一个. 要简单简洁的多.
不再需要像下面这使用uart官方提供的函数XUartPs_InterruptHandler, 也就不需要再使用
XUartPs_SetHandler 进行绑定了. 因为 XUartPs_InterruptHandler 中调用了XUartPs_SetHandler 设置的函数.

 XScuGic_Connect(gicPtr, XPAR_PS7_UART_0_INTR, Xil_InterruptHandler)XUartPs_InterruptHandler, (void *)xUart0Ptr);  
 XUartPs_SetHandler(xUart0Ptr, (XUartPs_Handler)uartIntrHandler, xUart0Ptr); 

据到FIFO

 /* Fill the FIFO from the buffer 
   填充发送数据到TX 的FIFO
*/
XUartPs_WriteReg(InstancePtr->Config.BaseAddress,  XUARTPS_FIFO_OFFSET,
		   ((u32)InstancePtr->SendBuffer.
		   NextBytePtr[SentCount]));

禁用TXEMPTY中断

 
//禁用TXEMPTY中断
XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL));

启用TXEMPTY中断

//启用TXEMPTY中断
XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL));

读取当前中断寄存器ISR的状态

//读取当前中断寄存器ISR的状态
/*
 * Read the interrupt ID register to determine which
 * interrupt is active
 */
u32 IsrStatus;
IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,  XUARTPS_IMR_OFFSET); 
IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,  XUARTPS_ISR_OFFSET);

判断是不是FITO TX发送完成触发的中断

//判断是不是FITO TX发送完成触发的中断
if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL))  != (u32)0)
{
	/* Transmit data interrupt */
	SendDataHandler(InstancePtr, IsrStatus);
}

判断是不是接收溢出或接收空或者接收满的触发的状态.

/* Dispatch an appropriate handler. */
//判断是不是接收溢出或接收空或者接收满的触发的状态.
if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |
		(u32)XUARTPS_IXR_RXFULL)) != (u32)0)
 { 
 	ReceiveDataHandler(InstancePtr);
}

上面的这些代码都是参考自 xuartps_intr.c,xuartps.c

void XUartPs_InterruptHandler(XUartPs *InstancePtr)
{
.....
}

把官方提供的库XUartPs_InterruptHandler 抄过来
改个名

void MyXUartPs_InterruptHandler(XUartPs *InstancePtr){
		u32 IsrStatus;

		Xil_AssertVoid(InstancePtr != NULL);
		Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

		/*
		 * Read the interrupt ID register to determine which
		 * interrupt is active
		 */
		IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,  XUARTPS_IMR_OFFSET);

		IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,  XUARTPS_ISR_OFFSET);

		/* Dispatch an appropriate handler. */
		if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |
				(u32)XUARTPS_IXR_RXFULL)) != (u32)0) {
			/* Received data interrupt */
//			ReceiveDataHandler(InstancePtr);
		}

		if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL))  != (u32)0)
		{
			/* Transmit data interrupt */
			SendDataHandler(InstancePtr, IsrStatus);
		}

		/* XUARTPS_IXR_RBRK is applicable only for Zynq Ultrascale+ MP */
		if ((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING |
				(u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK)) != (u32)0) {
			/* Received Error Status interrupt */
//			ReceiveErrorHandler(InstancePtr, IsrStatus);
		}

		if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) {
			/* Received Timeout interrupt */
//			ReceiveTimeoutHandler(InstancePtr);
		}

		if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) {
			/* Modem status interrupt */
//			ModemHandler(InstancePtr);
		}

		/* Clear the interrupt status. */
		XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, IsrStatus);

}

中断管理器中把函数和中断管理器进行连接. 这里连接到的是我上面自己修改过的MyXUartPs_InterruptHandler

	Status = XScuGic_Connect(IntcInstancePtr, UartIntrId,  (Xil_InterruptHandler) MyXUartPs_InterruptHandler,  (void *) UartInstancePtr);

03-27
<think>好的,我需要回答用户关于GRBL CNC控制系统的开源固件功能介绍和使用说明的问题。首先,我得回顾一下用户提供的引用资料。引用1提到GRBL的源码被编译后烧录到STM32微控制器,实现G-code控制。引用3介绍了GRBL v1.1版本,并提到了一些翻译的资料。而引用2推荐了FluidNC作为下一代CNC固件。我需要将这些信息整合起来,确保涵盖GRBL的主要功能和用法,同时可能提到FluidNC作为补充。 首先,GRBL的功能部分应该包括G代码支持、运动控制、硬件接口、配置工具和扩展性。每个功能点都需要简明扼要地解释,比如G代码支持哪些指令,运动控制如何实现,支持的硬件有哪些,配置方法等。然后使用说明部分需要分步骤,比如硬件准备、固件烧录、参数配置、G代码发送和常见问题处理。同时,根据用户提供的引用,可能需要在相关部分添加引用标识,比如在讨论源码和STM32时引用[^1],在提到GRBL版本时引用[^3],在推荐FluidNC时引用[^2]。 接下来需要生成相关问题。根据用户提供的示例,问题应围绕GRBL的扩展功能、与FluidNC的区别、STM32的优势、参数配置优化以及G代码兼容性展开。确保每个问题都与GRBL相关,并且能够引导用户进一步探索。 在组织内容时,要遵循系统级指令,特别是数学公式的格式,但在这个问题中可能不需要数学公式。要使用中文,结构清晰,分点说明。需要检查LaTeX语法是否正确,不过当前内容可能不涉及复杂公式,所以可能不需要处理这部分。最后,确保回答真实可靠,引用正确。</think>### GRBL CNC控制系统介绍 #### 一、GRBL开源固件核心功能 1. **G代码解析与控制** GRBL支持标准G代码(如G0、G1、G2/G3),可解析坐标定位、直线/圆弧插补等指令,适用于3轴CNC机床控制。 2. **实时运动控制** 通过预读缓冲区(Look-ahead)和加速度规划算法,实现平滑运动轨迹。核心公式: $$v(t) = v_0 + at$$ 其中$a$为加速度,$t$为时间,保证电机不丢步[^3]。 3. **硬件驱动支持** 兼容STM32等ARM Cortex-M系列微控制器,提供步进电机脉冲生成、限位开关检测、主轴PWM控制等功能。 4. **配置工具** 支持$$ \$0=10 $$类指令动态修改步进脉冲数、加速度等参数,可通过Arduino IDE或终端工具更新固件。 #### 二、使用流程说明 1. **硬件准备** - 主控板:STM32F103C8(BluePill) - 驱动模块:TB6560/A4988步进驱动器 - 供电:24V直流电源 2. **固件烧录** ```bash avrdude -c arduino -p m328p -P /dev/ttyUSB0 -U flash:w:grbl_v1.1.hex ``` 3. **参数配置示例** | 参数 | 指令 | 说明 | |------|------|------| | 步进分辨率 | $100=800 | 每毫米脉冲数 | | 最大速率 | $110=5000 | X轴最大速度(mm/min) | 4. **G代码执行** 通过Universal G-code Sender等软件发送指令: ```gcode G21 (单位毫米) G90 (绝对坐标) G1 X100 Y200 F1200 ``` #### 三、进阶对比:GRBL vs FluidNC FluidNC作为GRBL的升级版本(引用[^2]): - 支持更多轴数(5轴联动) - 集成网络接口(WiFi/Ethernet) - 增加触摸探针补偿算法 - 新增螺旋插补指令G2/G3 Z...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值