嵌入式系统与PC串行通信的实现

嵌入式系统开发中,经常需要与PC进行数据通信,以便于调试和数据交换。串行通信是一种常见的通信方式,本文将介绍如何在嵌入式系统上实现与PC的串行通信。

嵌入式系统中,RTOS(实时操作系统)是常用的任务调度机制。RTOS可以对任务进行时间片轮转,以保证各个任务的及时响应。然而,在与PC通信时,可能会遇到RTOS任务调度不及时响应PC请求的情况。因此,如果PC端的程序能够根据串口事件来发送请求、等待响应并获取响应,将大大提高通信的效率。

在嵌入式系统中,曾使用过ARM7和ARM9的串行端口(UART和USART)接口。通常,会利用串行FIFO“非空”条件,即当字符或字符缓冲区可用时,微控制器可以被中断,然后根据硬件条件而不是轮询端口寄存器来读取数据。

想,为什么不尝试在PC的串行端口上实现类似的功能呢?Windows是一个多任务、多线程的操作系统,它应该提供了实现这一功能的方法。确实如此,以下是一个可以帮助实现这一功能的应用程序。

代码使用

只需要调用以下C++函数:

OpenComPort(int port, int rate, int parity, int retries)

这个函数使用CreateFile函数打开指定的通信端口,实现通用的读写操作,并支持重叠(异步)I/O。

这个应用程序遵循了微软的知识库文章q115831,它允许打开大于9的通信端口号。指定的波特率和奇偶校验等串行端口参数将被输入到打开的通信端口的DCB结构中。

然后,使用GetCommMask函数获取当前事件掩码,并初始化它。

if (!GetCommMask(hPort, &fdwEventMask)) { // get current event mask fdwEventMask = 0; }

接下来,设置所需的事件掩码,并使用SetCommMask函数将其设置到事件寄存器中。当指定的事件发生时,Read线程将运行(将在下面进一步解释)。

fdwEventMask |= EV_RXCHAR | EV_TXEMPTY | EV_BREAK | EV_ERR | EV_RING | EV_RLSD | EV_CTS | EV_DSR; SetCommMask(hPort, fdwEventMask);

在嵌入式系统中,使用了以下类似的事件:

  • EV_RXCHAR(0x0001) - 接收到一个字符并放入输入缓冲区
  • EV_TXEMPTY(0x0004) - 输出缓冲区中的最后一个字符已发送

下一步是初始化临界区rxLock和rxBuffer的内存。

此时,创建Read线程。在RxThread中,初始化包括设置一个OVERLAPPED结构commSync用于接收数据。

使用CreateEvent函数创建一个事件commEvent,并将其同步到commSync的hEvent(句柄事件)。

使用WaitCommEvent函数等待串口事件:

waitState = WaitCommEvent(hPort, &fdwEventMask, &commSync);

WaitCommEvent函数等待指定的通信设备上发生事件。这个函数监控的事件集合包含在与设备句柄关联的事件掩码中。

一旦事件发生,将检查特定的事件,如EV_RXCHAR、EV_BREAK、EV_ERR、EV_TXEMPTY。

if (fdwEventMask & (EV_RXCHAR | EV_BREAK | EV_ERR | EV_TXEMPTY))

在应用程序中,EV_BREAK和EV_ERR用于传输错误(例如:错误的奇偶校验或由于硬件故障导致的通信中断)。另外两个事件被广泛使用。

接收到的数据将被传输到rxBuffer中(包括一些错误检查和数据大小检查)。

调用以下函数,将字符数组写入嵌入式系统:

WriteComPort(char *sendString, unsigned char txCount);

要写入的数组应根据通信所需的任何协议进行格式化。在应用程序中,数据包包含SOF和EOF。

SOF是嵌入式系统的地址(如果启用了地址),和/或字节计数。EOF是除了校验和之外的其余字节的256模校验和。

通常,写入的消息将由嵌入式系统响应,当数据到达PC的串行端口寄存器时,将生成一个或所有指定的事件。响应消息将在rxBuffer中可用。

可以使用ReadRxChar函数读取rxBuffer中接收到的数据。可以使用以下for循环读取一块数据:

for (int x = 128; x; --x) { if (ReadRxChar(&c)) return ((unsigned int)c); Sleep(10); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485