串口开发小小心得

原创 2007年10月15日 18:00:00

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

项目(先这么称呼吧)简介,简单的来说就是计算机通过串口分别控制4个二极管的亮度。

上位机部分:只说说我用到的一些函数,和遇到的问题。基本的比如什么是异步通讯啦之类的就不说了,随便网上一搜能找一箩筐!

下边是一些函数:

函数名  作用

1.CreateFile 打开串口

2.GetCommState  检测串口设置

3.SetCommState 设置串口

BuilderCommDCB 用字符串中的值来填充设备控制块

GetCommTimeouts 检测通信超时设置

SetCommTimeouts 设置通信超时参数

SetCommMask 设定被监控事件

WaitCommEvent 等待被监控事件发生

WaitForMultipleObjects 等待多个被监测对象的结果

4.WriteFile 发送数据

ReadFile  接收数据

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

5.PurgeComm 清空串口缓冲区,退出所有相关操作

6.ClearCommError 更新串口状态结构体,并清除所有串口硬件错误

7.CloseHandle  关闭串行口

红颜色标出来的是我用到的一些函数,因为是最简单的应用,所以用到的函数也都是最最简单的一些,都是非常容易理解的。只是通过计算机向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函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作。

ReadFileWriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果。例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING。如果GetLastError函数返回ERROR_IO_PENDING,则说明重叠操作还为完成,线程可以等待操作完成。

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

另一种办法是调用GetOverlappedResult函数等待,如果指定该函数的bWait参数为TRUE

那么该函数将等待OVERLAPPED结构的hEvent 事件。GetOverlappedResult可以返回一个OVERLAPPED结构来报告包括实际传输字节在内的重叠操作结果。

如果规定了读/写操作的超时,那么当超过规定时间后,hEvent成员会变成有信号的。因此,在超时发生后,WaitForSingleObjectGetOverlappedResult都会结束等待。WaitForSingleObjectdwMilliseconds参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值。注意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

;

说明:

 在调用ReadFileWriteFile之前,线程应该调用ClearCommError函数清除错误标志。

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

7CloseHandle();

功能:关闭串口

BOOL CloseHandleHANDLE 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!");

        Button1->Enabled=false;

        CheckBox1->Enabled=true;

        CheckBox2->Enabled=true;

        CheckBox3->Enabled=true;

        CheckBox4->Enabled=true;

        CheckBox5->Enabled=true;

 

        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;

  }

  }      

在与51通讯的过程中,一次有计算机发送两个数据给单片机,第一个是控制二极管亮度的数据,第二个是选择控制哪个二极管的数据。为了简单考虑,每次发送过程调用两次send函数。下面的是发送子程序:

void send(char channel,int Vdata)

{     PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);

      sendchar(char(Vdata));

      PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);

      sendchar(channel);

      Sleep(10);

 }

上位机的程序就这么样了。。。。。

 

单片机源码:这是根据上位机的程序来写的。

#include <reg51.h>

 

 

char datax=0;//作为判断接受的数据为控制信号的标志使用

char receive;

sbit a=P3^2;

sbit b=P3^3;

sbit c=P3^4;

sbit d=P3^5;

sbit e=P3^7;

 

void initial(void);

void P3con(char x);

void delay(short ms);

 

void main(void)

{

int i; 

for(i=0;i<5;i++)

  {

    e=0;d=0;c=0;b=0;a=0;P1=0;

    delay(2000);

    a=1;

    b=1;

    c=1;

    d=1;

    e=1;

    P1=0xFF;

    delay(2000);

   

  }

  initial();//串口初始化

  while(1);

}

 

 

void initial(void)      //初始化子程序

{

  IP=0x10;//串口中断优先级高

  IE=0x90;//开中断

  TMOD=0x20;//定时器1 工作模式2

  TH1=253;TL1=253;//设置定时器1初值,波特率为9.6k/s

  SCON=0x50;//串行模式1 8bit异步传输

  PCON=0x7f&PCON;//SMOD=0

  TR1=1;//计时器开

}

 

 

void Sinterrupt(void) interrupt 4 using 3 //串口中断响应程序;

{

  if(TI) TI=0;

  else if(RI)

  {   

     RI=0;

     receive=SBUF;

     delay(10);

     SBUF=receive;

     //delay(10);

     //while(!TI);

     //TI=0;

    if(datax==0)                

      {

        P1=receive;                

        datax++;

        return;

      }

    if(datax==1)                 

     {

        P3con(receive);

        datax=0; 

        return;

     }

  }

}

 

 

void P3con(char x)   //dac0809的片选信号

