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;
}
};
相關文章
- 串列埠通訊串列埠
- Android 串列埠通訊Android串列埠
- 11. 串列埠通訊串列埠
- (10)uart串列埠通訊串列埠
- 串列埠通訊型別串列埠型別
- 串列埠通訊協議串列埠協議
- 通過串列埠進行通訊 :串列埠
- 串列埠資料抓取及串列埠通訊模擬串列埠
- 串列埠無法正常通訊串列埠
- C# SerialPort 串列埠通訊C#串列埠
- AndroidSerialPort:安卓串列埠通訊庫Android安卓串列埠
- 安卓串列埠通訊疑問安卓串列埠
- ROS環境下串列埠通訊ROS串列埠
- 串列埠通訊gui介面顯示串列埠GUI
- 小型plc串列埠通訊簡介串列埠
- C# 串列埠通訊利器 SerialPortStream庫C#串列埠
- STM32串列埠通訊串列埠
- STMF4串列埠通訊使用串列埠
- 串列埠通訊與其他通訊方式相比有什麼優勢?串列埠
- 串列埠通訊利器:SerialPortStream庫詳解,輕鬆實現C#串列埠開發串列埠C#
- ros中使用serial包實現串列埠通訊ROS串列埠
- 打工筆記--------------------------c#實現串列埠通訊筆記C#串列埠
- C#實現掃碼槍串列埠通訊C#串列埠
- Arduino下的STM32的串列埠通訊UI串列埠
- 樹莓派已經通過網路連線通過串列埠通訊在串列埠除錯小助手列印與操作樹莓派串列埠除錯
- 串列埠通訊上位機資料傳輸協議串列埠協議
- 基於WebSocket的modbus通訊(三)- websocket和串列埠Web串列埠
- Java實現RS485串列埠通訊Java串列埠
- Linux串列埠程式設計Linux串列埠程式設計
- Linux下串列埠監視Linux串列埠
- 一種MODBUS RTU擴充套件串列埠通訊協議套件串列埠協議
- 串列埠通訊常見的錯誤和故障排除方法串列埠
- 定位模組LuatOS快速入門:源UART串列埠通訊串列埠
- 使用Modbus4J進行RTU模式串列埠通訊模式串列埠
- UART串列埠及Linux實現串列埠Linux
- linux串列埠命令列除錯Linux串列埠命令列除錯
- 張高興的 MicroPython 入門指南:(三)使用串列埠通訊Python串列埠
- 超級乾貨!Air780E的串列埠通訊分享AI串列埠