uart 485串口 read实现

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>

#include <time.h>
#include <poll.h>


#define BAUDRATE 115200


#define UART_DEVICE1     "/dev/ttyAMA4"
#define UART_DEVICE2     "/dev/ttyTHS2"  
#define UART_POLL_TIMEOUT_5000US 5000


const int speed_arr[] =
{
	B500000, B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400,
	B1800, B1200, B600, B300
};
const int name_arr[] =
{
	500000, 230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400,
	1800, 1200, 600, 300
};

int set_uart_speed(int fd, int speed)
{
	if (fd <= 0)
	{
		return -1;
	}

	int   i;
	int   status;
	struct termios   Opt;
	tcgetattr(fd, &Opt);
	for (i = 0;  i < (int)(sizeof(speed_arr) / sizeof(int));  i++)
	{
		if (speed == name_arr[i])
		{
			tcflush(fd, TCIOFLUSH);
			cfsetispeed(&Opt, speed_arr[i]);
			cfsetospeed(&Opt, speed_arr[i]);
			status = tcsetattr(fd, TCSANOW, &Opt);
			if (status != 0)
			{
				perror("tcsetattr fd1");
				return -1;
			}
			tcflush(fd, TCIOFLUSH);
			return 0;
		}
	}
	return -1;
}


int uart_init(const char *uart_port)
{
	int fd = -1;
	int status;
	struct termios options;
	memset(&options, 0, sizeof(struct termios));

	if (uart_port)
	{
		fd = open(uart_port,  O_RDWR | O_NOCTTY | O_NDELAY);
	}
	if (fd <= 0)
	{
		printf("uart port open failure\n");
		return -1;
	}

	options.c_cflag = HUPCL | CS8 | CREAD | CLOCAL | CRTSCTS;
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
	options.c_oflag &= ~OPOST;
	options.c_iflag = IGNPAR;

	options.c_cc[VTIME] = 0;
	options.c_cc[VMIN] = 1;
	if (tcsetattr(fd, TCSANOW, &options) != 0)
	{
		printf("error: tcsetattr failed\n");
		return -1;
	}
    ioctl(fd,TIOCMGET,&status);
	status &= ~TIOCM_RTS;//RTS引脚高电平
	ioctl(fd,TIOCMSET,&status);

	tcflush(fd, TCIOFLUSH);

	return fd;
}

int uart_read(int fd, unsigned char *pbuffer, int nlen, int timeout)
{
	if (pbuffer == NULL || nlen == 0 || fd < 0)
	{
		printf("read_uart: buffer is null or invalid uart port.\n");
		return -1;
	}

	int len = 0;
	int ret = 0;
	fd_set rfds;
	int retval = 0;
	struct timeval tv;
	while (len < nlen)
	{
		FD_ZERO(&rfds);
		FD_SET(fd, &rfds);
		tv.tv_sec = timeout / 1000000;
		tv.tv_usec = timeout % 1000000;
		retval = select(fd + 1, &rfds, NULL, NULL, &tv);
		if (retval < 0)
		{
			// 返回:错误为 -1.
			return -1;
		}
		else if (retval == 0)
		{
			// Translated comment from Chinese:
			// Where the return 0 is a bug, because even if the successful read data,
			// the last exit is also a timeout to exit
			//做好准备的文件描述符的个数,超时为0,
			//return 0;
			break;
		}
		else if (FD_ISSET(fd, &rfds))
		{
			ret = read(fd,  pbuffer + len, nlen - len);
			//printf("read: ");
			//for (int j = 0; j < ret; ++j)
			//{
			//	printf("%02x ", (pbuffer+len)[j]);
			//}
			//printf("\n");
			len += ret > 0 ? ret : 0;
			if (len >= nlen)
			{
				return len;
			}
		}
		else
		{
			usleep(1);
		}
	}

	return len ;
}

int uart_write(int fd, const unsigned  char *pbuffer, int nlen)
{
	if (pbuffer == NULL || nlen == 0 || fd < 0)
	{
		printf("write_uart: buffer (%p: %d) is null or invalid uart fd (%d).\n",
		       pbuffer, nlen, fd);
		return -1;
	}

	int ret = 0;
	int len = 0;
	fd_set wfds;
	int retval = 0;
	struct timeval tv;
	while (len < nlen)
	{
		FD_ZERO(&wfds);
		FD_SET(fd, &wfds);
		tv.tv_sec = 0;
		tv.tv_usec = 30000;
		retval = select(fd + 1, NULL, &wfds, NULL, &tv);
		if (retval < 0)
		{
			break;
		}
		else if (retval == 0)
		{
			break;
		}
		else if (FD_ISSET(fd, &wfds))
		{
			ret = write(fd,  pbuffer + len, nlen - len);
			//printf("%02x %02x", (unsigned char)(*(pbuffer + len)),
			//(unsigned char)(*(pbuffer + len + 1)));
			len += ret > 0 ? ret : 0;
		}
		else
		{
			usleep(1);
		}
	}
	//printf("\n");
	if (len != nlen)
	{
		printf("can't write %d bytes from %d just len = %d \n", nlen, fd, len);
	}

	//int nwrite_len =write(fd,pbuffer,nlen);
	//if(nwrite_len<=0)
	//{
	//	printf("write data to uart error\n");
	//	return -1;
	//}
	return len;
}

void *proc_uart_rev_thread(void *arg)
{
	unsigned char recv_buf[1024];
	int timeout = UART_POLL_TIMEOUT_5000US;
	int uart_fd = *((int *)arg);
	int i = 0;
	while(true){
		int recv_size = uart_read(uart_fd, recv_buf, sizeof(recv_buf), timeout);
		if(recv_size > 0){
            printf("**********收到了数据*************\n");
			for(i=0;i<recv_size;i++){
				printf("%x ",recv_buf[i]);
				if((i+1)%10 == 0){
					printf("\n");
				}
			}
		}			
	}
	return ((void*)0);
}
int main(int argc, char *argv[])
{
	int fd;
	pthread_t thread_uart_id;
	int ret;

	if(argc != 2){
		printf("Usage: uart_test [ttyS2/ttyS1]\n");
		exit(1);
	}
	
	
	if(strcmp("ttyS1",argv[1]) == 0){
		fd = uart_init(UART_DEVICE1);
		if (fd < 0){  
            printf("init uart (%s) fail\n",UART_DEVICE1);			
			exit(1);  
		}  
	}else if(strcmp("ttyS2",argv[1]) == 0){
		fd = uart_init(UART_DEVICE2);
		if (fd < 0){  
			printf("init uart (%s) fail\n",UART_DEVICE2);	 
			exit(1);  
		} 
	}else{
		printf("Usage: uart_test [ttyS2/ttyS1]\n");
		exit(1);
	}

    set_uart_speed(fd, BAUDRATE);
	ret = pthread_create(&thread_uart_id, NULL, proc_uart_rev_thread, &fd);
	while(1){
	  sleep(5);
	}
	close(fd);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值