Qt串口助手滑块与STM32进行通信,控制步进电机正反转以及转动固定距离

一、Qt滑块发送端

1、简介

QT中滑动条的控件叫QSlider,继承自QAbstractSlider类。
主要用途是通过滑块的滑动的方式在一定范围内调节某个值。根据调节的后得到的结果去执行一些处理,比如将值写入或者用这个值进行计算,或者进行值传输等等。

 通常使用这个控件是希望我们调节滑块到指定位置后,发生一个触发事件,在这个触发事件中,我们获取最后的值,然后进行处理操作。

2、滑块槽函数介绍

 其实这6个转换未槽函数的实现就是对应着QAbstractSlider的6个信号量触发函数

//Signals 信号量
 void actionTriggered(int action)
 void rangeChanged(int min, int max)
 void sliderMoved(int value)
 void sliderPressed()
 void sliderReleased()
 void valueChanged(int value)

前面转到槽函数的使用就是依据这6个信号量的触发,执行对应的函数。函数内容自己按需求设计。

 void sliderMoved(int value)

这个信号量触发的条件是按下滑块并滑动,就会发出这个信号量,触发对应的槽函数。需要注意的是只要滑块动就会触发,也就是你从1滑动到10,那么1-10中每有一个值是可取的,它都会触发一次。(除非你真就每次只滑动一格,那你没必要用滑动块了)

 void sliderPressed()

这个信号量是当滑块按下时触发信号量,执行槽函数,一般情况下也不会用吧,因为按下的时候值是没变的,此时触发不需要进行什么操作。

 void sliderReleased()

这个信号量是当滑块释放时,触发信号量可以执行对应的槽函数。这个就比较有用了,可以捕捉到滑动完滑块的那个瞬间,那也是最终的位置,此时的结果正是调节完的结果,执行对应的槽函数去进行值处理。其实这个信号量就可以完成滑块的基本需求了。 但是也还有些局限:通过点击滑动块的方式无法触发信号量。

 void valueChanged(int value)

这个信号量是滑块滑动,值发生变化时,就会触发,其实一般使用起来和前面的sliderMoved基本相同,就是少了一个按下滑动块的前提,(不管按不按下滑块)值发生变化时,这个信号量都会触发。同样的从1-10变化,中间每个值都会触发一次。

3、要实现的预期效果

鼠标释放滑块时,将滑块的变化值通过串口发送出去,并判断滑块是向右滑动还是向左滑动。将滑块的当前位置和变化距离显示在窗口。

 4、Qt窗口界面设置

 5、 .h文件

在.h文件添加滑块槽函数

private slots:

void on_X_distance_sliderReleased();
void on_X_distance_valueChanged(int value);

6、.cpp文件

以Hex格式数据包的形式发送给32,加上帧头帧尾

void MyMainWindow::on_X_distance_sliderReleased()
{
    // 获取滑块的当前值
    int currentValue = ui->X_distance->value();
    int previousSliderValue = 0; //跟踪滑块值

    // 判断滑块的滑动方向
    if (currentValue > previousSliderValue) {
        // 右滑  将距离显示到窗口
        ui->X_text_2->setText("+" +QString::number(currentValue-previousSliderValue));
        //串口控制步进电机运动
        // 转换16进制并通过串口发送
        // 创建一个 QByteArray 来包含帧头和数据
        QByteArray myString;
        myString.append(static_cast<char>(0xFF));  // 添加帧头 0xFF
        myString.append(static_cast<char>(0x01));  // 设置电机号
        myString.append(static_cast<char>(0x55));  // 设置电机方向 0x55表示正转 0x66表示反转
        // 将十六进制字符串转换为 QByteArray 并添加到 myString
        myString.append(QByteArray::fromHex(QString::number(currentValue-previousSliderValue, 16).toUtf8()).data());
        myString.append("\r\n");// 添加帧尾  \r为0x0D \n为0x0A
        serialPort->write(myString);// 通过串口把myString发送出去
    } else if (currentValue < previousSliderValue) {
        // 左滑
        ui->X_text_2->setText(QString::number(currentValue-previousSliderValue));
        //串口控制步进电机运动
        // 转换16进制并通过串口发送
        // 创建一个 QByteArray 来包含帧头和数据
        QByteArray myString;
        myString.append(static_cast<char>(0xFF));  // 添加帧头 0xFF
        myString.append(static_cast<char>(0x01));  // 设置电机号
        myString.append(static_cast<char>(0x66));  // 设置电机方向
        // 将十六进制字符串转换为 QByteArray 并添加到 myString
        myString.append(QByteArray::fromHex(QString::number(previousSliderValue-currentValue, 16).toUtf8()).data());
        myString.append("\r\n");// 添加回车和换行符
        // 通过串口发送数据
        serialPort->write(myString);
    }
    // 更新上一个值
    previousSliderValue = currentValue;
}

void MyMainWindow::on_X_distance_valueChanged(int value)
{
    // 更新文本框的值
    ui->X_text->setText(QString::number(value));
}

 7、效果演示

 二、STM32接收端

定义一个数组存放接收到的数据

uint16_t Serial_RxPacket[100];	//定义接收数据包数组,数据包格式"0xFF 0xxx 0x0D 0x0A"

1、串口中断函数

/**
  * 函    数:USART1中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void USART1_IRQHandler(void)
{
	static uint8_t RxState = 0;		//定义表示当前状态机状态的静态变量
	static uint8_t pRxPacket = 0;	//定义表示当前接收数据位置的静态变量
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)	//判断是否是USART1的接收事件触发的中断
	{
		uint16_t RxData = USART_ReceiveData(USART1);			//读取数据寄存器,存放在接收的数据变量
		
		/*使用状态机的思路,依次处理数据包的不同部分*/
		
		/*当前状态为0,接收数据包包头*/
		if (RxState == 0)
		{
			if (RxData == 0xFF && Serial_RxFlag == 0)		//如果数据确实是包头,并且上一个数据包已处理完毕
			{
				RxState = 1;			//置下一个状态
				pRxPacket = 0;			//数据包的位置归零
			}
		}
		/*当前状态为1,接收数据包数据,同时判断是否接收到了第一个包尾*/
		else if (RxState == 1)
		{
			if (RxData == 0x0D)			//如果收到第一个包尾
			{
				RxState = 2;			//置下一个状态
			}
			else						//接收到了正常的数据
			{
				Serial_RxPacket[pRxPacket] = RxData;		//将数据存入数据包数组的指定位置
				pRxPacket ++;			//数据包的位置自增
			}
		}
		/*当前状态为2,接收数据包第二个包尾*/
		else if (RxState == 2)
		{
			if (RxData == 0x0A)			//如果收到第二个包尾
			{
				RxState = 0;			//状态归0
				Serial_RxPacket[pRxPacket] = '\0';			//将收到的字符数据包添加一个字符串结束标志
				Serial_RxFlag = 1;		//接收数据包标志位置1,成功接收一个数据包
			}
		}
		
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);		//清除标志位
	}
}

2、主函数

	while(1)
	{
		
		if (Serial_RxFlag == 1)		//如果接收到数据包
		{
			/*将收到的数据包与预设的指令对比,以此决定将要执行的操作*/
			if (Serial_RxPacket[0] == 0x01)			//
			{
				if(Serial_RxPacket[1] == 0x55)
				{
					X_target_distance = Serial_RxPacket[2];    //目标距离=串口接收到的距离
					Serial_SendNumber(Serial_RxPacket[2], 3);  //将运动距离返回串口
					Serial_SendString("\r\n");                 //换行
					DIR_Forword();                             //正转
					TIM_Cmd(TIM2, ENABLE);                     //打开定时器
				}
				else if(Serial_RxPacket[1] == 0x66)
				{
					X_target_distance = Serial_RxPacket[2];    //目标距离=串口接收到的距离
					Serial_SendNumber(Serial_RxPacket[2], 3);  //将运动距离返回串口
					Serial_SendString("\r\n");                 //换行
					DIR_Reversal();                            //反转
					TIM_Cmd(TIM2, ENABLE);                     //打开定时器
				}
			}
			Serial_RxFlag = 0;			
		}	
	}

三、效果展示

Qt滑块控制步进电机

Qt滑块参考文章:QT——QSlider实现,QT滑动控件的使用-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值