串口通信编程

一、串口通信基础知识

1.1 串行通信与并行通信

并行通信:在一些联络信号的控制下,一次将8位、16位或32位数据同时进行传送的通信方式。特点:通信速率高,但成本高,易受干扰。
串行通信:只需一对传输线,数据的各位按照时间顺序一位一位地传送。特点:通信速率慢,但通信成本低,适合远距离通信。

在这里插入图片描述

1.2 串行通信的特点

串行通信由于在一条传输线上既传输数据信息,又传输控制联络信息,这就需要一系列约定,从而识别条线上传送的信息流,哪一部分是数据信号,哪一部分是联络信号。

串行通信的信息格式有异步和同步信息格式。与此对应,有异步串行通信和同步串行通信两种方式。

1.2.1 异步传输

在异步传输方式中,帧是数据传输单位。在通信的数据流中,帧之间异步,帧内部各位间同步。异步通信方式的“异步”主要体现在帧与帧之间通信没有严格的定时要求。在异步传输中,帧可以是连续地、一个个地发送,也可以是不连续地、随机地单独发送。
请添加图片描述

1.2.2 同步传输

同步通信中,数据开始传送前用同步字符来指示(常约定1~2个),并由时钟来实现发送端和接收端的同步,即检测到规定的同步字符后,下面就连续按顺序传送数据,直到一块数据传送完毕。同步传送时,字符之间没有间隙,也不要起始位和停止位,仅在数据开始时用同步字符SYNC来指示。
在这里插入图片描述

1.2.3 硬件握手和软件握手

握手信号实际上是控制信号,用来控制数据的传输。通过握手信号,发送端可以得知接收端是否有数据要发送。接收端通过握手信号通知发送端它是否已经准备好了接收信号。握手信号遵循某种协议。

当发送端和接收端处理数据的速度不一样时,可能会造成数据丢失。在传输中,如果发送端的发送速度大于接收端的接收速度,同时若接收端处理数据的速度不够快的话,那么接收端的缓冲区必定在一定时间后溢出,从而造成以后发送过来的数据不能进入缓冲区而丢失。发送端何时可以继续发送数据,何时必须暂停发送,从而让接收端有时间处理数据,称为流量控制,必须靠握手信号来解决这个问题。

  1. 硬件握手

    在硬件握手中,发送端通过将某一个导线拉到高电平或者低电平,来表示发送端可以发送数据。接收端已经准备好接收数据之后,也把某一个导线拉到高电平或者是低电平,来通知发送端,发送端一直在检测这个信号。接收端可以在任何时候把这个信号变为无效,甚至是在接收一个数据块过程中。当发送端检测到这个信号变为无效之后,就必须停止本次发送,直到这个信号变为有效为止。

  2. 软件握手

    在软件握手中,以数据线上的数据信号来代替实际的硬件电路。这种方法用在直接连接或者通过调制解调器连接的两台计算机之间进行双向通信的场合。
    对于软件握手现在已经建立了一些标准协议,其中最常用的是通信协议。通信协议是指通信双方的一种约定,约定包括对数据格式、同步方式、传输速度、传输步骤、检/纠错方式以及控制字符定义等问题进行统一规定,通信双方必须共同遵守,也叫做通信控制规程或称传输控制规程,它属于OSI七层参考模型中的数据链路层。

1.3 串行通信基本参数

在传输进行的过程中,双方明确传输信息的具体方式,否则双方就会没有一套共同的译码方式,从而无法了解对方所传输过来的信息的意义。因此双方为了进行通信,必须遵守一定的通信规则,这个共同的规则就是串口的初始化。

串口的初始化必须对以下几项参数进行设置。

1.3.1 数据传输速度

串行通信的传输受到通信双方配备性能及通信线路的特性所控制,收发双方必须按照同样的速率进行串行通信,即收发双方采用同样的波特率。我们通常将传输速度称为波特率,指的是串行通信中每秒所传输的数据位数,单位是b/s。我们经常可以看到仪器或Modem的规格书上都写着19200 b/s、38 400 b/s,…,所指的就是传输速度。

1.3.2 起始位与停止位

