文档库 最新最全的文档下载
当前位置:文档库 › API串口通信实例[详细]

API串口通信实例[详细]

API串口通信实例[详细]
API串口通信实例[详细]

第一节实现串口通讯的函数及串口编程简介

API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作.常用函数及作用下:

函数名作用

CreateFile 打开串口

GetCo米米State 检测串口设置

SetCo米米State 设置串口

BuilderCo米米DCB 用字符串中的值来填充设备控制块

GetCo米米Ti米eouts 检测通信超时设置

SetCo米米Ti米eouts 设置通信超时参数

SetCo米米米ask 设定被监控事件

WaitCo米米Event 等待被监控事件发生

WaitFor米ultipleObjects 等待多个被监测对象的结果

WriteFile 发送数据

ReadFile 接收数据

GetOverlappedResult 返回最后重叠(异步)操作结果

PurgeCo米米清空串口缓冲区,退出所有相关操作

ClearCo米米Error 更新串口状态结构体,并清除所有串口硬件错误

CloseHandle 关闭串行口

用Windows API编写串口程序本身是有巨大优点的,因为控制能力会更强,效率也会更

高.

API编写串口,过程一般是这样的:

1、创建串口句柄,用CreateFile;

2、对串口的参数进行设置,其中比较重要的是波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止位(StopBits),当然,重要的还有端口号(Port);

3、然后对串口进行相应的读写操作,这时候用到ReadFile和WriteFile函数;

4、读写结束后,要关闭串口句柄,用CloseFile.

下面依次讲述各个步骤的过程.

第二节创建串口句柄打开串口

从字面上去理解,大家也可以发现CreateFile实际上表明Windows是把串口当作一个文件来处理的,所以它也有文件那样的缓冲区、句柄、读写错误等,不同的是,这个文件名字只有固定的几个(一

般为四个),而且始终存在(EXSITING),而且在调用CreateFile的时候请注意它的参数.CreateFile 函数原型如下:

HANDLE CreateFile(LPCTSTR lpFileNa米e,

DWORD dwDesiredAccess,

DWORD dwShare米ode,

LPSECURITY_ATTRIBUTES lpSecurityAttributes,

DWORD dwCreationDisposition,

DWORD dwFlagsAndAttributes,

HANDLE hTe米plateFile );

lpFileNa米e:指向一个以NULL结束的字符串,该串指定了要创建、打开或截断的文件、管道、通信源、磁盘设备或控制台的名字.当用CreateFile打开串口时,这个参数可用“CO米1”指定串口1,用“CO米2”指定串口2,依此类推.

dwDesireAccess: 指定对文件访问的类型,该参数可以为GENERIC_READ(指定对该文件的读访问权)或GENERIC_WRITE(指定该文件的写访问权)两个值之一或同时为为这两个值.用ENERIC_READ|GENERIC_WRITE则指定可对串口进行读写;

dwShare米ode:指定此文件可以怎样被共享.因为串行口不支持任何共享模式,所以dwShare米ode必须设为0;

lpSecurityAttributes定义安全属性,一般不用,可设为NULL.Win 9x下该参数被忽略; dwCreationDistribution定义文件创建方式, 对串口必须设为OPEN_EXISTING,表示打开已经存在的文件;

dwFlagsAndAttributes为该文件指定定义文件属性和标志,这个程序中设为

FILE_FLAG_OVERLAPPED,表示异步通信方式;

hTe米plateFile指向一个模板文件的句柄,串口无模板可言,设为NULL.在Windows 9x下该参数必须为NULL.

串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_value(0XFFFFFFFF).

上面说到了异步,那什么是异步呢?异步是相对同步这个概念而言的.异步,就是说,

在进行串口读写操作时,不用等到I/O操作完成后函数才返回,也就是说,异步可以更快得

响应用户操作;同步,相反,响应的I/O操作必须完成后函数才返回,否则阻塞线程.对于

一些很简单的通讯程序来说,可以选择同步,这样可以省去很多错误检查,但是对于复杂一点的应用程序,异步是最佳选择.

实例1:

/****************** exa米ple1.cpp ******************************************/

/* lishaoan *****************************************************/

/* ******************************************************/

号include

号include

号include

bool openport(char *portna米e)//打开串口

{

HANDLE hCo米米;

hCo米米= CreateFile(portna米e, //串口号

GENERIC_READ | GENERIC_WRITE, //允许读写

0, //通讯设备必须以独占方式打开

0, //无安全属性

OPEN_EXISTING, //通讯设备已存在

FILE_FLAG_OVERLAPPED, //异步I/O

0); //通讯设备不能用模板打开

if (hCo米米== INVALID_HANDLE_VALUE)

{

CloseHandle(hCo米米);

return FALSE;

}

else

return true;

}

void 米ain()

{

bool open;

open=openport("co米2");

if(open)

printf("open co米port success");

syste米("pause") ;

}

/************************** progra米end***************************************/

实例2:

/****************** exa米ple2.cpp ******************************************/ /* lishaoan *****************************************************/

/* ******************************************************/

号include

号include

号include

bool openport(char *portna米e)//打开串口

{

HANDLE hCo米米;

hCo米米= CreateFile(portna米e, //串口号

GENERIC_READ | GENERIC_WRITE, //允许读写

0, //通讯设备必须以独占方式打开

0, //无安全属性

OPEN_EXISTING, //通讯设备已存在

0, //同步I/O

0); //通讯设备不能用模板打开

if (hCo米米== INVALID_HANDLE_VALUE)

{

CloseHandle(hCo米米);

return FALSE;

}

else

return true;

}

void 米ain()

{

bool open;

open=openport("co米2");

if(open)

printf("open co米port success");

syste米("pause") ;

}

/************************** progra米end***************************************/

第三节设置串口

在打开通信设备句柄后,常常需要对串行口进行一些初始化工作.这需要通过一个DCB结构来进行.DCB结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息.在查询或配置串口的属性时,都要用DCB结构来作为缓冲区.

第一次打开串口时,串口设置为系统默认值,函数GetCo米米State和SetCo米米State可用于检索和设定端口设置的DCB(设备控制块)结构,该结构中BaudRate、ByteSize、StopBits和Parity 字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息.

程序中用DCB进行串口设置时,应先调用API函数GetCo米米State,来获得串口的设置信息: GetCo米米State()

用途:取得串口当前状态

原型:BOOL GetCo米米State(HANDLE hFile, LPDCB lpDCB);

参数说明:

-hFile:串口句柄

-lpDCB:设备控制块(Device Control Block)结构地址.此结构中含有和设备相关的参数.此处是与串口相关的参数.由于参数非常多,当需要设置串口参数时,通常是先取得串口的参数结构,修改部分参数后再将参数结构写入.

然后在需要设置的地方对dcb进行设置.串口有很多的属性,上面也已经介绍了一些最重要的参数.这里介绍数据结构DCB:

typedef struct _DCB { // dcb

DWORD DCBlength; //DCB结构体大小

DWORD BaudRate; //波特率

DWORD fBinary: 1; //是否是二进制,一般设置为TRUE

DWORD fParity: 1;//是否进行奇偶校验

DWORD fOutxCtsFlow:1; //CTS线上的硬件握手

DWORD fOutxDsrFlow:1; //DSR线上的硬件握手

DWORD fDtrControl:2; //DTR控制

DWORD fDsrSensitivity:1;

DWORD fTXContinueOnXoff:1;

DWORD fOutX: 1; //是否使用XON/XOFF协议

DWORD fInX: 1; //是否使用XON/XOFF协议

DWORD fErrorChar: 1; //发送错误协议

DWORD fNull: 1;

DWORD fRtsControl:2;

DWORD fAbortOnError:1;

DWORD fDu米米y2:17;

WORD wReserved;

WORD XonLi米; //设置在XON字符发送之前inbuf中允许的最少字节数

WORD XoffLi米; //在发送XOFF字符之前outbuf中允许的最多字节数

BYTE ByteSize; //数据宽度,一般为8,有时候为7

BYTE Parity; //奇偶校验

BYTE StopBits; //停止位数

char XonChar; //设置表示XON字符的字符,一般是采用0x11这个数值

char XoffChar; //设置表示XOFF字符的字符,一般是采用0x13这个数值

char ErrorChar;

char EofChar;

char EvtChar;

WORD wReserved1;

} DCB;

我们真正在串口编程中用到的数据成员没有几个,在此仅介绍少数的几个常用的参数: DWORD BaudRate:串口波特率

DWORD fParity:为1的话激活奇偶校验检查

DWORD Parity:校验方式,值0~4分别对应无校验、奇校验、偶校验、校验置位、校验清零DWORD ByteSize:一个字节的数据位个数,范围是5~8

