热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

串口操作---C代码

com.h#ifndef__COM_H__#define__COM_H__#ifdef__cplusplusextern"C"{#endif打开串口intOpen

com.h

#ifndef __COM_H__
#define __COM_H__

#ifdef __cplusplus
extern "C" {
#endif
//打开串口
int OpenComPort(int port, int userBaudRate);//打开串口
//关闭串口
void CloseComPort(void);//关闭串口
int ReadComBlock(unsigned char *buf,int maxLen);
void _DoRxTx(void *args);

int ReadComBuf(unsigned char *buf, int maxLen);//读串口
int WriteComBuf(unsigned char *buf, int maxLen);//写串口
int WriteComByte(unsigned char byte);//往串口写一个字节
int ReadComByte(unsigned char byte);//从串口读取一个字节
void resetComPort(void);//重置串口
void resetRTS(void);//resetRTS_sub(150,20);
int ReceiveMessage(unsigned char *pBuf, int maxlen, int time);//带时间的接收操作
void resetRTSLowHigh(int Low,int High);//CTS高低电平操作
void SetRTSControlEnable(bool enable);//CTS操作:enable=true:上拉,false:下拉

#ifdef __cplusplus
}
#endif

#endif

com.c:

/*******************************************************************************
* FileName :com.cpp
* Author :
* Description :
* Create Data : 2005-6-28 9:09
* modify History:
*******************************************************************************/

//#include
//#include
//#include
#include
#include
#include

#include "com.h"
//#include "common.h"
//#include "Debug.h"
#include
#include

#define DelayXmsSleep
//#define EB_PrintfDebug_Printf

#define COM_OVERTIME5// 此延时控制Uart_ReadBuf中每次读串口的延时:步长为10ms
#define IS_OVERLAPPED_IO (TRUE)
#define MAX_BLOCK_SIZE (0x20000) // 缓冲区最大128Kbytes
#define MAX_Uart_SIZE (4096) // 缓冲区最大128Kbytes

HANDLE idComDev;
OVERLAPPED osWrite,osRead;
volatile int isCOnnected=FALSE;

volatile int txEmpty=TRUE;

unsigned char rxBuf[MAX_Uart_SIZE+1];
unsigned char RoundBuf[MAX_BLOCK_SIZE];

struct {
intEnable;// 允许接收
int Ok;// 接收成功
intOff1;// 缓冲区当前有效数据 开始偏移
intOff2;// 缓冲区当前有效数据 末尾偏移
unsigned intCnt;// 缓冲区当前有效数据 计数器=Off2-Off1
}rxFlag;

