linux下调用串口进行通信

最近一段时间做了一个项目,客户要使用串口进行通信,接收上位机的数据,根据数据控制一些外围器件和传递数据。下位机串口通信已写好,上位机使用windos的串口小助手进行调试,也已经OK。 还需要写一个linux端的应用程序,由于之前几年从事过linux android驱动调试,故调试起来很顺利。摸鱼之际,写下此篇博客记载之:
1.总体目录 见图:
在这里插入图片描述
main.c为主程序,接收参数进行处理。
uart.c为串口通信功能函数
inband.c为串口协议数据处理
makefile脚本----你懂得。。。

2.主程序
废话不多说,直接上代码:

void main(int argc, char **argv)
{
	char *uart1 ="/dev/ttyUSB0";  //USB串口  插入后 ls -l /dev/ttyUSB* 查看   
	int fd, uartfd;
	printf("this is the test file! \n");
	for (int i = 0; i < argc; i++)
		printf(" the argv[%d]:%s \n", i, argv[i]);


	if ((uartfd = open(uart1, O_RDWR | O_NOCTTY)) < 0)//非阻塞读方式 打开串口
	{
		printf("open %s is failed", uart1);
		exit(1);
	}

	if (set_opt(uartfd, 9600, 8, 'N', 1) != 0) 
	{
		printf("init uart fail \n");
		exit(1);
	}

	if(argc==1) //只有一个参数的情况下
	{
		printf("wrong paramters given \n");	
	}


	printf("enter the cmd...\n");
	if (strcmp(argv[1], "READ") == 0) //
	{
		
	    if(strcmp(argv[2], "brd_name") == 0)
		{
		write(uartfd, cmdGetFruBsn1, 9);    //
        read_fru();
		}
		else if(strcmp(argv[2], "brd_sn") == 0)
		write(uartfd, cmdfru1, 8);    
		else if(strcmp(argv[2], "brd_pn") == 0)
		write(uartfd, cmdfru2, 8);    
		else if(strcmp(argv[2], "brd_mfr") == 0)
		write(uartfd, cmdfru3, 8);    
		else if(strcmp(argv[2], "prd_name") == 0)
		write(uartfd, cmdfru4, 8);    
		else if(strcmp(argv[2], "prd_pn") == 0)
		write(uartfd, cmdfru5, 8);    
		else if(strcmp(argv[2], "prd_sn") == 0)
		write(uartfd, cmdfru6, 8);   
		else if(strcmp(argv[2], "prd_mfr") == 0)
		write(uartfd, cmdfru7, 8);   
		else if(strcmp(argv[2], "prd_pv") == 0)
		write(uartfd, cmdfru8, 8);    
		else if(strcmp(argv[2], "prd_pmn") == 0)
		write(uartfd, cmdfru9, 8);   

		if(strcmp(argv[2], "all") == 0)
		write(uartfd, cmdfru10, 8);   

		else
		{
	    printf("wrong paramters given \n");	
		exit(0);
		}
		 read_uart();  
	}

	else if (strcmp(argv[1], "mc") == 0) 
	{
		write(uartfd, cmdGetBmcVersion, 8);    
        read_uart();
		
	}
	else if (strcmp(argv[1], "sensor") == 0)
	{
	    write(uartfd, cmdsensor, 8);  
		read_uart();
	}
	else if (strcmp(argv[1], "param") == 0) 
	{
     write(uartfd, cmdparam, 8);  
     read_uart();
	}
	else if (strcmp(argv[1], "raw") == 0)
	{
		for (int i=0;i<=argc-2;i++ )
		{
			cmdraw[i]=argv[2+i];
		}
		write(uartfd, cmdfru, argc-2);  
		
	}
	else
	{
		printf("wrong paramters given \n");	
	}

    close(uartfd);
	printf("the end ! \n");
	exit(0);
}//end main

//读取串口数据函数
void read_uart(){
BYTE n=0;
	while (1) {
		while ((nByte = read(uartfd, recbuffer, 128)) > 0) {
			recbuffer[nByte + 1] = 0;// 
			printf(" the fur information len:%d \n", nByte);
			printf(" the fur information is :%s \n", recbuffer);  
			if ((recbuffer[0] == 0x5C) && (recbuffer[1] == 0x8D) && (recbuffer[2] == 0x1) &&
				(recbuffer[nByte - 2] == 0x5C) && (recbuffer[nByte-1] == 0xD8))
			{
				In_band_process(recbuffer, nByte);  //数据处理  
				Rev_Data[Rev_Real_DataLen + 1] = 0;
				memset(Rev_Data, 0, strlen(Rev_Data));
				memset(recbuffer, 0, strlen(recbuffer));
				nByte = 0;
		        close(uartfd);	
				return;  //读完毕,退出
			}
            close(uartfd);
			return;//exit(0);  
		}
		n++;
		if (n>=2)
		return ;
	} //end while(1)
		
}

2.串口设置函数

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
//#include <time.h>
#include <sys/types.h>
#include <termios.h>
#include <errno.h>
#include "uart.h"


int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio, oldtio;
	if (tcgetattr(fd, &oldtio) != 0) {
		perror("SetupSerial 1");
		return -1;
	}
	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;
	case 460800:
		cfsetispeed(&newtio, B460800);
		cfsetospeed(&newtio, B460800);
		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] = 100;///* 设置超时10 seconds*/
	newtio.c_cc[VMIN] = 0;
	tcflush(fd, TCIFLUSH);
	if ((tcsetattr(fd, TCSANOW, &newtio)) != 0)
	{
		perror("com set error");
		return -1;
	}

	//	printf("set done!\n\r");
	return 0;
}

3.数据处理,校验函数。没有参考价值,依具体情况而处理数据。故略之……

4.makefile脚本

test:main.o uart.o inband.o
	gcc  main.o uart.o inband.o -o test
uart.o:uart.c uart.h
	gcc -c uart.c -o uart.o
inband.o:inband.c inband.h
	gcc -c inband.c -o inband.o
main.o:main.c
	gcc -c main.c -o main.o

clean:
	rm -rf *.o test

测试可正常通信,获取到数据。
重点:在linux下需要root权限下,方可调用成功。
执行 ./test mc

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值