uart 485串口 write 实现

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.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 500000


#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;
	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)
		{
			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
			//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;
	//printf("write: ");
	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)
		{
			perror("uart write ");
			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_write_thread(void *arg)
{
	unsigned char buf[100]={0};
	int uart_fd = *((int *)arg);
	int len = 0;
	char *str = NULL;
	while(true){
		printf("please input the string:\n");
		scanf("%s",buf);
		str = (char*)buf;
		len = strlen(str);
		printf("len:%d\n",len);
        uart_write(uart_fd,buf,len);
        str = NULL;		
	}
	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_write_thread, &fd);
	while(1){
	  sleep(5);
	}
	close(fd);
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现上位机与下位机之间的UART串口通信,可以使用C语言编写上位机程序。下面是一个简单的示例代码,演示如何通过串口与下位机进行通信: ```c #include <stdio.h> #include <string.h> #include <fcntl.h> #include <termios.h> int main() { int fd; char data[255]; // 打开串口设备 fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); if (fd == -1) { perror("打开串口失败"); return -1; } // 配置串口参数 struct termios options; tcgetattr(fd, &options); cfsetispeed(&options, B9600); // 设置波特率为9600 cfsetospeed(&options, B9600); options.c_cflag |= CLOCAL; options.c_cflag |= CREAD; tcsetattr(fd, TCSANOW, &options); // 从终端读取输入数据 printf("请输入要发送的数据:"); fgets(data, sizeof(data), stdin); // 发送数据到串口 int len = write(fd, data, strlen(data)); if (len == -1) { perror("发送数据失败"); return -1; } printf("已发送数据:%s\n", data); // 关闭串口设备 close(fd); return 0; } ``` 在这个示例中,我们首先使用`open`函数打开了串口设备`/dev/ttyUSB0`,并指定了读写权限。然后,使用`tcgetattr`函数获取当前串口的配置参数,并使用`cfsetispeed`和`cfsetospeed`函数设置波特率为9600bps。接下来,我们将`CLOCAL`和`CREAD`标志位设置为1,表示本地连接和可读。然后使用`tcsetattr`函数将新的配置参数应用到串口设备上。 然后,我们使用`fgets`函数从终端读取用户输入的数据,并使用`write`函数将数据发送到串口。通过输出来验证是否成功发送了数据。最后,我们使用`close`函数关闭串口设备。 同样,请注意,此示例仅用于演示目的,实际使用中可能需要根据具体情况进行适当的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值