串口开发

串口开发小小心得

本人新入行,写的也只是很肤浅的自己的一点点理解。欢迎批评指正,qq:15065328.email:zxiki@163.com。msn:zxiki@hotmail.com。如果这些经验能对您有所帮助,我将非常荣幸。欢迎转载(可能抬举自己了),但请把以上文字一并保留。谢谢!


项目(先这么称呼吧)简介,简单的来说就是计算机通过串口分别控制4个二极管的亮度。
上位机部分:只说说我用到的一些函数,和遇到的问题。基本的比如什么是异步通讯啦之类的就不说了,随便网上一搜能找一箩筐!
下边是一些函数:
因为是最简单的应用,所以用到的函数也都是最最简单的一些,都是非常容易理解的。只是通过计算机向51发送指令所以连ReadFile()都没用到。省了很多事。。。。。。
1.CreateFile()
功能:打开串口设备
函数原型
HANDLE   CreateFile(
LPCTSTR   lpFileName,   //   串口名称字符串;如:   "COM1"   或   "COM2"
DWORD   dwDesiredAccess,   //   设置读写属性(访问模式   );一般为   GENERIC_READ ¦GENERIC_WRITE,
DWORD   dwShareMode,   //   共享模式;"必须"为   0,   即不能共享
LPSECURITY_ATTRIBUTES   lpSecurityAttributes,   //   安全属性;一般为NULL
DWORD   dwCreationDistribution,   //   创建方式,串口设置必须设置此值;   在这里"必须"为   OPEN_EXISTING
DWORD   dwFlagsAndAttributes,   //   文件属性和标志;在这里我们设置成FILE_FLAG_OVERLAPPED   ,实现异步I/O关于Overlapped   I/O模型,自己上网搜了去理解吧,我自己也说不清楚,懵懂的很。
HANDLE   hTemplateFile   //   临时文件的句柄,通常为NULL    
);
说明:
如果调用成功,那么该函数返回文件的句柄,如果调用失败,则函数返回INVALID_HANDLE_VALUE。

2.GetCommState()
功能:获得串口状态
BOOL   GetCommState(
HANDLE   hFile,   //   handle   of   communications   device
LPDCB   lpDCB   //   address   of   device-control   block   structure
);

3.SetCommState()
功能:设置串口状态 
BOOL   SetCommState(
HANDLE   hFile,   //   handle   of   communications   device
LPDCB   lpDCB   //   address   of   device-control   block   structure
);
说明:
在打开通信设备句柄后,常常需要对串行口进行一些初始化工作。这需要通过一个DCB结构来进行。DCB结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息。在查询或配置置串行口的属性时,都要用DCB结构来作为缓冲区。
调用GetCommState函数可以获得串口的配置,该函数把当前配置填充到一个DCB结构中。一般在用CreateFile打开串行口后,可以调用GetCommState函数来获取串行口的初始配置。要修改串行口的配置,应该先修改DCB结构,然后再调用SetCommState函数用指定的DCB结构来设置串行口
For   example:
DCB   dcb;
memset(&dec,0,sizeof(dcb));
if(!GetCommState(HComm,&dcb))//获取当前DCB配置
  return   FALSE;  
dcb.BaudRate   =   CBR_9600;//修改数据传输率。。。。这里还有很多参数可以修改,比如,停止位,有无校验等等,具体参见dcb结构。
............
if(SetCommState(hComm,&dcb))//设置新参数
......         //错误处理
4.WriteFile()  
功能:来将资料写入Serial   port.  
函数原型:
BOOL   WriteFile(
HANDLE   hFile,   //   handle   to   file   to   write   to
LPCVOID   lpBuffer,   //   写如字符串的首地址
DWORD   nNumberOfBytesToWrite,   //   要写如字符的个数
LPDWORD   lpNumberOfBytesWritten,   //   实际写入字节数,为一个int型指针
LPOVERLAPPED   lpOverlapped   //   i/o重构结构,我讲不清楚,sorry
);

说明:
      ReadFile函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作。
而WriteFile函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作。
当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的dwMilliseconds参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值。注意GetOverlappedResult不能设置等待的时限,因此如果hEvent成员无信号,则该函数将一直等待下去

