【006】上位机开发及简单通信

标签: 上位机 IMU STM32 串口 Qt
1人阅读 评论(0) 收藏 举报
分类:

上位机开发及简单通信

1. 上位机开发的意义

  常见的上位机定义为一台可以发出特定操控命令的计算机,通过操作预先设定好的命令,将命令传递给下位机,通过下位机来控制设备完成各项操作。此定义着重于强调控制指令的发送,实际上除了发送控制命令,上位机还能提供许多额外的功能:

  a. 可视化功能

  上位机位于MCU与使用者之间,在MCU软件开发过程中,通常直接处理控制数据,优先考虑处理的实时性与能耗,对于数据的易于理解性及可视化程度不作考虑。MCU处理的数据虽然能够通过串口或者其他方式输出,但是直接输出的数据可读性较差,不利于直观的理解。上位机能够首先对MCU的输出数据进行处理,将其转化为易于理解的方式在显示屏上展现。

  b. 数据高速处理能力

  大多数MCU实时性好,但计算能力较弱。上位机具有较强的计算能力,但实时性较弱。因此,利用MCU采集数据并发送至上位机处理能够充分发挥双方优势。

  c. 算法仿真能力

  在进行嵌入式开发时,我们需要搭建平台,每次的软件修改都需要使用专门的工具进行烧写与调试,相比PC端软件开发更为繁琐,不利于调试。因此,可以将MCU采集到的数据发送至上位机,在PC端进行算法的验证,直到满足需求后再在MCU上进行测试,可以缩短开发周期,降低开发成本。

2. 基本需求

  在【004】基于STM32标准库的IMU9250数据读取【005】基于STM32标准库IMU9250数据读取(二)文中,我们基于STM32F429XXMCU成功读取了加速度计、陀螺仪、磁力计的原始数据,这里我们希望上位机能够实现以下功能:

  • 实时获取MCU采集的原始数据;
  • 以曲线的方式动态显示加速度计、陀螺仪、磁力计数据;
  • 以3D的方式动态显示欧拉角-Roll,Pitch,Yaw;
  • 提供算法仿真验证能力。

3. 上位机开发

3.1 开发环境

  对于上位机开发有许多开发环境可选,例如:MFC、Qt、Matlab、C#等。每种开发环境适用场合不同,例如MFC在Windows平台具有较强的通用性,在较老的计算机中也能够运行。Qt支持跨平台,能够在Windows、Linux等多个平台上运行。Matlab开发简单方便,适合矩阵向量的计算。这里我们选用Qt作为开发环境,同时使用QCustomPlot来实现加速度计、陀螺仪、磁力计数据的动态绘制,使用qextserialport作为串口通信的API。

3.2 通信方式

  上位机与下位机常见的通信方式有:串口通信、SPI通信、以太网通信等。串口通信速率较低,设备便宜,易于开发。以太网通信速率高,开发难度较高。SPI通信速率高于串口通信,但通常需要USB转SPI设备。这里选用串口作为上位机与下位机之间的通信方式。

3.3 简单协议

  设置简单的协议是为了让上位机能够准确、及时、高效地获取MCU采集的数据,这里我们采用的简单协议如图1所示。


图1 简单通信协议

  在此协议中,0xFF 0xFF为上位机的数据头,COM为控制指令用于实现请求数据(0x01)等任务。MCU在收到请求数据指令后,将会计算当前采集的数据个数(或组数),然后发送数据至上位机。在此过程中0xFF 0xFE为下位机数据头,N为当前采集的数据个数(或组数)。

  为了实现数据的先入先出,我们需要实现队列结构,一共需要三个队列:一个用于存储MCU的采集数据,一个用于存储上位机收到的数据,还有一个用于存储MCU收到上位机发来的控制指令。这里我们采用环形队列,它是在写程序时候一种队列的特殊表达方式,把队列数据组中的最后一个元素和第一个元素相连构成环,所以称为环形队列。环形队列在C/C++编程中首元素出队后不需要把队列所有元素向前移动,而取代把把队首指针向后移动,由于其环形结构,在插入元素后队尾指针会循环到队首原来的位置。相对普通队列的出队操作减少了大量的运算量。程序如下:

uint8_t RawDataQueueBuffer[QUEUE_SIZE];
uint16_t QueueHead, QueueTail, QueueLength;

void RawDataQueueBuffer_Init()
{
	QueueHead = 0;
	QueueTail = 0;
	QueueLength = 0;
}

uint8_t PushQueue(uint8_t Val)
{
	RawDataQueueBuffer[QueueTail] = Val;
	QueueTail++;
	QueueTail = QueueTail % QUEUE_SIZE;
	QueueLength++;
	if (QueueLength > QUEUE_SIZE)
	{
		QueueLength = QUEUE_SIZE;
	}
	return 0;
}

uint8_t PopQueue(uint8_t *Val)
{
	if (QueueLength > 0)
	{
		*Val = RawDataQueueBuffer[QueueHead];
		QueueHead++;
		QueueHead = QueueHead % QUEUE_SIZE;
		QueueLength--;
		return 0;
	}
	else
	{
		return 255;
	}
}

