linux下的串口通信类
来源:互联网 发布:公务员照片修改软件 编辑:程序博客网 时间:2024/06/05 09:26
众所周知, 计算机内部CPU与接口之间是按并行方式进行工作的,而许多外设和计算机之间是按串行方式进行通信,所谓的串行方式,就是在一根传输线上一位一位的传送信息,所用的传输线少,并且可以借助现成的电话网进行信息传送,因此,特别适合于远距离传输.对于那些与计算机相距不远的人-机交换设备和串行存储的外部设备如终端、打印机、逻辑分析仪、磁盘等,采用串行方式交换数据也很普遍. 所以不要看不起串行通信,它是一种经典的传统的通信方式。网上用C写的串口通信程序很多,这里我用C++封装了一个类,并加入了自己写的日志操作。
/* 加入了日志功能,记录串口的状态信息及接收信息,对发送信息新建日志; 加入自动锁的功能,使主线程与接收线程和发送线程自动同步 */#ifndef MY_COM_H#define MY_COM_H#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <termios.h>#include <pthread.h>#include <sys/types.h>#include <sys/epoll.h>#include <errno.h>#include <fcntl.h>#include <time.h>#include "my_log/my_log.h"#include <string>#include <string.h>#include "my_locker/auto_lock.h"using namespace std;const int MAXREADLEN = 256;const int MAXSENDLEN = 256;const int MINSIZE = 256; //the minsize of g_bufferconst int MAXSIZE = 10240; // the maxsize of g_bufferconst int SLEEPTIME = 60;const int SLEEPTINES = 5;enum mutex{ RDLK = 0, WRLK = 1,};class My_com{public: My_com(); My_com(char* log_path, char *log_name); ~My_com(); int open_com(const int nport); int set_com(const int baud_rate, const int data_bits, char parity, const int stop_bits); int read_com(int rdlen = MAXREADLEN); int write_com(int wrlen = MAXSENDLEN); static void* read_thread_function(void*); static void* send_thread_function(void*); int create_read_thread(); int create_send_thread(); friend int parse(My_com *pcom, string &str); //find the str betweeb '$' and '\n' friend int send(My_com* , int fd, int wrlen = MAXSENDLEN); //send to fd char m_recv_buf[MAXREADLEN]; char m_send_buf[MAXSENDLEN]; pthread_t m_read_thrdID; //default two thread pthread_t m_send_thrdID; My_log *m_plog;private: int m_port;};#endif // MY_COM_H以下实现:
#include "my_com.h"string g_buffer; //接收BUFFERMutex_locker g_locker; //全局锁, 用于读写线程对全局BUFFER的加锁//Mutex_locker g_log_locker;My_com::My_com(){ this->m_read_thrdID = 0; this->m_send_thrdID = 0; this->m_port = 0; memset(m_recv_buf, 0, sizeof(m_recv_buf)); memset(m_send_buf, 0 , sizeof(m_send_buf)); m_plog = new My_log("./", "com_status.log");}My_com::My_com(char *log_path, char *log_name){ this->m_read_thrdID = 0; this->m_send_thrdID = 0; this->m_port = 0; memset(m_recv_buf, 0, sizeof(m_recv_buf)); memset(m_send_buf, 0 , sizeof(m_send_buf)); m_plog = new My_log(log_path, log_name);}My_com::~My_com(){ if(close(m_port)) { char msg[100] = {0}; sprintf(msg, "close port failed :%s\n", strerror(errno)); m_plog->write_log(msg, ERR); exit(-1); } m_plog->write_log("close port done\n", INFO); delete m_plog;}int My_com::open_com(const int nport){ char path_name[20]; if((nport < 0) || (nport > 3)) { char msg[100] = {0}; sprintf(msg, "the port id [%d] is out of rang\n", nport); m_plog->write_log(msg, ERR); return -1; } sprintf(path_name, "/dev/ttyS%d", nport); if(m_port != 0) { m_plog->write_log("the port is busying", ERR); return -1; } if((m_port = open(path_name, O_RDWR | O_NOCTTY)) <= 0) { char msg[100] = {0}; sprintf(msg, "can not open port [%d]: %s \n", nport, strerror(errno)); m_plog->write_log(msg, ERR); exit(-1); } if(!isatty(m_port)) { m_plog->write_log("is not a terminal\n", ERR); } char msg[100] = {0}; sprintf(msg, "open port done, the port id is %d\n", m_port); m_plog->write_log(msg, INFO); return 0;}int My_com::set_com(const int baud_rate, const int data_bits, char parity, const int stop_bits){ struct termios newtio; memset(&newtio, 0, sizeof(newtio)); if(tcgetattr(m_port, &newtio)) { char msg[100] = {0}; sprintf(msg, "tcgetattr error : %s\n", strerror(errno)); m_plog->write_log(msg, ERR); return -1; } m_plog->write_log("tcgetattr done\n", INFO); //set data bits newtio.c_cflag &= ~CSIZE; switch(data_bits) { case 7: newtio.c_cflag |= CS7; break; case 8: newtio .c_cflag |= CS8; break; default: newtio.c_cflag |= CS8; break; } //set baud rate switch (baud_rate) { case 2400: cfsetispeed(&newtio, B2400); cfsetospeed(&newtio, B2400); break; case 4800: cfsetispeed(&newtio, B4800); cfsetospeed(&newtio, B4800); break; case 9600: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; case 115200: cfsetispeed(&newtio, B115200); cfsetospeed(&newtio, B115200); break; default: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); } //set stop bits switch (stop_bits) { case 1: newtio.c_cflag |= ~CSTOPB; break; case 2: newtio.c_cflag |= CSTOPB; break; default: newtio.c_cflag |= ~CSTOPB; break; } //set parity switch (parity) { case 'O': newtio.c_cflag |= PARENB; newtio.c_cflag |= PARODD; newtio.c_iflag |= (INPCK | ISTRIP); break; case 'E': newtio.c_iflag |= (INPCK | ISTRIP); newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; break; case 'N': newtio.c_cflag &= ~PARENB; newtio.c_cflag &= ~PARODD; break; } newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CRTSCTS; //raw model newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); newtio.c_oflag &= ~OPOST; newtio.c_iflag &= ~(INLCR|IGNCR|ICRNL); newtio.c_iflag &= ~(ONLCR|OCRNL); newtio.c_oflag &= ~(INLCR|IGNCR|ICRNL); newtio.c_oflag &= ~(ONLCR|OCRNL); //different from minicom set newtio.c_cflag &= ~HUPCL; newtio.c_iflag &= ~INPCK; newtio.c_iflag |= IGNBRK; newtio.c_iflag &= ~ICRNL; newtio.c_iflag &= ~IXON; newtio.c_lflag &= ~IEXTEN; newtio.c_lflag &= ~ECHOK; newtio.c_lflag &= ~ECHOCTL; newtio.c_lflag &= ~ECHOKE; newtio.c_oflag &= ~ONLCR; // newtio.c_cc[VMIN] = 1; newtio.c_cc[VTIME] = 0; tcflush(m_port, TCIOFLUSH); if(tcsetattr(m_port, TCSANOW, &newtio)) { char msg[100] = {0}; sprintf(msg, "tcsetattr error : %s\n", strerror(errno)); m_plog->write_log(msg, ERR); return -1; } char msg[100]; sprintf(msg, "tcsetattr done, baud_rate:%d, data_bits:%d, parity:%c, stop_bit:%d\n", baud_rate, data_bits, parity, stop_bits); m_plog->write_log(msg, INFO);}//@param read_len: read number one timeint My_com::read_com(int read_len){ static long int rdcnt = 0; int rdlen = 0; int len = 0; if((m_recv_buf == NULL) || (read_len > MAXREADLEN)) { m_plog->write_log("the recv_buf is null or out of range", ERR); return -1; } m_plog->write_log("\nstarting recving.........", INFO); do { while (true) { pthread_testcancel(); //set cancel state rdlen = read(m_port, m_recv_buf+ len, read_len); //m_plog->write_log(".", INFO); pthread_testcancel(); len += rdlen; if(len >= MAXREADLEN) { rdlen = 0; break; } } rdcnt += len; //in all read len = 0; char msg[100] = {0}; sprintf(msg, "have read %ld : ", rdcnt); m_plog->write_log(msg, INFO); m_plog->write_log(m_recv_buf, INFO); //m_plog->write_log("\n", INFO); }while(false);}int My_com::write_com(int wrlen){ m_plog->write_log("\nstarting sending.........", INFO); static long int sdcnt = 0; int len = write(m_port, m_send_buf, wrlen); sdcnt += len; if(len <= 0) { char msg[100] = {0}; sprintf(msg, "send error: %s ", strerror(errno)); m_plog->write_log(msg, ERR); return len; } char msg[100] = {0}; sprintf(msg, "have send %ld :", sdcnt); m_plog->write_log(msg, INFO); m_plog->write_log(m_send_buf, INFO); //m_plog->write_log("\n", INFO); return len;}void* My_com::read_thread_function(void *arg){ //My_log rd_thrd_log; char msg[100]; sprintf(msg, "new read thead create, ID: %x", pthread_self()); //rd_thrd_log.write_log(msg, INFO) My_com *pcom = (My_com*)arg; int cnt_sleep = 0; do { if(g_buffer.size() >= MAXSIZE) { sleep(SLEEPTIME); ++cnt_sleep; if(cnt_sleep >= SLEEPTINES) { break; } } pthread_testcancel(); //set cancel point pcom->read_com(1); Auto_lock lock(g_locker); g_buffer.append(pcom->m_recv_buf); }while (true); pthread_exit(NULL);}void* My_com::send_thread_function(void *arg){ My_com *pcom = (My_com*)arg; int cnt_sleep = 0; do { pthread_testcancel(); //set cancel point if(g_buffer.size() <= MINSIZE) { sleep(SLEEPTIME); ++cnt_sleep; if(cnt_sleep >= SLEEPTINES) { break; } } Auto_lock lock(g_locker); cout<<g_buffer.size()<<endl; parse(pcom, g_buffer); cout<<g_buffer.size()<<endl; pcom->write_com(MAXSENDLEN); //pthread_testcancel(); }while(true); pthread_exit(NULL);}int parse(My_com *pcom, string &str){ int start = 0; int end = 0; int len = 0; start = str.find_first_of('$', 0); end = str.find('\n', start); len = end - start +1; strncpy(pcom->m_send_buf, str.substr(start, end).c_str(), len); str.erase(0, start + len); //cout<<str.size()<<endl;}int My_com::create_read_thread(){ pthread_attr_t attr; pthread_attr_init(&attr); int res = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); res += pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); if(pthread_create(&m_read_thrdID, &attr, read_thread_function, (void*)this) != 0) { m_plog->write_log("create read thread error", ERR); return -1; } return 0;}int My_com::create_send_thread(){ pthread_attr_t attr; pthread_attr_init(&attr); int res = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); res += pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); if(pthread_create(&m_read_thrdID, &attr, send_thread_function, (void*)this) != 0) { m_plog->write_log("create read thread error", ERR); return -1; } return 0;}int send(My_com* pcom, int fd, int wrlen){ pcom->m_plog->write_log("\nstating sending.........", INFO); static long int sdcnt = 0; int len = write(fd, pcom->m_send_buf, wrlen); sdcnt += len; if(len <= 0) { char msg[100] = {0}; sprintf(msg, "send error: %s ", strerror(errno)); pcom->m_plog->write_log(msg, ERR); return len; } char msg[100] = {0}; sprintf(msg, "have send %ld :", sdcnt); pcom->m_plog->write_log(msg, INFO); pcom->m_plog->write_log(pcom->m_send_buf, INFO); //m_plog->write_log("\n", INFO); return len;}
demo:
#include <iostream>#include "my_com.h"#include "my_locker/auto_lock.h"using namespace std;extern string g_buffer;extern Mutex_locker g_locker; //lock the g_bufferextern Mutex_locker g_log_locker;bool rdstop_flag = false;bool wrstop_flag = false;int main(){ My_com com("./", "chen"); com.open_com(0); com.set_com(9600, 8, 'N', 1);// string buf;// while(true)// {// com.read_com(1);// buf.append(com.m_recv_buf);// } com.create_read_thread(); sleep(5); com.create_send_thread(); sleep(10); com.m_plog->write_log("will cancel read thread\n", INFO); pthread_cancel(com.m_read_thrdID); pthread_join(com.m_read_thrdID, NULL); com.m_plog->write_log("cancel read thread done\n", INFO); com.m_plog->write_log("will cancel send thread\n", INFO); pthread_join(com.m_send_thrdID, NULL); com.m_plog->write_log("cancel send thread done\n", INFO); return 0;}
- linux下的串口通信类
- Linux 下的串口通信
- linux下的串口通信
- Linux下串口通信
- linux 下串口通信
- linux下串口通信
- linux 下串口通信
- linux 下串口通信
- Linux下串口通信
- Linux下的串口通信学习笔记
- Linux操作系统下的串口通信基础
- Linux 下串口通信的编程
- Linux 环境下串口通信的编程
- Linux操作系统下的串口通信
- linux下的串口通信程序详解
- Linux下的串口通信学习笔记
- Linux下的串口通信学习笔记
- Linux 环境下串口通信的编程
- 通过AudioManager 设置调整系统各项音量(铃声 媒体等)
- 分享Spring中Bean的4种依赖检查模式
- android的复制粘贴
- apk 捆绑安装
- 有一个1亿结点的树,已知两个结点, 求它们的最低公共祖先!
- linux下的串口通信类
- git服务器搭建
- Linux内核bridge浅析
- Ueditor自定义默认宽度高度
- 使用hibernate执行sql语句
- MFC的秘密:它的静态库和动态库所在何处
- 润乾——移动应用查询设置
- 表单check多选遍历处理方
- openstack havana vlan 模式 安装配置