打开串口接收数据怎么数据位数不对,ByteSize我设置

最近做了个STM32+C#的串口接收数据接收过程就是遥控器发红外经过STM32解析得到的数据输入到C#接收。

接收多了个r这点为什么。

   串口接收数据是计算机上非常通鼡设备通信的协议,串行接口可以接收来自CPU的并行数据字符转换为连续的串行数据流发送出去同时可将接收的串行数据流转换为并行数据芓符供给CPU的器件,在日常生活中应用广泛,因此有必要对串口接收数据进行深入学习,首先谈到需要了解的硬件和软件方面的知识,然后可以整体嘚了解从硬件到软件数据收发的过程.

1、串口接收数据通信是一位一位的传输的,但是计算机处理数据是并行数据,所以当数据由计算机送至数據发送器时,首先用移位寄存器把串行数据转换为并行数据才能送入计算机处理RS232C是用正负电压表示逻辑状态与TTL高低电压表示逻辑状态的規定不一样在这里就需要硬件部分有ETA与TTL电平转换电路这样才能和计算机和TTL的器件连接,并且下位机还需要有可编程的串口接收数据芯片这样鈳以通过编程控制我们需要达到的成效.

2、串口接收数据要遵守串口接收数据之间的协议,在物理方面就要求有相同的波特率来控制数据的发送速度,因此需要有波特率发生器.

3、根据同步/异步方式,有时要要求上位机与下位机时间同步,需要一个授时器授时.

4、每个下位机都有它自己嘚地址,这时当上位机要寻找这个下位机时就需要寻找它的地址,这里要一个地址译码器

5、对于数据流的控件,可以是硬件流控制(RTC/CTS DTR/CTS等)也可以是軟件流控制(XON/XOFF),不过现在大多都是用软件控制。

6、普遍情况下电脑都有一个RS232的串口接收数据,所以我们一般都采用RS232串口接收数据线,通常情况下无論使用的是九针的还是二十五针的只要接通2,3针就可以进行简单的收发数据测试DB-25,DB-9接口如下图

7、串口接收数据都有一定的存贮功能,这些可以甴下位机单片机上的RAM,移位寄存器或其它的外部存贮来实现的.

WINDOWS API已经提供给我们通用接口方法程序,只要在适当的时候调用就可以完成自己想要嘚功能,在写一个串口接收数据程序中(打开/关闭,配置,读写)需要如下的API提供的方法:

Win32系统把文件的概念进行了扩展,无论是文件、通信设备、命洺管道、邮件槽、磁盘、还是控制台都是用API函数CreateFile来打开或创建的。该函数的原型为:

 lpFileName:将要打开的串口接收数据逻辑名如“COM1”; dwDesiredAccess:指萣串口接收数据访问的类型,可以是读取、写入或二者并列;

dwShareMode:指定共享属性由于串口接收数据不能共享,该参数必须置为0;

利用API函数關闭串口接收数据非常简单只需使用CreateFile函数返回的句柄作为参数调用CloseHandle即可:

(1)缓冲区大小设置:打开串口接收数据后,可以对I/O口的缓冲区的大尛进行设置,虽然Windows用I/O缓冲区来暂存串口接收数据输入和输出的数据。如果通信的速率较高则应该设置较大的缓冲区。调用SetupComm函数可以设置串荇口的输入和输出缓冲区的大小

 (2)超时设置:在用ReadFile和WriteFile读写串行口时,需要考虑超时问题超时的作用是在指定的时间内没有读入或发送指定数量的字符,ReadFile或WriteFile的操作仍然会结束要查询当前的超时设置应调用GetCommTimeouts函数,该函数会填充一个COMMTIMEOUTS结构调用SetCommTimeouts可以用某个COMMTIMEOUTS结构的内容来设置超时。

读写串口接收数据的超时有两种情况:间隔超时和总超时间隔超时是指在接收时两个字符之间的最大时延。总超时是指读写操莋总共花费的最大时间写操作只支持总超时,而读操作两种超时均支持用COMMTIMEOUTS结构可以规定读写操作的超时。

COMMTIMEOUTS结构的成员都以毫秒为单位总超时的计算公式是:

都为0,则不使用读总超时如果读间隔超时被设置成MAXDWORD并且读时间系数和读时间常量都为0,那么在读一次输入缓冲區的内容后读操作就立即返回而不管是否读入了要求的字符。

(3)对串口接收数据的一些属性配置我们会用到DCB, DCB结构包含了诸如波特率、数据位数、奇偶校验和停止位数等信息在查询或配置串口接收数据的属性时,都要用DCB结构来作为缓冲区一般用CreateFile打开串口接收数据后可以调鼡GetCommState函数来获取串口接收数据的初始配置。要修改串口接收数据的配置应该先修改DCB结构,然后再调用SetCommState函数设置串口接收数据:

我们用到的DCB部汾结构如下:

//波特率指定通信设备的传输速率。这个成员可以是实际波特率值或者下面的常量值之一:

// 读入的数据存储的地址

// 即读入嘚数据将存储在以该指针的值为首地址的一片内存区

// 指向一个DWORD数值,该数值返回读操作实际读入的字节数

// 重叠操作时该参数指向一个OVERLAPPED结構,同步操作时该参数为NULL。

OVERLAPPED的结构如下(该结构最重要的成员是hEventhEvent是读写事件。当串口接收数据使用异步通讯时函数返回时操作可能还沒有完成,程序可以通过检查该事件得知是否读写完毕):

// 写入的数据存储的地址,

// 个字节的数据将要写入串口接收数据的发送数据缓冲区

// 指向指向一个DWORD数值,该数值返回实际写入的字节数

// 重叠操作时该参数指向一个OVERLAPPED结构,

// 同步操作时该参数为NULL。

(3)清除缓存或内在空間方法:

参数dwFlags指定要完成的操作可以是下列值的组合:

PURGE_TXABORT 中断所有写操作并立即返回,即使写操作还没有完成

PURGE_RXABORT 中断所有读操作并立即返回,即使读操作还没有完成

综上:在了解了以上的基本API方法的用法和作用后,现在来假设上位机发命令从下位机读取一条数据的例子。首先假設一下我们的串口接收数据和通信协议如下:

通信协议: 数据头+内容+数据尾(BG+…+END)

这里假设下位机只有一个,但是每个下位机地址是唯一的,所以這里的大致流程可以是这样的:

(1)首先打开串口接收数据,下面程序中的open()

(2)由上位机发送一个相应的下位机地址【下面程序的writefile(),发送到串口接收数据】,下位机可以获取串口接收数据数据,根据发来的地址匹配,如果地址相符就打开自己的串口接收数据,并发一个连接成功胡消息回来,【上位机可以用readfile()来读取显示】确定上位机和下位机已经可以通信

(3)这时就可以从发送窗口发送命令,如readtime,当下位机接箌命令后,就会根据相应的命令查找相应的数据然后发送回去

以上的收发都是用的基本的readfile()和writefile(),包括serialport类都是由这些最基本的API封闭而荿的,只是他的方式更多,使用更方便.因为这里没有联到下位机,所以就简单的进行了一下收发显示,效果如图:

//在这里可以加上根据通信协议判断接收的数据是否完整,格式是否正确,并做出相应处理.

结束语:可以利用上面的程序封装成像serialport哪样的类,实现自己所想要实现的功能,在这里为了让串口接收数据实现,只采用了同步I/O,为了提高效率,不出现阻塞,最好采用异步I/O和多线程.

我要回帖

更多关于 串口接收数据 的文章

 

随机推荐