栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux串口通信

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux串口通信

1、发现设备

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_

#include 


#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
3、对端收发

对端可以直接使用scanf从串口上接收数据,使用printf将数据发送到串口。

注意:当在对端使用scanf接收来自串口的数据时,Linux发送端应在数据末尾加上换行符'n'。

4、参考资料

1)linux串口通信编程 - Malphite - 博客园 (cnblogs.com)

2)linux下的串口通信_u013485792的专栏-CSDN博客_linux 串口通信

3)linux下串口通信与管理 - ssooking - 博客园 (cnblogs.com)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/277363.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号