c语言串口收发数据VS2013
2017-11-27 10:48
267 查看
最近师兄师姐在做GPS定姿的项目,需要把天线解算的结果从电脑串口发送出去,对于VS和C语言小白的我承担了把数据从串口发送出去的任务。网上串口通讯的例子倒是不少,在发送数据方面,下的功夫倒也不是很多,主要是老师还让我把数据接收下来校验发送的对不对,于是开始了调试代码的不归路,现在把我的过程记录下来,代码供大家参考。首先是把数据发送出去,发送数据协议是自己定义的,一个数据头2个字节,20个字节数据位,2个字节CRC校验位,每个数据共24字节的数据。
void main(){
/*****************************打开串口*************************************/
HANDLE hCom;//全局变量,串口句柄
hCom = CreateFile(_T("COM2"),//COM1口
GENERIC_READ | GENERIC_WRITE,//允许读和写
0,//独占方式
NULL,
OPEN_EXISTING,//打开而不是创建
0,//同步方式
//FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERAPPLE,//重叠方式
NULL);
if (hCom == (HANDLE)-1)
{
printf("打开COM失败!");
return ;
}
/*********************************配置串口*********************************/
SetupComm(hCom, 20480, 20480);//输入缓冲区和输出缓冲区的大小都是20480
COMMTIMEOUTS TimeOuts;
//设定读超时
TimeOuts.ReadIntervalTimeout = 1000;
TimeOuts.ReadTotalTimeoutMultiplier = 500;
TimeOuts.ReadTotalTimeoutConstant = 5000;
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier = 500;
TimeOuts.WriteTotalTimeoutConstant = 2000;
SetCommTimeouts(hCom, &TimeOuts);//设置超时
DCB dcb;
GetCommState(hCom, &dcb);
dcb.BaudRate = 115200;//波特率为115200
dcb.ByteSize = 8;//每个字节有8位
dcb.Parity = NOPARITY;//无奇偶校验位
dcb.StopBits = TWOSTOPBITS;//两个停止位
dcb.fParity = FALSE;
dcb.fNull = FALSE;
SetCommState(hCom, &dcb);
PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);//在读写串口之前清空缓冲区
/******************************同步写串口*************************************/
unsigned long temp = 0;
short int crc;
unsigned char i;
short int MessageLen = 20;//数据头:数据长度,不包括数据头和校验位
short int Hour = (Result.ultime / 3600 + 8) % 24;//要发送的数据,时分秒
short int Minute = (Result.ultime % 3600) / 60;
short int Sceond = Result.ultime % 60;
short int SVNnum = Result.SVN;//卫星个数
float Len = Result.len;//基线长度
float Yaw = Result.dYaw;//航向角
float Pitch = Result.dPitch;//俯仰角
unsigned char result[100] = { 0 };//写入串口缓存区的数组
int len = sizeof(short int);
int len1 = sizeof(float);
//int len2 = sizeof(int);
memcpy(result, &MessageLen, len);
memcpy(result + len, &Hour, len);
memcpy(result + 2 * len, &Minute, len);
memcpy(result + 3 * len, &Sceond, len);
memcpy(result + 4 * len, &SVNnum, len);
memcpy(result + 5 * len, &Len, len1);
memcpy(result + 5 * len + len1, &Yaw, len1);
memcpy(result + 5 * len + 2 * len1, &Pitch, len1);
//计算出CRC校验码
char result_len = 22;
unsigned char *ptr = result;
while (result_len--){
for (i = 0x80; i != 0; i = i >> 1){
temp = temp * 2;
if ((temp & 0x10000) != 0)
temp = temp ^ 0x11021;
if ((*ptr & i) != 0)
temp = temp ^ (0x10000 ^ 0x11021);
}
ptr++;
}
crc = temp;
memcpy(result + 5 * len + 3 * len1, &crc, len1);
DWORD dwwrittenLen = 0;
if (!WriteFile(hCom, result, 24, &dwwrittenLen, NULL))
{
printf("发送数据失败!\n");
}
printf("Main Baseline往串口发送数据成功!");
/***********关闭串口***********/
CloseHandle(hCom);}
数据发送成功,主要是接收的程序调试了很久,一开始也是打算一个数据24个字节24个字节来循环接收,但是每组数据会在固定的第10-13个字节出错,一直搞不明白,后来在CSDN发帖,赵老师的帮助下,把接收数据改成8个字节8个字节来接收就没有问题了。非常感谢赵老师。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <conio.h>
#include "tchar.h"
int main()
{
HANDLE hCom1;
hCom1 = CreateFile(_T("COM1"),//COM1口
GENERIC_READ | GENERIC_WRITE,//允许读和写
0,//独占方式
NULL,
OPEN_EXISTING,//打开而不是创建
0,//同步方式
NULL);
if (hCom1 == (HANDLE)-1)
{
printf("打开COM失败!\n");
return FALSE;
}
else
{
printf("COM打开成功!\n");
}
SetupComm(hCom1, 20480, 20480);//输入缓冲区和输出缓冲区的大小都是1024
COMMTIMEOUTS TimeOuts;
//设定读超时
TimeOuts.ReadIntervalTimeout = 1000;
TimeOuts.ReadTotalTimeoutMultiplier = 500;
TimeOuts.ReadTotalTimeoutConstant = 5000;
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier = 500;
TimeOuts.WriteTotalTimeoutConstant = 2000;
SetCommTimeouts(hCom1, &TimeOuts);//设置超时
DCB dcb1;
GetCommState(hCom1, &dcb1);
dcb1.BaudRate = 115200;//波特率为9600
dcb1.ByteSize = 8;//每个字节有8位
dcb1.Parity = NOPARITY;//无奇偶校验位
dcb1.StopBits = TWOSTOPBITS;//两个停止位
//dcb1.fParity = FALSE;
//dcb1.fNull = FALSE;
SetCommState(hCom1, &dcb1);
DWORD wCount=8;//读取的字节数
PurgeComm(hCom1, PURGE_TXCLEAR | PURGE_RXCLEAR);//清空缓冲区
while (1)
{
unsigned char str[8];
if (!ReadFile(hCom1, str, wCount, &wCount, NULL))
{
printf("读串口失败!");
return FALSE;
}
FILE *fp1;
fp1 = fopen("串口发送的数.txt", "a+");
int i = 0;
for (i = 0; i < wCount; i++)
{
printf("读串口成功!读取数据为: %02X \n", str[i]);
fprintf(fp1, "%02X ", str[i]);
}
fclose(fp1);
}
CloseHandle(hCom1);
}
最后 就是将发送的数据和接收的数据放到TXT文件里进行了比对,完全没有问题。
void main(){
/*****************************打开串口*************************************/
HANDLE hCom;//全局变量,串口句柄
hCom = CreateFile(_T("COM2"),//COM1口
GENERIC_READ | GENERIC_WRITE,//允许读和写
0,//独占方式
NULL,
OPEN_EXISTING,//打开而不是创建
0,//同步方式
//FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERAPPLE,//重叠方式
NULL);
if (hCom == (HANDLE)-1)
{
printf("打开COM失败!");
return ;
}
/*********************************配置串口*********************************/
SetupComm(hCom, 20480, 20480);//输入缓冲区和输出缓冲区的大小都是20480
COMMTIMEOUTS TimeOuts;
//设定读超时
TimeOuts.ReadIntervalTimeout = 1000;
TimeOuts.ReadTotalTimeoutMultiplier = 500;
TimeOuts.ReadTotalTimeoutConstant = 5000;
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier = 500;
TimeOuts.WriteTotalTimeoutConstant = 2000;
SetCommTimeouts(hCom, &TimeOuts);//设置超时
DCB dcb;
GetCommState(hCom, &dcb);
dcb.BaudRate = 115200;//波特率为115200
dcb.ByteSize = 8;//每个字节有8位
dcb.Parity = NOPARITY;//无奇偶校验位
dcb.StopBits = TWOSTOPBITS;//两个停止位
dcb.fParity = FALSE;
dcb.fNull = FALSE;
SetCommState(hCom, &dcb);
PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);//在读写串口之前清空缓冲区
/******************************同步写串口*************************************/
unsigned long temp = 0;
short int crc;
unsigned char i;
short int MessageLen = 20;//数据头:数据长度,不包括数据头和校验位
short int Hour = (Result.ultime / 3600 + 8) % 24;//要发送的数据,时分秒
short int Minute = (Result.ultime % 3600) / 60;
short int Sceond = Result.ultime % 60;
short int SVNnum = Result.SVN;//卫星个数
float Len = Result.len;//基线长度
float Yaw = Result.dYaw;//航向角
float Pitch = Result.dPitch;//俯仰角
unsigned char result[100] = { 0 };//写入串口缓存区的数组
int len = sizeof(short int);
int len1 = sizeof(float);
//int len2 = sizeof(int);
memcpy(result, &MessageLen, len);
memcpy(result + len, &Hour, len);
memcpy(result + 2 * len, &Minute, len);
memcpy(result + 3 * len, &Sceond, len);
memcpy(result + 4 * len, &SVNnum, len);
memcpy(result + 5 * len, &Len, len1);
memcpy(result + 5 * len + len1, &Yaw, len1);
memcpy(result + 5 * len + 2 * len1, &Pitch, len1);
//计算出CRC校验码
char result_len = 22;
unsigned char *ptr = result;
while (result_len--){
for (i = 0x80; i != 0; i = i >> 1){
temp = temp * 2;
if ((temp & 0x10000) != 0)
temp = temp ^ 0x11021;
if ((*ptr & i) != 0)
temp = temp ^ (0x10000 ^ 0x11021);
}
ptr++;
}
crc = temp;
memcpy(result + 5 * len + 3 * len1, &crc, len1);
DWORD dwwrittenLen = 0;
if (!WriteFile(hCom, result, 24, &dwwrittenLen, NULL))
{
printf("发送数据失败!\n");
}
printf("Main Baseline往串口发送数据成功!");
/***********关闭串口***********/
CloseHandle(hCom);}
数据发送成功,主要是接收的程序调试了很久,一开始也是打算一个数据24个字节24个字节来循环接收,但是每组数据会在固定的第10-13个字节出错,一直搞不明白,后来在CSDN发帖,赵老师的帮助下,把接收数据改成8个字节8个字节来接收就没有问题了。非常感谢赵老师。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <conio.h>
#include "tchar.h"
int main()
{
HANDLE hCom1;
hCom1 = CreateFile(_T("COM1"),//COM1口
GENERIC_READ | GENERIC_WRITE,//允许读和写
0,//独占方式
NULL,
OPEN_EXISTING,//打开而不是创建
0,//同步方式
NULL);
if (hCom1 == (HANDLE)-1)
{
printf("打开COM失败!\n");
return FALSE;
}
else
{
printf("COM打开成功!\n");
}
SetupComm(hCom1, 20480, 20480);//输入缓冲区和输出缓冲区的大小都是1024
COMMTIMEOUTS TimeOuts;
//设定读超时
TimeOuts.ReadIntervalTimeout = 1000;
TimeOuts.ReadTotalTimeoutMultiplier = 500;
TimeOuts.ReadTotalTimeoutConstant = 5000;
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier = 500;
TimeOuts.WriteTotalTimeoutConstant = 2000;
SetCommTimeouts(hCom1, &TimeOuts);//设置超时
DCB dcb1;
GetCommState(hCom1, &dcb1);
dcb1.BaudRate = 115200;//波特率为9600
dcb1.ByteSize = 8;//每个字节有8位
dcb1.Parity = NOPARITY;//无奇偶校验位
dcb1.StopBits = TWOSTOPBITS;//两个停止位
//dcb1.fParity = FALSE;
//dcb1.fNull = FALSE;
SetCommState(hCom1, &dcb1);
DWORD wCount=8;//读取的字节数
PurgeComm(hCom1, PURGE_TXCLEAR | PURGE_RXCLEAR);//清空缓冲区
while (1)
{
unsigned char str[8];
if (!ReadFile(hCom1, str, wCount, &wCount, NULL))
{
printf("读串口失败!");
return FALSE;
}
FILE *fp1;
fp1 = fopen("串口发送的数.txt", "a+");
int i = 0;
for (i = 0; i < wCount; i++)
{
printf("读串口成功!读取数据为: %02X \n", str[i]);
fprintf(fp1, "%02X ", str[i]);
}
fclose(fp1);
}
CloseHandle(hCom1);
}
最后 就是将发送的数据和接收的数据放到TXT文件里进行了比对,完全没有问题。
相关文章推荐
- VS2013下串口数据char型转COleVariant问题
- linux环境下C语言实现非阻塞方式读取字符串数据的串口测试程序,即串口工具的编写
- 基于OK6410的串口数据收发
- VS2013中C#读取SQLite数据
- ZigBee单播通信原理、串口配置 (对于理解收发数据的过程非常重要)
- 基于QT5实现十六进制串口数据的收发
- vs2013运行c语言出现:无法查找或打开 PDB 文件。
- 用C语言socket RAW功能实现同一台主机两个网口间数据收发
- 20160426 VC++(VS2013)串口编程图文教程(MSComm的使用)
- c#串口收发数据
- VS2013编译C语言遇到Debug Assertion Failed! Expression:(str!=NULL)
- Linux下QT串口通过无线模块收发十六进制数据
- VS2013MFC对话框工程学习笔记六 - 了解C++的数据类型
- STM32F407的串口采用DMA收发数据
- stm32串口DMA收发,可以接收不定长数据,格式化输出。
- 浏览器中使用js调用Activex、NPAPI打开串口并收发数据
- 解决VS2013使用MySQL无法创建ADO.NET实体数据类型的问题
- vs2013 + QT组件开发串口程序
- 新手系列VS2013---C语言"金字塔图案"
- 英伟达tk1板的串口数据收发出错问题