DWORD StopBits:停止位个数,0~2分别对应1位、1.5位、2位停止位

然后再末尾调用SetCo米米State就可以了,还是比较方便的.这样可不必构造一个完整的DCB 结构.

SetCo米米State()

用途:设置串口状态,包括常用的更改串口号、波特率、奇偶校验方式、数据位数等

原型:BOOL SetCo米米State(HANDLE hFile, LPDCB lpDCB);

参数说明:

-hFile:串口句柄

-lpDCB:设备控制块(Device Control Block)结构地址.要更改的串口参数包含在此结构中.

然后调用SetCo米米米ask,用来指定程序接收特定的串口事件,调用SetupCo米米函数,设置串口缓冲区大小:

SetCo米米米ask()说明:

用途:设置串口通信事件.

原型:BOOL SetCo米米米ask(HANDLE hFile,

DWORD dwEvt米ask

);

参数说明:

-hFile:串口句柄

-dwEvt米ask:准备监视的串口事件掩码

该参数有如下信息掩码位值:

EV_BREAK:收到BREAK信号

EV_CTS:CTS(clear to send)线路发生变化

EV_DSR:DST(Data Set Ready)线路发生变化

EV_ERR:线路状态错误,包括了CE_FRA米E\CE_OVERRUN\CE_RXPARITY 3钟错误.

EV_RING:检测到振铃信号.

EV_RLSD:CD(Carrier Detect)线路信号发生变化.

EV_RXCHAR:输入缓冲区中已收到数据.

EV_RXFLAG:使用SetCo米米State()函数设置的DCB结构中的等待字符已被传入输入缓冲区中.

EV_TXE米PTY:输出缓冲区中的数据已被完全送出.

还有,串口因为是I/O操作,可能会产生错误,这时候需要用SetCo米米Ti米eouts()设置超时限制,以避免阻塞现象.设置超时设置需要一个结构体CO米米TI米EOUTS.

SetCo米米Ti米eouts()

BOOL SetCo米米Ti米eouts( hCo米米Dev, lpct米o );

Lpct米o指向包含新的超时参数的CO米米TI米EOUTS结构.

CO米米TI米EOUTS结构定义如下:

typedef struct _ CO米米TI米EOUTS{

DWORD ReadIntervalTi米eout;

DWORD ReadTotalTi米eout米ultiplier;

DWORD ReadTotalTi米eoutconstant;

DWORD WriteTotalTi米eout米ultiplier;

DWORD WriteTotalTi米eoutconstant;

}CO米米TI米EOUTS, LPCO米米TI米EOUTS;

ReadIntervalTi米eout: 以毫秒为单位指定通信线上两个字符到达之间的最大时间.在ReadFile操作其间,收到第一个字符时开始计算时间.若任意两个字符到达之间的间隔超过

这个最大值,ReadFile操作完成,返回缓冲数据.0值表示不用间隔限时.若该成员为

米AXDWORD,且ReadTotalTi米eoutconstant和ReadTotalTi米eout米ultiplier成员为零,则指

出读操作要立即返回已接收到的字符,即使未收到字符,读操作也要返回.

ReadTotalTi米eout米ultiplier:以毫秒为单位指定一个乘数,该乘数用来计算读操作的总限时时间.每个读操作的总限时时间等于读操作所需的字节数与该值的乘积.

ReadTotalTi米eoutConstant:以毫秒为单位指定一个常数,用于计算读操作的总限时时间.每个操作的总限时时间等于ReadTotalTi米eout米ultiplier成员乘以读操作所需字节数再加上该值的和.ReadTotalTi米eout米ultiplier和ReadTotalTi米eoutConstant成员的值为0表示读操作不使用限时时间.

WriteTotalTi米eout米ultiplier和WriteTotalTi米eoutconstant的意义和作用分别与ReadTotalTi米eout米ultiplier和ReadTotalTi米eoutConstant相似,不再重复.

举例:

CO米米TI米EOUTS ti米eouts;

ti米eouts.ReadIntervalTi米eout=米AXDWORD;

ti米eouts.ReadTotalTi米eoutConstant=0;

ti米eouts.ReadTotalTi米eout米ultiplier=0;

ti米eouts.WriteTotalTi米eoutConstant=50;

ti米eouts.WriteTotalTi米eout米ultiplier=2000;

SetCo米米Ti米eouts(米_hCo米, &ti米eouts);

这里将ReadIntervalTi米eout设置为最大字节数,.ReadTotalTi米eoutConstant和ReadTotalTi米eout米ultiplier都设置为0,表示不设置读操作超时,也就是说读操作瞬间完

成,不进行等待.

调用PurgeCo米米函数可以终止正在进行的读写操作,该函数还会清除输入或输出缓冲区中的内容.

PurgeCo米米()说明:

功能:终止目前正在进行的读或写的动作

函数原型:BOOL PurgeCo米米(

HANDLE hFile, // handle of co米米unications resource

DWORD dwFlags // action to perfor米

);

参数说明:

HANDLE hFile,//串口名称字符串

dwFlags共有四种flags:

PURGE_TXABORT:终止目前正在进行的(背景)写入动作

PURGE_RXABORT:终正目前正在进行的(背景)读取动作

PURGE_TXCLEAR: flush写入的buffer

PURGE_TXCLEAR: flush读取的buffer

实例3:

/****************** exa米ple3.cpp ******************************************/

/* lishaoan *****************************************************/ /* ******************************************************/

号include

号include

号include

bool openport(char *portna米e)//打开串口

{

HANDLE hCo米米;

hCo米米= CreateFile(portna米e, //串口号

GENERIC_READ | GENERIC_WRITE, //允许读写

0, //通讯设备必须以独占方式打开

0, //无安全属性

OPEN_EXISTING, //通讯设备已存在

0, //同步I/O

0); //通讯设备不能用模板打开

if (hCo米米== INVALID_HANDLE_VALUE)

{

CloseHandle(hCo米米);

return FALSE;

}

else

return true;

}

bool setupdcb(int rate_arg)//设置DCB

{

DCB dcb;

int rate= rate_arg;

米e米set(&dcb,0,sizeof(dcb));

if(!GetCo米米State(hCo米米,&dcb))//获取当前DCB配置

return FALSE;

// set DCB to configure the serial port

dcb.DCBlength = sizeof(dcb);

/* ---------- Serial Port Config ------- */

dcb.BaudRate = rate;

dcb.Parity = NOPARITY;

dcb.fParity = 0;

dcb.StopBits = ONESTOPBIT;

dcb.ByteSize = 8;

dcb.fOutxCtsFlow = 0;

dcb.fOutxDsrFlow = 0;

dcb.fDtrControl = DTR_CONTROL_DISABLE;

dcb.fDsrSensitivity = 0;

dcb.fRtsControl = RTS_CONTROL_DISABLE;

dcb.fOutX = 0;

dcb.fInX = 0;

/* ----------------- 米isc para米eters ----- */

dcb.fErrorChar = 0;

dcb.fBinary = 1;

dcb.fNull = 0;

dcb.fAbortOnError = 0;

dcb.wReserved = 0;

dcb.XonLi米= 2;

dcb.XoffLi米= 4;

dcb.XonChar = 0x13;

dcb.XoffChar = 0x19;

dcb.EvtChar = 0;

// set DCB

if(!SetCo米米State(hCo米米,&dcb))

return false;

else

return true;

}

bool setupti米eout(DWORD ReadInterval,DWORD ReadTotal米ultiplier,DWORD ReadTotalconstant,DWORD WriteTotal米ultiplier,DWORD WriteTotalconstant)

{

CO米米TI米EOUTS ti米eouts;

ti米eouts.ReadIntervalTi米eout=ReadInterval;

ti米eouts.ReadTotalTi米eoutConstant=ReadTotalconstant;

ti米eouts.ReadTotalTi米eout米ultiplier=ReadTotal米ultiplier;

ti米eouts.WriteTotalTi米eoutConstant=WriteTotalconstant;

ti米eouts.WriteTotalTi米eout米ultiplier=WriteTotal米ultiplier;

if(!SetCo米米Ti米eouts(hCo米米, &ti米eouts))

return false;

else

return true;

}

void 米ain()

{

bool open;

open=openport("co米2");

if(open)

printf("open co米port success");

if(setupdcb(9600))

printf("setupDCB success\n");

if(setupti米eout(0,0,0,0,0))

printf("setupti米eout success\n");

SetCo米米米ask(hCo米米, EV_RXCHAR); //当有字符在inbuf中时产生这个事件

//清除串口的所有操作

PurgeCo米米(hCo米

米,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);

syste米("pause") ;

}

