RS485通信

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/gpio.h>
#include <termios.h>
#include <linux/ioctl.h>
#include <linux/serial.h>
#include <asm-generic/ioctls.h> /* TIOCGRS485 + TIOCSRS485 ioctl definitions */
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
#include<pthread.h>
#include <signal.h>

int gpio_init();
void gpio_setnum(unsigned char value);
int port_open(char *device);
int port_init(int fd,struct termios oldtio ,int nSpeed, int nBits, char nEvent, int nStop);
static void print_usage(FILE *stream, int exit_code);
void print_usage(FILE *stream, int exit_code);

struct pthread_par
{
	int fd,sig;                      //fd:串口设备
	struct gpiohandle_request req;   //申请gpio的结构体信息
    struct gpiohandle_data data;     //设置gpio的值   
	char *write_buf;
	char read_buf[100];
	pthread_mutex_t mut;
}par;
int gpio_init()
{
    int fd1,ret1;
    fd1 = open("/dev/gpiochip3", 0);
    if (fd1 == -1) {
        ret1 = -errno;
        fprintf(stderr, "Failed to open %s\n","/dev/gpiochip3");
        exit(1);
    }
    /* request GPIO line: GPIO_D_12 */
    par.req.lineoffsets[0] = 12;
    par.req.flags = GPIOHANDLE_REQUEST_OUTPUT;  //output 
    //memcpy(req->default_values, data, sizeof(req->default_values));
    strcpy(par.req.consumer_label, "gpio_d_12");
    par.req.lines = 1;
    ret1 = ioctl(fd1, GPIO_GET_LINEHANDLE_IOCTL, &par.req);
    if (ret1 == -1) {
        ret1 = -errno;
        fprintf(stderr,"Failed to issue GET LINEHANDLE IOCTL (%d)\n",ret1);
    }
    if (close(fd1) == -1)
        perror("Failed to close GPIO character device file");
    return 0;
}

void gpio_setnum(unsigned char value)
{
    int ret;
    par.data.values[0] = value;
    ret = ioctl(par.req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &par.data);
    if (ret == -1) 
    {
        ret = -errno;
        fprintf(stderr,"Failed to issue %s (%d)\n", ret);
    }
}

int port_open(char *device)
{
	int fd;
	fd = open(device, O_RDWR);
	if (fd < 0)
	{
		perror("port_open");
	}
    return fd;
}

