C Uart连接

1 篇文章 0 订阅
1 篇文章 0 订阅

 步骤:

1、打开设备述符。

#define UART_PATH_NAME                "/dev/ttyPS0" // 根据实际修改

fd = open(UART_PATH_NAME,O_RDWR | O_NOCTTY | O_NDELAY);​

2、设置串口波特率

int set_baud_ratet(struct termios *serial_Setting, int baud_rate)
{
	int i = 0;
	//支持波特率的列表
	int speed_array[] = {B460800, B115200, B19200, B9600, B4800, B2400, B1200, B300};  
	int name_array[] = {460800, 115200,  19200,  9600,  4800,  2400,  1200,  300};  
	
	if (serial_Setting == NULL) {
		printf("The serial_Setting is NULL. \n");
		return -1;
	}
	
	//设置串口输入波特率和输出波特率
	for ( i= 0;  i < sizeof(speed_array) / sizeof(int);  i++)  
	{  
		if  (baud_rate == name_array[i])  
		{               
			cfsetispeed(serial_Setting, speed_array[i]);   
			cfsetospeed(serial_Setting, speed_array[i]);  
			break;		
		}  
	}
	
	return 0;
}

3、设置数据位

int set_nBits(struct termios *serial_Setting, int nBits)
{
	if (serial_Setting == NULL) {
		printf("The serial_Setting is NULL. \n");
		return -1;
	}
	
    //屏蔽其他标志位  
	serial_Setting->c_cflag &= ~CSIZE;  
	switch( nBits )
	{
	case 7:
		serial_Setting->c_cflag |= CS7;
		break;
	case 8:
		serial_Setting->c_cflag |= CS8;
		break;
	}
	
	return 0;
}

4、设置校验位

int set_nEvent(struct termios *serial_Setting, int nEvent)
{
	if (serial_Setting == NULL) {
		printf("The serial_Setting is NULL. \n");
		return -1;
	}
	
	switch( nEvent )
	{
	case 'o':
	case 'O':
		serial_Setting->c_cflag |= PARENB;
		serial_Setting->c_cflag |= PARODD;
		serial_Setting->c_iflag |= (INPCK | ISTRIP);
		break;
	case 'e': 
	case 'E': 
		serial_Setting->c_iflag |= (INPCK | ISTRIP);
		serial_Setting->c_cflag |= PARENB;
		serial_Setting->c_cflag &= ~PARODD;
		break;
	case 'n': 
	case 'N': 
		serial_Setting->c_cflag &= ~PARENB;
		break;
	}
	
	return 0;
}

5、设置停止位

int set_nStop(struct termios *serial_Setting, int nStop)
{
	if (serial_Setting == NULL) {
		printf("The serial_Setting is NULL. \n");
		return -1;
	}
	
	if( nStop == 1 )
		serial_Setting->c_cflag &=  ~CSTOPB;
	else if ( nStop == 2 )
		serial_Setting->c_cflag |=  CSTOPB;
	
	return 0;
}

6、设置流控制

void flow_ctrl(struct termios *serial_Setting, int ctrl)
{
	//设置数据流控制  
	switch(ctrl)  
	{
		//不使用流控制
		case 0 : serial_Setting->c_cflag &= ~CRTSCTS;  
		break;     
		//使用硬件流控制 
		case 1 : serial_Setting->c_cflag |= CRTSCTS;  
		break;
		//使用软件流控制  
		case 2 : serial_Setting->c_cflag |= IXON | IXOFF | IXANY;  
		break;
	}	
}

完整连接代码

#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h> /* thread */
#include <termios.h> /* POSIX Terminal Control Definitions */
#include <signal.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <time.h>
#include <sys/ioctl.h>

#define UART_PATH_NAME                "/dev/ttyPS0" // 根据实际修改
#define UART_BAUD_RATE                115200
#define UART_BITE                     8
#define UART_EVENT                    'N'
#define UART_STOP                     1

int  fd; 