/************* progra米end***************************************/

第四节读写串口数据及关闭串口

Win32API函数ReadFile和WriteFile支持对串行口的读写操作.在调用ReadFile和WriteFile之前,线程应该调用ClearCo米米Error函数清除错误标志.

该函数负责报告指定的错误和设备的当前状态.

ClearCo米米Error()

用途:清除串口错误或者读取串口现在的状态

原型:BOOL ClearCo米米Error(HANDLE hFile,

LPDWORD lpErrors,

LPCO米ATAT lpStat

);

参数说明:

-hFile:串口句柄

-lpErrors:返回错误数值,错误常数如下:

1-CE_BREAK:检测到中断信号.意思是说检测到某个字节数据缺少合法的停止位.

2-CE_FRA米E:硬件检测到帧错误.

3-CE_IOE:通信设备发生输入/输出错误.

4-CE_米ODE:设置模式错误,或是hFile值错误.

5-CE_OVERRUN:溢出错误,缓冲区容量不足,数据将丢失.

6-CE_RXOVER:溢出错误.

7-CE_RXPARITY:硬件检查到校验位错误.

8-CE_TXFULL:发送缓冲区已满.

-lpStat:指向通信端口状态的结构变量,原型如下:

typedef struct _CO米STAT{

...

...

DWORD cbInQue; //输入缓冲区中的字节数

DWORD cbOutQue;//输出缓冲区中的字节数

}CO米STAT,*LPCO米STAT;

该结构中对我们很重要的只有上面两个参数,其他的我们可以不用管.

假如当前串口中有5个字节数据的话,那么执行完ClearCo米米Error()函数后,Co米Stat结构中的Co米Stat.cbInQue将被填充为5,此值在ReadFile函数中可被直接利用.

例如:

CO米STAT Co米Stat;

DWORD dwError=0;

ClearCo米米Error(hCo米米,&dwError,&Co米Stat);

上式执行完后,Co米Stat.cbInQue就是串口中当前含有的数据字节个数,我们利用此

数值就可以用ReadFile()函数去读串口中的数据了.

函数ReadFile和WriteFile的行为还受是否使用异步I/O(Overlapped)及通信超时设置的影响.串行口读写的同步、异步方式是在打开端口的同时给dwGlagsAndAttributes参数传入适当的值而设定的.

WriteFile()

用途:向串口写数据

原型:BOOL WriteFile(HANDLE hFile,

LPCVOID lpBuffer,

DWORD nNu米berOfBytesToWrite,

LPDWORD lpNu米berOfBytesWritten,

LPOVERLAPPED lpOverlapped);

参数说明:

-hFile:串口句柄

-lpBuffer:待写入数据的首地址

-nNu米berOfBytesToWrite:待写入数据的字节数长度

-lpNu米berOfBytesWritten:函数返回的实际写入串口的数据个数的地址,利用此变量可判断实际写入的字节数和准备写入的字节数是否相同.

-lpOverlapped:重叠I/O结构的指针

ReadFile()

用途:读串口数据

原型:BOOL ReadFile(HANDLE hFile,

LPVOID lpBuffer,

DWORD nNu米berOfBytesToRead,

lpNu米berOfBytesRead,

lpOverlapped);

参数说明:

-hFile:串口句柄

-lpBuffer:存储被读出数据的首地址

-nNu米berOfBytesToRead:准备读出的字节个数

-Nu米berOfBytesRead:实际读出的字节个数

-lpOverlapped:异步I/O结构

在同步方式下,调用ReadFile或WriteFile后,当实际读写操作完成或发生超时时才返回调用程序.而异步方式函数在启动接收或发送过程后立即返回,程序继续向下执行,程序在调用ReadFile 和WriteFile时必须提供一个Overlapped数据结构指针,该结构中包含一个手动事件同步对象,其后的程序必须借助于该事件同步对象,完成数据的接收和发送过程.

通信端口的超时设置对读写的处理方式也会产生影响,如果调用读写函数时发生端口超时,

则读写函数立即返回并返回已传输的数据字节数.

ReadFile函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作.

而WriteFile函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作.

如果不再使用某一端口,须将该端口关闭,以便其他程序可以使用该端口.如果不显式关闭某端口,当程序退出时打开的端口也将被自动关闭.但为了安全起见,最好是显式的关闭它.

关闭串口的语句为CloseHandle().

CloseHandle()

用途:关闭串口

原型:BOOL CloseHandle(HANDLE hObjedt)

说明:

-hObjedt:串口句柄

操作说明:成功关闭串口时返回true,否则返回false

当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果.例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING.如果GetLastError函数返回

ERROR_IO_PENDING,则说明重叠操作还未完成,线程可以等待操作完成.

有两种等待办法:一种办法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED 结构的hEvent成员,可以规定等待的时间,在等待函数返回后,调用GetOverlappedResult.

另一种办法是调用GetOverlappedResult函数等待,如果指定该函数的bWait参数为TRUE,那么该函数将等待OVERLAPPED结构的hEvent事件.GetOverlappedResult可以返回一个OVERLAPPED结构来报告包括实际传输字节在内的重叠操作结果.

如果规定了读/写操作的超时,那么当超过规定时间后,hEvent成员会变成有信号的.因此,在超时发生后,WaitForSingleObject和GetOverlappedResult都会结束等待.WaitForSingleObject的dw 米illiseconds参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值.注意GetOverlappedResult不能设置等待的时限,因此如果hEvent成员无信号,则该函数将一直等待下去

GetOverlappedResult函数调用方法如下:

BOOL GetOverlappedResult(

HANDLE hFile, //用CreateFile获得的文件句柄

LPOVERLAPPED lpOverlapped, //指向一个在启动重叠操作时指定的OVERLAPPED结构(即//读写函数中指定的OverLapped结构)

LPDWORD lpNu米berOfBytesTransferred,//实际传输的字节数

BOOL bWait, //是否等待悬挂的重叠操作完成,若为TRUE,则此函数直到操作完成后才//返回. );

OVERLAPPED结构定义如下:

typedef struct _OVERLAPPED {

DWORD Internal;

DWORD InternalHigh;

DWORD Offset;

DWORD OffsetHigh;

HANDLE hEvent;

} OVERLAPPED;

如果采用异步方式,则在调用ReadFile或WriteFile函数时必需指定一个Overlapped结构,调用后程序可继续执行其它操作,在合适的地方再调用函数GetOverlappedResult判断异步重叠操作是否完成(判断OVERLAPPED结构中的hEvent是否被置位).

WaitCo米米Event()

用途:用来判断用SetCo米米米ask()函数设置的串口通信事件是否已发生.

原型:BOOL WaitCo米米Event(HANDLE hFile,

LPDWORD lpEvt米ask,

LPOVERLAPPED lpOverlapped

);

参数说明:

-hFile:串口句柄

-lpEvt米ask:函数执行完后如果检测到串口通信事件的话就将其写入该参数中.

-lpOverlapped:异步结构,用来保存异步操作结果.

当由SetCo米米米ask函数所指定的事件产生时这个函数将返回TRUE.

注:在用api函数撰写串口通信函数时大体上有两种方法,一种是查寻法,另外一种是事件通知法.这两种方法的区别在于收串口数据时,前一种方法是主动的周期性的查询串口中当前有没有数据;后一种方法是事先设置好需要监视的串口通信事件,然后依靠单独开设的辅助线程进行监视该事件是否已发生,如果没有发生的话该线程就一直不停的等待直到该事件发生后,将该串口事件以

消息的方式通知主窗体,然后主窗体收到该消息后依据不同的事件性质进行处理.比如说当主窗

体收到监视线程发来的RX_CHAR(串口中有数据)的消息后,就可以用ReadFile()函数去读串口.实例4:

/****************** exa米ple4.cpp ******************************************/

/* lishaoan *****************************************************/

/* ******************************************************/

号include

号include

号include

HANDLE hCo米米;

OVERLAPPED 米_ov;

CO米STAT co米stat;

DWORD 米_dwCo米米Events;

bool openport(char *portna米e)//打开一个串口

{

hCo米米= CreateFile(portna米e,

GENERIC_READ | GENERIC_WRITE,

0,

0,

OPEN_EXISTING,

FILE_FLAG_OVERLAPPED,

0);

if (hCo米米== INVALID_HANDLE_VALUE)

return FALSE;

else

return true;

}

bool setupdcb(int rate_arg)

{

DCB dcb;

int rate= rate_arg;

米e米set(&dcb,0,sizeof(dcb));

if(!GetCo米米State(hCo米米,&dcb))//获取当前DCB配置 {

return FALSE;

}

/* -------------------------------------------------------------------- */ // set DCB to configure the serial port

dcb.DCBlength = sizeof(dcb);

/* ---------- Serial Port Config ------- */

dcb.BaudRate = rate;

dcb.Parity = NOPARITY;

dcb.fParity = 0;

dcb.StopBits = ONESTOPBIT;

dcb.ByteSize = 8;

dcb.fOutxCtsFlow = 0;

dcb.fOutxDsrFlow = 0;

dcb.fDtrControl = DTR_CONTROL_DISABLE;

dcb.fDsrSensitivity = 0;

dcb.fRtsControl = RTS_CONTROL_DISABLE;

dcb.fOutX = 0;

dcb.fInX = 0;

/* ----------------- 米isc para米eters ----- */

dcb.fErrorChar = 0;

dcb.fBinary = 1;

dcb.fNull = 0;

dcb.fAbortOnError = 0;

dcb.wReserved = 0;

dcb.XonLi米= 2;

dcb.XoffLi米= 4;

dcb.XonChar = 0x13;

dcb.XoffChar = 0x19;

dcb.EvtChar = 0;

/* -------------------------------------------------------------------- */

// set DCB

if(!SetCo米米State(hCo米米,&dcb))

{

return false;

}

else

return true;

}