//打开串口
int OpenComPort(int port, int userBaudRate)
//port=0,1,2,3
{
//TCHAR *textCom[]={TEXT("COM1"),TEXT("COM2"),TEXT("COM3"),TEXT("COM4"),TEXT("COM5"),TEXT("COM6"),TEXT("COM7"),TEXT("COM8"),TEXT("COM9"),TEXT("\\\\.\\COM10"),TEXT("\\\\.\\COM11"),TEXT("\\\\.\\COM12")};
TCHAR textCom[255][14];
int i;

DCB dcb;
COMMTIMEOUTS commTimeOuts;

for(i=0;i<255;i++)
{
swprintf(textCom[i],14,L"\\\\.\\COM%d",i);
}

if(isConnected)// 若重复打开时先关闭
{
CloseComPort();
/*Debug_Printf("\n[OK:Already Opened. Close first!]");*/
}
//====================================================
osRead.Offset=0;
osRead.OffsetHigh=0;
osWrite.Offset=0;
osWrite.OffsetHigh=0;

osRead.hEvent = CreateEvent(NULL,TRUE/*bManualReset*/,FALSE,NULL);
//manual reset event object should be used.
//So, system can make the event objecte nonsignalled.
//osRead.hEvent & osWrite.hEvent may be used to check the completion of
// WriteFile() & ReadFile(). But, the DNW doesn't use this feature.
if(osRead.hEvent==NULL)
{
/*Debug_Printf("\n[ERROR:CreateEvent for osRead.]");*/
return FALSE;
}

osWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if(osWrite.hEvent==NULL)
{
/*Debug_Printf("\n[ERROR:CreateEvent for osWrite.]");*/
return FALSE;
}


//====================================================
idComDev=CreateFile(textCom[port],
GENERIC_READ|GENERIC_WRITE,
0, //exclusive access
/*FILE_SHARE_READ|FILE_SHARE_WRITE,*/
NULL,
OPEN_EXISTING,
#if IS_OVERLAPPED_IO
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
#else
/*FILE_ATTRIBUTE_NORMAL,*/ 0,
#endif
NULL);

if(idComDev==INVALID_HANDLE_VALUE)
{
/*Debug_Printf("\n[ERROR:CreateFile for opening COM port.]" );*/
return FALSE;
}

SetCommMask(idComDev,EV_RXCHAR);
SetupComm(idComDev,MAX_Uart_SIZE,MAX_Uart_SIZE);
PurgeComm(idComDev,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

commTimeOuts.ReadIntervalTimeout=0xffffffff;
commTimeOuts.ReadTotalTimeoutMultiplier=0;
commTimeOuts.ReadTotalTimeoutCOnstant=1000;
commTimeOuts.WriteTotalTimeoutMultiplier=0;
commTimeOuts.WriteTotalTimeoutCOnstant=1000;
SetCommTimeouts(idComDev,&commTimeOuts);

//====================================================
dcb.DCBlength=sizeof(DCB);
GetCommState(idComDev,&dcb);

dcb.fBinary=TRUE;
dcb.fParity=FALSE;
dcb.BaudRate=userBaudRate; //CBR_115200;
dcb.ByteSize=8;
dcb.Parity=0;
dcb.StopBits=0;
dcb.fDtrCOntrol=DTR_CONTROL_ENABLE;//DTR_CONTROL_DISABLE; //2009-9-4 9:36:26 zzt
dcb.fRtsCOntrol=RTS_CONTROL_DISABLE;
dcb.fOutxCtsFlow=0;
dcb.fOutxDsrFlow=0;

if(SetCommState(idComDev,&dcb)==TRUE)
{
isCOnnected=TRUE;
_beginthread( (void (*)(void *))_DoRxTx,0x2000,(void *)0);

rxFlag.Off1=0;
rxFlag.Off2=0;
rxFlag.Cnt=0;
rxFlag.Enable=1;// 允许串口接收
/*Debug_Printf("\n[OK:OpenComPort port=%d baud=%d.]", port, userBaudRate);*/

return TRUE;
}
else
{
isCOnnected=FALSE;
CloseHandle(idComDev);
return FALSE;
}
}


void resetComPort(void)
{
rxFlag.Off1=0;
rxFlag.Off2=0;
rxFlag.Cnt=0;
rxFlag.Enable=1;// 允许串口接收
rxFlag.Ok=0;// 允许串口接收
}

static void resetRTS_sub(int Low,int High)
{
DCB dcb;

//====================================================
dcb.DCBlength=sizeof(DCB);

GetCommState(idComDev,&dcb);
dcb.fRtsCOntrol=RTS_CONTROL_ENABLE;
SetCommState(idComDev,&dcb);

DelayXms(Low);

GetCommState(idComDev,&dcb);
dcb.fRtsCOntrol=RTS_CONTROL_DISABLE;
SetCommState(idComDev,&dcb);

DelayXms(High);
}

void SetRTSControlEnable(bool enable)
{
DCB dcb;
dcb.DCBlength=sizeof(DCB);
GetCommState(idComDev,&dcb);
if(true ==enable)
{
dcb.fRtsCOntrol=RTS_CONTROL_ENABLE;
}
else
{
dcb.fRtsCOntrol=RTS_CONTROL_DISABLE;
}
SetCommState(idComDev,&dcb);
}
void resetRTS(void)
{
resetRTS_sub(150,20);
}
void resetRTSLowHigh(int Low,int High)
{
return resetRTS_sub(Low,High);
}
//关闭串口
void CloseComPort(void)
{
if(isConnected)
{
isCOnnected=FALSE;
SetCommMask(idComDev,0);
//disable event notification and wait for thread to halt
EscapeCommFunction(idComDev,CLRDTR);
PurgeComm(idComDev,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
CloseHandle(idComDev);

CloseHandle(osRead.hEvent);
CloseHandle(osWrite.hEvent);
}

Sleep(100);
//wait until CloseComPort() effective.
//If not, OpenComPort()::CreateFile(...) will fail.

}

//读取串口块
int ReadComBlock(unsigned char *buf,int maxLen)
{
BOOL fReadStat;
COMSTAT comStat;
DWORD dwErrorFlags;
DWORD dwLength;

ClearCommError(idComDev,&dwErrorFlags,&comStat);
dwLength=min((DWORD)maxLen,comStat.cbInQue);
if(dwLength>0)
{
#if IS_OVERLAPPED_IO
fReadStat=ReadFile(idComDev,buf,dwLength,&dwLength,&osRead);
if(!fReadStat) //Apr.28.2003:GetOverlappedResult() may be needed.
{
//By experiment, fReadStat was always TRUE,of course, and the following was never executed.
/*Debug_Printf("\n[RX_RD_WAIT]\n" ); */
if(GetLastError()==ERROR_IO_PENDING)
{
GetOverlappedResult(idComDev,&osRead,&dwLength,TRUE);
}
else
{
/*Debug_Printf("[RXERR]" );*/
}
}
#else
fReadStat=ReadFile(idComDev,buf,dwLength,&dwLength,NULL);
if(!fReadStat)
{
Debug_Printf("[RXERR]" );
}
#endif
}
return dwLength;
}


void _DoRxTx(void *args)
{
OVERLAPPED os;
DWORD dwEvtMask;
int nLength;
BOOL fStat;
DWORD temp;

int i;

memset(&os,0,sizeof(OVERLAPPED));
os.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if(os.hEvent==NULL)
{
/*EB_Printf("[ERROR:DoRxTx os.hEvent]\n");*/
_endthread();
}

if(!SetCommMask(idComDev,EV_RXCHAR|EV_TXEMPTY|EV_ERR))
{
/*EB_Printf("[ERROR:SetCommMask()]\n");*/
CloseHandle(os.hEvent);
_endthread();
}

while(isConnected)
{
dwEvtMask=0;
#if IS_OVERLAPPED_IO
fStat=WaitCommEvent(idComDev,&dwEvtMask,&os);
//Apr.28.2003: fStat should be checked for the cpu time saving.
if(!fStat) //Apr.28.2003:GetOverlappedResult() is needed.
{
//By experiment. Only when there was no signalled event, the following was executed.
//EB_Printf("\n[WaitCommEvent=false]\n");
if(GetLastError()==ERROR_IO_PENDING)
{
GetOverlappedResult(idComDev,&os,&temp,TRUE);
}
else
{
/*EB_Printf("[RXTX_THREAD_ERR]" );*/
}
}
#else
WaitCommEvent(idComDev,&dwEvtMask,NULL); //wait until any event is occurred.
#endif

if( (dwEvtMask & EV_TXEMPTY) == EV_TXEMPTY )
txEmpty=TRUE;

if((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
{
if(rxFlag.Enable) {
do{ //Apr.28.2003:The caveat on MSDN,"Serial Communications in Win32" recommends while();
if( nLength=ReadComBlock(rxBuf,MAX_Uart_SIZE) )
{
// if(nLength>=MAX_BLOCK_SIZE /*for debug*/)
// {
//EB_Printf("\n[ERROR1:nLength>MAX]\n");
// rxFlag.Off1=0;
// rxFlag.Off2=0;
// rxFlag.Cnt=0;
// }
// else
{
rxFlag.Ok=0;
for(i=0; iif(rxFlag.Cnt >= MAX_BLOCK_SIZE) {
/*EB_Printf("\n[ERROR2:nLength>MAX]\n");*/
rxFlag.Off1=0;
rxFlag.Off2=0;
rxFlag.Cnt=0;
}
rxFlag.Cnt++;
RoundBuf[rxFlag.Off2++] = rxBuf[i];
rxFlag.Off2 %= MAX_BLOCK_SIZE;
}
rxFlag.Ok=1;
}
}
}while(nLength);
}
}

// Clear OVERRUN condition.
// If OVERRUN error is occurred,the tx/rx will be locked.
if(dwEvtMask & EV_ERR)
{
COMSTAT comStat;
DWORD dwErrorFlags;
ClearCommError(idComDev,&dwErrorFlags,&comStat);
//EB_Printf("[DBG:EV_ERR=%x]\n",dwErrorFlags);
}
}
CloseHandle(os.hEvent);
_endthread();
}

//读取串口缓冲区
int ReadComBuf(unsigned char *buf, int maxLen)
{
unsigned int time=0;
unsigned int i, len;

if(!rxFlag.Enable)return 0;
while(rxFlag.Cnt <(unsigned int)maxLen){//delay 50ms
Sleep(10);
if( time++ >= COM_OVERTIME )break;
}
if(0==rxFlag.Ok)return 0;

len =(rxFlag.Cnt > (unsigned int)maxLen)? maxLen:rxFlag.Cnt;
for(i=0; i*(buf+i)= RoundBuf[rxFlag.Off1++];
rxFlag.Cnt--;
rxFlag.Off1 %= MAX_BLOCK_SIZE;
}
return len;
}
//写串口缓冲区
int WriteComBuf(unsigned char *buf, int maxLen)
{
void *txBlk;
DWORD txBlkSize;
DWORD temp;

while(txEmpty==FALSE);
txBlk=buf;
txBlkSize=maxLen;

//Debug_Printf("[OK:WriteComBuf len=%d.]\n", maxLen);
//for(temp=0; temp//Debug_Printf(" %02x", *(buf+temp));
//}

//txEmpty=FALSE; why needed??? this line should be removed.
#if IS_OVERLAPPED_IO
WriteFile(idComDev,txBlk,txBlkSize,&temp,&osWrite);
#else
WriteFile(idComDev,txBlk,txBlkSize,&temp,NULL);
#endif
while(txEmpty==FALSE);
return TRUE;
}


//往串口写一个字节
int WriteComByte(unsigned char byte)
{
return WriteComBuf(&byte, 1);
}
//从串口读取一个字节
int ReadComByte(unsigned char byte)
{
return ReadComBuf(&byte, 1);
}


/*******************************************************************************
* Fuc Name : PC_DelayXms
* Input : num--延时的毫秒数
* Return : void
* Description : PC延时程序,毫秒级
*******************************************************************************/
#include
#include
void PC_DelayXms(int num)
{
LARGE_INTEGER litmp;
LONGLONG QPart1,QPart2;
double dfMinus, dfFreq, dfTim;

QueryPerformanceFrequency(&litmp);
dfFreq = (double)litmp.QuadPart; // 获得计数器的时钟频率
QueryPerformanceCounter(&litmp);
QPart1 = litmp.QuadPart; // 获得初始值
do{
QueryPerformanceCounter(&litmp);
QPart2 = litmp.QuadPart;// 获得中止值
dfMinus = (double)(QPart2-QPart1);
dfTim = dfMinus / dfFreq; // 获得对应的时间值,单位为秒
}while(dfTim<(0.001*num));
}

int ReceiveMessage(unsigned char *pBuf, int maxlen, int time)
{
int ret =0;
DWORD startTime;
int nLen;

startTime=GetTickCount();
int len =0;
while(1)
{
//timeout
if(GetTickCount() -startTime >time)
return 0;

len =ReadComBuf(pBuf,maxlen-1);
if(len)
{
*(pBuf +len) ='\0';
return len;
}
else
{
Sleep(1);
}
}
return 0;
}





推荐阅读
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
author-avatar
手机用户2502887947_784
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有