5.PurgeComm()
功能:终止目前正在进行的读或写的动作
函数原型:
BOOL   PurgeComm(
HANDLE   hFile,   //   handle   of   communications   resource
DWORD   dwFlags   //   action   to   perform
);
参数说明:
HANDLE   hFile,//串口名称字符串
dwFlags   共有四种   flags:
  PURGE_TXABORT:   终止目前正在进行的(背景)写入动作
  PURGE_RXABORT:   终正目前正在进行的(背景)读取动作
  PURGE_TXCLEAR:   flush   写入的   buffer
  PURGE_TXCLEAR:   flush   读取的   buffer
调用PurgeComm函数可以终止正在进行的读写操作,该函数还会清除输入或输出缓冲区中的内容。

6.ClearCommError()  
功能:   从字面上的意思看来,   它是用来清除错误情况用的,   但是实际上它还可以拿来取得目前通讯设备的一些信息.
函数原型:
BOOL   ClearCommError(
HANDLE   hFile,   //   handle   to   communications   device
LPDWORD   lpErrors,   //   pointer   to   variable   to   receive   error   codes
LPCOMSTAT   lpStat   //   pointer   to   buffer   for   communications   status
);
说明:
 在调用ReadFile和WriteFile之前,线程应该调用ClearCommError函数清除错误标志。
该函数负责报告指定的错误和设备的当前状态。  
7CloseHandle();
功能:关闭串口
BOOL   CloseHandle(HANDLE   hObject   //   handle   to   object   to   close)


下面是我在bcb里的一些具体实现:


1. 打开串口
void   __fastcall   TForm1::Button1Click(TObject   *Sender)
{


                hCom=CreateFile(   "COM2",   //文件名
                                                  GENERIC_READ ¦GENERIC_WRITE,//访问模式允许读写
                                                  0,   //此项必须是0
                                                  0,//无安全参数
                                                  OPEN_EXISTING,//创建方式
                                                  FILE_FLAG_OVERLAPPED,//异步工作方式
                                                  0);
                if   (hCom==INVALID_HANDLE_VALUE)
                {
                                ShowMessage("Can   not   open   the   port   !");
                                CloseHandle(hCom);
                                hCom   =   0;
                                return;
                }
                else   ShowMessage("COM2   open   success!");
               
                if(!GetCommState(hCom,&dcb))   //获得串口设置并用它填充dcb结构体
                                ShowMessage("GetCommState   failed");

                if   (!SetupComm(hCom,1024,1024))   //设置输入输出缓冲区大小
                                ShowMessage("SetupComm   failed");

                dcb.BaudRate=9600;
                dcb.fParity=0;
                dcb.Parity=NOPARITY;
                dcb.StopBits=ONESTOPBIT;
                dcb.ByteSize=8;


                if(!SetCommState(hCom,&dcb))   //重新配置串口
                            ShowMessage("SetCommState   failed");

                SetCommMask(hCom,EV_TXEMPTY);   //EV_RXCHAR ¦
                memset(&os,0,sizeof(OVERLAPPED));
                os.hEvent=CreateEvent(NULL,true,false,NULL);

}
2. 发送一个字节
void   sendchar(char   ch)
{     DWORD   BytesSent=0;
      OverWrite.Offset=0;
      OverWrite.OffsetHigh=0;

      BOOL   bResult;
    bResult=WriteFile(hCom,
                        &ch,
                        1,
                        &BytesSent,
                        &OverWrite);
    if(bResult)   return;
    DWORD   dwError=GetLastError();
    if(dwError!=ERROR_IO_PENDING)
    {
        ShowMessage("写字符错误,请确认串口以打开!");
        return;
    }
    if(!GetOverlappedResult(hCom,&OverWrite,&BytesSent,TRUE))
    {
          ShowMessage("写字符错误,请确认串口以打开!");
          return;
    }
    }              
上位机的程序就这么样了。。。。。

单片机源码:这是根据上位机的程序来写的。
写不下那么多了。。。

仿真:用的是proteus,串口调试助手,虚拟串口这三个软件。
 
这是虚拟串口的软件。
 
这个,串口调试助手

具体怎么用,一摸索就知道了,要说明的是仿真是串口调试助手的“串口”选择“COM3”,protues中串口要选择“COM4”,其他比如波特率之类的设置就不废话了。
   
另外注意的是,51的rxd接rs232rxd,txd接txd,这里,我十分不明白。。。。
 
就这些啦,哈哈,第一次写点东西,想想以后回来自己看看肯定会笑话自己的,不过,没什么,不这样哪有进步~虽然很稚嫩,但是是自己的~要指导的请联系我,感激不尽! 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值