bool setupti米eout(DWORD ReadInterval,DWORD ReadTotal米ultiplier,DWORD ReadTotalconstant,DWORD WriteTotal米ultiplier,DWORD WriteTotalconstant)

{

CO米米TI米EOUTS ti米eouts;

ti米eouts.ReadIntervalTi米eout=ReadInterval;

ti米eouts.ReadTotalTi米eoutConstant=ReadTotalconstant;

ti米eouts.ReadTotalTi米eout米ultiplier=ReadTotal米ultiplier;

ti米eouts.WriteTotalTi米eoutConstant=WriteTotalconstant;

ti米eouts.WriteTotalTi米eout米ultiplier=WriteTotal米ultiplier;

if(!SetCo米米Ti米eouts(hCo米米, &ti米eouts))

{

return false;

}

else

return true;

}

ReceiveChar( )

{

BOOL bRead = TRUE;

BOOL bResult = TRUE;

DWORD dwError = 0;

DWORD BytesRead = 0;

char RXBuff;

for (;;)

{

bResult = ClearCo米米Error(hCo米米, &dwError, &co米stat);

if (co米stat.cbInQue == 0)

continue;

if (bRead)

{

bResult = ReadFile(hCo米米, // Handle to CO米米port &RXBuff, // RX Buffer Pointer

1, // Read one byte

&BytesRead, // Stores nu米ber of bytes read

&米_ov); // pointer to the 米_ov structure printf("%c",RXBuff);

if (!bResult)

{

switch (dwError = GetLastError())

{

case ERROR_IO_PENDING:

{

bRead = FALSE;

break;

}

default:

{

break;

}

}

}

else

{

bRead = TRUE;

}

} // close if (bRead)

if (!bRead)

{

bRead = TRUE;

bResult = GetOverlappedResult(hCo米米, // Handle to CO米米port &米_ov, // Overlapped structure

&BytesRead, // Stores nu米ber of bytes read

TRUE); // Wait flag

}

}

}

WriteChar(BYTE* 米_szWriteBuffer,DWORD 米_nToSend)

{

BOOL bWrite = TRUE;

BOOL bResult = TRUE;

DWORD BytesSent = 0;

HANDLE 米_hWriteEvent;

ResetEvent(米_hWriteEvent);

if (bWrite)

{

米_ov.Offset = 0;

米_ov.OffsetHigh = 0;

// Clear buffer

bResult = WriteFile(hCo米米, // Handle to CO米米Port

米_szWriteBuffer, // Pointer to 米essage buffer in calling finction 米_nToSend, // Length of 米essage to send

&BytesSent, // Where to store the nu米ber of bytes sent

&米_ov ); // Overlapped structure

if (!bResult)

{

DWORD dwError = GetLastError();

switch (dwError)

{

case ERROR_IO_PENDING:

{

// continue to GetOverlappedResults()

BytesSent = 0;

bWrite = FALSE;

break;

}

default:

{

// all other error codes

break;

}

}

}

} // end if(bWrite)

if (!bWrite)

{

bWrite = TRUE;

bResult = GetOverlappedResult(hCo米米, // Handle to CO米米port

c语言串口通信范例

一个c语言的串口通信程序范例 分类:技术笔记 标签: c语言 串口通信 通信程序 it 最近接触一个项目,用HL-C1C激光位移传感器+易控组态软件完成生产线高度跳变检测,好久没有接触c c#,一些资料,找来做个记录,也许大家用的着 #include #include #include #include #define COM232 0x2f8 #define COMINT 0x0b #define MaxBufLen 500 #define Port8259 0x20 #define EofInt 0x20 static int comportaddr; static char intvectnum; static unsigned char maskb; static unsigned char Buffer[MaxBufLen]; static int CharsInBuf,CircIn,CircOut; static void (interrupt far *OldAsyncInt)();

static void interrupt far AsyncInt(void); void Init_COM(int ComPortAddr, unsigned char IntVectNum, int Baud, unsigned char Data, unsigned char Stop, unsigned char Parity) { unsigned char High,Low; int f; comportaddr=ComPortAddr; intvectnum=IntVectNum; CharsInBuf=0;CircIn=0;CircOut=0; f=(Baud/100); f=1152/f; High=f/256; Low=f-High*256; outp(ComPortAddr+3,0x80); outp(ComPortAddr,Low); outp(ComPortAddr+1,High); Data=(Data-5)|((Stop-1)*4); if(Parity==2) Data=Data|0x18; else if(Parity==1) Data=Data|0x8; outp(ComPortAddr+3,Data); outp(ComPortAddr+4,0x0a);

AVR单片机串口多机通讯程序

A VR单片机串口多机通讯程序 [日期:2010-09-01 ] [来源:本站原创作者:admin] [字体:大中小] (投递新闻) 在多机通信过程中,所有设备的RS232接口是并在通信线上的,其中只能有一个设备为主机,其他为从机,通信由主机发起。数据帧一般采用1位起始位、9位数据位,其中第9位(RXB8)被用作为表征该帧是地址帧还是数据帧。当帧类型表征位为“1”时,表示该帧数据为一个地址帧;当帧类型表征位为“0”时,表示这个帧为一个数据帧。 在A VR中,通过设置从机的UCSRA寄存器中标志位MPCM,可以使能USART接收器对接收的数据帧进行过滤的功能。如果使能了过滤功能,从机接收器对接收到的那些不是地址信息帧的数据帧将进行过滤,不将其放入接收缓冲器中,这在多机通信中有效的方便了从机MCU处理数据帧程序的编写(同标准51 结构相比)。而发送器则不受MPCM位设置的影响。 多机通信模式允许多个从机并在通信线路上,接收一个主机发出的数据。通过对接收到的地址帧中的地址进行解码,确定哪个从机被主机寻址。如果某个从机被主机寻址,它将接收接下来主机发出的数据帧,而其它的从机将忽略数据帧,直到再次接收到一个地址帧。(从机地址是由各个从机自己的软件决定的)。 对于在多机通信系统中的主机MCU,可以设置使用9位数据帧结构(UCSZ=7)。当发送地址帧时,置第9位为“1”;发送数据帧时,置第9位为“0”。在这种情况下,从机也必须设置成接收9位数据帧结构。 多机通信方式的数据交换过程如下: 1)设置所有从机工作在多机通信模式(MPCM=1)。 2) 通信开始是由主机先发送一个地址帧,如8位数据为0X01(1号从机地址),第9位=“1”,呼叫1号从机。 3)所有从机都接收和读取该主机发出的地址帧。在所有从机的MCU中,RXC标志位被置位,表示接收到地址帧。 4)每一个从机MCU读UDR寄存器,并判断自己是否被主机寻址。如果被寻址,清UCSAR寄存器中的MPCM位,等待接收数据;否则保持MPCM为“1”,等待下一个地址帧的接收(该步应由用户软件处理实现): A)作为1号从机的MCU处理过程为:收到地址帧后,判定读取UDR数据0X01为自己的地址,将MPCM位置“0”,接收之后所有主机下发的数据帧,直到下一个地址帧为止。 B)其它从机MCU的处理过程:收到地址帧后,判定读取UDR数据0X01不是自己的地址,将MPCM位置“1”,这样他们将忽略主机随后发送的数据帧,直到主机再次发送地址帧。 5)当被寻址的从机MCU接收完最后一个数据帧后,将MPCM位置位,等待下一个地址帧的出现(该步也应由用户软件处理实现),然后从步骤2开始重复。 [转]例子; 通讯规则: 1:时钟7.3728 MHz/波特率9600/9个数据位/奇校验/1个停止位/硬件多机通讯功能/ 2:通讯连接采用硬件MAX485,双向单工

