You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
276 lines
6.1 KiB
C++
276 lines
6.1 KiB
C++
/*
|
|
* CSerial.cpp
|
|
*
|
|
* Created on: 2010-7-20
|
|
* Author: yzm
|
|
*/
|
|
|
|
#include "CSerial.h"
|
|
#include <sys/select.h>
|
|
#include <sys/time.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h> /*Unix 标准函数定义*/
|
|
#include <string.h>
|
|
//#include <pthread.h>
|
|
|
|
|
|
CCriticalSection::CCriticalSection()
|
|
{
|
|
pthread_mutex_init(&mutex,NULL);
|
|
}
|
|
CCriticalSection::~CCriticalSection()
|
|
{
|
|
pthread_mutex_destroy(&mutex);
|
|
}
|
|
void CCriticalSection::Lock()
|
|
{
|
|
pthread_mutex_lock(&mutex);
|
|
}
|
|
void CCriticalSection::Unlock()
|
|
{
|
|
pthread_mutex_unlock(&mutex);
|
|
}
|
|
|
|
|
|
int speed_arr[] = {B115200,B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400,
|
|
B19200, B9600, B4800, B2400, B1200, B300, };
|
|
int name_arr[] = {115200,38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200,
|
|
9600, 4800, 2400, 1200, 300, };
|
|
string BYTE2HEX(unsigned char* buffer,int nSize)
|
|
{
|
|
char buf[1024];
|
|
memset(buf,0,1024);
|
|
int len = 0;
|
|
for(int i = 0;i < nSize;i++)
|
|
{
|
|
int tmp = sprintf(buf + len,"%02x ",buffer[i]);
|
|
len += tmp;
|
|
}
|
|
string str(buf);
|
|
return str;
|
|
}
|
|
|
|
CSerial::CSerial()
|
|
{
|
|
m_ExitThreadFlag = false;
|
|
m_PortName = "/dev/ttyS0";
|
|
m_baudrate = 2400;
|
|
m_databits = 8;
|
|
m_stopbits = 1;
|
|
m_parity = 'e';
|
|
}
|
|
|
|
CSerial::~CSerial()
|
|
{
|
|
// ClosePort( );
|
|
}
|
|
|
|
int CSerial::OpenPort(string PortName, int baudrate, char databits,
|
|
char stopbits, char parity)
|
|
{
|
|
/*以读写方式打开串口*/
|
|
int iRet;
|
|
m_fd = open(PortName.data(), O_RDWR);
|
|
if (-1 == m_fd) {
|
|
/* 不能打开串口一*/
|
|
perror(" 提示错误!");
|
|
return -1;
|
|
} else {
|
|
m_PortName = PortName;
|
|
m_baudrate = baudrate;
|
|
m_databits = databits;
|
|
m_stopbits = stopbits;
|
|
m_parity = parity;
|
|
//设置参数
|
|
set_speed(m_fd, baudrate);
|
|
iRet =set_Parity(m_fd, databits, stopbits, parity);
|
|
|
|
pthread_create(&m_thread,NULL,CSerial::CSerial::ReceiveThreadFunc,this);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int CSerial::ClosePort( )
|
|
{
|
|
m_ExitThreadFlag = true;
|
|
close(m_fd);
|
|
pthread_join(m_thread,NULL);
|
|
return 1;
|
|
}
|
|
|
|
int CSerial::PackagePro( unsigned char* Buf, int len )
|
|
{
|
|
//string str = BYTE2HEX(Buf,len);
|
|
//printf("%s\r\n",str.data());
|
|
//WritePort(Buf,len);
|
|
return 0;
|
|
}
|
|
|
|
void* CSerial::ReceiveThreadFunc(void* lparam) {
|
|
CSerial *pSer = (CSerial*) lparam;
|
|
fd_set fdRead;
|
|
int ret;
|
|
struct timeval aTime;
|
|
while (1) {
|
|
//收到退出事件,结束线程
|
|
//printf("Thread...\r\n");
|
|
if (pSer->m_ExitThreadFlag) {
|
|
break;
|
|
}
|
|
FD_ZERO(&fdRead);
|
|
FD_SET(pSer->m_fd,&fdRead);
|
|
aTime.tv_sec = 2;
|
|
aTime.tv_usec = 100;
|
|
ret = select(pSer->m_fd + 1, &fdRead, NULL, NULL, &aTime);
|
|
if (ret < 0) {
|
|
//关闭串口
|
|
pSer->ClosePort();
|
|
break;
|
|
}
|
|
if (ret > 0) {
|
|
//判断是否读事件
|
|
if (FD_ISSET(pSer->m_fd, &fdRead))
|
|
{
|
|
//data available, so get it!
|
|
pSer->m_DatLen = read(pSer->m_fd, pSer->DatBuf, BUFFER_LENGTH);
|
|
// 对接收的数据进行处理,这里为简单的数据回发
|
|
if (pSer->m_DatLen > 0) {
|
|
pSer->PackagePro(pSer->DatBuf, pSer->m_DatLen);
|
|
}
|
|
// 处理完毕
|
|
}
|
|
}
|
|
}
|
|
//printf("ReceiveThreadFunc finished\n");
|
|
pthread_exit(NULL);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*@brief 设置串口通信速率
|
|
*@param fd 类型 int 打开串口的文件句柄
|
|
*@param speed 类型 int 串口速度
|
|
*@return void
|
|
*/
|
|
void CSerial::set_speed(int fd, int speed) {
|
|
unsigned int i;
|
|
int status;
|
|
struct termios Opt;
|
|
tcgetattr(fd, &Opt);
|
|
for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {
|
|
if (speed == name_arr[i]) {
|
|
tcflush(fd, TCIOFLUSH);
|
|
cfsetispeed(&Opt, speed_arr[i]);
|
|
cfsetospeed(&Opt, speed_arr[i]);
|
|
status = tcsetattr(fd, TCSANOW, &Opt);
|
|
if (status != 0) {
|
|
perror("tcsetattr fd1");
|
|
return;
|
|
}
|
|
tcflush(fd, TCIOFLUSH);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*@brief 设置串口数据位,停止位和效验位
|
|
*@param fd 类型 int 打开的串口文件句柄
|
|
*@param databits 类型 int 数据位 取值 为 7 或者8
|
|
*@param stopbits 类型 int 停止位 取值为 1 或者2
|
|
*@param parity 类型 int 效验类型 取值为N,E,O,,S
|
|
*/
|
|
int CSerial::set_Parity(int fd, int databits, int stopbits, int parity) {
|
|
struct termios options;
|
|
if (tcgetattr(fd, &options) != 0) {
|
|
perror("SetupSerial 1");
|
|
return (false);
|
|
}
|
|
options.c_cflag &= ~CSIZE;
|
|
switch (databits) /*设置数据位数*/
|
|
{
|
|
case 7:
|
|
options.c_cflag |= CS7;
|
|
break;
|
|
case 8:
|
|
options.c_cflag |= CS8;
|
|
break;
|
|
default:
|
|
//fprintf(stderr, "Unsupported data size\n");
|
|
return -1;
|
|
}
|
|
switch (parity) {
|
|
case 'n':
|
|
case 'N':
|
|
options.c_cflag &= ~PARENB; /* Clear parity enable */
|
|
options.c_iflag &= ~INPCK; /* Enable parity checking */
|
|
break;
|
|
case 'o':
|
|
case 'O':
|
|
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
|
|
options.c_iflag |= INPCK; /* Disnable parity checking */
|
|
break;
|
|
case 'e':
|
|
case 'E':
|
|
options.c_cflag |= PARENB; /* Enable parity */
|
|
options.c_cflag &= ~PARODD; /* 转换为偶效验*/
|
|
options.c_iflag |= INPCK; /* Disnable parity checking */
|
|
break;
|
|
case 'S':
|
|
case 's': /*as no parity*/
|
|
options.c_cflag &= ~PARENB;
|
|
options.c_cflag &= ~CSTOPB;
|
|
break;
|
|
default:
|
|
//fprintf(stderr, "Unsupported parity\n");
|
|
return -2;
|
|
}
|
|
/* 设置停止位*/
|
|
switch (stopbits) {
|
|
case 1:
|
|
options.c_cflag &= ~CSTOPB;
|
|
break;
|
|
case 2:
|
|
options.c_cflag |= CSTOPB;
|
|
break;
|
|
default:
|
|
//fprintf(stderr, "Unsupported stop bits\n");
|
|
return -3;
|
|
}
|
|
|
|
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN); /*Input*/
|
|
|
|
options.c_iflag &= ~(IXON | IXOFF | IXANY);//关流控
|
|
options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IUCLC | IGNBRK|BRKINT|PARMRK|ISTRIP);
|
|
|
|
options.c_oflag &= ~(ONLCR | OCRNL | ONLRET | ONOCR | OLCUC | OFILL | CRTSCTS);
|
|
options.c_oflag &= ~OPOST; /*Output*/
|
|
|
|
/* Set input parity option */
|
|
if (parity != 'n')
|
|
options.c_iflag |= INPCK;
|
|
tcflush(fd, TCIFLUSH);
|
|
options.c_cc[VTIME] = 50; /* 设置超时15 seconds*/
|
|
options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
|
|
if (tcsetattr(fd, TCSANOW, &options) != 0) {
|
|
//perror("SetupSerial 3");
|
|
return -4;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int CSerial::WritePort( unsigned char* Buf, int len )
|
|
{
|
|
mutex.Lock();
|
|
int ToWrite = len;
|
|
int hasWrite = 0;
|
|
int wPos = 0;
|
|
while(ToWrite > 0){
|
|
hasWrite = write(m_fd, Buf + wPos, ToWrite);
|
|
if(hasWrite <= 0)break;
|
|
ToWrite -= hasWrite;
|
|
wPos += hasWrite;
|
|
}
|
|
mutex.Unlock();
|
|
return len - ToWrite;
|
|
}
|