由于异步串行传输中并没有使用同步脉冲作为基准,故接收端完全不知道发送端何时将进行数据的传输。发送端准备要开始传输数据时,发送端会在所送出的字符前后分别加上高电位的起始位(逻辑0)及低电位的停止位(逻辑1),它们分别是所谓的起始位和停止位,也就是说,当发送端要开始传输数据时,便将传输线上的电位由低电位提升至高电位,而当传输结束后,再将电位降至低电位。接收端会因起始位的触发(因电压由低电位升至高电位)而开始接收数据;并因停止位的通知(因电压维持在低电位)而明确数据的字符信号已经结束;加入了起始位及停止位才能比较容易达到多字符的接收能力。起始位固定为1位,而停止位则有1、1.5、2位等多种选择,如何选择呢?只要通信双方协议通过即可,没有强制规定。

1.3.3 校验位

为了预防错误的产生,使用校验位作为检查的机制。校验位是用来检查所传输数据的正确性的一种核对码,又可分成奇校验与偶校验两种,分别是检查字符码中1的数目是奇数或偶数。以偶校验为例,“A"的ASCI码是41H(十六进制),将它以二进制表示时,是01000001,其中1的数目是2,因此校验位便是0,使1的数目保持偶数;同样地,校验位是奇校验时,“A”的校验位便是1,使1的数目保持在奇数。接收端重新计算奇偶校验位,如果新的计算值正确,那么表示正常。如果新的计算值错误,那么接收端就会发出一些指示,表示此次接收的数据有误。

1.4 串行通信的传输方式

1.4.1 信号传输方式

  • 近距离传输时,采用按信号原样传输的基波传输。
  • 远距离传输时,使用Modem将原信号调制为高频的模拟仿号,然后通过电话网络,进行远距离传输。

1.4.2 线路传输方式

  • 单工方式:信息只能沿一个方向传输
  • 半双工方式:同一时刻,信息只能沿一个方向传输
  • 全双工方式:通信双方都能在同一时刻发送和接受

1.5 串口通信及其标准

1.5.1 RS-232C标准

RS-232C是PC与通信工业中应用最广泛的一种串行接口。它适合于数据传输速度在 0~20000 b/s范围内的通信。这个标准对串行通信接口的有关问题,如信号电平、信号线功能、电气特性、机械特性等都作了明确的规定。

由于RS-232C并未定义连接器的物理特性,因此,出现了 DB-25 和 DB-9 各种类型的连接器,其引脚的定义也各不相同。现在计算机上一般只提供 DB-9 连接器,都为公头。相应的连接线上的串口连接器也有公头和母头之分,见下图。请添加图片描述
从功能上看,全部信号线从功能来看,全部信号线分为三类,即数据线(TXD,RXD)、地线(GND)和联络控制线(DSR,DTR,RI,DCD,RTS,CTS)

当两台RS-232串口设备通信距离较近时(<15m),可以用电缆线直接将2台设备的RS-232端口连接,若通信距离较远(>15m)时,需附加调制解调器(Modem)。

1.5.2 RS-422标准

RS-422由RS-232发展而来,它是为了弥补RS-232的不足而提出的。为了改进RS-232抗干扰能力差、通信距离短、传输速度低等缺点,RS-422定义了一种平衡通信接口,将传输速度提高到10 Mb/s,速率低于100 kb/s时传输距离延长到4000英尺(1英尺=0.3048 m),并允许在一条平衡总线上连接最多10个接收器。RS-422是一种单机发送、多机接收的单向、平衡传输规范,被命名为TIA/EIA-428-A标准。

1.5.3 RS-488标准

为扩展应用范围,EIA又于1983年在RS-422基础上制定了RS-485标准,增加了多点、双向通信能力,即允许多个发送器连接到同一条总线上,同时增加了发送器的驱动能力和冲突保护特性,扩展了总线共模范围,后命名为TIA/EIA-488-A标准。由于EIA提出的建议标准都是以“RS”作为前缀的,所以在通信工业领域,仍然习惯将上述标准以RS作为前缀。

1.5.4 参数比较

RS-232,RS-422与RS-485标准只对接口的电气特性做出规定,而不涉及接插件、电缆或协议,在此基础上用户可以建立自己的高层通信协议。有关电气参数见下表。
在这里插入图片描述

1.6 个人计算机中的串口

1.6.1 观察计算机上串口位置和几何特征

在PC主机箱后面板上,有各种各样的接口,其中有个9针的接头区,这就是RS-232C串口。PC上的串行接口有多个名称:RS-232口、串口、通信口、COM口、异步口等。

1.6.2 查看串口设备信息

打开“设备管理器”。在列表中有端口COM和LPT设备信息,如图所示。
在这里插入图片描述
右键单击“通信端口(COM1)”,选择属性,在这里可以查看端口的低级设置,也可查看其资源。在“端口设置”选项卡中,可以看到缺省的波特率和其他设置,这些设置可以在这里改变,也可以在应用程序中很方便地修改。在“资源”选项卡中,可以看到,COM1口的地址分配信息(03F8-03FF)和中断请求号(04),如图所示。
请添加图片描述

二、Windows串口编程

Windows API是由操作系统所提供的函数,这些函数可以为程序设计人员提供相当多的执行功能。Windows的API包括了串口通信的函数,因而在串口通信中使用调用API接口的方法,是实现在C中直接控制串口硬件的简便可行的解决方案。

2.1 动态链接库与API函数

Windows是多任务操作系统。在多任务环境中,应用程序共享内存资源,如果多个应用程序都调用库文件中相同的函数,则在链接时把该函数复制给每个应用程序,运行时在内存中生成同一函数的多个复制,造成内存资源的浪费;此外,如果修改了库中函数的代码,则必须对调用该函数的应用程序重新进行链接。因此,在Windows环境下,通常使用动态链接库(Dynamic Link Libaray,DLL)。动态链接库是一个函数库,是可被其他程序或DLL调用的函数集合组成的可执行文件模块。之所以被称为动态链接库,是因为DLL的代码并不是某个应用程序的组成部分,而是在运行时链接到应用程序中。

动态链接分为两个阶段,即链接过程和装入过程。

当应用程序调用动态链接库中的某个函数时,链接程序并不复制被调用函数的代码,而只是从引入库中复制一些指示信息,指出被调用函数属于哪个动态链接库(.DLL文件)。因此,在应用程序的可执行文件中,存放的不是被调用的函数的代码,而是DLL中该函数的内存地址。程序运行后,当需要调用该函数时,进入装入过程,把应用程序与DLL库一起装入内存,由Windows读入DLL中的函数并运行程序。

可以看出,动态链接是在应用程序被装入到内存中进行的。这样,当多个应用程序调用库中的同一个函数时,不会在内存中有该函数的多个复制,而是只有一分复制,每个应用程序的可执行文件中装入的只是该函数的内存地址,程序运行时再把应用程序代码与被调用函数代码动态链接起来,从而可以节省内存资源。同时,由于DLL与应用程序分开,即使更新DLL,也不用修改已编译好的可执行文件。

常用的动态链接库是安装在Windows目录下,随Windows软件包提供的DLL。这些动态链接库中所包含的函数就称为Windows API函数。

2.2 与串口通信有关的API函数

虽然串口是属于硬件层面,可Windows却将它当成一个文件来操作,因此打开串口时,就必须像打开文件那样操作。在使用完串口时,必须使用关闭文件的函数将串口关闭。

与串口通信有关的API函数均在\Window\system32子目录下的USER.EXE动态链接库中,API中与串行通信相关的函数约有20个,本节只讨论经常使用的函数。

2.2.1 打开串口

Win32 中用于打开串口的API 函数为CreateFile,其原型为:

HANDLE CreateFile (
	LPCTSTR lpFileName, //将要打开的串口逻辑名,如COM1 或COM2
	DWORD dwAccess, //指定串口访问的类型,可以是读取、写入或两者并列
	DWORD dwShareMode, //指定共享属性,由于串口不能共享,该参数必须置为0
	LPSECURITY_ATTRIBUTES lpsa, //引用安全性属性结构,缺省值为NULL
	DWORD dwCreate, //创建标志,对串口操作该参数必须置为OPEN_EXISTING
	DWORD dwAttrsAndFlags, //属性描述,用于指定该串口是否可进行异步操作,FILE_FLAG_OVERLAPPED:可使用异步的I/O
	HANDLE hTemplateFile //指向模板文件的句柄,对串口而言该参数必须置为NULL
);

例如,以下程序用于以同步读写方式打开串口COM1:

HANDLE hCom;
DWORD dwError;
hCom = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hCom == (HANDLE)0xFFFFFFFF)
{
	dwError = GetLastError();
	MessageBox(dwError);
}