int port_init(int fd,struct termios oldtio, int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio;
	memset(&oldtio, 0, sizeof(oldtio));
	/* save the old serial port configuration */
	if (tcgetattr(fd, &oldtio) != 0)
	{
		perror("set_port/tcgetattr");
		exit(1);
	}
	memset(&newtio, 0, sizeof(newtio));
	/* ignore modem control lines and enable receiver */
	newtio.c_cflag |= CLOCAL | CREAD;
	newtio.c_cflag &= ~CSIZE;
	/* set character size */
	switch (nBits)
	{
	case 8:
		newtio.c_cflag |= CS8;
		break;
	case 7:
		newtio.c_cflag |= CS7;
		break;
	case 6:
		newtio.c_cflag |= CS6;
		break;
	case 5:
		newtio.c_cflag |= CS5;
		break;
	default:
		newtio.c_cflag |= CS8;
		break;
	}
	/* set the parity */
	switch (nEvent)
	{
	case 'o':
	case 'O':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'e':
	case 'E':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'n':
	case 'N':
		newtio.c_cflag &= ~PARENB;
		break;
	default:
		newtio.c_cflag &= ~PARENB;
		break;
	}
	/* set the stop bits */
	switch (nStop)
	{
	case 1:
		newtio.c_cflag &= ~CSTOPB;
		break;
	case 2:
		newtio.c_cflag |= CSTOPB;
		break;
	default:
		newtio.c_cflag &= ~CSTOPB;
		break;
	}
	/* set output and input baud rate */
	switch (nSpeed)
	{
	case 0:
		cfsetospeed(&newtio, B0);
		cfsetispeed(&newtio, B0);
		break;
	case 50:
		cfsetospeed(&newtio, B50);
		cfsetispeed(&newtio, B50);
		break;
	case 75:
		cfsetospeed(&newtio, B75);
		cfsetispeed(&newtio, B75);
		break;
	case 110:
		cfsetospeed(&newtio, B110);
		cfsetispeed(&newtio, B110);
		break;
	case 134:
		cfsetospeed(&newtio, B134);
		cfsetispeed(&newtio, B134);
		break;
	case 150:
		cfsetospeed(&newtio, B150);
		cfsetispeed(&newtio, B150);
		break;
	case 200:
		cfsetospeed(&newtio, B200);
		cfsetispeed(&newtio, B200);
		break;
	case 300:
		cfsetospeed(&newtio, B300);
		cfsetispeed(&newtio, B300);
		break;
	case 600:
		cfsetospeed(&newtio, B600);
		cfsetispeed(&newtio, B600);
		break;
	case 1200:
		cfsetospeed(&newtio, B1200);
		cfsetispeed(&newtio, B1200);
		break;
	case 1800:
		cfsetospeed(&newtio, B1800);
		cfsetispeed(&newtio, B1800);
		break;
	case 2400:
		cfsetospeed(&newtio, B2400);
		cfsetispeed(&newtio, B2400);
		break;
	case 4800:
		cfsetospeed(&newtio, B4800);
		cfsetispeed(&newtio, B4800);
		break;
	case 9600:
		cfsetospeed(&newtio, B9600);
		cfsetispeed(&newtio, B9600);
		break;
	case 19200:
		cfsetospeed(&newtio, B19200);
		cfsetispeed(&newtio, B19200);
		break;
	case 38400:
		cfsetospeed(&newtio, B38400);
		cfsetispeed(&newtio, B38400);
		break;
	case 57600:
		cfsetospeed(&newtio, B57600);
		cfsetispeed(&newtio, B57600);
		break;
	case 115200:
		cfsetospeed(&newtio, B115200);
		cfsetispeed(&newtio, B115200);
		break;
	case 230400:
		cfsetospeed(&newtio, B230400);
		cfsetispeed(&newtio, B230400);
		break;
	default:
		cfsetospeed(&newtio, B115200);
		cfsetispeed(&newtio, B115200);
		break;
	}
    /* set timeout in deciseconds for non-canonical read */
	newtio.c_cc[VTIME] = 1;
	/* set minimum number of characters for non-canonical read */
	newtio.c_cc[VMIN] = 100;
	/* flushes data received but not read */
	tcflush(fd, TCIFLUSH);
	/* set the parameters associated with the terminal from
		the termios structure and the change occurs immediately */
	if ((tcsetattr(fd, TCSANOW, &newtio)) != 0)
	{
		perror("set_port/tcsetattr");
		exit(1);
	}
	return 0;
}
int input_init(int argc,char**argv,struct termios oldtio)
{
	int r=1,speed,fd;
	char *device;
	int next_option;
	int speed_flag = 0, device_flag = 0;

	const char *const short_options = "hd:s:b:e:";
	const struct option long_options[] = {
		{"help", 0, NULL, 'h'},
		{"device", 1, NULL, 'd'},
		{"string", 1, NULL, 's'},
		{"baudrate", 1, NULL, 'b'},
		{NULL, 0, NULL, 0}};

	if (argc < 2)
	{
		print_usage(stdout, 0);
		exit(0);
	}
	while (r)
	{
		next_option = getopt_long(argc, argv, short_options, long_options, NULL);
		if (next_option < 0)
			break;
		switch (next_option)
		{
		case 'h':
			print_usage(stdout, 0);
			break;
		case 'd':
			device = optarg;
			device_flag = 1;
			break;
		case 'b':
			speed = atoi(optarg);
			speed_flag = 1;
			break;
		// case 's':
		// 	write_buf = optarg;
		// 	break;
		case 'e':
			r = atoi(optarg);
			break;
		case '?':
			print_usage(stderr, 1);
			break;
		default:
			abort();
		}
	}
	if ((!device_flag) || (!speed_flag))
	{
		print_usage(stderr, 1);
		exit(0);
	}
	fd = port_open(device);
	port_init(fd,oldtio, speed, 8, 'N', 1);
	return fd;
}
void print_usage(FILE *stream, int exit_code)
{
	fprintf(stream, "Usage: option [ dev... ] \n");
	fprintf(stream,
			"\t-h  --help     Display this usage information.\n"
			"\t-d  --device   The device ttyS[0-3] or ttySCMA[0-1]\n"
			"\t-b  --baudrate Set the baud rate you can select\n"
			"\t               [230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300]\n"
			"\t-s  --string   Write the device data\n");
			//"\t-e  --1 or 0   Write 1 to enable the rs485_mode(only at atmel)\n");
	exit(exit_code);
}
void *thread_func1()
{	
    int nread;
	while (1)
	{
		//pthread_mutex_lock(&par.mut);
		if(par.sig%2 == 0)
		{
			//pthread_mutex_lock(&par->mut);
			memset(par.read_buf,0,sizeof(par.read_buf));
			gpio_setnum(0);
			nread = read(par.fd,par.read_buf,sizeof(par.read_buf));
			if(nread<0)
			{
				perror("read error");
				exit(1);
			}
			//pthread_mutex_unlock(&par->mut);	
			if(nread > 0)
			{
				printf("RECV[%3d]: ", nread);
				for (int i = 0; i < nread; i++)
					printf("%c", par.read_buf[i]);
				printf("\n");
			}
			if(strcmp("quit",par.read_buf)==0)
			{
				par.sig ++;
			}	
		}
	}	
    printf("thread1 stop\n");
    pthread_exit(NULL);
}
void *thread_func2()
{
    int nwrite;
	//struct pthread_par *par = p;
	par.write_buf = malloc(100);
	while (1)
	{
		if(par.sig%2 == 1)
		{
			//pthread_mutex_lock(&par->mut);
			printf("please input something\n");
			scanf("%[^\n]",par.write_buf);
			getchar();
			//gets(par.write_buf);
			gpio_setnum(1);
			nwrite = write(par.fd, par.write_buf,strlen(par.write_buf));
			usleep(40000);			 // 40ms
			//pthread_mutex_unlock(&par->mut);
			if(strcmp("quit",par.write_buf)==0)
			{
				par.sig ++;
			}
		} 	
	}
	free(par.write_buf);
	printf("thread2 stop\n");
	pthread_exit(NULL);
}
	
