1)首先查看串口驱动是否存在:
lsmod | grep usbserial
若不存在,则可通过下述方式安装驱动:
sudo apt-get install setserial
2)插入串口设备,可在/dev/目录下查看到串口设备的存在,串口设备文件的一般格式为:
/dev/ttyUSBx(x表示0,1,...)
同时,可通过下述发现串口设别是否已经成功接入:
dmesg | grep ttyUSB*
3)以程序的形式发现串口设备
函数定义:
static int GetAvailableUartDev(char (*strDevList)[MAX_DEV_NAME_LENS], size_t u32MaxItem, const char* strCmd)
{
char buf[MAX_DEV_NAME_LENS] = {0};
char tmp[MAX_DEV_NAME_LENS] = {0};
FILE *pf = NULL;
int s32Size = 0;
pf = popen(strCmd, "r");
if(NULL == pf)
{
perror("It's failed to open the shell of cmd");
return -1;
}
while(fgets(buf, sizeof(buf), pf) && s32Size < u32MaxItem)
{
sscanf(buf, "%sn", tmp);
memcpy(strDevList[s32Size], tmp, sizeof(tmp));
s32Size++;
}
pclose(pf);
printf("Device lists as follow: (%d items)n", s32Size);
for(int i = 0; i < s32Size; ++i)
{
printf("%d, %sn", i, strDevList[i]);
}
return s32Size;
}
上述方法通过系统函数popen,执行shell命令,得以将结果返回。传入的shell命令为:
ls /dev/ttyUSB* -l | awk '{print $NF}' | sort
2、串口通信
uart.c文件
#include "uart.h" #include#include #include #include #include #include #include #include #include #include #include UART_CTRL pstCtrl = {0}; void CleanUpFunc(int sig_num) { if(pstCtrl.fd != -1) { close(pstCtrl.fd); } printf("Program exit via signal function!n"); exit(1); } static int SetUartAttr(int fd, int nSpeed, int nBits, char nEvent, int nStop) { struct termios newtio; bzero(&newtio, sizeof(newtio)); newtio.c_cflag |= CLOCAL | CREAD; //本地连接,接收使能 newtio.c_cflag &= ~CSIZE; //屏蔽数据位 switch( nBits ) { case 7: newtio.c_cflag |= CS7; break; case 8: newtio.c_cflag |= CS8; break; } switch( nEvent ) { 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; //无校验 break; } switch( nSpeed ) { 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); break; } if( nStop == 1 ) { newtio.c_cflag &= ~CSTOPB; } else if ( nStop == 2 ) { newtio.c_cflag |= CSTOPB; } newtio.c_cc[VTIME] = 0; // 等待时间,单位百毫秒 (读) newtio.c_cc[VMIN] = 0; // 最小字节数 (读) tcflush(fd, TCIFLUSH); // 刷清输入队列,即将配置信息立即刷入系统 if((tcsetattr(fd, TCSANOW, &newtio)) != 0) // TCSANOW立即生效 { perror("com set error"); return -1; } printf("SetUartAttr exec ok!n"); return 0; } static int OpenUartDev(char* strDevFile) { int fd = 0; int ret = 0; printf("Opening device: "%s"n", strDevFile); fd = open(strDevFile, O_RDWR|O_NOCTTY|O_NDELAY); if (-1 == fd) { perror("Can't Open Serial Port"); return -1; } ret = fcntl(fd, F_SETFL, 0); if(ret < 0) { printf("fcntl failed!n"); } ret = isatty(STDIN_FILENO); if(ret == 0) { printf("Standard input is not a terminal devicen"); } printf("Open device ok, fd=%d, dev=%sn", fd, strDevFile); return fd; } static int GetAvailableUartDev(char (*strDevList)[64], size_t u32MaxItem, const char* strCmd) { char buf[MAX_DEV_NAME_LENS] = {0}; char tmp[MAX_DEV_NAME_LENS] = {0}; FILE *pf = NULL; int s32Size = 0; pf = popen(strCmd, "r"); if(NULL == pf) { perror("It's failed to open the shell of cmd"); return -1; } while(fgets(buf, sizeof(buf), pf) && s32Size < u32MaxItem) { sscanf(buf, "%sn", tmp); memcpy(strDevList[s32Size], tmp, sizeof(tmp)); s32Size++; } pclose(pf); printf("Device lists as follow: (%d items)n", s32Size); for(int i = 0; i < s32Size; ++i) { printf("%d, %sn", i, strDevList[i]); } return s32Size; } int UartInit(int nSpeed, int nBits, char nEvent, int nStop) { int ret = -1; signal(SIGINT, CleanUpFunc); pstCtrl.u32DevNums = GetAvailableUartDev(pstCtrl.strDevList, MAX_DEV_NUMS, "ls /dev/ttyUSB* -l | awk '{print $NF}' | sort"); if(pstCtrl.u32DevNums <= 0) { printf("There isn't any available device be found!n"); return -1; } pstCtrl.fd = OpenUartDev(pstCtrl.strDevList[0]); if(pstCtrl.fd < 0) { perror("open_port error"); return -2; } ret = SetUartAttr(pstCtrl.fd, nSpeed, nBits, nEvent, nStop); if(ret < 0) { perror("SetUartAttr error"); return -3; } printf("UartInit exec ok!n"); return 0; } int UartSendData(const void *buf, size_t size) { if(NULL == buf || 0 == size) { printf("The send data is error occured! buf=%p, size=%ld", buf, size); return -1; } write(pstCtrl.fd, buf, size); return 0; } size_t UartRecvData(void *buf, size_t size) { if(NULL == buf || 0 == size) { printf("The send data is error occured! buf=%p, size=%lu", buf, size); return -1; } ssize_t s64RecvSize = 0; s64RecvSize = read(pstCtrl.fd, buf, size); return s64RecvSize; }
uart.h文件
#ifndef _UART_H_ #define _UART_H_ #include3、对端收发#define MAX_DEV_NAME_LENS (64) #define MAX_DEV_NUMS (64) typedef struct _UART_CTRL_ { int fd; //串口设备的文件描述符 int u32DevNums; //扫描到的串口设备的数量 char strDevList[MAX_DEV_NUMS][MAX_DEV_NAME_LENS]; //设备列表,包含扫描到的所有串口设备 }UART_CTRL; int UartInit(int nSpeed, int nBits, char nEvent, int nStop); int UartSendData(const void *buf, size_t size); size_t UartRecvData(void *buf, size_t size); #endif
对端可以直接使用scanf从串口上接收数据,使用printf将数据发送到串口。
注意:当在对端使用scanf接收来自串口的数据时,Linux发送端应在数据末尾加上换行符'n'。
4、参考资料1)linux串口通信编程 - Malphite - 博客园 (cnblogs.com)
2)linux下的串口通信_u013485792的专栏-CSDN博客_linux 串口通信
3)linux下串口通信与管理 - ssooking - 博客园 (cnblogs.com)



