资源描述
C语言与通讯数据处理实验报告
一、 实验目的
1、熟悉c语言的编译,链接和运行过程
2、掌握c语言的数据类型,熟悉整型,实型,字符型变量的定义方式与赋值,掌握不同类型数据之间赋值规则和赋值方法
3、掌握数组的定义,赋值引用及输入输出方法,并正确用字符数组储存字符串,学会字符串的使用
4、掌握结构体变量的定义和使用
5、掌握指针变量和指向指针的指针变量的定义及使用
6、熟悉通讯数据的处理规则及不同处理方法的优缺点
7、掌握VS中简单的界面编辑能力及编辑框的关联变量的定义
二、 实验平台:
Microsoft Visual Studio 2010
三、 实验内容
1、编写界面,在预先给定的对话框中添加静态文本框和编辑框,设置静态文本框内容和编辑框的关联变量,变量保存在ComDateProcessDlg.h文件中
2、按钮编辑
1)、发送按钮
将不同格式数据赋给预先定义的对应格式的变量之中
2)、接收按钮
将发送按钮中已赋值的变量中数据赋值给界面编辑框相对应的关联变量
3、调试程序
四、 实验步骤
1、了解通讯协议
数据格式如下:
地址码
长度
状态量
无符号整数
符号
整数
无符号长整数
符号长整数
无符号
定点小数
浮点数
双精
度数
校验码
1字节
1字节
2字节
2字节
2字节
4字节
4字节
2字节
4字节
8字节
1字节
说明:
1)、状态量定义如下:
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
状态码
保留
开关7
开关6
开关5
开关4
开关3
开关2
开关1
2)、无符号定点小数定义如下:
高9位:整数,低7位:小数
3)、校验码:
为校验码之前所有字节的求和。
2、 界面编辑
在界面添加静态文本框以及编辑框,编辑文本框内容与编辑框将显示的数据一一对应,并为每个编辑框添加对应的关联变量,优化界面。
3、发送和接收数据处理:
打开ComDataProcessDlg,cpp文件对按钮进行编译
1)、首先定义中间变量,即通讯数据的储存变量
unsigned short *pishort;
float *pf;
unsigned long *pulong;
long *plong;
…
2)、运用指针变量进行赋值:
sendbuf[0]=0x01;//地址号
sendbuf[1]=31;//数据帧长度
pishort=(unsigned short *)(sendbuf+2);
*pishort=0xf03e;//状态码
pishort=(unsigned short *)(sendbuf+4);
*pishort=255;
---
3)、状态量处理:
状态量前五位为状态码,后为七位开关变量,中间四位保留
首先定义变量
unsigned char sw1,sw2,…sw7;
unsigned char statecode;
unsigned short statecode16;//16位临时状态变量
unsigned short status;//前面定义的状态变量
……
状态码及开关的获取:用关系运算符“&”来选择位置,并用移位运算符“>>”将高位数字移至最低位
statecode16= status&0xf800;//1111 1000 0000 0000
statecode= (unsigned char)(statecode16>>11);
statecode16= status&0x0040;//0000 0000 0100 0000
sw7= (unsigned char)(statecode16>>6);
……
4)、定点小数的转化:
在给中间变量赋值时,先给定点小数赋一个无符号整形变量,在编写接收按钮时除以2^n确定小数点的位置,即将小数点前移n位
m_fixeddecimal=(float)(16 utmp)/128.0f
5)、方法缺陷:
由于使用了数组指针进行赋值,对每个变量的位置和长度也就固定了下来,所以对于数据类型的修改会比较困难
4、 了解并应用通讯协议的数据结构
针对上述问题,可使用结构变量进行优化
1)、结构的重要特征:
(1)、数据集中存放
(2)、数据按定义的先后顺序存放
2) 、结构体字节对齐规则
(1)、结构体成员按低地址到高地址的顺序储存在内存,即按声明的顺序储存
(2)、每个成员的地址必须满足:是sizeof(该成员)的整数倍
(3)、总的字节数是最大内置(就是基本类型)成员所占字节的整数倍
为满足以上规则,通讯协议改进如下:
地址码
长度
状态量
无符号整数
符号
整数
无符号长整数
符号长整数
双精
度数
浮点数
无符号
定点小数
校验码
1字节
1字节
2字节
2字节
2字节
4字节
4字节
8字节
4字节
2字节
1字节
3) 、首先,新建一个头文件”struct.h”,在文件中定义结构体:
---
struct Comm_Data
{
unsigned char addr;
unsigned char len;
STATE_BITS states;
unsigned short uishort;
short ishort;
unsigned long uilong;
long ilong;
double dtmp;
float ftmp;
unsigned short uffix;
unsigned char check;
};
---
4)、在ComDataProcessDlg.h文件开头加入” #include”struct.h” ”以调用struct.h文件中的内容,增加两个用于发送和接收的全局变量Comm_Data_Unioncomm_data_Send和Comm_Data_Unioncomm_data_Rcv
。打开omDataProcessDlg.cpp文件对发送和接收按钮进行编写:
comm_data_S_data.addr=2;
comm_data_S_data.len=30;
---
m_addr=comm_data_R_data.addr;
m_length=comm_data_R_data.len;
---
注:对于定点小数的处理同上,不再重复说明
五、 实验结果及分析
本次试验运用了两种方法进行通讯数据处理。第一种方法因为用了指针,发送和接收按钮变量赋值都有顺序要求,第二种由于定义结构体时已有顺序,所以赋值时没有这个要求;第一种状态码的开关要用&控制赋值,第二种所有变量都可以直接赋值;第一种对于协议的数据类型顺序没有要求,第二种结构体变量要满足字节对齐规则的要求。
// ComDataProcessDlg.h : header file
//
#include"struct.h"
#pragmaonce
// CComDataProcessDlg dialog
classCComDataProcessDlg : publicCDialogEx
{
// Construction
public:
//---------请在这里定义变量和函数-----------------------------
unsignedcharsendbuf[1024];//发送缓冲区
unsignedcharrecvbuf[1024];//接收缓冲区
unsignedcharGetCheckSum(unsignedchar *pStartPos,int length);//生¦¨²成¨¦一°?个?字Á?节¨²的校¡ê验¨¦码?---求¨®和¨ª
Comm_Data_Unioncomm_data_Send;
Comm_Data_Unioncomm_data_RCV;
//---------定义变量和函数结束---------------------------------
CComDataProcessDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_COMDATAPROCESS_DIALOG };
protected:
virtualvoidDoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msgvoidOnSysCommand(UINT nID, LPARAM lParam);
afx_msgvoidOnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msgvoidOnBnClickedButtonSend();
afx_msgvoidOnBnClickedButtonReceive();
CStringm_SendString;
BYTE m_addr;//界?面?上显示º地址¡¤”¡À的变量
BYTE m_len;//界?面?上显?示º长度¨¨”¡À的变量
doublem_double;//界?面?上显?示º双精?度¨¨数的变量
floatm_fixeddecimal;//界?面?上显?示º无T符号?定¡§点小?数的变量
floatm_float;//界?面?上显?示º浮?点数的变量
longm_long;//界?面?上显?示º符号?长¡è整?数的变量
DWORD m_ulong;//界?面?上显?示º无T符号?长¡è整?数的变量
shortm_unsignedint;//界?面?上显?示º无T符号?整?数的变量
shortm_short;//界?面?上显示º符号?整?数的变量
BYTE m_state;//界?面?上显?示º状态码的变量
BYTE m_SW1;//界?面?上显?示º开a关?1”¡À的变量
BYTE m_SW2;//界?面?上显?示º开a关的变量
BYTE m_SW3;//界?面?上显?示º开a关的变量
BYTE m_SW4;//界?面?上显?示º开a关的变量
BYTE m_SW5;//界?面?上显?示º开a关的变量
BYTE m_SW6;//界?面?上显?示º开a关的变量
BYTE m_SW7;//界?面?上显?示º开a关的变量
BYTE m_check;//界?面?上显?示º校¡ê验¨¦码的变量
};
#define TotalLen 31//定义通讯数据总长度
struct STATE_BITS
{
unsignedshort SW1:1;
unsignedshort SW2:1;
unsignedshort SW3:1;
unsignedshort SW4:1;
unsignedshort SW5:1;
unsignedshort SW6:1;
unsignedshort SW7:1;
unsignedshort reserved:4;
unsignedshort statecode:5; 自建的头文件
};
struct Comm_Data
{
unsignedchar addr;
unsignedchar len;
STATE_BITS states;
unsignedshort uishort;
short ishort;
unsignedlong uilong;
long ilong;
double dtmp;
float ftmp;
unsignedshort uffix;
unsignedchar check;
};
union Comm_Data_Union
{
Comm_Data com_data;
unsignedchar buf[TotalLen];
};
发送按钮
//----------发¤¡é送¨ª按ã¡ä钮£¤消?息¡é响¨¬应®|函¡¥数ºy------------------------------------
void CComDataProcessDlg::OnBnClickedButtonSend()
{
// TODO: Add your control notification handler code here
comm_data_S_data.addr=0x02;
comm_data_S_data.len=31;
comm_data_S_data.states.SW1 =1;
comm_data_S_data.states.SW2 =1;
comm_data_S_data.states.SW3 =1;
comm_data_S_data.states.SW4 =1;
comm_data_S_data.states.SW5 =0;
comm_data_S_data.states.SW6 =0;
comm_data_S_data.states.SW7 =0;
comm_data_S_data.states.reserved =0;
comm_data_S_data.states.statecode =14;
comm_data_S_data.uishort =234;
comm_data_S_data.ishort =-123;
comm_data_S_data.uilong =123456;
comm_data_S_data.ilong =-123456;
comm_data_S_data.uffix =0x00c0;
comm_data_S_data.ftmp =333.444f;
comm_data_S_data.dtmp =-777.88888;
comm_data_S_data.check =GetCheckSum(comm_data_Send.buf ,TotalLen-1);
for(int i=0;i<TotalLen;i++)
{
sendbuf[i]=comm_data_Send.buf[i];
}
CString str=_T("");
CString strtmp;
for(int i=0;i<TotalLen;i++)
{
strtmp.Format (_T("%.2x "),sendbuf[i] );
str=str+strtmp;
}
m_SendString=str;
UpdateData(false);
}
接收按钮
void CComDataProcessDlg::OnBnClickedButtonReceive()
{
// TODO: Add your control notification handler code here
for(int i=0;i<TotalLen;i++)
{
recvbuf[i]=sendbuf[i];
}
BYTE check1=GetCheckSum(recvbuf,TotalLen-1);
if(check1!=recvbuf[TotalLen-1])return;
for(int i=0;i<TotalLen;i++)
{
comm_data_RCV.buf[i]=recvbuf[i];
}
m_addr=comm_data_RCV.com_data .addr;
m_len=comm_data_RCV.com_data.len;
m_state=comm_data_RCV.com_data.states.statecode;
m_SW1=comm_data_RCV.com_data.states.SW1;
m_SW2=comm_data_RCV.com_data.states.SW2;
m_SW3=comm_data_RCV.com_data.states.SW3;
m_SW4=comm_data_RCV.com_data.states.SW4;
m_SW5=comm_data_RCV.com_data.states.SW5;
m_SW6=comm_data_RCV.com_data.states.SW6;
m_SW7=comm_data_RCV.com_data.states.SW7;
m_unsignedint=comm_data_RCV.com_data.uishort;
m_short=comm_data_RCV.com_data.ishort;
m_ulong=comm_data_RCV.com_data.uilong;
m_long=comm_data_RCV.com_data.ilong;
unsignedshort u16tmp=comm_data_RCV.com_data.uffix;
m_fixeddecimal=(float)(u16tmp)/128.0f;
m_float=comm_data_RCV.com_data.ftmp;
m_double=comm_data_RCV.com_data.dtmp;
m_check=comm_data_RCV.com_data.check;
UpdateData(false);
}
unsignedchar CComDataProcessDlg::GetCheckSum(unsignedchar *pStartPos,int length)
{
unsignedchar sum=0;
for(int i=0;i<length;i++)
{
sum=sum+*(pStartPos+i);
}
return sum;
}
实验结果
五、 实验总结
展开阅读全文