/****************************************************************************************************
* set_baud_ratet() set seriol setting baud rate.
*
* @Param
*	serial_Setting is the struct of termios, baud_rate is the baud rate.
*
* @Return
*	If succeed return 0.
****************************************************************************************************/
int set_baud_ratet(struct termios *serial_Setting, int baud_rate)
{
	int i = 0;
	//支持波特率的列表
	int speed_array[] = {B460800, B115200, B19200, B9600, B4800, B2400, B1200, B300};  
	int name_array[] = {460800, 115200,  19200,  9600,  4800,  2400,  1200,  300};  
	
	if (serial_Setting == NULL) {
		printf("The serial_Setting is NULL. \n");
		return -1;
	}
	
	//设置串口输入波特率和输出波特率
	for ( i= 0;  i < sizeof(speed_array) / sizeof(int);  i++)  
	{  
		if  (baud_rate == name_array[i])  
		{               
			cfsetispeed(serial_Setting, speed_array[i]);   
			cfsetospeed(serial_Setting, speed_array[i]);  
			break;		
		}  
	}
	
	return 0;
}

/****************************************************************************************************
* set_nBits() set seriol setting data bits.
*
* @Param
*	serial_Setting is the struct of termios, nBites is the data bits.
*
* @Return
*	If succeed return 0.
****************************************************************************************************/
int set_nBits(struct termios *serial_Setting, int nBits)
{
	if (serial_Setting == NULL) {
		printf("The serial_Setting is NULL. \n");
		return -1;
	}
	
    //屏蔽其他标志位  
	serial_Setting->c_cflag &= ~CSIZE;  
	switch( nBits )
	{
	case 7:
		serial_Setting->c_cflag |= CS7;
		break;
	case 8:
		serial_Setting->c_cflag |= CS8;
		break;
	}
	
	return 0;
}

/****************************************************************************************************
* set_uEvent() set seriol setting of mode.
*
* @Param
*	serial_Setting is the struct of termios, nStop is the mode.
*
* @Return
*	If succeed return 0.
****************************************************************************************************/
int set_nEvent(struct termios *serial_Setting, int nEvent)
{
	if (serial_Setting == NULL) {
		printf("The serial_Setting is NULL. \n");
		return -1;
	}
	
	switch( nEvent )
	{
	case 'o':
	case 'O':
		serial_Setting->c_cflag |= PARENB;
		serial_Setting->c_cflag |= PARODD;
		serial_Setting->c_iflag |= (INPCK | ISTRIP);
		break;
	case 'e': 
	case 'E': 
		serial_Setting->c_iflag |= (INPCK | ISTRIP);
		serial_Setting->c_cflag |= PARENB;
		serial_Setting->c_cflag &= ~PARODD;
		break;
	case 'n': 
	case 'N': 
		serial_Setting->c_cflag &= ~PARENB;
		break;
	}
	
	return 0;
}

/****************************************************************************************************
* set_nStop() set seriol setting of stop bit.
*
* @Param
*	serial_Setting is the struct of termios, nStop is stop bit.
*
* @Return
*	If succeed return 0.
****************************************************************************************************/
int set_nStop(struct termios *serial_Setting, int nStop)
{
	if (serial_Setting == NULL) {
		printf("The serial_Setting is NULL. \n");
		return -1;
	}
	
	if( nStop == 1 )
		serial_Setting->c_cflag &=  ~CSTOPB;
	else if ( nStop == 2 )
		serial_Setting->c_cflag |=  CSTOPB;
	
	return 0;
}

void flow_ctrl(struct termios *serial_Setting, int ctrl)
{
	//设置数据流控制  
	switch(ctrl)  
	{
		//不使用流控制
		case 0 : serial_Setting->c_cflag &= ~CRTSCTS;  
		break;     
		//使用硬件流控制 
		case 1 : serial_Setting->c_cflag |= CRTSCTS;  
		break;
		//使用软件流控制  
		case 2 : serial_Setting->c_cflag |= IXON | IXOFF | IXANY;  
		break;
	}	
}

