23,215
社区成员




//主程序
#include "CSerial.h"
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
CSerial::CSerial serial;
serial.OpenPort("/dev/ttySAC0", 115200, 8, 1, 'N');//报错!!
while(1);
return 0;
}
/*自定义串口类
* CSerial.h
*
* Created on: 2010-7-20
* Author: yzm
*/
#ifndef CSERIAL_H_
#define CSERIAL_H_
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX 终端控制定义*/
#include <errno.h> /*错误号定义*/
#include <string.h>
#include <string>
#include "CCriticalSection.h"
using namespace std;
#define BUFFER_LENGTH 1024
namespace CSerial {
class CSerial
{
private:
string m_PortName;
int m_baudrate;
int m_databits;
int m_stopbits;
char m_parity;
//通讯线程标识符ID
pthread_t m_thread;
CCriticalSection mutex;
// 串口数据接收线程
static void* ReceiveThreadFunc( void* lparam );
public:
CSerial();
virtual ~CSerial();
// 已打开的串口文件描述符
int m_fd;
int m_DatLen;
unsigned char DatBuf[BUFFER_LENGTH];
int m_ExitThreadFlag;
// 按照指定的串口参数打开串口,并创建串口接收线程
int OpenPort( string PortName, int baudrate, int databits, int stopbits, char parity );
// 关闭串口并释放相关资源
int ClosePort( );
// 向串口写数据
int WritePort( unsigned char* Buf, int len );
// 接收串口数据处理函数
virtual int PackagePro( unsigned char* Buf, int len );
private:
void set_speed(int fd, int speed);
int set_Parity(int fd,int databits,int stopbits,int parity);
};
}
#endif /* CSERIAL_H_ */
/*
* 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 标准函数定义*/
namespace CSerial {
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);
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, int databits,
int stopbits, char parity) {
/*以读写方式打开串口*/
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);
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 1;
}
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) {
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr);
cfsetospeed(&Opt, speed_arr);
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 (false);
}
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 (false);
}
/* 设置停止位*/
switch (stopbits) {
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr, "Unsupported stop bits\n");
return (false);
}
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 (false);
}
return (true);
}
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;
}
}
#ifndef __CCRITICALSECTION_H
#define __CCRITICALSECTION_H
#include <pthread.h>
class CCriticalSection
{
private:
pthread_mutex_t mutex;
public:
CCriticalSection();
~CCriticalSection();
public:
void Lock();
void Unlock();
};
#endif
#include "CCriticalSection.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);
}
<iostream>
<string>
using namespace std;