在制作上位机中,我们常常要把单片机上的数据,比如曲线图、电机速度、信号频率幅值等显示在上位机软件中,那么就需要下位机方将数据不断传给上位机以在Qt的QLCDNumber或者Qchart不断刷新,这是上位机对下位机的数据传输。
另外我们有时候需要在上位机里修改单片机的参数,比如设置当前速度需要将速度设置为100、设置模式时等场景,都需要上位机发送数据至下位机,然后下位机通过解析到的数据调用对应的函数以设置参数。
那么如何将让数据实现上、下位机间的传输呢,我分享一下上一篇关于电机控制我的做法。
我用的通讯方式是串口通信,stm32用串口连接至电脑后,当点击套用参数时,调用槽函数。在槽函数里将数据发送给stm32,由于还有其他按钮要发送不同的数据,所以我在发送这串数据时,我加了一个报头:PID。
PID:0.3p0.015i0.2d20s
将所要发送的数据整理成这种形式,四个数据分别是 KP、KI、KD、和目标速度。即在调用槽函数时,在槽函数中调用串口类的write函数,将数据打包发给stm32
//套用按钮
void SerialPort::on_setButton_clicked()
{
QString s = "PID:";
QString str1 = ui->KPEdit->text();
float str1f = str1.toFloat();
QString s1 = QString::number(str1f);
s.append(s1);
QString str2 = ui->KIEdit->text();
float str2f = str2.toFloat();
QString s2 = QString::number(str2f);
s.append("p");
s.append(s2);
QString str3 = ui->KDEdit->text();
float str3f = str3.toFloat();
QString s3 = QString::number(str3f);
s.append("i");
s.append(s3);
QString str4 = ui->setSpeed->text();
int str4f = str4.toInt();
QString s4 = QString::number(str4f);
s.append("d");
s.append(s4);
s.append("s");
s.append("\r\n");
char *temp=s.toLocal8Bit().data();
port->write(temp);
qDebug()<<temp;
ui->setSpeed->setEnabled(false);
ui->KPEdit->setEnabled(false);
ui->KIEdit->setEnabled(false);
ui->KDEdit->setEnabled(false);
}
通过 QString类下的append和各种类型转换函数将所发数据拼接成一条字符串打包通过串口发送给stm32。然后stm32串口接收到数据触发串口中断来处理数据。
#define GetChPos(thisBuf,ch) (int)strchr(thisBuf, ch) - (int)thisBuf
if(USART_ReceiveString[0] == 'P' && USART_ReceiveString[1] == 'I' && USART_ReceiveString[2] == 'D')
{
//PID:0.2p0.015i0.2d50s
float p,i,d,s;
int a = GetChPos(USART_ReceiveString,':');
int b = GetChPos(USART_ReceiveString,'p');
int c = GetChPos(USART_ReceiveString,'i');
int e = GetChPos(USART_ReceiveString,'d');
int f = GetChPos(USART_ReceiveString,'s');
// KP
memcpy(USART_ReceiveString1, USART_ReceiveString1+a+1, sizeof(USART_ReceiveString1)-(a+1));
memset(USART_ReceiveString1+b-(a+1), 0, sizeof(USART_ReceiveString1)+b-(a+1));
float dval1;
dval1 = atof(USART_ReceiveString1);
printf("%1f\r\n",dval1);
p=dval1;
// KI
memcpy(USART_ReceiveString2, USART_ReceiveString2+b+1, sizeof(USART_ReceiveString2)-(b+1));
memset(USART_ReceiveString2+c-(b+1), 0, sizeof(USART_ReceiveString2)+c-(b+1));
float dval2;
dval2 = atof(USART_ReceiveString2);
printf("%1f\r\n",dval2);
i=dval2;
// KD
memcpy(USART_ReceiveString3, USART_ReceiveString3+c+1, sizeof(USART_ReceiveString3)-(c+1));
memset(USART_ReceiveString3+e-(c+1), 0, sizeof(USART_ReceiveString3)+e-(c+1));
float dval3;
dval3 = atof(USART_ReceiveString3);
printf("%1f\r\n",dval3);
d=dval3;
// Targetspeed
memcpy(USART_ReceiveString4, USART_ReceiveString4+e+1, sizeof(USART_ReceiveString4)-(e+1));
memset(USART_ReceiveString4+f-(e+1), 0, sizeof(USART_ReceiveString4)+f-(e+1));
int dval4;
dval4 = atoi(USART_ReceiveString4);
printf("%d\r\n",dval4);
s=dval4;
pid_set(p,i,d);
INPUT=s;
}
先确实是以 PID 开始的报头,然后开始接收数据,将数据利用memset和memcpy分隔解析出来,然后传入pid_set这个函数实现pid的调参,这一套流程就实现了上位机改变参数,然后下位机响应调整pid。
下一篇将说明下位机(stm32)传数据给上位机(Qt)的数据解析。如果觉得这篇文章对您有帮助,可以点赞、收藏,有疑问可以私信我,看到都会回。
文章浏览阅读1.9k次。unity_c# string转long
文章浏览阅读249次。在混淆矩阵中,行表示预测结果,列表示真实标签。例如,上述混淆矩阵中有3个真正例(预测正确的正例)、4个真反例(预测正确的反例)、1个假正例(预测错误的正例)和2个假反例(预测错误的反例)。在R语言中,我们可以使用一些库来计算混淆矩阵,如caret和e1071。假设我们有一个二分类问题,类别分别为"正例"和"反例",并且已经得到了一个分类模型的预测结果和真实标签。通过使用R语言提供的库函数,我们可以轻松计算混淆矩阵并获取各种性能指标。除了混淆矩阵本身之外,我们还可以通过混淆矩阵对象获取其他性能指标。_r做混淆矩阵
文章浏览阅读1.8k次。vscode下.vue文件初始化当我们在使用vscode编写vue文件的时候,每次都需要输入<template></template>,<script></script>,<style></style>这些标签如何像我们之前一样写html使用emmet插件一样使用 !自动出来html的格式呢1 安装Vetur扩展让V..._vscode初始化vue
文章浏览阅读1.7k次。这是一个简单的例子_导入一个架包:cglib-nodep-2.1.3.jar
文章浏览阅读2.2k次,点赞2次,收藏4次。完美卸载CDH一个节点并重新安装_cdh卸载重装
文章浏览阅读3k次。PHP message: PHP Warning: require(/data/wwwroot/blog.sgfoot.com/bootstrap/autoload.php): failed to open stream: Operation not permitted in /data/wwwroot/blog.sgfoot.com/public/index.php on line 22PHP ..._notice: php message: php warning: require(/start.php): failed to open stream
文章浏览阅读1.1k次。本文介绍了 TCN 在股市趋势预测任务中的应用,表明在集成新闻事件和知识图谱后,TCN 的性能大幅超过 RNN。
文章浏览阅读82次。用户有一张信用卡,信用卡有一个总额度;每个月会有信用卡账单显示月消费总额,月消费总额是小于信用卡总额度的;用户有若干储蓄卡,可选择某张储蓄卡进行还款;还款是指从储蓄卡中划走信用卡的月消费总额到信用卡;如果储蓄卡余额不足则还款动作不成功。要求如下:①必须使用委托②事件的触发方式是每个月的到期还款日;using System;namespace windows_practice{ //信用卡类 class CreditCard { private int C...
文章浏览阅读857次。Reference:http://blog.exbot.net/archives/249https://blog.csdn.net/weixin_43822994/article/details/85566552https://zhuanlan.zhihu.com/p/45845001https://blog.csdn.net/c2a2o2/article/details/77336551..._learn from demonstration
文章浏览阅读1.6k次,点赞41次,收藏22次。最新最详细的配置Node.js环境教程,已经将所有坑都踩了一遍!!超级超级详细详细!!!_node配置
文章浏览阅读127次。mvc 1,什么是mvc? model,view,controller 是一种软件架构模式,其基本思想是:将一个软件的组成部分划分成三部分,即: 模型:封装业务逻辑 视图:数据展现,也就是表示逻辑(即将模型中提供的数据以合适的方法展示出来), 另外还提供UI(用户接口),用户通过视图向系统发送请求。 控制器:将视图与模型的关系解耦,即视图与模型的调用要通过..._web开发中的mvc
文章浏览阅读1.2k次。粒子群优化算法是一种模拟鸟群社会行为的群体搜素算法。它分为全局最佳粒子优化和局部最佳粒子优化,对于全局最佳PSO,或者叫做gbest PSO,每个粒子的邻域都是整个群,其算法伪代码如下:创建并初始化一个n维的粒子群repeatfor 每个粒子i=1,2,…n do//设置个体最佳位置if f(i)y=f(i);end//设置全局最佳位置if yY=y;endendfor每个粒子i=1,2,…n ..._pso伪代码