int uart_init(int uart_fd, int baud_rate, int nBits, int nEvent, int nStop)
{
	struct termios serial_Setting;
	
	bzero( &serial_Setting, sizeof( serial_Setting ) );        // 设置SerialPortSetting所有字节为0
	tcflush(uart_fd, TCIFLUSH);
	
	/* tcgetattr(serialFd,&options)得到与fd指向对象的相关参数,并将它们保存于options,
	该函数还可以测试配置是否正确,该串口是否可用等。
	若调用成功,函数返回值为0,若调用失败,函数返回值为1. */
	if  (0 != tcgetattr(uart_fd, &serial_Setting))  
	{  
		printf("Setup Serial Error \n");      
		return -1;   
	}  
	
	// set baud rate 
	if ( set_baud_ratet(&serial_Setting, baud_rate) != 0)
		return -1;

	//修改控制模式,保证程序不会占用串口  (CLOCAL:忽略任何调制解调器状态)
    serial_Setting.c_cflag |= CLOCAL;  
    //修改控制模式,使得能够从串口中读取输入数据  (CREAD:启动接收器)
    serial_Setting.c_cflag |= CREAD;  
    serial_Setting.c_oflag &= ~(ONLCR | OCRNL);
	serial_Setting.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
	serial_Setting.c_iflag &= ~(ICRNL | INLCR);
	serial_Setting.c_iflag &= ~(IXON | IXOFF | IXANY);
	
	flow_ctrl(&serial_Setting, 0); // 设置数据流控制
	
	serial_Setting.c_cflag  &= ~CSIZE;                         // Clears the mask for setting the data size
	
	// set data bits
	if ( set_nBits(&serial_Setting, nBits) != 0)
		return -1;
	
	// set the mode
	if ( set_nEvent(&serial_Setting, nEvent) != 0)
		return -1;
	
	// set stop bit
	if ( set_nStop(&serial_Setting, nStop) != 0)
		return -1;
	
    serial_Setting.c_oflag &= ~OPOST;                           // No Output Processing raw format output (Output)
    serial_Setting.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  // Non Cannonical mode (Input)
	// serial_Setting.c_iflag &= ~(IXON | IXOFF | IXANY);          // Disable XON/XOFF flow control both i/p and o/p 
	
	
    // Setting Time outs 
	serial_Setting.c_cc[VTIME]  = 5;                           // (单位100ms)
	serial_Setting.c_cc[VMIN]   = 1;                           // 最少读xx个
	tcflush(uart_fd,TCIFLUSH);

	if((tcsetattr(uart_fd,TCSANOW,&serial_Setting))!=0)
	{
		printf("Com set error \n");
		return -1;
	}
	
	return 0;
}

int main(int argc, char *argv[])
{
    fd = open(UART_PATH_NAME,O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd < 0){
        printf("bd uart open faild \n");
        return -1;
    }
    
     //设置串口为阻塞状态
    if(fcntl(fd,F_SETFL,0)<0) {
		printf("fcntl failed\n");
	}
	//测试是否为终端设备
	if(0 == isatty(fd))  
    {
        printf("Standard input is not a terminal device\n");  
        return -1;
	}  
	
    //设置参数
    if((uart_init(fd, UART_BAUD_RATE, UART_BITE, UART_EVENT, UART_STOP))<0){
        return -1;
    }

    return 0;
}

 创建接收线程

pthread_t tid_uart_rcv;
fd_uart_rcv = pthread_create(&tid_uart_rcv, NULL, (void *)&threat_uart_rcv, "Uart rcv thread");
if (fd_uart_rcv < 0) {
	printf("Create thread of uart receive failed. ");
}

接收函数

#define READ_BUFF_LENGTH 500
int exit_flag = 0;
void threat_uart_rcv()
{
	int ret     = 0;
	u32 rcv_len = 0;                      // 接收buff长度
	u8 buf_tmp[READ_BUFF_LENGTH] = {0};   // 临时缓存区
	fd_set rcv_fd_set;                    // fd集合
	struct timeval timeout;               // 超时时长
	
	printf("Create thread of uart_receive secceed. \n");

	while (!exit_flag) {
		
		FD_ZERO(&rcv_fd_set);
		FD_SET(fd, &rcv_fd_set);
		// 设置等待超时时长
		timeout.tv_sec  = 3; // 秒 
		timeout.tv_usec = 1; // 微妙
		
		ret = select(fd + 1,&rcv_fd_set,NULL,NULL,&timeout);
		
		if (ret <= 0) {
			continue;
		}
	
		if( FD_ISSET(fd,&rcv_fd_set) ){ // 检测fd在集合rcv_fd_set的状态是否变化,变化为true,否则,为false
			
			memset(buf_tmp, 0, sizeof(buf_tmp));            // 清空缓存
            rcv_len = read(fd,&buf_tmp,sizeof(buf_tmp));    // 读取buffer
			if (rcv_len == 0) {
				continue;
			}
			
			// Printf  receive buffer.		
			printf("\n\n rcv_len: %d Line: %d \n", rcv_len, __LINE__);
			int i = 0;
			for (i=0; i<rcv_len; i++) {
				printf("0x%02x ", buf_tmp[i]);
			}
			printf("\n");
		}
	}
	return ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值