void sigint_handler()
{
    par.sig ++;
	printf("\n");
	if(par.sig%2 == 0)
	{
		gpio_setnum(0);
	}
	else
	{
		gpio_setnum(1);
	}
}

int main(int argc, char **argv)
{
    int ret;
	struct termios oldtio;
    pthread_t pthread[2];
	memset(&pthread,0,sizeof(pthread));
	/*input device ... and open device*/
	par.fd = input_init(argc,argv,oldtio);
	par.sig = 0;
	/*request gpio_d_12*/
	gpio_init();
	signal(SIGINT, sigint_handler);
	pthread_mutex_init(&par.mut,NULL);
	printf("creat thread\n");
    ret = pthread_create(&pthread[0], NULL, thread_func1, NULL);
    if(ret != 0)
    {
        perror("pthread[0] error");
        exit(1);
	}
	usleep(10);
    ret = pthread_create(&pthread[1], NULL, thread_func2, NULL);
    if(ret != 0)
    {
        perror("pthread[1] error");
        exit(1);
    }
    /*等待线程结束*/
    pthread_join(pthread[0],NULL);
	pthread_join(pthread[1],NULL);
	printf("thread close\n");
	tcsetattr(par.fd,TCSANOW,&oldtio);
	//pthread_mutex_destroy(&par.mut);
	close(par.fd);
	ret = close(par.req.fd);
    if (ret == -1) 
    {
        perror("Failed to close GPIO LINEHANDLE device file");
        ret = -errno;
    }	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值