pzsb的笔记 https://bbs.21ic.com/?551778 [收藏] [复制] [RSS] 新手上路  大家多多指教!

日志

RS232串口通信字节方式

已有 2011 次阅读2009-4-4 09:09 |个人分类:串行通信|系统分类:通信网络| RS232, 串口通信, 字节方式

两个程序一样的,只是使用的串口不同:一个使用COM3,一个使用COM4


COM3,COM4是计算机上添加的一对虚拟串口


打开两个程序,它们之间可以通信:一方请求数据,一方回应数据


请求数据帧格式: 帧长度(6),命令特征码(00H),起始值,字节数,增量,检验和
回应数据帧格式: 帧长度, 数据特征码(FFH),……数据场……,检验和



程序设计概述
界面设计(纸上画出界面图)
制作界面(在对话框中添加控件,控件布局,命名ID,为控件添加变量)
全局常数和变量定义,
函数声明和打框架(未实现的部分使用“占位符”)


逐步实现
结合串口调试助手调试


代码如下(工程名RS232,字节通信)


/////////////////////////////////////////////////////////////////////


// 常数定义及全局变量说明
unsigned char RxData[1024]; // 接收数据存储区
static int SavePointer=0; // 数据存储指针
unsigned char TxData[1024]; // 发送数据存储区



// 初始化对话框 中 初始化串口
BOOL CRS232Dlg::OnInitDialog()
{
 CDialog::OnInitDialog();


 ……
 // TODO: Add extra initialization here
 // 增加:串口初始化代码
 m_Comm.SetCommPort(4);  //
 if(!m_Comm.GetPortOpen()) //
  m_Comm.SetPortOpen(TRUE);
 m_Comm.SetInputMode(1);   // 设置输入方式为二进制方式 )
 m_Comm.SetSettings("4800, n, 8, 1"); // 设置波特率等参数
 m_Comm.SetRThreshold(1);  // 当串口接收缓冲区中有≥1个字符时将引发一个
            // 关于接收数据Oncomm事件
 m_Comm.SetInputLen(0);      // 每次读取缓冲区中 所有数据
 m_Comm.GetInput();       // 先预置缓冲区以清除残留数据
 //_________________________________________________________


 
 return TRUE;  // return TRUE  unless you set the focus to a control
}


// 发送按钮单击消息响应
void CRS232Dlg::OnButtonTrans()
{
 // TODO: Add your control notification handler code here
 // 为发送按钮添加鼠标单击消息处理函数
 UpdateData(TRUE); // 获取用户输入的数据
 TxData[0]=0x06;  // 命令帧长度为6
 TxData[1]=0x00;  // 命令帧特征码为00H
 TxData[2]=m_Init; // 指定数据初始值
 TxData[3]=m_Size; // 指定数据长度值
 TxData[4]=m_Step; // 指定数据增量值
 Transmitt();  // 发送命令
}



// 发送函数
void CRS232Dlg::Transmitt()
{
 int i;
 unsigned char sum=0, count;
 CByteArray array;   // 定义字节数组
  
 count=TxData[0];   // 帧长度
 for(i=0; i<count-1; i++)  // 计算无进位校验和
  sum+=TxData;
 TxData[count-1]=sum;
 array.RemoveAll();   ////
 array.SetSize(count);
 for(i=0; i<count; i++)   // 待发送数据放入字节数组
  array.SetAt(i, TxData);
 if(!m_Comm.GetPortOpen())  // 打开串口
  m_Comm.SetPortOpen(TRUE);
 m_Comm.SetOutput(COleVariant(array)); // 由字节数组获得变体类型变量,放入发送缓冲区
 // 显示发送的数据
 char str[10];
 m_Tdata="";
 for(i=0; i<count; i++)  
 {
  sprintf(str, "%02X,", TxData); // HEX格式
  m_Tdata+=str;
 }
 UpdateData(FALSE);
}


// 串口消息响应函数
void CRS232Dlg::OnComm()
{
 // TODO: Add your control notification handler code here
 VARIANT vResponse;
 int k;
 if(m_Comm.GetCommEvent()==2) // 如果是接收事件
 {
  k=m_Comm.GetInBufferCount(); // 接收缓冲区中数据长度
  if(k>0)
  {
   m_Comm.SetInputLen(k);  // 设置读取长度
   vResponse=m_Comm.GetInput();// 读接收缓冲区
   SavaData(k,(unsigned char*)vResponse.parray->pvData); // 存储数据(自定义函数)
  }
 }
}


// 保存接收到的数据
void CRS232Dlg::SavaData(int count, unsigned char *pbval)
{
 int i;
 for(i=0; i<count; i++)
  RxData[SavePointer+i]=pbval;
 SavePointer+=count;
 if(SavePointer>=RxData[0]) // 接收到一帧,处理
  ProcessData();
}


// 接收数据处理
// 最后的代码显示有点紊乱,它是怕断断续续接收两帧,顾及第2帧吧。
void CRS232Dlg::ProcessData()
{
 int i, count;
 unsigned char sum=0;
 char str[10];
 count=RxData[0];
 for(i=0; i<count-1; i++)
  sum+=RxData;
 if(sum!=RxData[count-1])
 {
  MessageBox("ERROR! 接收数据检验和错误!");
  m_Comm.SetOutBufferCount(0); //
  SavePointer=0;
 }
 else
 {
  int len;
  unsigned char step;
 // MessageBeep(0xFFFFFFFF); ////
 // system("pause");
  if(RxData[1]==0)  // 命令帧的特征码
  {
   
   TxData[0]=RxData[3]+3; // 数据帧长度(帧长度,特征码,数据,检验和)
   TxData[1]='\xFF';  // 数据帧特征码为FFH
   TxData[2]=RxData[2]; // 数据初值
   len=RxData[3];   // 数据长度
   step=RxData[4];  // 数据增量
   for(i=3; i<TxData[0]-1; i++)
   TxData=TxData[i-1]+step;
   // 显示接收数据
   for(i=0; i<count; i++) //
   {
    sprintf(str, "%02X,", RxData);
    m_Rdata+=str;
   }
   // 发送请求的数据
   Transmitt();
  }


  m_Rdata="";
  for(i=0; i<count; i++)   //
  {
   sprintf(str, "%02X,", RxData);
   m_Rdata+=str;
  }


  UpdateData(FALSE);
  for(i=0; i<SavePointer-count; i++) //
   RxData=RxData[count+i];
  SavePointer-=count;   //
 }
}


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)