2019-02-22 22:27:02 LuDanTongXue 阅读数 585
  • MFC上位机与STM32下位通讯精讲

    本课程主要介绍C++类库MFC上位机与STM32单片机的RS232、RS422、RS485、USB、LWIP以太网、CAN等接口进行稳定通信。课程主要从MFC和STM32基础开始,以编写上位机以及下位机为主,非常注重实践。

    9306 人正在学习 去看看 王凯杰

程序下载地址:
https://download.csdn.net/download/ludantongxue/10971448
对应硬件线路连接见上章:
https://blog.csdn.net/LuDanTongXue/article/details/87869557
对应单片机程序见上章:
https://blog.csdn.net/LuDanTongXue/article/details/87869806

程序界面:
上位机图片

程序参数说明:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

各个曲线段参数设置举例:
第一段S曲线加速30°:1转/秒启动,5转/秒结束
在这里插入图片描述

第二段匀速运动120°:5转/秒匀速
在这里插入图片描述

第三段S曲线减速30°:5转/秒启动,0.5转/秒结束
在这里插入图片描述

第四段S曲线反转加速30°:0.5转/秒启动,5转/秒结束
在这里插入图片描述

第五段匀速反转运动120°:5转/秒匀速
同第二段

第六段S曲线反转减速30°:5转/秒启动,1转/秒结束
在这里插入图片描述

至此各个曲线段对应的数组均已生成,将各数组复制到单片机程序即可(记得更改数组名称)。(微信ID:saskingku)

2018-01-13 11:02:33 qq_38021919 阅读数 7598
  • MFC上位机与STM32下位通讯精讲

    本课程主要介绍C++类库MFC上位机与STM32单片机的RS232、RS422、RS485、USB、LWIP以太网、CAN等接口进行稳定通信。课程主要从MFC和STM32基础开始,以编写上位机以及下位机为主,非常注重实践。

    9306 人正在学习 去看看 王凯杰

上位机采用的是组态王这款监控软件,单片机采用的是STM32,系统的总框架分为4层:

       服务器(组态王)——网关2——网关1——节点

通信过程中遇到的问题如下:

1. 将单片机与组态王连接完成后,组态王上没显示

(1)首先检查电路有没有连接正确(已经确定连接无误)

(2)利用串口查看网关1跟网关2打印出来的数据(对照代码中的内容,确定运行到每一步应有什么标志,可以通过打印不同的数据来监测运行到哪一步)

2. 网关2打印的数据总是显示网关2已经给网关1下发查询命令了,但是却没有收到网关1给它回复的数据,而且网关1也没有数据打印

分析可以知道网关2已经给网关1下发查询命令了,但是可能它的命令没有下发成功卡在485那块,导致网关1没有接收到命令所以没有打印数据,或者是网关2已经成功发送出去,只是网关1不接收而已,又或者是网关1已经接收到了但没有解包执行。

出现这种现象,原因有以下几种:

(1)程序跑死了 2485有问题 (3)硬件问题

因为这程序在之前一直跑得没问题,所以暂时先排除代码问题,先检查485那块的线路

检查结果:线路没连错,但是485线那块的RX,TX,GND这3根线裸露在空气中,而且有几根是相互接触了,用绝缘胶布包好之后,再一次通讯,这时网关1和2都有数据了,但是组态王还是没有显示

                         (网关2)

  

由我这个网关2打印的数据对照通信协议可知,网关2已经把节点上报的所有数据都上传给组态王了,而且打印出来的数据都是正确的,因为由系统的框架可知,节点的数据是通过485线传给相应的网关1的,网关1再将接收到的数据传给网关2,网关2再将所有的数据打包上报给上位机组态王,每个网关1打印的数据都跟它底下连着的节点状态一样,所以网关1和网关2都没问题。

3. 但是网关2已经把网关1上传的所有节点信息都上报给组态王的,但是组态王依然没有显示。

因为网关2跟组态王连接是通过一根USB转RS232线,会不会是这根线有问题?

换一根,果然,组态王有显示且显示各实验室的状态都正确。

后来由于我们要弄一套试验版,所以我们又得焊一套新的电源管理板子,一个网关2板子,一个网关1板子和五个节点板子。

4. 焊完之后,我们把各自的程序下进去,发现用不了,网关2和网关1都没数据

后来我们采用替换法,用旧的那套网关1和节点板子替换新的,目的是检测是否是新网关2出问题。

