⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialbase.c

📁 这是实际项目中的一个串口通信程序. Makefile通过开关, 可使此程序适用于 Linux 和嵌入式 ARM Linux. 代码注释较多. 是学习UART或Serail Port 通信的一个好例子.
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifdef __cplusplus
extern {
#endif

#include "SerialBase.h"

static char m_szComName[12] ="/dev/ttyS0"; // Serial port name, such as COM1 and COM2 
static int  m_bComDevOpen = 0;        //True for being open; False for being close. Serail device.
static int  m_hComDev;        //com port 

//static  HANDLE m_hCommWatchThread;	// identification for CommWatchPorc;
//static  HANDLE m_hCommWatchThreadExit;	// the flag of the exit of CommWatchPorc thread;

static  SafeMsgQue m_AckMsgQue; //the responsive message from APP CPU
static  SafeMsgQue m_RxMsgQue;	//the message received from APP CPU. it is not a responsive message 

static  unsigned char m_szAckCmd[129];

static const unsigned char  m_nPackageHeadLen = 5; // the length of the package head 2 +1 +2
static const unsigned char  m_nPackageTailLen=4;   // the length of the package tail 2 + 2

//the following three variable for  condition variable.
//static    unsigned int  m_nDataTimeout;
//static    pthread_cond_t  m_hDataCond;
//static    pthread_mutex_t m_hDataMutex;  

//sub thread variable.
static  pthread_t  m_hSubThread;

//return value: 0 for false; 1 for success
int InitComDev(char szComName[])
{
//Step 1: to initilize the UART poort
	m_bComDevOpen = 0;
	
    m_hComDev = open(szComName,O_RDWR|O_NOCTTY|O_NDELAY);
    if(m_hComDev <0)
    {
        return 0;
    }

    struct termios tmio;  //set the parameter at 8N1 

    tcgetattr(m_hComDev, &tmio); 

    tmio.c_cflag |= (CLOCAL|CREAD);//Enable the receiver and set local mode.

    //8N1
    tmio.c_cflag &=  ~PARENB;
    tmio.c_cflag &=  ~CSTOPB;
    tmio.c_cflag &=  ~CSIZE;
    tmio.c_cflag |=  CS8 ;
    
   //Disable hardware flow controlmain
   //tmio.c_cflag &=  ~CNEW_RTSCTS;  //for other linux or Unix
   tmio.c_cflag &=  ~CRTSCTS;

   //disable software control 
   tmio.c_iflag &= ~(IXON | IXOFF |IXANY); 

   //chose Raw input 
   tmio.c_lflag &= ~(ICANON |ECHO |ECHOE |ISIG);
   //chose Raw outputmain
   tmio.c_oflag &= ~OPOST;
 

    cfsetispeed(&tmio,B9600);
    cfsetospeed(&tmio,B9600);

    tmio.c_cc[VTIME] = 100;  //iner-character time unused.
    tmio.c_cc[VMIN]  = 1;    //block read until 1 char received  

    tcflush(m_hComDev, TCIFLUSH); //Clear the input buffer.

    tcsetattr(m_hComDev,TCSANOW, &tmio);  //Set the parameter for the UART.

//Now, we can use the UART     
    m_bComDevOpen = 1;

    return 0;
}

//return value: 0 for false; 1 for success

int Init(unsigned char szAckCmd[],char szComName[])
{
//UART name
    strcpy(m_szComName,szComName);
    
//Init UART	
	if(InitComDev(szComName) != 0)
	{
		return -1;
	}
	
//initilize the queues.	
	SafeMsgQueInit(&m_AckMsgQue);
	SafeMsgQueInit(&m_RxMsgQue);

//initilze the condition varioable and the concerned mutex
//	pthread_mutex_init(&m_hDataMutex, NULL);
//	pthread_cond_init(&m_hDataCond, NULL);

//initialize the AckCmd.  
    unsigned char *pCmd =m_szAckCmd;
	while((*pCmd++ = *szAckCmd++) != 0x00) ;

//Create a sub thread
//	int rc;               /* return value for pthread functions.            */
	/* create the new thread. */ 
	// thr_id = pthread_create(&p_thread, NULL, do_loop, (void*)&a);
	int rc = pthread_create(&m_hSubThread, NULL, CommWatchPorc, NULL);
	/* and if that succeeded, detach the newly created thread. */
	if (rc != 0) 
	{
	    return -2;
	}  
	
	return 0;
}

int CleanUp()
{
	m_bComDevOpen = 0;

//Wait for quit of the sub thread.
//	pthread_join();

//To destroy the Com essential Event handle identify. wait for quit of the sub thread.
	pthread_join(m_hSubThread, 0);

//To destroy the Com port handle identify.
	if(m_hComDev > 0)
	{
		close(m_hComDev);
		//m_hComDev = -1;
	}

	return 0;
}

int WriteRawDataToUart(unsigned char* lpBuffer, const unsigned int nBytesToWrite)
{
//only if the Com device is initialized correctly, and it has been open, it can work.
	if(!m_bComDevOpen)
	{
		return -1;
	}

	unsigned short nAllBytesWritten = 0;  // the length of data is sent 
	unsigned short nAllBytesLeft = nBytesToWrite;  // the length of data is sent 
//	unsigned short nBytesSent = 0;  // the length of data is sent to COM port 
//	unsigned short nRemainderBytesToWrite = nBytesToWrite;
	
    while(nAllBytesLeft > 0)
    {
        int nBytesWrittenOneTime = write(m_hComDev,lpBuffer + nAllBytesWritten, nAllBytesLeft);
		if(nBytesWrittenOneTime >0)
		{
            nAllBytesLeft -= nBytesWrittenOneTime;
	    	nAllBytesWritten += nBytesWrittenOneTime;
		}
		else
		{
			return -2;
		}
    }

	return 0;  
}


int WriteComm(unsigned char* lpBuffer, const unsigned int nBytesToWrite)
{
	unsigned char szHead[3] = {0xFF,0xFF} ;
	unsigned char szSumCheck_Tail[5] = {0x00,0x00,0xFE,0xFE} ; // Sum check and the Tail of 0xFE, 0xFE
//	unsigned char chSumCheck = 0x00;

//To make the Sum Check
//	unsigned short* pSumCheck = (unsigned short*)chSumCheck_Tail;
	unsigned char* pSumCheck = szSumCheck_Tail;
	unsigned int  i = 0;
  
	for(i= 0; i< nBytesToWrite; i++)
	{
		//pSumCheck += *(lpBuffer + i );  This line is error.
		*pSumCheck += *(lpBuffer + i ); 
	}

// To write the UART head
	if(WriteRawDataToUart(szHead,2) != 0)
	{
		return -1;
	}
			

	//To write the DATA
	if(WriteRawDataToUart(lpBuffer,nBytesToWrite) != 0)
	{
		return -2;
	}

	//To Write the Check sum and UART tail
	if(WriteRawDataToUart(szSumCheck_Tail,4) !=0)
	{
		return -3;	
	}

	return 0;  
}

//This function is to write a message into acknowledged message queue or common message queue;
//if the message is a responsive message, it will be insert into acked message queue.
//if the message if a message originally sent by APP CPU, such as urgent messages,
// it will be insert received message queue.  

int WriteOneMsgIntoQue(unsigned char szMessage[], unsigned int nMegLen)
{

	if(m_bComDevOpen == 0 || nMegLen > 256)
	{
		return -1;
	}

	int bAckCmd = 0; // whether the message is an original upload command.

	unsigned char *pAckCmd = m_szAckCmd;

	while(*pAckCmd != '\0' )
	{
		if(szMessage[0] == *pAckCmd)  //the first character holds the command.
		{
			bAckCmd = 1;
			break;
		}

		pAckCmd++;
	}

	MsgNode* pMsgNode = (MsgNode*)malloc(sizeof(MsgNode));
	memset((void*)pMsgNode, 0, sizeof(MsgNode));

	pMsgNode->next = NULL;
	memcpy(pMsgNode->Buf, szMessage,nMegLen); 

	if(bAckCmd)
	{
		if(InsertOneMsg(pMsgNode, &m_AckMsgQue))
		{
			return -2;
		}
/*				
		//Notify the codition variable     Rock.li....
		pthread_mutex_lock(&m_hDataMutex);
		int rc = pthread_cond_signal(&m_hDataCond);
		if(rc != 0)
		{
			return -3; 
		}
		
		pthread_mutex_unlock(&m_hDataMutex);		
*/
	}
	else
	{
		if(InsertOneMsg(pMsgNode, &m_RxMsgQue))
		{
			return -4;
		}
	}

	return 0;
}

//This function is to Receive a whole message from APP CPU. 
//If the data received is not a message, we should pack some data into a message. 
//If the Message is a responsive message from APP CPU, it will be insert into m_AckedMsgQue (the acked message queue).
//the function that has sent data to APP CPU, should wait the responsive message by waiting for an semaphore.
//if the message is a initial message from APP CPU, it will be insert into RxMsgQue(the received message queue).
//
//Parameters: none.
//This function should be advanced by the change of the Serial code of APP CPU
//we can make this function read one package
int ReadComm()
{
	static int bNewMessage = 1;
	static unsigned char szRevBuf[256 + 10];  // The length of MailBox plus the package head and tail
	
	static unsigned int nAllBytesToRead = 5;//m_nPackageHeadLen; //the length of data to be read
	static unsigned int nAllBytesRead =0;      //the length of data that has been read.

	unsigned int nBytesToRead = 0; //the length of data to be read by one time. 
	unsigned int nBytesRead = 0;    //the length of data to have been read by one time.
	
	if(!m_bComDevOpen)
	{
		return -1;
	}

	if(bNewMessage)//initialization of the static various.
	{
		memset((void*)szRevBuf, 0, sizeof(szRevBuf));
		
		nAllBytesToRead = m_nPackageHeadLen;
		nAllBytesRead = 0;
	}

	unsigned int nBtyesAvailableToRead =0; 
    ioctl(m_hComDev, FIONREAD, &nBtyesAvailableToRead);

    if(nBtyesAvailableToRead <= 0)
    {
    	return -2;
    }

	nBytesToRead = nAllBytesToRead - nAllBytesRead;  //To try to read BytesToRead bytes.
	//To Adjust the dwBytesToRead according to the UART input buffer.
	nBytesToRead = nBytesToRead < nBtyesAvailableToRead ? nBytesToRead : nBtyesAvailableToRead;

	nBytesRead = read(m_hComDev, szRevBuf + nAllBytesRead , nBytesToRead);
	
	if(nBytesRead < 0 )//UART error.
	{
		bNewMessage = 1;
		return -3;
	}
	else if(nBytesRead == 0 )
	{
		return -4;
	}	
	
	nAllBytesRead += nBytesRead;  // all the bytes that has been read from UART 
//	nAllBytesToRead   -=  nBytesRead; //The remained bytes to be read next time 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -