欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

VS2015+Win32API串口通信函数与Arduino通信

程序员文章站 2022-06-29 23:43:38
...

实现上位机与Arduino板子的串口通信,读写均可,上位机用VS2015实现,Arduino型号是mega2560,亲测可用。有问题可以写在评论区,看到都会回复,这是我的第一篇分享博客,如果对你有用的话,请点个赞吧~

VS2015新建Win32控制台项目,只需要额外添加一个源文件即可。代码如下

// ConsoleSerial.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include "windows.h"
#include <stdio.h> 
#include <conio.h> 
#include <math.h>
#include<fstream>
#include<iostream>

using namespace std;

HANDLE hDevice = CreateFile(L"\\\\.\\COM4",  //注意COM1~COM10与COM10以上的窗口的命名规则
	GENERIC_READ | GENERIC_WRITE,   //使用读写方式
	0,
	0,
	OPEN_EXISTING,
	0,
	0);
BOOL Serial_open()
{
	SetupComm(hDevice, 1024, 1024); //输入缓冲区和输出缓冲区的大小都是1024 
	COMMTIMEOUTS TimeOuts;
	TimeOuts.ReadIntervalTimeout = 1000;
	TimeOuts.ReadTotalTimeoutMultiplier = 500;
	TimeOuts.ReadTotalTimeoutConstant = 5000; 
	//设定写超时
	TimeOuts.WriteTotalTimeoutMultiplier = 500;
	TimeOuts.WriteTotalTimeoutConstant = 2000;
	SetCommTimeouts(hDevice, &TimeOuts);

	DCB lpTest;
	GetCommState(hDevice, &lpTest);  //获取当前的参数设置
	lpTest.BaudRate = CBR_9600;       //设置波特率
	lpTest.ByteSize = 8;              //数据位数为8
	lpTest.Parity = NOPARITY;         //无校验
	lpTest.StopBits = ONESTOPBIT;   //1位停止位
	SetCommState(hDevice, &lpTest);  //设置通信参数
	PurgeComm(hDevice, PURGE_TXCLEAR | PURGE_RXCLEAR);
	return true;
}

int Serial_read(char str[], int size)    //同步读串口
{

	DWORD rCount=0;    //读取的字节数
	BOOL bReadStat;
	while(rCount<6)
	bReadStat = ReadFile(hDevice, str, size, &rCount, NULL);
	printf("read_success\n");
	if (!bReadStat)
	{
		printf("读串口失败!\n");
		return FALSE;
	}
	return rCount;
}

BOOL Serial_write(char test[])
{
	DWORD btsIO;
	char a=0;
	while (true)
	{
		a++;
		WriteFile(hDevice,test , strlen(test), &btsIO, NULL);    //发送数据
		Sleep(2000);    
		if (a == 3)
			break;
	}
	PurgeComm(hDevice, PURGE_TXCLEAR | PURGE_RXCLEAR);
	return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
	char test[] = "1";  //点亮
	char test2[] = "0";
	char for_read[100];
	int len;
	double value=0;
	int input;
	if (hDevice != INVALID_HANDLE_VALUE)
	{
		
		Serial_open();
		printf("Port opened!\n");
		Sleep(500);
		Serial_write(test);
		printf("write_success\n");
		while (1)
		{
			printf("开始读\n");
			len = Serial_read(for_read, 100);
			PurgeComm(hDevice, PURGE_TXCLEAR | PURGE_RXCLEAR);
			value = 0;
			if (len)
			{
				printf("len=%d\n", len);
				for (size_t j = 0; j<len; j++)
				{
					printf("read %d\n", for_read[j] - 1);

					value = value + (for_read[j] - 1)*pow(10, j);
				}
				printf("value=%f\n", value);
			}
			ofstream out("D:\\data.txt");
			out << value;
			out.close();
			Sleep(500);
			//Serial_write(test);
			
			ifstream in("D:\\输入.txt");
			in >> input;
			printf("input=%d\n", input);
			if (input)
			{
				Serial_write(test);
				printf("write test success\n");
			}
			else
			{
				Serial_write(test2);
				printf("write test2 success\n");
			}
				
			in.close();
		}
		CloseHandle(hDevice);    //关闭串口 
	}
	system("pause");
	return 0;
}

Serial_open()函数实现打开串口,并配置一些串口参数。

Serial_read()函数实现读取串口,代码中会将串口读到的数据位数len,每一位的数值和所有位拼在一起组成的数字的值value显示出来。并将value值实时保存在D盘的data.txt文件中。

Serial_write()函数实现写串口,代码会将D盘的输入.txt文件中的数值赋给input变量,并根据它的值来写串口。

这是一个实时更新的系统,读写操作都在循环中进行。

 

Arduino端的代码如下:

char buff2[6]={1,1,1,2,4,6};
char a=0;
int i;
int data=4911;
int data2=4911;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(13, OUTPUT);

  for(i=5;i>=0;i--)
  {
    buff2[i]=(data%10)+1;
    data=data/10;
    Serial.write(buff2[i]);
  }
  
  
}

void loop() {
  
  delay(10000);//每10s发送一次数据
  // put your main code here, to run repeatedly:
 
  data2++;
  data=data2;
  if(data>14911)//这个14911是随便设的
  {data=0;
  data2=0;
  }

  for(i=5;i>=0;i--)
  {
    buff2[i]=(data%10)+1;
    data=data/10;
    Serial.write(buff2[i]);
    //delay(100);
  }
  
  while(Serial.available())
  {
    a=Serial.read();
  }
  if(a=='1')
  digitalWrite(13, HIGH);
  if(a=='0')
  digitalWrite(13,LOW);
}

 Arduino每10s给上位机传一个data值,并且逐次加1,同时单片机会根据上位机传给自己的值对led灯进行点亮或者熄灭操作。

 

要注意的问题:

1. 当Arduino板子刚接到电脑上时,运行VS程序,虽然提示串口会打开,但是读写操作均不能进行,原因我没找到,但是先打开串口助手软件,将连接单片机的串口手动打开可以解决这个问题,我也不知道为什么,菜鸡哭了。

其他问题暂时没想到,想到会补充。