2.2.2 关闭串口

利用API 函数实现串口通信时关闭串口非常简单,只需使用CreateFile 函数返回的句柄作为参数调用CloseHandle 即可:

BOOL CloseHandle(
	HANDLE hObject // handle to object to close
);

2.2.3 配置串口

串口通信中,使用该数据结构存放通信参数。由于该结构包括的通信参数很多,逐个设置不方便。通常的做法是首先将串口的当前设置值读出到一个DCB结构中,然后根据需要修改该DCB结构中的某些参数,再以该结构来设置串口通信参数。

接收缓冲区和发送缓冲区的大小可通过SetupComm 函数来设置。

typedef struct _DCB { // dcb
	DWORD DCBlength; // DCB结构的大小
	DWORD BaudRate; // 通信波特率
	DWORD fBinary: 1; // 是否允许二进制方式通信。只能设为TRUE,即使用二进制方式通信。因为WinAPI只支持二进制方式通信。若设为FALSE则通信不能正常工作。
	DWORD fParity: 1; // 是否允许奇偶校验。若设为TRUE,则通信时执行奇偶校验检测,并且当出现奇偶校验错时,将会产生错误信息。
	DWORD fOutxCtsFlow:1; // 指定串口输出数据时,是否使用CTS作为流控制信号。
	DWORD fOutxDsrFlow:1; // 指定串口输出数据时,是否使用DSR作为流控制信号。
	DWORD fDtrControl:2; // 指定DTR流控制信号的工作方式。可取的值:DTR_CONTROL_DISABLE,禁止DTR信号线,并保持禁止状态;DTR_CONTROL_ENABLE,允许DTR信号线,并保持允许状态;DTR_CONTROL_HANDSHAKE,允许DTR握手。此时不允许在程序中使用EscapeCommFunction()函数调整DTR信号线的状态。
	DWORD fDsrSensitivity:1; // 指定通信驱动程序对DSR信号是否敏感。如果设为TRUE,则当DSR线为无效状态时,串口接收的任何数据将被忽略。
	DWORD fTXContinueOnXoff:1; // 指定当接收缓冲区已满,并且驱动程序已经发出XoffChar字符时,发送是否停止。如果为FALSE则停止。fOutX:指定在发送串口数据时是否使用Xon/Xoff流控制。当该成员设为TRUE时,则率门在收到XofChar时传输将停止,直到接收到XonChar时,发送操作才继续进行。
	DWORD fOutX: 1; // 指定在发送串口数据时是否使用Xon/Xoff流控制。当该成员设为TRUE时,则串口在收到XoffChar时传输将停止,直到接收到XonChar时,发送操作才继续进行。
	DWORD fInX: 1; // finX:指定在接收审口数据时是否使用Xon/Xoff流控制。当该成员设为TRUE时,则在接收缓冲区中数据长度达到接收界限值(接收缓冲区长度与XofLim之差)时,驱动程序将发送XofrChar,以通知发送方停止发送数据。直到接收缓冲区中数据长度小于XonLim时,驱动程序才发送XonChar,以通知发送方可以继续发送数据。
	DWORD fErrorChar: 1; // 当数据发生奇偶校验错时,指定是否用ErrorChar成员值替换该错误数据。若该成员值设为TRUE,则当fParity设为TRUE并且发生奇偶校验错时,将进行此替换操作。
	DWORD fNull: 1; // 指定是否忽略接收数据中的空字符(ASCI1码值为0)。该成员值设为TRUE,则执行忽略的操作。
	DWORD fRtsControl:2; // 指定RTS流控制方式。
	DWORD fAbortOnError:1; // 指定当发生错误时,是否终止发送和接收操作。若设为TRUE,则发生通信错误时,将终止所有的发送和接收操作。此时,驱动程序不再响应任何通信操作。直到程序调用了ClearCommError()函数响应该错误,通信才恢复正常。
	DWORD fDummy2:17; // 系统保留不使用
	WORD wReserved; // 不使用,设为0
	WORD XonLim; // 指定在发出Xon字符前,接收缓冲区中允许的最小字符数量。
	WORD XoffLim; // 指定在发出Xoff字符前,接收缓冲区中允许的最大字符数量。该最大字符数量为接收缓冲区长度与XoffLim之差。
	BYTE ByteSize; // 指定通信数据位数, 4-8
	BYTE Parity; // 指定奇偶校验方式
	BYTE StopBits; // 指定停止位数

	char XonChar; // 指定通信时发送XON字符使用的字符值(ASCII码值)。
	char XoffChar; // 指定通信时发送XOFF字符使用的字符值(ASCII码值)。
	char ErrorChar; // 指定通信发生奇偶校验错误时,用于替换错误数据的字符值。
	char EofChar; // 指定表示传输结束的字符值
	char EvtChar; // 指定事件字符。当传输中出现该宁符时,将产生一个事件。
	WORD wReserved1; // 系统保留不使用
} DCB;