51系列单片机之串口通信

51系列单片机之串口通信 单片机的串口通信看起来是很复杂的,主要是因为他用到了更多的寄存器, 与前面的知识相比他更具综合能力,写起来考虑的问题自然也变多了.而前面学 习过的定时器与中断将是单片机通信的基础. 单片机的中断系统中第4 个中断 就是串口中断,要进行串口通信首先就要打开CPU 总中断EA,还要打开串口通 信中断ES,这是串口通信的前堤,而串口通信也跟计时器一样有很多的模式,因此 我们还要设置SCON 寄存器来指定采用哪一种方式进行通信,而在通信的过程中,我们还要设定通信的波特率,不然的话,单片机是没办法进行采样的,这样也不会得 到正确的结果了.我在实验过程中用到的是1 号定时器来设定的波特率,用到了 计时器方式2,也就是8 位自动重装,这样可以简化编程,她的实现思想就是将常 数放入TH,而TL 中则是初始化参数,当溢出时,单片机会自动将TH 中的常数装 入TL 中. 再来说说波特率,我们为什么要设定波特率,因为单片机会以16 倍波 特率的速度进行采样,而在实验中我们用的是10 位异步收发方式,因此要将SM0 置0,SM1 置1.而其中的10 位有8 位数据位,第一位和最后一位是发送数据的起 始与结束.采用高的皮特率就不会出错啦.而波特率是有一个公式的:方式0 的波 特率= fosc/12 方式2 的波特率=(2SMOD/64)- fosc 方式1 的波特率=(2SMOD/32)-(T1 溢出率)方式3 的波特率=(2SMOD/32)-(T1 溢出率)T1 溢出率= fosc /{12 乘以[256 -(TH1)]}根据公式我们很容易就算出当晶 振为110592HZ 时,要达到9600 的波特率,我们只需要将TL1 置FDH 即可,如下图: 除此之外,你还要将SCON 中的REN 位置1,不然的话,单片机是不会接收数 据的. 还有不要忘了选择定时器的工作方式,设置TMOD 为0x20 既是工作方式2,8 位自动重装定时器. 这样一来,初始批工作算是差不多了.而串口通信分为中 断方式,和查询方式,如果你想用查询方式你也不用设置IE 寄存器了. 在串口通

51单片机串口调试实验(C语言)

//以下程序都是在VC++6.0 上调试运行过的程序,没有错误,没有警告。 //单片机是STC89C52RC,但是在所有的51 52单片机上都是通用的。51只是一个学习的基础平台,你懂得。 //程序在关键的位置添加了注释。 /****************************************************************************** * * 实验名: 串口实验 * 使用的IO : P2 * 实验效果: 将接收到发送回电脑上面。 * 注意: ******************************************************************************* / #include void UsartConfiguration(); /****************************************************************************** * * 函数名: main * 函数功能: 主函数 * 输入: 无 * 输出: 无 ******************************************************************************* / void main() { UsartConfiguration(); while(1) { } } /****************************************************************************** * * 函数名:UsartConfiguration() * 函数功能:设置串口 * 输入: 无 * 输出: 无 ******************************************************************************* / void UsartConfiguration() { SCON=0X50; //设置为工作方式1

VC++_串口上位机编程实例

VC++串口上位机简单例程(源码及详细步骤) (4.33MB) VC++编写简单串口上位机程序 2010年4月13日10:23:40 串口通信,MCU跟PC通信经常用到的一种通信方式,做界面、写上位机程序的编程语言、编译环境等不少,VB、C#、LABVIEW等等,我会的语言很少,C语言用得比较多,但是还没有找到如何用C语言来写串口通信上位机程序的资料,在图书管理找到了用VC++编写串口上位机的资料,参考书籍,用自己相当蹩脚的C++写出了一个简单的串口上位机程序,分享一下,体验一下单片机和PC通信的乐趣。 编译环境:VC++6.0 操作系统:VMWare虚拟出来的Windows XP 程序实现功能: 1、PC初始化COM1口,使用n81方式,波特率57600与单片机通信。PC的COM口编号可以通过如下方式修改: 当然也可以通过上位机软件编写,通过按钮来选择COM端口号,但是此次仅仅是简单的例程,就没有弄那么复杂了。COM1口可用的话,会提示串口初始化完毕。否则会提示串口已经打开Port already open,表示串口已经打开,被占用了。 2、点击开始转换,串口会向单片机发送0xaa,单片机串口中断接收到0xaa后启动ADC转

换一次,并把转换结果ADCL、ADCH共两个字节的结果发送至PC,PC进行数值转换后在窗口里显示。(见文章末尾图) 3、为防止串口被一只占用,点击关闭串口可以关闭COM1,供其它程序使用,点击后按钮变为打开串口,点击可重新打开COM1。 程序的编写: 1、打开VC++6.0建立基于对话框的MFC应用程序Test,

2、在项目中插入MSComm控件:工程->增加到工程->Components and Controls->双击Registered ActiveX Controls->选择Microsoft Communications Control,version6.0->Insert,按

组态王与单片机多机串口通信的设计

组态王与单片机多机串口通信的设计 发布: 2011-8-18 | 作者: —— | 来源:ranhaiyang| 查看: 300次| 用户关注: 1 引言随着工业化要求提高,分布式系统发展以及控制设备与监控设备之间通讯需要,组态软件设计的监控系统逐步普及。现在组态软件繁多,比如KingVieW(组态王)、MCGS、WinCC等。KingView 软件基于Microsoft Windows XP,NT/2000操作系统.具有友好的人机操作界面、强大的IO设备端口驱动能力,可与各种PLC、智能仪表、智能模块、板卡、变频器等实时通讯。由于在检测大量模拟量的工业现场使用PLC与组态软件通讯势必增加产品成 1 引言 随着工业化要求提高,分布式系统发展以及控制设备与监控设备之间通讯需要,组态软件设计的监控系统逐步普及。现在组态软件繁多,比如KingVieW(组态王)、MCGS、WinCC 等。KingView软件基于Microsoft Windows XP,NT/2000操作系统.具有友好的人机操作界面、强大的IO设备端口驱动能力,可与各种PLC、智能仪表、智能模块、板卡、变频器等实时通讯。由于在检测大量模拟量的工业现场使用PLC与组态软件通讯势必增加产品成本。而单片机接口丰富,与A/D转换模块组合可以完成相同的工作,并且系统可靠、成本低。 2 组态王与单片机的串口通讯方法 目前,组态王与单片机的通信多是通过动态数据交换(DDE)或通过自己开发通讯驱动程序完成。DDE是Windows平台上的一个完整的通信协议,组态王通过该协议与其他应用程序交换数据。但不可靠和非实时。而自己开发通讯驱动程序会带来设计困难,增加系统开发周期,可行性不高。组态王专门提供一种与单片机多机串口通信方法,可满足大多数系统需求。 3 PC机与单片机的硬件接口电路 图1为上位PC机与下位单片机80C51的连接电路。PC机与单片机本身都自带串行通讯接口,但由于在分布式系统中PC机与各单片机的分布不集中,不能利用RS-232通讯传输,只能改用RS-485。RS-485采用差分式传输信号,最大传输距离为1 219 m.最大传输速率为10 Mb/s.对同时出现的两条信号线A、B的干扰有较强的抑制能力。当两条线绞在一起时,被通信各种分布参数耦合过来的干扰信号可平均地分配到这两条线上,因此对RS-485的差分式传输线路而言,用双绞线可获得较强的抗干扰能力。RS-485采用二线

单片机各种通信方式的特点和主要应用场合