{

  switch(x)

 {

  case '1': a=1;delay(2);a=0;break;

  case '2': b=1;delay(2);a=0;break;

  case '3': c=1;delay(2);a=0;break;

  case '4': d=1;delay(2);a=0;break;

  case '5': e=1;delay(2);a=0;break;

  default : break;

  }

}

 

 

void delay(int ms)

{

  int i,j;

  for (i=0;i<ms;i++)

    for (j=0;j<120;j++)

    {}

} 

 

这里就不多说了,基本懂得51c的都能看懂。

 

 

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

这是虚拟串口的软件。

这个,串口调试助手

 

具体怎么用,一摸索就知道了,要说明的是仿真是串口调试助手的“串口”选择“COM3”protues中串口要选择“COM4”,其他比如波特率之类的设置就不废话了。

 

 

 

 

 

 

 

 

 

 

 

下面这个是仿真的截图

 

另外注意的是,51rxdrs232rxdtxdtxd,这里,我十分不明白。。。。

就这些啦,哈哈,第一次写点东西,想想以后回来自己看看肯定会笑话自己的,不过,没什么,不这样哪有进步~虽然很稚嫩,但是是自己的~要指导的请联系我,感激不尽!

 

串口通信的心得

串口是我的最爱,成本低,容易实现,连接简单方便。在我设计的硬件中,无一不配置一个串口,在主要功能完成之后,我会在计算机上再编写一个终端软件。这个软件可不只用来监控,我用这个软件完全控制硬件的所有功能,...
  • gzw1623231307
  • gzw1623231307
  • 2017年02月22日 07:16
  • 100

致第一次安装(yong)小小输入法的你

致第一次安装(yong)小小输入法的你目录致第一次安装yong小小输入法的你目录强大全开放的外挂内置输入平台 支持各种编码 方便的词库维护功能 最温情的输入法 本文的题目就参考了百度贴吧「致第一次安装...
  • liming0931
  • liming0931
  • 2016年12月07日 20:55
  • 6227

小小输入法使用小记

从网上得知,适合自定义、折腾的输入法非Rime和小小输入法了,前段时间接触了rime,也集成了小鹤双拼(音形方案),把其余不用的输入方式统统删除了,也罢整个界面调整为简体了,除了不能修改的之外。 以前...
  • liming0931
  • liming0931
  • 2016年12月04日 19:11
  • 3227

SSH框架小小心得

本帖主要目的是了解在开发的过程中,ssh框架应用开发步骤和注意环节,还有就是偶的小小心得,O(∩_∩)O哈哈~ 一、 开发步骤 1.加入struts框架支持(注意命名) 2.加入spring框架...
  • lihushiwoa
  • lihushiwoa
  • 2013年12月07日 11:53
  • 386

stm32gpio寄存器小小心得

寄存器配置io口的时候,一开始总会有很多的疑问。虽然看了某些教程,但是有些东西还是似懂非懂的状态。所以带着深入理解的态度,我再次重温了gpio的配置。 对于STM32F1的IO可以配置成8种模式,三...
  • chanshaan1957
  • chanshaan1957
  • 2017年04月21日 19:06
  • 156

关于适配的一些小小心得(iOS7)

iOS7的view坐标计算与之前不太一样。 1.navibar和statusbar作为一个整块 2.view的原点在整个屏幕的左上角,上面那个块叠在其上面 关于navibar 与 view重叠的解...
  • u012220260
  • u012220260
  • 2013年09月25日 11:09
  • 1244

一个小小的计算器

(一) 需求和规格说明 输入是一个带有括号的四则运算表达式,输出是计算得出的正确计算结果。例如:输入:123+213-67*34+345/23*45*(34+34-345+245+567)回车,然后...
  • CLAYFire
  • CLAYFire
  • 2015年07月13日 16:39
  • 388

VB 串口编程 开发心得

接触vb的串口控件也有一段时间了 经常被它弄得晕头转向 最重要的是死机  死机  死机   其實關鍵在於 寫好接收函數 现将自己的经验写下来供大家参考 1,使用串口   ...
  • zqrhzyj
  • zqrhzyj
  • 2017年07月27日 08:20
  • 553

Android开发心得(一)

Android开发心得之MVC这一个学期在上潘老师的系统设计与分析课程时,我们小组开发了基于安卓平台的电影购票软件。在开发过程中收获了挺多,现在在课程结束前,把其分享出来。 MVC是软件工程中的一种...
  • a1054513777
  • a1054513777
  • 2017年06月10日 21:02
  • 321

iOS开发心得记录1

iOS关于可以window 中key window的使用
  • solerLiang
  • solerLiang
  • 2015年10月21日 11:06
  • 337
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:串口开发小小心得
举报原因:
原因补充:

(最多只允许输入30个字)