而SetupComm 函数的原型则为:

BOOL SetupComm(
	HANDLE hFile, // 指向一个串口设备的句柄,该句柄由CreateFile()函数返回
	DWORD dwInQueue, // 指示输入缓冲区大小,以字节为单位
	DWORD dwOutQueue // 指示输出缓冲区大小,以字节为单位
);

要设置串行通信参数,首先定义一个DCB结构类型的变量。根据通信要求,设置该结构变量的数值,然后以该结构变量作为参数,执行SetCommState() 函数即可完成串口通信参数的设置。

BOOL Setcomnstate(
HANDLE hFile, // 指向要设置参数的串口句柄。该句柄通常是CreateFile 函数的返回值。
LPDCB IpDCB ); //指向DCB结构变量的指针。该结构变量中存放着通信参数设置的具体数值。

以下程序将串口设置为:波特率为9600,数据位数为7 位,停止位为2 位,偶校验,接收缓冲区和发送缓冲区大小均为1024 个字节,最后用PurgeComm 函数终止所有的后台读写操作并清空接收缓冲区和发送缓冲区:

DCB dcb;
dcb.BaudRate = 9600; //波特率为9600
dcb.ByteSize = 7; //数据位数为7 位
dcb.Parity = EVENPARITY; //偶校验
dcb.StopBits = 2; //两个停止位
dcb.fBinary = TRUE;
dcb.fParity = TRUE;
if (!SetCommState(hCom, &dcb))
{
	MessageBox("串口设置出错!");
}
SetupComm(hCom, 1024, 1024);
PurgeComm(hCom, PURCE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

2.2.4 超时设置

超时设置是通过改变COMMTIMEOUTS 结构体的成员变量值来实现的,COMMTIMEOUTS 的原型为:

typedef struct _COMMTIMEOUTS
{
	DWORD ReadIntervalTimeout; //定义两个字符到达的最大时间间隔,单位:毫秒
	//当读取完一个字符后,超过了ReadIntervalTimeout,仍未读取到下一个字符,就会发生超时
	
	DWORD ReadTotalTimeoutMultiplier;
	DWORD ReadTotalTimeoutConstant;
	//其中各时间所满足的关系如下:
	//ReadTotalTimeout = ReadTotalTimeOutMultiplier* BytesToRead + ReadTotalTimeoutConstant
	DWORD WriteTotalTimeoutMultiplier;
	DWORD WriteTotalTimeoutConstant;
	
} COMMTIMEOUTS, *LPCOMMTIMEOUTS;

设置超时的函数为SetCommTimeouts,其原型中接收COMMTIMEOUTS 的指针为参数:

BOOL SetCommTimeouts(
	HANDLE hFile, // handle to communications device
	LPCOMMTIMEOUTS lpCommTimeouts // pointer to comm time-out structure
);

以下程序将串口读操作的超时设定为10 毫秒:

COMMTIMEOUTS to;
memset(&to, 0, sizeof(to));
to.ReadIntervalTimeout = 10;
SetCommTimeouts(hCom, &to);

2.2.5 事件设置

在读写串口之前,需要用SetCommMask ()函数设置事件掩模来监视指定通信端口上的事件,其原型为:

BOOL SetCommMask(
	HANDLE hFile, //标识通信端口的句柄
	DWORD dwEvtMask //能够使能的通信事件
);

有了Set 当然还会有Get,与SetCommMask 对应的GetCommMask()函数的原型为:

BOOL GetCommMask(
	HANDLE hFile, //标识通信端口的句柄
	LPDWORD lpEvtMask // address of variable to get event mask
);

串口上可以发生的事件可以是如下事件列表中的一个或任意组合:EV_BREAK、EV_CTS、EV_DSR、EV_ERR、EV_RING、EV_RLSD、EV_RXCHAR、EV_RXFLAG、EV_TXEMPTY。

我们可以用WaitCommEvent()函数来等待串口上我们利用SetCommMask ()函数设置的事件:

BOOL WaitCommEvent(
	HANDLE hFile, //标识通信端口的句柄
	LPDWORD lpEvtMask, // address of variable for event that occurred
	LPOVERLAPPED lpOverlapped, // address of overlapped structure
);

WaitCommEvent()函数一直阻塞,直到串口上发生我们用所SetCommMask ()函数设置的通信事件为止。一般而言,当WaitCommEvent()返回时,程序员可以由分析*lpEvtMask 而获得发生事件的类别,再进行相应的处理。

2.2.6 读串口

对串口进行读取所用的函数和对文件进行读取所用的函数相同,读函数原型如下:

BOOL ReadFile(
	HANDLE hFile, // 指向串口句柄。该句柄由CreateFile()函数返回。
	LPVOID lpBuffer, // 指向某个缓冲区的指针。该缓冲区存放接收到的二进制数据。
	DWORD nNumberOfBytesToRead, // 要接收的字节数。
	LPDWORD lpNumberOfBytesRead, // 实际接收到的字节数。
	LPOVERLAPPED lpOverlapped // 指向重叠结构变量的指针。当使用重叠操作时,必须设置该成员,否则必须设为NULL
);

2.2.7 写串口

对串口进行写入所用的函数和对文件进行写入所用的函数相同,写函数原型如下:

BOOL WriteFile(
	HANDLE hFile, // 指向串口句柄。该句柄由CreateFile 函数返回。
	LPCVOID lpBuffer, // 指向某个缓冲区的指针。该缓冲区存放待发送的二进制数据。
	DWORD nNumberOfBytesToWrite, // 要发送的字节数。
	LPDWORD lpNumberOfBytesWritten, // 实际发送了的字节数。
	LPOVERLAPPED lpOverlapped // 指向重叠结构变量的指针。当使用重叠操作时,必须设置该成员,否则,必须设为NULL。
);

参考资料:

  1. 曹卫杉 . C/C++串口通信典型应用实例编程实践 . 电子工业出版社 , 2009
  2. 深入浅出VC++串口编程
  3. 龚建伟 , 熊光明 . Visual C++/Turbo C串口通信编程实践 . 电子工业出版社, 2004
  4. 张筠莉 , 刘书智 . VISUAL C++实践与提高:串口通信与工程应用篇 . 中国铁道出版社
  5. 梦小羊博客:串口通信知识总结
  • 6
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C 串口通信编程是指在 C 语言中通过串口与外设进行通信的编程技术。串口通信是一种常用的数据传输方式,适用于各种嵌入式设备和外设之间的数据交互。 首先,要进行串口通信编程,需要先设置串口相关的参数,包括波特率、数据位、校验位和停止位等。这些参数可以通过相应的寄存器进行设置。然后,需要打开串口,使其处于可用状态。 在发送数据时,可以通过对应的寄存器将数据写入发送缓冲区,待数据发送完成后,可以进行下一步的操作。在接收数据时,可以通过查询接收缓冲区的状态,判断是否有数据到达,并从接收缓冲区中读取数据进行处理。 为了简化串口通信编程的操作,可以使用相关的库函数和函数库,比如在 Windows 系统下可以使用 WinAPI 中提供的函数进行串口通信编程,而在 Linux 系统下可以使用 termios 库进行串口通信编程。这些函数库提供了一系列的函数,可以方便地实现串口的配置、数据的发送与接收等操作。 例如,在 C 语言中使用 WinAPI 进行串口通信编程时,可以使用 CreateFile 函数打开串口设备,使用 SetCommState 函数设置串口参数,使用 WriteFile 函数向串口发送数据,使用 ReadFile 函数从串口接收数据。通过这些函数的组合调用,可以实现串口通信功能。 总结起来,C 串口通信编程是一种通过设置串口参数、发送和接收数据的程序设计技术。它需要了解串口相关的硬件知识和相关函数库,将其应用于实际的嵌入式设备和外设之间的数据交互中。通过合理地选择函数库和编写相应的代码,可以实现稳定、高效的串口通信功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值