5. 替换之后发现网关2还是没有打印出数据,不用说组态王肯定也没有显示

我们先检测硬件问题,发现网关2的器件不小心焊错了,换回来之后,发现还是不行,后来我们自己写个485调试的程序(含有对串口2的调用),发现这个程序跑不了,我们定位是板子的主芯片STM32F103有问题,先排除是不是芯片引脚虚焊,然后发现是这个芯片坏了(不过一般情况下芯片很少会坏的),换个新的芯片后,程序能跑了。而且网关1和2都打印出正确的数据,组态王也显示正确。

噢,还有一个补充的是,之前那套旧的板子,曾出现过这么一个情况:时而有数据打印,时而没有。我们之前还以为是所处的环境干扰太大(有很多大型服务器在周围),其实是串口排针焊接不良导致的。(那时还没发现是USB转232线损坏,所以网关有数据,组态王没显示

 所以综合目前所出现的所有情况可以得出:上位机与单片机通信的问题大多都是出现在硬件问题上。

一、是否电路都连接正确?

二、是否焊接不良? 这步可以利用万用表来一步步地检测

三、485通信的那三根485线RX,TX,GND是否有接触?

四、与上位机相连的那个USB转232线是否损坏?  数据传送的过程可以用示波器来检测,便于查看数据传送到哪一步卡住了


    在整个调试的过程中,我们得出一个很好的习惯,就是写代码的时候,最好加上一些标志,比如程序运行到哪一步就会打印出哪些提示或者数据,然后制成一个通信协议,方便以后出问题可以对照通信协议来找出问题所在。还有就是懂得利用一些相关的仪器来检测问题。




2019-02-21 22:12:28 LuDanTongXue 阅读数 2446
  • MFC上位机与STM32下位通讯精讲

    本课程主要介绍C++类库MFC上位机与STM32单片机的RS232、RS422、RS485、USB、LWIP以太网、CAN等接口进行稳定通信。课程主要从MFC和STM32基础开始,以编写上位机以及下位机为主,非常注重实践。

    9306 人正在学习 去看看 王凯杰

单片机控制步进电机-线路连接

说明:如何利用单片机去控制步进电机?本案例讲解的内容是硬件连接部分,采用常用的电子器件去实现单片机控制步进电机的功能。后续会分别讲解单片机程序,S曲线生成方法,上位机等相关内容。

硬件清单:
1、单片机最小系统(本案例使用Atmega16芯片)
2、步进电机(二相四线)
3、稳压电源(24V)
4、步进电机驱动器(TB6600)
步进电机单片机最小系统
稳压电源驱动器
整体连接图:
整体图
原理图:
原理图

控制原理:
1、单片机最小系统作用:
①输出脉冲到步进电机驱动器,从而控制步进电机的速度大小
②控制步进电机的使能
③控制步进电机的转动方向
2、步进电机作用:
①提供机械动力
3、稳压电源作用:
①为步进电机提供电源
4、步进电机驱动器作用:
①将单片机脉冲信号转化为步进电机的驱动信号,简化控制过程

硬件连接图:
实物连接图与原理图如上图所示。Atmega16单片机最小系统(其他单片系统接线原理类同)与步进电机驱动器(TB6600)采用共阴极接法(驱动器的ENA-、DIR-、PUL-与单片机的GND连接)。
单片机PA0口控制ENA+,PA0高电位的时,步进电机掉电,步进电机自由状态,用手可以转动;PA0低电位的时,步进电机上电,根据输入的脉冲信号进行转动,无脉冲信号时处于自锁状态;
单片机PA1口控制DIR+,PA1高电位与低点位分别对应步进电机的正转与反转;
单片机PA2口控制PUL+,通过PA2口高低电位的切换形成脉冲,单片机输出一个脉冲(一个高电位加一个低电位即为一个脉冲),步进电机就会走一步。对于二相四线步进电机而言,在驱动器无细分的情况下,单片机一个脉冲对应步进电机一个步距角1.8°;驱动器如果是2细分状态,单片机一个脉冲对应步进电机转动角度为1.8°/2=0.9°;驱动器如果是4细分状态,单片机一个脉冲对应步进电机转动角度为1.8°/4=0.45°;其他细分依次类推。TB6600驱动器上的SW1、SW2、SW3三个拨码开关控制细分数(1细分、2细分、4细分、8细分、16细分、32细分),细分数越大,步进电机转动过程中越平稳。通过脉冲的快慢可以控制步进电机的速度,一般分为三个过程:开始加速、然后匀速、最后减速,后续会单独讲解控制程序部分。
步进电机的A、B相分别接在驱动器A、B相。在不知道步进电机那两根线是一相的时候,有个简单的判断方法:将步进电机的任意两更线接在一起,用手转动步进电机,如果有较大的阻力说明这两根线对应的是一相。
稳压电源输入端接交流220V,输出端正负极(本案例采用的是24V步进电机)分别接在驱动器VCC、GND即可。
至此硬件电路连接完成,下篇将讲解单片机程序。https://blog.csdn.net/LuDanTongXue/article/details/87869806
(微信ID:saskingku)

2018-06-02 16:07:00 Mculover666 阅读数 30293
  • MFC上位机与STM32下位通讯精讲

    本课程主要介绍C++类库MFC上位机与STM32单片机的RS232、RS422、RS485、USB、LWIP以太网、CAN等接口进行稳定通信。课程主要从MFC和STM32基础开始,以编写上位机以及下位机为主,非常注重实践。

    9306 人正在学习 去看看 王凯杰

上百篇原创人工智能系列教程,从理论到实战,手把手带你掌握人工智能,点击☞这里☜进入传送门~

 

  在单片机项目开发中,上位机也是一个很重要的部分,主要用于数据显示(波形、温度等)、用户控制(LED,继电器等),下位机(单片机)与 上位机之间要进行数据通信的两种方式都是基于串口的:

  • USB转串口 —— 上位机和下位机通过USB转串口连接线直接相连进行数据交互;
  • 串口转WIFI(ESP8266) ——  上位机和下位机基于TCP/IP协议通过WIFI传输数据;
  • 串口转蓝牙(HC-06)—— 不多用,暂不介绍;

  上位机软软件开发主要包括以下两种:

  1、Windows上位机(EXE可执行程序)

     在Windows上,最早用VB语言开发,后来由于C++的发展,采用MFC开发,近几年,微软发布了基于.NET框架的面向对象语言C#,更加稳定安全,再配合微软强大的VS进行开发,效率奇高;

    另外,如果想要在Linux上跨平台运行,可以选用Qt;如果想要更加丰富好看的数据显示界面,可以选用Labview开发;

  2、Android上位机(APP)

    在Android操作系统上,主要采用Java语言,使用WIFI或者蓝牙基于TCP/IP协议传输数据,利用Android Studio开发;

  在此,我们主要介绍如何通过VS + C#开发电脑上位机,其它上位机的开发暂且不论。

 

 注:VS下载与安装参考这篇较详细的博客

   https://blog.csdn.net/qq_36556893/article/details/79430133

 

2014-10-05 00:53:24 DevinTT 阅读数 3225
  • MFC上位机与STM32下位通讯精讲

    本课程主要介绍C++类库MFC上位机与STM32单片机的RS232、RS422、RS485、USB、LWIP以太网、CAN等接口进行稳定通信。课程主要从MFC和STM32基础开始,以编写上位机以及下位机为主,非常注重实践。

    9306 人正在学习 去看看 王凯杰

为了方便大家学习,工程已打包上传,http://download.csdn.net/detail/devintt/8029477


安卓设备一般都配备了蓝牙模块,我们可以使用蓝牙模块和一些外设进行数据交换,并且在安卓设备上处理和显示出来。

 

蓝牙编程:主要使用到系统提供的BroadcastReceiver使得我们可以对蓝牙模块接收到的数据进行广播接收。


蓝牙操作第一步就是检查蓝牙状态和打开蓝牙设备

        /**
	 * 打开buletooth
	 */
	private void openBluetoothSettings() {
		bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
		if (!bluetoothAdapter.isEnabled()) { // 蓝牙未开启,则开启蓝牙
			Intent enableIntent = new Intent(
					BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
		} else {
			IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
			receiver = new BluetoothReceiver();
			registerReceiver(receiver, filter);
			Toast.makeText(MainActivity.this, "open buletooth success",
					Toast.LENGTH_LONG).show();
			bluetoothAdapter.startDiscovery();
			Toast.makeText(MainActivity.this, "searching", Toast.LENGTH_LONG)
					.show();
		}
	}

再注册蓝牙广播接收BroadcastReceiver

private class BluetoothReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			Log.e("TAG", "onReceive");
			String action = intent.getAction();
			if (BluetoothDevice.ACTION_FOUND.equals(action)) {
				// Toast.makeText(MainActivity.this, "ACTION_FOUND",
				// Toast.LENGTH_LONG).show();
				BluetoothDevice device = intent
						.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				if (isLock(device)) {
					Toast.makeText(MainActivity.this, "isLock",
							Toast.LENGTH_LONG).show();
					devices.add(device.getName() + " : " + device.getAddress());
					Log.e("TAG", "isLock");
				} else {
					devices.add(device.getName());
					Log.e("TAG", "device.getName()");
				}
				deviceList.add(device);
			}
			showDevices();
		}
	}