MCU采用中断的方式将上位机数据存至对应的队列并将指令校验标志置一,同样采用中断的方式将进行IMU数据采集。采用轮询的方式检测相应标志是否为一,若为一则进行相应操作并清零该标志位,对应过程如图2所示。


图2 MCU简单协议处理流程

对应代码如下:

uint8_t MPU6050_Task()
{
	while(1)
	{
//		if (TaskFlag_GetData == 1)
//		{
//			//Clear_PCF_Status();
//			MPU6050_Get_RawData();
//			TaskFlag_GetData = 0;
//		}
		if (TaskFlag_CheckData == 1)
		{
			switch (Check_Command(USART_QueueBuffer))
			{
			case 0:
				MPU6050_Send_Data();
				break;
			default:
				;
			}
			TaskFlag_CheckData = 0;
		}
	}
	return 0;
}

uint8_t Check_Command(uint8_t *Buffer)
{
	if ((Buffer[(USART_QueueTail - 3 + 3) % 3] == 0xFF) && (Buffer[(USART_QueueTail - 2 + 3) % 3] == 0xFE))
	{
		return Buffer[(USART_QueueTail - 1 + 3) % 3];
	}
	else
	{
		return 255;
	}
}

int main(void)
{
	Blinking_GPIO_Init();

	MPU6050_Init();
	Clear_PCF_Status();
	MPU6050_Task();
	return 0;
}
中断服务程序代码:
extern uint8_t TaskFlag_GetData;
extern uint8_t TaskFlag_CheckData;

void USART2_IRQHandler(void)
{
	if(USART_GetITStatus(USART2, USART_IT_RXNE))
	{
		USART_PushQueue((uint8_t)USART_ReceiveData(USART2));
		TaskFlag_CheckData = 1;
	}
}

uint16_t cnt;
void EXTI15_10_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line12) != RESET)
	{
		TaskFlag_GetData = 1;
		EXTI_ClearITPendingBit(EXTI_Line12);
		MPU6050_Get_RawData();
		cnt++;
		if (cnt == 20)
		{
			cnt = 0;
			GPIO_ToggleBits(GPIOB, GPIO_Pin_1);
		}
	}
}

3.4上位机效果

最终上位机初步效果如图3所示,包含基本的串口参数设置及数据显示,将MCU采集的IMU数据经过处理后分别以文字、曲线、图像的方式形象展示。


图3 上位机初步效果



联系作者


查看评论

MFC上位机与STM32下位机通讯精讲

-
  • 1970年01月01日 08:00

用vb.net开发的简易(通用)上位机

这里写的是上位机基本的程序,有什么额外功能的话可以自己加上。我是参与别人项目里做的,主要实现了自动检测,断点重连,发送检测消息。因为要实时使用,所以要最大程度的避免程序崩溃,因此程序里使用了比较多的t...
  • fengasdfgh
  • fengasdfgh
  • 2017-08-04 01:22:42
  • 841

基于C++的USB通信上位机程序

  • 2013年10月22日 09:49
  • 48.83MB
  • 下载

上位机与USB设备通信

首先使用CreateFile打开USB端口,CreateFile函数会返回一个HANDLE类型的句柄,该句柄可以用于下述的ReadFile和WriteFile之间的操作。    CreateFile(...
  • chen_0306
  • chen_0306
  • 2015-05-26 23:16:12
  • 2537

基于C#简单上位机通讯程序_可扩展

  • 2013年09月17日 11:03
  • 195KB
  • 下载

上位机与单片机的通信问题

上位机采用的是组态王这款监控软件,单片机采用的是STM32,系统的总框架分为4层:        服务器(组态王)——网关2——网关1——节点 通信过程中遇到的问题如下: 1. 将单片机与组态王...
  • qq_38021919
  • qq_38021919
  • 2018-01-13 11:02:33
  • 272

WiFi通信上位机实现

最终的目标: 上位机功能:键盘发出 前后左右移动信号 + 其他云台、机械臂等信号,通过Socket网络编程,实现WiFi与下位机通信。 然后Win32开发相关的和Socket是现学现用,业余的。 ...
  • sinat_36330809
  • sinat_36330809
  • 2017-08-23 22:50:04
  • 899

c# usb-hid通信上位机示例

  • 2016年03月23日 10:13
  • 134KB
  • 下载

用于学习USB通信的上位机程序范例。

  • 2010年03月25日 21:18
  • 56KB
  • 下载

初涉USB,初学者USB入门总结(5)USB上位机读写开发

上一部分说了固件和驱动的编程,这里再谈一下上位机的程序,因为我开发的范围也就是传传数据,所以太深入的没有去做,不过一般的工程调试应该足够了。     固件的程序和驱动编写好了后,把设备插入就可以正确...
  • JRENSKY
  • JRENSKY
  • 2015-06-23 13:10:35
  • 2150
    个人资料
    持之以恒
    等级:
    访问量: 229
    积分: 70
    排名: 157万+
    文章分类
    文章存档