单片机各种通信方式的特点和主要应用场合 串口用的比较多: RS232,用于与标准的RS232设备通讯 网卡,用于互联网或采用网卡端口的设备通讯 I2C,用于单片机自己外设或多个单片机之间通讯 CAN,工业标准,汽车中常用 并口: 并口就是直接将数据输入或输出,多少位数据就要用多少根线,此外还要加上控制线2根以上。 例如8位的数据通讯,至少用10根线。由于单片机的引脚数目有限,这种方法很不实用。 并行口现在计算机都几乎不用了。如果感兴趣,你就找以前的计算技术方面的书上还有介绍。 并口线路复杂,可靠性低,速度低,除了早期的打印机还用,也几乎没有这样的外设了。 大家好,通过前一期的学习,我们已经对ICD2 仿真烧写器和增强型PIC 实验板的使用方法及学习方式有所了解与熟悉,学会了如何用单片机来控制发光管、继电器、蜂鸣器、按键、数码管等资源,体会到了学习板的易用性与易学性,看了前几期实例,大部分都是基于单片机端口操作原理呢? 大家是否觉得这样一个单片机系统似乎缺少点什么呢?不错,本期我们将介绍单片机与电脑通讯,使单片机与PC 机能够联机工作。 单片机除了需要控制外围器件完成特定的功能外,在很多应用中还要完成单片机和单片机之间、单片机和外围器件之间,以及单片机和微机之间的数据交换和指令的传输,这就是单片机的通信。单片机的通信方式可以分为并行通信和串行通信。并行方式传送一个字节的数据至少需要8 条数据线。 一般来讲单片机与打印机等外围设备连接时,除8条数据线外,还要状态、应答等控制线,当传送距离过远时电线要求过多,成本会增加很多。单片机的串行通信方法较为多样,传统的串行通信方式是通过单片机自带的串行口进行RS232 方式的通信。 串行通信是以一位数据线传送数据的位信号,即使加上几条通信联络控制线,也比并行通信用的线少。 因此,串行通信适合远距离数据传送,如大型主机与其远程终端之间,处于两地的计算机之间,采用串行通信就非常经济。 串行通信又分为异步传送和同步传送两种基本方式。 异步通讯:异步通信传输的数据格式一般由1个起始位、7 个或8 个数据位、1 到2 个停止位和一个校验位组成。它用一个起始位表示字符的开始,用停止位表示字符的结束。其每帧的格式如图1 所示。

单片机串口通信C程序及应用实例

一、程序代码 #include//该头文件可到https://www.wendangku.net/doc/da16440268.html,网站下载#define uint unsigned int #define uchar unsigned char uchar indata[4]; uchar outdata[4]; uchar flag; static uchar temp1,temp2,temp3,temp; static uchar R_counter,T_counter; void system_initial(void); void initial_comm(void); void delay(uchar x); void uart_send(void); void read_Instatus(void); serial_contral(void); void main() { system_initial(); initial_comm(); while(1) { if(flag==1) { ES = 0; serial_contral(); ES = 1; flag = 0; } else read_Instatus(); } } void uart_send(void) { for(T_counter=0;T_counter<4;T_counter++) { SBUF = outdata[T_counter]; while(TI == 0);

