(一) 串口的参数设置及打开
 

对RS-232-C串行端口进行参数配置是使用串口进行通讯的必要条件。而且由于场合不同、用途、功能的不同对串口也采取不同的配置方式,为了使本程序更灵活,适应面更广,采取将所有的可能参数都预先设置在几个组合框中,可以在程序运行后随时更改设置。自定义一个设置串口参数的数据结构:

typedef struct tagCOM_CONFIG
{
int nPort; file://端口号,从COM1到COM4
int nBaud; file://波特率,从1200bps到57600bps(对应的宏为CBR_1200到CBR_57600)
int nData; file://数据位个数,7位或是8位
int nStop; file://停止位个数,可以是1位、1.5位、2位。
int nParity;//采取的校验方式,有无校验(NOPARITY)、
file://奇校验(ODDPARITY)和偶校验(EVENPARITY)等。
}COM_CONFIG;

当选择好适当的参数后就可以根据设置好的端口配置情况打开通讯端口了。与以往DOS下串行通信程序不同的是,Windows操作平台下不提倡应用程序直接控制硬件(包括端口),也不让使用中断(除非打入到Ring0系统级),而是通过Windows操作系统提供的设备驱动程序来进行数据传递。在Windows操作系统下串行口和其他通讯端口一样是作为文件来进行处理的,而不是直接对端口进行操作,对于串行通信,Win 32 提供了相应的文件I/O函数与通信函数,通过了解这些函数的使用,可以编制出符合不同需要的通信程序。与通信设备相关的结构有COMMCONFIG ,COMMPROP,COMMTIMEOUTS,COMSTAT,DCB,MODEMDEVCAPS,MODEMSETTINGS共7个,与通信有关的Windows API函数共有26个,具体说明可参考MSDN帮助文件。下面是打开串口的部分关键代码:

//以创建文件的形式打开文件,并将返回的端口句柄保存于句柄idComDev之中。
idComDev =CreateFile( g_szCom_Port[g_com_config.nPort],
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
……
file://cfg为COMMCONFIG结构的实例对象,获取当前通讯口的状态。
cfg.dcb.DCBlength = sizeof( DCB ) ;
GetCommState( idComDev, &(cfg.dcb) ) ;
file://设置发送、接收缓存大小
SetupComm( idComDev, 4096, 4096 ) ;
// PurgeComm()是一个清除函数,它可以用来中止任何未决的后台读或写,并且可以冲掉I/O
file://缓冲区.其中:PURGE_TXABORT 用于中止后台写操作;PRUGE_RXABORT用于中止后台
file://读操作 ;PRUGE_TXCLEAR用于清除发送缓冲区;PRUGE_RXCLEAR用于清除接收缓冲区
PurgeComm(idComDev,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
file://根据设置的参数填充DCB结构对象dcb的各个数据成员变量
dcb.DCBlength = sizeof( DCB ) ;
GetCommState( idComDev, &dcb ) ;
file://设置端口通讯参数
dcb.BaudRate =g_Com_Baud[g_com_config.nBaud];
dcb.ByteSize =g_Com_ByteSize[g_com_config.nData];
dcb.Parity =g_Com_Parity[g_com_config.nParity] ;
dcb.StopBits =g_Com_StopBits[g_com_config.nStop];
file://硬件流控制
dcb.fDtrControl = DTR_CONTROL_DISABLE ;
dcb.fOutxCtsFlow = FALSE ;
dcb.fRtsControl = RTS_CONTROL_DISABLE ;
file://软件流控制
dcb.fInX = dcb.fOutX = FALSE ;
dcb.XonChar = (char)0xFF ;
dcb.XoffChar = (char)0XFF ;
dcb.XonLim = 100 ;
dcb.XoffLim = 100 ;
dcb.EvtChar=0x0d;
dcb.fBinary = TRUE ;
dcb.fParity = TRUE ;

file://超时控制的设置。超时有两种:区间超时:(仅对从端口中读取数据有用)它指定在读取两个字符之间要经历的时间;总超时: 当读或写特定的字节数需要的总时间超过某一阈值时,超时触发。计算超时可以根据公式:
file://ReadTotalTimeout = (ReadTotalTimeoutMultiplier * bytes_to_read)+
// ReadToTaltimeoutConstant
file://WriteTotalTimeout = (WriteTotalTimeoutMuliplier * bytes_to_write)+
// WritetoTotalTimeoutConstant
file://如果在设置超时时参数为0则为无限等待,即无超时。
CommTimeOuts.ReadIntervalTimeout =MAXDWORD;
CommTimeOuts.ReadTotalTimeoutMultiplier =0;
CommTimeOuts.ReadTotalTimeoutConstant = 0 ;
CommTimeOuts.WriteTotalTimeoutMultiplier =2*9600/dcb.BaudRate ;
CommTimeOuts.WriteTotalTimeoutConstant = 25 ;
SetCommTimeouts(idComDev , &CommTimeOuts ) ;
file://根据设置好的dcb结构设置好通讯口的状态,并开启用于侦听端口,监视从外设传来的数
file://据的线程COMReadThreadProc。
if (SetCommState( idComDev, &dcb ))
{
m_bComPortOpen=TRUE;
g_hCom=idComDev;
AfxBeginThread(COMReadThreadProc,NULL,THREAD_PRIORITY_NORMAL);
return;
}


(二) 侦听监视线程
 

当成功的打开端口之后通过执行线程开启函数AfxBeginThread(COMReadThreadProc,NULL,THREAD_PRIORITY_NORMAL);开启了一个用于侦听端口的工作线程COMReadThreadProc。其具体处理过程
如下:

UINT COMReadThreadProc(LPVOID pParam)
{
……
file://设置读端口线程执行标志的标识
g_comthread.SetReadThreadKillFlag(FALSE);
while(1)
{
file://读取端口开启状态的标识
if(TRUE==g_comthread.GetCloseCOMFlag())
{
g_comthread.SetReadThreadKillFlag(TRUE);
return 0;//正常关闭
}
file://读端口操作
dwNeedRead=500;
file://从端口读取数据到缓存中
if(!ReadFile(g_hCom,buf,dwNeedRead,&dwActRead,NULL))
{
ClearCommError(g_hCom,&dwErrorMask,&comstat);
PurgeComm(g_hCom,PURGE_RXCLEAR);
continue;
}
file://读字符加入到全局缓冲
g_comreadbuf.Add(buf,dwActRead);
Sleep(1);
}
……
return 0;
}


  其中用到的g_comthread和g_comreadbuf分别是线程类CCOMThread和读端口类COMReadBuf的实例对象。这两个类里都用类CCriticalSection m_Lock;实现了临界区技术,用以保持线程间的同步。CCOMReadBuf类的两个函数GetOneByte(……)、Add(……)分别用于从端口读取一个字符和向缓冲区添加读取的字符。其主要实现代码如下:

BOOL CCOMReadBuf::GetOneByte(BYTE *cb)
{
m_Lock.Lock();
if(m_nHead==m_nTail)
{
m_Lock.Unlock();
return FALSE;//空
}
*cb=m_readbuf[m_nTail];
if(m_nTail < m_nBufSize-1)
m_nTail++;
else
m_nTail=0;
m_Lock.Unlock();
return TRUE;//空
}

void CCOMReadBuf::Add(BYTE buf[],int nBytes)
{
int nt,i;
m_Lock.Lock();
for(i=0;i BR> {
nt=(m_nHead-m_nTail);
if(nt<0)
nt+=m_nBufSize;
if(nt+1==m_nBufSize)
break;//缓冲区满
m_readbuf[m_nHead]=buf[i];
if(m_nHead < m_nBufSize-1)
m_nHead++;
else
m_nHead=0;
}
m_Lock.Unlock();
}

(三) 控制命令的发送
 

控制命令可以从对话条上的编辑框获取,然后就可以通过写文件形式从端口发送出去,这部分实现起来较简单,也牵扯不到线程等技术。主要的代码主要有:

……
file://从对话条获取命令行
nRead=m_wndDlgBar.GetDlgItemText(IDC_EDIT_SEND,buf,500);
file://向端口发送命令
if(nRead>0)
{
buf[nRead]=0x0d;
buf[nRead+1]=0x00;
::WriteFile(g_hCom,buf,nRead+1,&dwActWrite,NULL);
}
……

转载于:https://www.cnblogs.com/dengsu888666/archive/2006/04/03/365847.html

C++串行编程步骤介绍相关推荐

  1. Storm之——流组件简单串行编程实践

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/78447229 Storm是一个分布式是实时计算系统,它设计了一种对流和计算的抽象, ...

  2. PIC单片机在线串行编程(ICSP)的实现

    ICSP(In-Circuit Serial Programming)即在线串行编程,通过保持RB6和RB7引脚为低电平,VDD 为编程电压,并将MCLR(VPP)引脚电压从VIL增加到VIHH,器件 ...

  3. pic10f220 c语言,PIC10F202高性能8位全静态闪存CMOS微控制电路串行编程(ICSP™)功能...

    是一款低成本,高性能,8位,全静态, 基于闪存的cmos微控制器. 它采用risc架构, 只有33个单字/单周期指令. 除程序分支外, 所有指令均为单周期(1μs), 程序分支需要两个周期. 它提供的 ...

  4. 告别ASP(主动串行编程)下载模式

    告别ASP(主动串行编程)下载模式 --JTAG---EPCS1 序 一直以来,一般人下载FPGA 的配置芯片,都是用ASP下载模式,USB Blaster接口要插来插去,真的是麻烦,其实,下载FPG ...

  5. 高速串行自同步方式介绍及原理

    高速串行信号与并行信号相比,最主要的就是通信方式的改进,这种通信方式又叫自同步方式,也即两块芯片之间通信,其中发送芯片产生的数据流同时包括数据和时钟信息,如下图所示. 要实现上图所示的通信,在芯片内部 ...

  6. SPI、I2C、UART 三种串行总线对比介绍

    转载自https://blog.csdn.net/oqqHuTu12345678/article/details/65445338 参考博客 https://blog.csdn.net/xiaodin ...

  7. 串行 RapidIO接口介绍

    串行 RapidIO: 高性能嵌入式互连技术 作者: 德州仪器技术应用工程师 冯华亮/ Brighton Feng/ bf@ti.com 摘要 串行RapidIO针对高性能嵌入式系统芯片间和板间互连而 ...

  8. protues仿真中12864液晶屏串行编程的感想(从实际硬件驱动芯片 ST7565R到仿真硬件驱动芯片SED1565)

    因为疫情的原因,没办法回学校拿毕业设计,自然也就没办法调试,虽然硬件电路都搭好了,但没法调试也就意味着不知道程序编写是否有问题,所以就想着在protues上把硬件电路搭起来调试程序,因为单片机用的是s ...

  9. rs485编程java_串行编程RS485

    我的任务是通过RS485 2线系统实现ModBus协议 . (实际上它是三根线,A / B和GND) . 虽然ModBus不是重点,但是之前的步骤......界面上的简单I / O. 我正在使用FTD ...

最新文章

  1. 一个几何不等式的最佳常数
  2. mysql存储过程或函数中传入参数与表字段名相同引发的悲剧
  3. SQL2008 收缩日志和数据脚本
  4. java中b的平方表示_第七届蓝桥杯Java B——四平方和
  5. [IPhone] 仅在Debug编译的NSLog
  6. PyCharm安装和配置教程
  7. 可视化电脑处理变量赋值、循环、程序运行的过程
  8. 漫画:当程序员有了下一代.....
  9. 构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统(52)-美化EasyUI皮肤和图标
  10. myeclipse 10.7 for linux激活
  11. Linux管理员手册
  12. BZOJ2754 [SCOI2012]喵星球上的点名
  13. matlab方差 anov,MATLAB单因素方差分析
  14. python制作ico图标_Python 批量 png 转 ico
  15. u盘插上显示计算机限制,U盘插到电脑上不显示图标的解决方法(以金士顿8GU盘为例)...
  16. 史上首例!阿里程序员写的这一行代码,被国家博物馆收藏了
  17. c语言坐标反算方位角函数,反三角函数/简易正反算or方位角转度分秒
  18. 解决win7 anaconda 安装 Failed to create menus
  19. 如何用mysql创建orders表_MySQL学习十四创建和操纵表
  20. windows CMD批处理中的一些特殊连接符号

热门文章

  1. 云主机挂载硬盘 - 开机自动挂载 fdisk and parted
  2. STM32CubeMX中文用户手册下载方法
  3. Hadoop3——集群搭建以及初体验
  4. AttributeError: 'module' object has no attribute 'main'
  5. Pytorch:线性代数
  6. prometheus源码阅读 - target管理
  7. 对扩展openflow协议的一点思考
  8. 《Android游戏开发详解》一2.2 设置开发机器
  9. docker mysql 主从配置
  10. CentOS6.5安装python2.7.6(慎重升级)