写在前面
待更
串口通信
待更
Linux实现
标准库
1 2 3 4 5 6
| #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <errno.h>
|
封装
功能/步骤清单 serialcom.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #ifndef _SERIALCOM_H_ #define _SERIALCOM_H_
#include <stdio.h> #include <stdlib.h> #include <termios.h>
class SerialCom { private: int fd; struct termios opts; char data[512]; public: ~SerialCom(); bool setBaud(int); bool setDatabit(int); bool setParityStopbit(int,int); bool getSerial(char*); bool closeSerial(); bool recieveData(); void sendData(); void setSyn(int); };
#endif
|
打开串口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| bool SerialCom::getSerial(char* addr){ this->fd = open(addr,O_RDWR | O_NOCTTY); if(this->fd < 0){ perror("Failed to open serial!"); close(this->fd); return false; } if(tcgetattr(this->fd,&this->opts) != 0){ perror("Failed to get serial options!"); return false; } fcntl(this->fd,F_SETFL,0); fcntl(this->fd,F_SETOWN,getpid());
return true; }
|
设置波特率
1 2 3 4 5 6 7 8 9 10 11
| bool SerialCom::setBaud(int baud){ int status; cfsetispeed(&this->opts,baud); cfsetospeed(&this->opts,baud); status = tcsetattr(this->fd, TCSANOW, &this->opts); if(status != 0){ perror("set Baud Option fail!"); return false; } return true; }
|
设置校验位和停止位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| bool SerialCom::setParityStopbit(int p,int s){ int status; switch(p){ case 1: this->opts.c_cflag |= PARENB; this->opts.c_cflag |= PARODD; this->opts.c_iflag |= INPCK; break; case 2: this->opts.c_cflag |= PARENB; this->opts.c_cflag &= ~PARODD; this->opts.c_iflag |= INPCK; break; case 0: this->opts.c_cflag &= ~PARENB; this->opts.c_iflag |= INPCK; default: perror("Error Parity bit id to Option!"); return false; } if(s == 1){ this->opts.c_cflag &= ~CSTOPB; }else if(s == 2){ this->opts.c_cflag |= CSTOPB; }else{ perror("Error Stop bit id to Option!"); return false; } status = tcsetattr(this->fd, TCSANOW, &this->opts); if(status != 0){ perror("set parity&Stop Option fail!"); return false; } return true; }
|
设置数据位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| bool SerialCom::setDatabit(int data_bit){ int status; this->opts.c_cflag &= ~CSIZE; switch (data_bit){ case 7: this->opts.c_cflag |= CS7; break; case 8: this->opts.c_cflag |= CS8; break; default: perror("Error data bit num to Option!"); return false; } status = tcsetattr(this->fd, TCSANOW, &this->opts); if(status != 0){ perror("set data bit Option fail!"); return false; } return true; }
|
发送与接收
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void SerialCom::sendData(){ char put[512]; printf("请输入:"); scanf("%s",put); write(this->fd,put,strlen(put)); } bool SerialCom::recieveData(){ int Isget; Isget = read(this->fd,this->data,512); if(Isget > 0){ printf("\n$ Get Message:\n\t"); this->data[Isget] = 0; printf("%s\n",this->data); return true; } return false; }
|
是否相应SIGIO中断
1 2 3 4 5 6 7
| void SerialCom::setSyn(int flag){ if(flag == 0){ fcntl(this->fd,F_SETFL,0); }else{ fcntl(this->fd,F_SETFL,FASYNC); } }
|
关闭串口(析构函数)
1 2 3
| SerialCom::~SerialCom(void){ close(this->fd); }
|
查询方式
循环查找
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include "SerialCom_src/serialcom.h" #include <stdio.h> int main(void){
char path[] = "/dev/ttyS1"; SerialCom* uart = new SerialCom(); uart->getSerial(path); uart->setBaud(B9600); uart->setDatabit(8); uart->setParityStopbit(2,2); while(1){ uart->sendData(); uart->recieveData(); } delete uart; return 0; }
|
select()函数
待更
多线程扩展
此处利用Linux下的pthread.h实现多线程处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| #include "SerialCom_src/serialcom.h" #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <iostream>
using namespace std;
void* get_message(void* args){ printf("接收线程 启动!\n"); SerialCom* uart = (SerialCom*)args; while(1){ uart->recieveData(); sleep(1); } pthread_exit(NULL); }
void* send_message(void* args){ printf("发送线程 启动!\n"); SerialCom* uart = (SerialCom*)args; while(1){ uart->sendData(); sleep(1); } pthread_exit(NULL); }
int main(void){
int ret; bool flag = false; char path[] = "/dev/ttyS1"; pthread_t tid1,tid2; SerialCom* uart = new SerialCom();
uart->getSerial(path); uart->setBaud(B9600); uart->setDatabit(8); uart->setParityStopbit(2,2); ret = pthread_create(&tid1,NULL,get_message,(void*)uart); if(ret){ cout << "Error:接受消息线程创建失败 [error code:" << ret << "]" << endl; exit(-1); } ret = pthread_create(&tid2,NULL,send_message,(void*)uart); if(ret){ cout << "Error:发送消息线程创建失败 [error code:" << ret << "]" << endl; exit(-1); } pthread_exit(NULL); }
|
信号/中断方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include "SerialCom_src/serialcom.h"
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<sys/signal.h>
bool flag = false;
void signal_handler_IO(int status){ flag = true; }
int main(void){
char path[] = "/dev/ttyS1"; SerialCom* uart = new SerialCom();
struct sigaction saio; saio.sa_handler = signal_handler_IO; sigemptyset (&saio.sa_mask); saio.sa_flags = 0; saio.sa_restorer = NULL; sigaction(SIGIO, &saio, NULL);
uart->getSerial(path); uart->setBaud(B9600); uart->setDatabit(8); uart->setParityStopbit(2,2); uart->setSyn(1);
while(1){ usleep(100000); if(flag){ uart->recieveData(); flag = false; } uart->sendData(); } return 0; }
|
仿真实践
所需软件:
- Virtual Serial Port Driver Pro 9.0|下载地址
- Uart assist|下载地址
- cutecom |debian系统可通过
sudo apt-get install cutecom命令安装
参考
- 串口通信. 简小黑. 简书
- 串口通信详解. 泪无痕z. CSDN
- linux下的RS232通信实践. 平凡淡定面对生活. 博客园
- 主机和虚拟机通过虚拟串口通信. adgentleman. CSDN
- Linux系统串口接收数据编程. bg2bkk. CSDN
- Linux下串口编程入门. 冷烟花. 博客园