以下两个方法可以不使用

用于锁定指定的蓝牙设备

        private boolean isLock(BluetoothDevice device) {
		boolean isLockName = (device.getName()).equals(lockName);
		boolean isSingleDevice = devices.indexOf(device.getName()) == -1;
		return isLockName && isSingleDevice;
	}

用于被其他蓝牙设备可搜索到

        private void showDevices() {
		Log.e("TAG", "showDevices");
		// Toast.makeText(MainActivity.this, "showDevices",
		// Toast.LENGTH_LONG).show();
		ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, devices);
		listView.setAdapter(arrayAdapter);
	}

接下来新建一个类,用于蓝牙连接、发送、接收和运行线程,将接收到的数据用masssage发送到UI进程,更新UI。

 

这是用于连接蓝牙设备,由于通信是耗时操作,这里为了不堵塞UI线程,新建了一个线程。

public void connect(final String message) {
		Thread threadConnect = new Thread(new Runnable() {

			public void run() {
				BluetoothSocket tmp = null;
				Method method;

				try {
					method = device.getClass().getMethod("createRfcommSocket",
							new Class[] { int.class });
					tmp = (BluetoothSocket) method.invoke(device, 1);
					Log.d("TAG", device.getName()+" : "+device.getAddress());
				} catch (Exception e) {
					setState(CONNECT_FAILED);
					Log.e("TAG", "fail creat: " + e.toString());
				}
				socket = tmp;
				try {
					socket.connect();
					isConnect = true;
					Log.d("TAG", "socket connected");
					setState(CONNECT_SUCCESS);
				} catch (Exception e) {
					setState(CONNECT_FAILED);
					isConnect = false;
					Log.e("TAG", "fail connect: " + e.toString());
				}
			}
		});
		threadConnect.start();
	}

这是用于发送信息,使用OutputStream以流输出,单片机可以直接接收。注意的是,安卓蓝牙波特率9800,1位停止位,无校验,这是不能修改的,也是默认的。

public void chatOUT(String msg) {
		if (isConnect) {
			Log.e("TAG", "chatOUT...");
				try {
					OutputStream outStream = socket.getOutputStream();
					Log.d("DATA", "output: " + msg.length());
					//outStream.write(getHexBytes(msg));
					outStream.write(msg.getBytes());
				} catch (IOException e) {
					setState(WRITE_FAILED);
					Log.e("TAG", "fail send: " + e.toString());
				}
//			}
		}
	}

蓝牙接收是耗时操作,用一个线程进行长链接,以BufferedInputStream流读取,将接收到的数据用masssage发送到UI进程,更新UI。

	public void chatIN() {
		Thread threadChat = new Thread(new Runnable() {
			public void run() {
				if (isConnect) {
					Log.e("TAG", "chatIN...");
					try {
						BufferedInputStream inputStream =new BufferedInputStream(socket.getInputStream());
						while (true) {
							try {
								char buff = (char) inputStream.read();
									Message msg = handler.obtainMessage();
									msg.what = DATA;
									msg.obj = data;
									handler.sendMessage(msg);
									data = "";
//								Log.e("DATA", "input: " + buff);
								
							} catch (IOException e) {
								setState(READ_FAILED);
								Log.e("TAG", "fail get: " + e.toString());
								break;
							}
						}
					} catch (IOException e) {
						setState(WRITE_FAILED);
						Log.e("TAG", e.toString());
					}
				}

				if (socket != null) {
					try {
						socket.close();
					} catch (IOException e) {
						Log.e("TAG", "fail close: " + e.toString());
					}
				}
				
			}

		});
		threadChat.start();
	}

为了方便大家学习,工程已打包上传,http://download.csdn.net/detail/devintt/8029477


没有更多推荐了,返回首页