linux 串列埠通訊
自己弄了一個串列埠通訊的程式碼,比較少就沒上傳git了。
h檔案
#ifndef __SERIAL__INCLUDE__
#define __SERIAL__INCLUDE__
#include <stdio.h>
#include <iostream>
#include <stdint.h>
namespace sharenew {
class SerialControl {
public:
SerialControl(){}
virtual ~SerialControl(){}
virtual int open_serial(const char* path) = 0;
virtual void close_serial() = 0;
virtual int send_data(uint8_t* data, int len) = 0;
virtual int recv_data(uint8_t* data, int len) = 0;
//設定波特率
// speed 引數型別(int),用來設定串列埠的波特率
// return 返回值型別(int),函式執行成功返回零值
virtual int setSpeed(int speed) = 0;
// 設定串列埠資料位,停止位和效驗位
// databits 引數型別(int), 資料位,取值為7或者8
// parity 引數型別(int),效驗型別 取值為N,E,O,,S
// stopbits 引數型別(int),停止位,取值為1或者2
// return 返回值型別(int),函式執行成功返回零值,否則返回大於零的值
virtual int setParity(int databits, int parity, int stopbits) = 0;
static SerialControl* getSerialControl(int type);
};
};
#endif
cpp檔案
#include "SerialControl.h"
#include <string>
#include <mutex>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
using namespace std;
namespace sharenew {
#define SERIAL_CONTROL_HEADER_0 (0x49)
#define SERIAL_CONTROL_HEADER_1 (0x85)
#define SERIAL_CONTROL_VERSION_0 (0x00)
#define SERIAL_CONTROL_VERSION_1 (0x01)
struct SerialControlData {
uint8_t m_header[2];//0x49 85
uint8_t m_version[2];//0x00 0x01
uint16_t m_len;//資料長度
uint16_t crc16;//
uint8_t data;
};
//struct termios {
// uint8_t c_cflag;
// uint8_t c_oflag;
// uint8_t c_iflag;
// uint8_t c_cc[8];
//};
static uint16_t getCrc16Serial(const uint8_t* data, int offset, int len);
class SerialControlDefault:public SerialControl {
public:
SerialControlDefault();
virtual ~SerialControlDefault();
virtual int open_serial(const char* path);
virtual void close_serial();
virtual int send_data(uint8_t* data, int len);
virtual int recv_data(uint8_t* data, int len);
//設定波特率
virtual int setSpeed(int speed);
virtual int setParity(int databits, int parity, int stopbits);
protected:
mutex m_fd_ctx;
int m_fd;
string m_path;
struct termios m_ntm; // 新的串列埠裝置選項
struct termios m_otm; // 舊的串列埠裝置選項
SerialControlData* m_write_data;//組裝資料
static const int g_send_data_max_len;
int write_data(uint8_t* data, int len);
int read_data(uint8_t* data, int len);
};
const int SerialControlDefault::g_send_data_max_len = 256;
SerialControl* SerialControl::getSerialControl(int type) {
switch (type)
{
case 0:
return new SerialControlDefault();
default:
break;
}
}
SerialControlDefault::SerialControlDefault():m_fd(-1){
bzero(&m_ntm, sizeof(m_ntm));
bzero(&m_otm, sizeof(m_otm));
m_write_data = (SerialControlData*)malloc(sizeof(SerialControlData) - 4 + g_send_data_max_len);
}
SerialControlDefault::~SerialControlDefault() {
close_serial();
if (NULL != m_write_data) {
free(m_write_data);
m_write_data = NULL;
}
}
int SerialControlDefault::open_serial(const char* path) {
lock_guard<mutex> lock(m_fd_ctx);
if (m_fd >= 0 || NULL == m_write_data) {
return -1;
}
//m_fd = open(path, O_RDWR | O_NOCTTY | O_NDELAY);
if (m_fd < 0) {
//開啟失敗
return -1;
}
//開啟成功
m_path = path;
//儲存原有的配置
//tcgetattr(m_fd, &m_otm);
}
void SerialControlDefault::close_serial() {
lock_guard<mutex> lock(m_fd_ctx);
if (m_fd >= 0) {
tcsetattr(m_fd, TCSANOW, &m_otm);
//close(m_fd);
m_fd = -1;
}
bzero(&m_ntm, sizeof(m_ntm));
bzero(&m_otm, sizeof(m_otm));
}
int SerialControlDefault::send_data(uint8_t* data, int len) {
lock_guard<mutex> lock(m_fd_ctx);
if (m_fd < 0 || NULL == m_write_data || len > g_send_data_max_len) {
return -1;
}
//先計算crc16
m_write_data->crc16 = getCrc16Serial(data, 0, len);
//組裝資料
memcpy((void*)(&(m_write_data->data)), data, len);
//確定資料頭
m_write_data->m_header[0] = SERIAL_CONTROL_HEADER_0;
m_write_data->m_header[1] = SERIAL_CONTROL_HEADER_1;
m_write_data->m_version[0] = SERIAL_CONTROL_VERSION_0;
m_write_data->m_version[1] = SERIAL_CONTROL_VERSION_1;
//傳送資料
return write_data((uint8_t*)&m_write_data, sizeof(SerialControlData) - 4 + len);
}
int SerialControlDefault::recv_data(uint8_t* data, int len) {
lock_guard<mutex> lock(m_fd_ctx);
if (m_fd < 0 || NULL == m_write_data) {
return -1;
}
//接收資料
int ret = read_data((uint8_t*)&m_write_data, sizeof(SerialControlData) - 4 + g_send_data_max_len);
if (ret <= 0) {
return -1;
}
//確定資料頭和版本
if (SERIAL_CONTROL_HEADER_0 != m_write_data->m_header[0] || SERIAL_CONTROL_HEADER_1 != m_write_data->m_header[1]
|| SERIAL_CONTROL_VERSION_0 != m_write_data->m_version[0] || SERIAL_CONTROL_VERSION_1 != m_write_data->m_version[1]) {
return -1;//接收資料錯誤
}
//確定長度
if (ret != (m_write_data->m_len + sizeof(SerialControlData) - 4)) {
return -1;//接收資料錯誤
}
//crc校驗
uint16_t crc16 = getCrc16Serial((uint8_t*)(&(m_write_data->data)), 0, m_write_data->m_len);
if (crc16 != m_write_data->crc16) {
return -1;//crc16錯誤
}
if (len < m_write_data->m_len) {
return -1;//長度太短了
}
memcpy(data, (void*)(&(m_write_data->data)), m_write_data->m_len);
return m_write_data->m_len;
}
int SerialControlDefault::write_data(uint8_t* data, int len) {
int ret, nleft;
uint8_t* ptmp;
ret = 0;
nleft = len;
ptmp = data;
while (nleft > 0)
{
{
lock_guard<mutex> lock(m_fd_ctx);
ret = write(m_fd, ptmp, nleft);
}
if (ret > 0)
{
nleft -= ret;
ptmp += ret;
}
//usleep(100);
}
return len - nleft;
}
int SerialControlDefault::read_data(uint8_t* data, int len) {
int ret, left, bytes;
left = len;
while (left > 0)
{
ret = 0;
bytes = 0;
{
lock_guard<mutex> lock(m_fd_ctx);
ioctl(m_fd, FIONREAD, &bytes);
if (bytes > 0){
ret = read(m_fd, data, left);
}
}
if (ret > 0){
left -= ret;
data += ret;
}
usleep(100);
}
return len - left;
}
//設定波特率
int SerialControlDefault::setSpeed(int speed) {
lock_guard<mutex> lock(m_fd_ctx);
bzero(&m_ntm, sizeof(m_ntm));
//儲存配置
//tcgetattr(m_fd, &m_ntm);
m_ntm.c_cflag = CLOCAL | CREAD;//CS8
switch (speed)
{
case 300:
m_ntm.c_cflag |= B300;
break;
case 1200:
m_ntm.c_cflag |= B1200;
break;
case 2400:
m_ntm.c_cflag |= B2400;
break;
case 4800:
m_ntm.c_cflag |= B4800;
break;
case 9600:
m_ntm.c_cflag |= B9600;
break;
case 19200:
m_ntm.c_cflag |= B19200;
break;
case 38400:
m_ntm.c_cflag |= B38400;
break;
case 115200:
m_ntm.c_cflag |= B115200;
break;
}
m_ntm.c_iflag = IGNPAR;
m_ntm.c_oflag = 0;
return 0;
}
int SerialControlDefault::setParity(int databits, int parity, int stopbits) {
lock_guard<mutex> lock(m_fd_ctx);
if (0 != tcgetattr(m_fd, m_ntm)) {
return -1;
}
bzero(&m_ntm, sizeof(m_ntm));
//儲存配置
//tcgetattr(m_fd, &m_ntm);
m_ntm.c_cflag = CS8 | CLOCAL | CREAD;
m_ntm.c_iflag = IGNPAR;
m_ntm.c_oflag = 0;
//設定串列埠的各種引數
m_ntm.c_cflag &= ~CSIZE;
switch (databits)
{ //設定資料位數
case 7:
m_ntm.c_cflag |= CS7;
break;
case 8:
m_ntm.c_cflag |= CS8;
break;
default:
//printf("Unsupported data size\n");
return 5;
}
switch (parity)
{ // 設定奇偶校驗位數
case n:
case N:
m_ntm.c_cflag &= ~PARENB; /* Clear parity enable */
m_ntm.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case o:
case O:
m_ntm.c_cflag |= (PARODD | PARENB); /* 設定為奇效驗*/
m_ntm.c_iflag |= INPCK; /* Disnable parity checking */
break;
case e:
case E:
m_ntm.c_cflag |= PARENB; /* Enable parity */
m_ntm.c_cflag &= ~PARODD; /* 轉換為偶效驗*/
m_ntm.c_iflag |= INPCK; /* Disnable parity checking */
break;
case S:
case s: /*as no parity*/
m_ntm.c_cflag &= ~PARENB;
m_ntm.c_cflag &= ~CSTOPB;
break;
default:
printf("Unsupported parity\n");
return 2;
}
//
// 設定停止位
switch (stopbits)
{
case 1:
m_ntm.c_cflag &= ~CSTOPB;
break;
case 2:
m_ntm.c_cflag |= CSTOPB;
break;
default:
printf("Unsupported stop bits\n");
return 3;
}
//
//
m_ntm.c_lflag = 0;
m_ntm.c_cc[VTIME] = 0; // inter-character timer unused
m_ntm.c_cc[VMIN] = 1; // blocking read until 1 chars received
tcflush(m_fd, TCIFLUSH);
if (tcsetattr(m_fd, TCSANOW, &m_ntm) != 0)
{
printf("SetupSerial \n");
return 4;
}
return 0;
}
static uint16_t getCrc16Serial(const uint8_t* data, int offset, int len) {
uint16_t ret = 0x00;
for (int i = 0; i < len; ++i) {
ret &= data[offset + i];
ret = ret << 1;
}
return ret;
}
};
相關文章
- 串列埠通訊串列埠
- 串列埠通訊 (轉)串列埠
- Linux下串列埠通訊詳解(下)讀寫串列埠及關閉串列埠Linux串列埠
- 串列埠通訊協議串列埠協議
- Android 串列埠通訊Android串列埠
- C# 串列埠通訊C#串列埠
- 11. 串列埠通訊串列埠
- 串列埠通訊型別串列埠型別
- (10)uart串列埠通訊串列埠
- 通過串列埠進行通訊 :串列埠
- 串列埠資料抓取及串列埠通訊模擬串列埠
- 安卓串列埠通訊疑問安卓串列埠
- java串列埠通訊例項 -Java串列埠
- VC++ 串列埠通訊(轉)C++串列埠
- 串列埠無法正常通訊串列埠
- 詳解linux下的串列埠通訊開發Linux串列埠
- AndroidSerialPort:安卓串列埠通訊庫Android安卓串列埠
- 串列埠通訊gui介面顯示串列埠GUI
- ROS環境下串列埠通訊ROS串列埠
- Android藍芽串列埠通訊Android藍芽串列埠
- VC++ 的串列埠通訊 (轉)C++串列埠
- 小型plc串列埠通訊簡介串列埠
- STM32串列埠通訊串列埠
- C#串列埠通訊遇到的坑C#串列埠
- android ndk 虛擬串列埠通訊Android串列埠
- C#串列埠通訊程式SerialPort類C#串列埠
- 用VB除錯串列埠通訊 (轉)除錯串列埠
- .NET Compact Framework下的串列埠通訊Framework串列埠
- STMF4串列埠通訊使用串列埠
- 串列埠通訊與其他通訊方式相比有什麼優勢?串列埠
- Arduino下的STM32的串列埠通訊UI串列埠
- ros中使用serial包實現串列埠通訊ROS串列埠
- VC++串列埠通訊程式設計詳解C++串列埠程式設計
- 在VB中利用API進行串列埠通訊API串列埠
- 打工筆記--------------------------c#實現串列埠通訊筆記C#串列埠
- C#實現掃碼槍串列埠通訊C#串列埠
- 串列埠通訊利器:SerialPortStream庫詳解,輕鬆實現C#串列埠開發串列埠C#
- 串列埠通訊系列六-串列埠與上位機通訊呼叫Flash及Flash視訊切換(非互動)串列埠