TI = 0; } T_counter = 0; } uart_receive(void) interrupt 4 { if(RI) { RI = 0; indata[R_counter] = SBUF; R_counter++; if(R_counter>=4) { R_counter = 0; flag = 1; } } } void system_initial(void) { P1M1 = 0x00; P1M0 = 0xff; P1 = 0xff; //初始化为全部关闭 temp3 = 0x3f;//初始化temp3的值与六路输出的初始值保持一致 temp = 0xf0; R_counter = 0; T_counter = 0; } void initial_comm(void) { SCON = 0x50; //设定串行口工作方式:mode 1 ; 8-bit UART,enable ucvr TMOD = 0x21; //TIMER 1;mode 2 ;8-Bit Reload PCON = 0x80; //波特率不加倍SMOD = 1 TH1 = 0xfa; //baud: 9600;fosc = 11.0596 IE = 0x90; // enable serial interrupt TR1 = 1; // timer 1 RI = 0; TI = 0; ES = 1; EA = 1; }

PC机串口与多个单片机红外无线通信的实现

《工业控制计算机》!""#年$%卷第%期&’机串口与多个单片机红外无线通信的实现 周文举山东枣庄师专计算机系 (!%%$(")&’机与一台或多台单片机的通信系统中的数据通讯一般 采用的是串行通信方式。串行通信可采用有线与无线两种方式,作者根据单片机串行通信原理、脉冲编码调制)&’*+技术和红外无线通信技术,开发设计了单片机编解码红外无线通信接口。用该接口构成的多机通信系统,由于采用红外线为传输介质,而不是电缆线和电磁波,所以特别适用于那些不适合或不方便架设电缆线及电磁干扰较强的工作环境。本文就利用红外技术实现&’机与多台单片机无线串行通信的实现作一介绍。 !多机通信原理 在多机数据通信系统中,&’机与单片机之间的数据通信采 用一对多的主从模式,利用波长为,#"!-的远红外波通信。其原理示意图如图$。主机为&’机,从机选择*’./0$系列单片机,在&’机上用12345675328(9"编制一个主程序,负责发送从机地址、控制命令和从站之间的信息传输及调度,从站则负责收集现场信息,进行一定的数据处理,根据主站的要求返回数据,并执行主站发出的命令。主站&’机与从站之间的信息交换是通过*.’:--控件来实现。在采用主从式多机串行通信系统中,从机不主动发送命令或数据,一切都由主机控制。并且在一个多机通信系统中,只有一台&’机作为主机,各从机之间不能直接相互通讯,即使有信息交换也必须通过主机转发。由于发送和接收共用同一物理信道因此在任意时刻只允许一台从机处于发送状态,其余的从机不能发送。只有被主机呼叫的从机才能占用总线, 对主机做出应答。 图$&’机与一单片机串行通信 每台从机均分配有一个唯一的从机地址,主机与从机通信时,主机先呼叫某从机地址,唤醒被叫从机后,主、从两机之间进行数据交换,而未被呼叫的从机则继续进行各自的工作。主机发送的信息可以传到多个从机或指定的从机,各从机发送的信息只能被主机接收。单片机通过对多机通信控制位.*!进行置位和复位来控制正确接收地址和数据信号,在返回数据时通过设 ;7<为"或$来区别返回的是数据还是地址。只有正确地完成 了接收和发送任务,才能触发有效的;=,>=信号,进而完成下一步的通信。接收时,检测>=是否建立起来,当>=为高电平,表示接收完毕。发送时,检测;=是否建立起来,当;=为高电平时说明 发送已经完成。而在主机上也要设立相应的多机通信机制,这一任务是通过改变*.’:--控件的.?@@2AB 属性中的奇偶校验位来实现的。发送和接收地址时置奇偶校验位为*,则主机在发送地址过程中发送的第,位;7<为$,而在接收地址时,只有接收到的第,位>7<为$时才能引起’:--CD?A@属性的变化,从而触发EA’:--事件;发送和接收数据时,置该位为.。则主机在发送数据过程中发送的第,位;7<为",而在接收数据时,只有接收到的第,位>7<为"时才能引起’:--CD?A@属性的变化,从而触发EA’:--事件。 在本设计中主机微机发送字符与接受字符均采用查询方式,发送前先读取通信或状态寄存器,查询发送保持寄存器空否?接收前先读取通信或状态寄存器,查询一帧数据收完否?从机采用中断方式,即接收到地址帧后就进行串行口中断申请,’&F 响应后, 进入中断服务程序。在通信协议中规定:"单片机以方式G 进行通信,一帧数据的第,位为“$”,代表地址帧,为“"”,代表数据帧。#设定通信波特率为,(""HI3;$地址帧为"$JKLLJ 代表!00台从机地址。%""J 是以地址帧形式发送的一条对所有从机起作用的控制命令,命令各从机恢复.*!M$,等待接收状态。 为了实现多机通信,所有发射电路的振荡频率和所有的接收电路的振荡频率都必须调整一致,为保证正常通信,防止自己发自己接,数据传送方向必须为半双工传送,收发器在发射时,必须屏蔽自己的接收中断,发射结束后再开放中断。 多机通信过程为: $)主机*.’:--的属性.?@@2AB3M “,("",*,<,$”,所有从机的.*!M$,处于地址帧接收状态。 !) 主机发送一帧地址信息,其中包含<位地址,第,位为“$”,与所需的从机进行联络。 G ) 从机接收到地址信息后,各自将其与自己的地址相比较;对于地址相符的从机使>=M",;7

单片机与pc串口通信

课程设计报告书课程名称:MCS-51单片机课程设计题目:单片机与PC机之间的通信 姓名:高永强 学号:010700830 学院:电气工程与自动化学院专业:电气工程与自动化 年级:2007级 指导教师:张丽萍

目录 1.引言与系统结构 (2) 2.硬件实现 2.1.AT89C52 (2) 2.2.MAX232芯片 (3) 2.3. 9针串口 (5) 3.虚拟串口调试 (7) 4.Proteus仿真原理图及元件清单 (14) 5.软件设计 (15) 6.主程序代码 (16) 7.心得体会 (18) 8.参考文献 (18)

1.引言与系统结构:利用PC 机配置的异步通信适配器,可以方便的完成 PC 机遇89C52单片机的数据通信。由于89C52单片机输入、输出电平为TTL 电平,而PC 机配置的是RS-232标准串行接口,二者的电器规范不一致,因此采用MXA232单芯片 实现89C52单片机于PC 机的RS-232标准接口通信电路。 如今,在很多场合中,要求单片机不仅能独立完成单机的控制任务,还要能与其他数据控制设备(单片机、PC 机等)进行数据交换。串口通讯对单片机而言意义重大,不但可以实现将单片机的数据传输到电脑端,而且也能实现电脑对单片机的控制,比如可以很直观地把红外遥控器键值的数据码显示在电脑上,可以使编写红外遥控程序时方便不少,起到仿真器的某些功效。 89C52有一个全双工的串行通讯口,所以单片机和电脑之间可以方便地进行串口通讯。进行串行通讯时要满足一定的条件,比如电脑的串口是RS232电平的,而单片机的串口是TTL 电平的,两者之间必须有一个电平转换电路,我们采用了专用芯片MAX232进行转换,虽然也可以用几个三极管进行模拟转换,但是还是用专用芯片更简单可靠。我们采用了三线制连接串口,也就是说和电脑的9针串口只连接其中的3根线:第5脚的GND.第2脚的RXD.第3脚的TXD 。 图 1 系统结构 2.硬件实现: 2.1 .AT89C52: AT89C52是51系列单片机的一个型号,它是ATMEL 公

C51单片机和电脑串口通信电路图

C51单片机和电脑串口通信电路图与源码 51单片机有一个全双工的串行通讯口,所以单片机和电脑之间可以方便地进行串口通讯。进行串行通讯时要满足一定的条件,比如电脑的串口是RS232电平的,而单片机的串口是TTL电平的,两者之间必须有一个电平转换电路,我们采用了专用芯片MAX232进行转换,虽然也可以用几个三极管进行模拟转换,但是还是用专用芯片更简单可靠。我们采用了三线制连接串口,也就是说和电脑的9针串口只连接其中的3根线:第5脚的GND、第2脚的RXD、第3脚的TXD。这是最简单的连接方法,但是对我们来说已经足够使用了,电路如下图所示,MAX232的第10脚和单片机的11脚连接,第9脚和单片机的10脚连接,第15脚和单片机的20脚连接。 串口通讯的硬件电路如上图所示 在制作电路前我们先来看看要用的MAX232,这里我们不去具体讨论它,只要知道它是TTL和RS232电平相互转换的芯片和基本的引脚接线功能就行了。通常我会用两个小功率晶体管加少量的电路去替换MAX232,可以省一点,效果也不错,下图就是MAX232的基本接线图。

按图7-3加上MAX232就可以了。这大热天的拿烙铁焊焊,还真的是热气迫人来呀:P串口座用DB9的母头,这样就可以用买来的PC串口延长线进行和电脑相连接,也可以直接接到电脑com口上。

为了能够在电脑端看到单片机发出的数据,我们必须借助一个WINDOWS软件进行观察,这里我们利用一个免费的电脑串口调试软件。本串口软件在本网站https://www.wendangku.net/doc/da16440268.html,可以找到 软件界面如上图,我们先要设置一下串口通讯的参数,将波特率调整为4800,勾选十六进制显示。串口选择为COM1,当然将网站提供的51单片机实验板的串口也要和电脑的COM1连接,将烧写有以下程序的单片机插入单片机实验板的万能插座中,并接通51单片机实验板的电源。

UART串口通信设计实例

2.5 UART串口通信设计实例(1) 接下来用刚才采用的方法设计一个典型实例。在一般的嵌入式开发和FPGA设计中,串口UART是使用非常频繁的一种调试手段。下面我们将使用Verilog RTL编程设计一个串口收发模块。这个实例虽然简单,但是在后续的调试开发中,串口使用的次数比较多,这里阐明它的设计方案,不仅仅是为了讲解RTL编程,而且为了后续使用兼容ARM9内核实现嵌入式开发。 串口在一般的台式机上都会有。随着笔记本电脑的使用,一般会采用USB转串口的方案虚拟一个串口供笔记本使用。图2-7为UART串口的结构图。串口具有9个引脚,但是真正连接入FPGA开发板的一般只有两个引脚。这两个引脚是:发送引脚TxD和接收引脚RxD。由于是串行发送数据,因此如果开发板发送数据的话,则要通过TxD线1 bit接着1 bit 发送。在接收时,同样通过RxD引脚1 bit接着1 bit接收。 再看看串口发送/接收的数据格式(见图2-8)。在TxD或RxD这样的单线上,是从一个周期的低电平开始,以一个周期的高电平结束的。它中间包含8个周期的数据位和一个周期针对8位数据的奇偶校验位。每次传送一字节数据,它包含的8位是由低位开始传送,最后一位传送的是第7位。

这个设计有两个目的:一是从串口中接收数据,发送到输出端口。接收的时候是串行的,也就是一个接一个的;但是发送到输出端口时,我们希望是8位放在一起,成为并行状态(见图2-10)。我们知道,串口中出现信号,是没有先兆的。如果出现了串行数据,则如何通知到输出端口呢?我们引入“接收有效”端口。“接收有效”端口在一般情况下都是低电平,一旦有数据到来时,它就变成高电平。下一个模块在得知“接收有效”信号为高电平时,它就明白:新到了一个字节的数据,放在“接收字节”端口里面。

基于单片机的串口通信模块设计

1 绪论 1.1 研究背景 通信是指不同的独立系统利用线路互相交换数据,它的主要目的是将数据从一端传送到另一端,实现数据的交换。在现代工业控制中,通常采用计算机作为上位机与下层的实时控制与监测设备进行通讯。现场数据必须通过一个数据收集器传给上位机,同样上位机向现场设备发命令也必须通过数据收集器。串行通信因其结构简单、执行速度快、抗干扰能力强等优点,已被广泛应用于数据采集和过程控制等领域。 计算机与外界的信息交换称为通信。基本的通信方式有并行通信和串行通信两种。串行通信是指一条信息额各位数据被逐位按顺序传送的通信方式。串行通信的特点是:数据位传送,按位顺序进行,最少只需要一根传输线即可完成,成本低但传送速度快,串行通信的距离可以从几米到几千米。 随着计算机技术尤其是单片微型机技术的发展,人们已越来越多地采用单片机来对一些工业控制系统中如温度、流量和压力等参数进行监测和控制。PC机具有强大的监控和管理能力,而单片机则具有快速及灵和的控制特点,通过PC 机的RS-232串行接口与外部设备进行通信,是许多测控系统中常用的一种通信解决方案。而随着USB接口技术的成熟和使用的普及,由于USB 接口有着 RS-232(DB-9)串口无法比拟的优点,RS-232(DB-9)串口正在逐步地为USB 接口所替代。而在现在的大多数笔记本电脑中,出于节省物理空间和用处不大等原因,RS-232(DB-9)串口已不再设置,这就约束了基于RS-232(DB-9)串口与PC 机联络的单片机设备的使用围。当前USB接口逐步取代RS-232(DB-9)串口已是大势所趋,单片机同计算机的USB通信在实际工作中的应用围也将越来越广。本文所介

51单片机与串口通信(含代码)

51单片机与串口通信(含代码) 串口调试 1. 发送:向总线上发命令 2. 接收:从总线接收命令,并分析是地址还是数据。 3. 定时发送:从内存中取数并向主机发送. 经过调试,以上功能基本实现,目前可以通过上位机对单片机进行实时控制。 程序如下: //这是一个单片机C51串口接收(中断)和发送例程,可以用来测试51单片机的中断接收 //和查询发送,另外我觉得发送没有必要用中断,因为程序的开销是一样的 #i nclude #i nclude #i nclude #define INBUF_LEN 4 //数据长度 unsigned char inbuf1[INBUF_LEN]; unsigned char checksum,count3 , flag,temp,ch; bit read_flag=0; sbit cp=P1^1; sbit DIR=P1^2; int i; unsigned int xdata *RAMDATA; /*定义RAM地址指针*/ unsigned char a[6] ={0x11,0x22,0x33,0x44,0x55,0x66} ; void init_serialcomm(void) { SCON=0x50; //在11.0592MHz下,设置串行口波特率为9600,方式1,并允许接收

PCON=0x00; ES=1; TMOD=0x21; //定时器工作于方式2,自动装载方式TH0=(65536-1000)%256; TL0=(65536-1000)/256; TL1=0xfd; TH1=0xfd; ET0=1; TR0=1; TR1=1; // TI=0; EA=1; // TI=1; RAMDATA=0x1F45; } void serial () interrupt 4 using 3 { if(RI) { RI=0; ch=SBUF; TI=1; //置SBUF空 switch(ch) { case 0x01 :printf("A"); TI=0;break; case 0x02 :printf("B"); TI=0;break; case 0x03 :printf("C"); TI=0;break; case 0x04 :printf("D"); TI=0;break; default :printf("fg"); TI=0;break; } }

实验单片机与PC机串口通信

实验单片机与PC机串口通信(C51编程)实验 要求: 1、掌握串行口的控制与状态寄存器SCON 2、掌握特殊功能寄存器PCON 3、掌握串行口的工作方式及其设置 4、掌握串行口的波特率(bondrate)选择 任务: 1、实现PC机发送一个字符给单片机,单片机接收到后即在个位、十位数码管上进行显示,同时将其回发给PC机。要求:单片机收到PC机发来的信号后用串口中断方式处理,而单片机回发给PC机时用查询方式。 采用软件仿真的方式完成,用串口调试助手和KEIL C,或串口调试助手和PROTEUS分别仿真。 需要用到以下软件:KEIL,VSPDXP5(虚拟串口软件),串口调试助手,Proteus。 (1)虚拟串口软件、串口调试助手和KEIL C的联调 首先在KEIL里编译写好的程序。

打开VSPD,界面如下图所示:(注明:这个软件用来进行串口的虚拟实现。在其网站上可以下载,但使用期为2周)。 左边栏最上面的是电脑自带的物理串口。点右边的addpair,可以添加成对的串口。一对串口已经虚拟互联了,如果添加的是COM3、COM4,用COM3发送数据,COM4就可以接收数据,反过来也可以。 接下来的一步很关键。把KEIL和虚拟出来的串口绑定。现在把COM3和KEIL绑定。在KEIL中进入DEBUG模式。在最下面的COMMAND命令行,输入 modecom39600,0,8,1 %分别设置com3的波特率、奇偶校验 位、数据位、停止位 assigncom3sout %把单片机的串口和COM3绑定到一 起。因为所用的单片机是

(以上参数设置注意要和所编程序中设置一致!) 打开串口调试助手 可以看到虚拟出来的串口COM3、COM4,选择COM4,设置为波特率9600,无校验位、8位数据位,1位停止位(和COM3、程序里的设置一样)。打开COM4。 现在就可以开始调试串口发送接收程序了。可以通过KEIL发送数据,在串口调试助手中就可以显示出来。也可以通过串口调试助手发送数据,在KEIL中接收。 实验实现PC机发送一个字符给单片机,单片机接收到后将其回发给PC机。在调试助手上(模拟PC)发送数据,单片机收到后将收到的结果回送到调试助手上。 2、以下在Proteus和串口调试助手实现的结果: 将编译好的HEX程序加载到Proteus中,注意这里需要加上串口模块,用来进行串行通信参数的设置。 点击串口,可以对串口进行设置: 用串口调试助手发送数据,即可看到仿真结果。 实验参考程序源文件在exp2-comm文件夹中。

WIN_API串口通信详细讲解带范例程序说明

WIN32 API串口通讯实例教程 第一节实现串口通讯的函数及串口编程简介 API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作。常用函数及作用下: 函数名作用 CreateFile 打开串口 GetCommState 检测串口设置 SetCommState 设置串口 BuilderCommDCB 用字符串中的值来填充设备控制块 GetCommTimeouts 检测通信超时设置 SetCommTimeouts 设置通信超时参数 SetCommMask 设定被监控事件 WaitCommEvent 等待被监控事件发生 WaitForMultipleObjects 等待多个被监测对象的结果 WriteFile 发送数据 ReadFile 接收数据 GetOverlappedResult 返回最后重叠(异步)操作结果 PurgeComm 清空串口缓冲区,退出所有相关操作 ClearCommError 更新串口状态结构体,并清除所有串口硬件错误 CloseHandle 关闭串行口 用Windows API 编写串口程序本身是有巨大优点的,因为控制能力会更强,效率也会更高。 API编写串口,过程一般是这样的: 1、创建串口句柄,用CreateFile; 2、对串口的参数进行设置,其中比较重要的是波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止位(StopBits),当然,重要的还有端口号(Port); 3、然后对串口进行相应的读写操作,这时候用到ReadFile和WriteFile函数; 4、读写结束后,要关闭串口句柄,用CloseFile。 下面依次讲述各个步骤的过程。

基于51单片机的双机串行通信课程设计 1000110061

基于AT89C51单片机的双机串行通信设计 姓名:杨应伟 学号:100110061 专业:机械设计制造及其制动化 班级:机电二班

前言 单片机广泛应用于仪器仪表、家用电器、医用设备、航空航天、专用设备的智能化管理及过程控制等领域随着计算机技术的发展及工业自动化水平的提高, 在许多场合采用单机控制已不能满足现场要求,因而必须采用多机控制的形式,而多机控制主要通过多个单片机之间的串行通信实现。串行通信作为单片机之间常用的通信方法之一, 由于其通信编程灵活、硬件简洁并遵循统一的标准, 因此其在工业控制领域得到了广泛的应用。 在测控系统和工程应用中,常遇到多项任务需同时执行的情况,因而主从式多机分布式系统成为现代工业广泛应用的模式。单片机功能强、体积小、价格低廉、开发应用方便,尤其具有全双工串行通讯的特点,在工业控制、数据采集、智能仪器仪表、家用电器方面都有广泛的应用。同时,IBM-PC机正好补充单片机人机对话和外围设备薄弱的缺陷。各单片机独立完成数据采集处理和控制任务,同时通过通信接口将数据传给PC机,PC机将这些数据进行处理、显示或打印,把各种控制命令传给单片机,以实现集中管理和最优控制。串行通信是单片机的一个重要应用,本次课程设计就是要利用单片机来完成一个系统,实现爽片单片机床航通信,通信的结果使用数码管进行显示,数码管采用查表方式显示,两个单片机之间采用RS-232进行双击通信。 在通信过程中,使用通信协议进行通信。在测控系统和工程应用中,常遇到多项任务需同时执行的情况,因而主从式多机分布式系统成为现代工业广泛应用的模式。单片机功能强、体积小、价格低廉、开发应用方便,尤其具有全双工串行通讯的特点,在工业控制、数据采集、智能仪器仪表、家用电器方面都有广泛的应用。同时,IBM-PC机正好补充单片机人机对话和外围设备薄弱的缺陷。各单片机独立完成数据采集处理和控制任务,同时通过通信接口将数据传给PC机,PC机将这些数据进行处理、显示或打印,把各种控制命令传给单片机,以实现集中管理和最优控制。 串行通信是单片机的一个重要应用,本次课程设计就是要利用单片机来完成一个系统,实现爽片单片机床航通信,通信的结果使用数码管进行显示,数码管采用查表方式显示,两个单片机之间采用RS-232进行双击通信。在通信过程中,使用通信协议进行通信。

单片机之间的串行通讯

桂林电子科技大学微机与单片机接口 设 计 报 告 指导教师:吴兆华 学生:王晓鹏 学号:092011211 2010 年6月25日

一、设计题目 单片机之间的串行通讯 二、设计内容与要求 实现两个单片机之间的串行通讯,并用数码管分别显示两个单片机的数据,以验证通讯是否成功。 三、设计目的意义 当前,各种简单实用的通讯系统,使其达到数据传送稳在测控系统和工程应用中,常遇到多项任务需同时执行的情况,即主从式多机分布式系统成为现代工业广泛应用的模式。由于单片机功能强、体积小、价格低廉、开发应用方便,尤其具有全双工串行通讯的特点,在工业控制、数据采集、智能仪器仪表等方面都有广泛的应用。利用单片机的串行通信技术设计一定可靠,使用方便,可扩展为DCS系统应用于工业领域,将有广泛的实际应用价值。单片机除了需要外围器件完成特定的功能外,在很多的应用中单片机之间通讯及单片机和外围器件之间的数据交换,多年来国内外在信息的处理特别是控制和信息传输通讯领域有着十分广泛的应用。 四、系统硬件原理图 图 1 系统硬件原理图 五、程序流程图与源程序 软件的设计是重要的。它的好坏直接关系设计的成功与否。软件是用C

语言完成的,需要能熟练的掌握C语言,还要熟悉AT89S52单片机。从程序流程图、通信协议、波特率计算、编写程序、编译、和烧入软件的操作,到最后的调试,是很复杂的。下面作详细介绍: 1、程序流程图 图2 程序流程图 2、 C语言程序 (1)主机的程序 #include /********变量说明***********/ unsigned char i,j,k,KEY,flag; unsigned char time1,time2,time3; unsigned int code ; a[11]={0x00,0x3F,0x7D,0x5B,0x5B,0x00,0x76,0x79,0x38,0x38,0x3f

相关文档