我是靠谱客的博主 无辜眼神,最近开发中收集的这篇文章主要介绍Uart 配置,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

serialcode.c
/*******************************************************************************
  * @file        serialcode.c
  * @copyright   2022 
  * @author     
  * @date        2022-6-14
  * caption:								
*******************************************************************************/
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h> 
#include <linux/kernel.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include "serialcode.h"



unsigned char Write_RingBuff(unsigned char data);
unsigned char Read_RingBuff(unsigned char *rData);


pthread_mutex_t mutex ;
int uart_fd;
Uart_RingBuff_t RingBuff;

 
 
int Set_Com_Config(int fd, int baud_rate, int data_bits, char parity, int stop_bits)
{
   struct termios new_cfg, old_cfg;
   int speed;
   
   /*保存并测试现有串口参数设置,在这里如果串口号等出错,会有相关出错信息*/
	if(tcgetattr(fd, &old_cfg) != 0)       /*该函数得到fd指向的终端配置参数,并将它们保存到old_cfg变量中,成功返回0,否则-1*/
	{
		perror("tcgetttr");
		return -1;
	}

    /*设置字符大小*/
   new_cfg = old_cfg;   
   cfmakeraw(&new_cfg); /*配置为原始模式*/ 
   new_cfg.c_cflag &= ~CSIZE; /*用位掩码清空数据位的设置*/  

  /*设置波特率*/
   switch(baud_rate)
   {
		case 2400:
			speed = B2400;			
			break;

		case 4800:			
			speed = B4800;			
			break;

		case 9600:
			speed = B9600;			
			break;

		case 19200:			
			speed = B19200;			
			break;

		case 38400:			
			speed = B38400;			
			break;

		default:
		case 115200:			
			speed = B115200;			
			break;
  }

   cfsetispeed(&new_cfg, speed); //设置输入波特率
   cfsetospeed(&new_cfg, speed); //设置输出波特率

	/*设置数据长度*/
	switch(data_bits)
	{
		case 5:
			new_cfg.c_cflag &= ~CSIZE;//屏蔽其它标志位
			new_cfg.c_cflag |= CS5;
			break;

		case 6:
			new_cfg.c_cflag &= ~CSIZE;//屏蔽其它标志位
			new_cfg.c_cflag |= CS6;
			break;

		case 7:
			new_cfg.c_cflag &= ~CSIZE;//屏蔽其它标志位
			new_cfg.c_cflag |= CS7;
			break;

		default:			
		case 8:
			new_cfg.c_cflag &= ~CSIZE;//屏蔽其它标志位
			new_cfg.c_cflag |= CS8;
			break;
	}
 
	/*设置奇偶校验位*/
	switch(parity)
	{
		default:
			
		case 'n':
		case 'N': //无校验
		{
			new_cfg.c_cflag &= ~PARENB;
			new_cfg.c_iflag &= ~INPCK;
		}	
		break;
 
		case 'o': //奇校验
		case 'O':
		{
			new_cfg.c_cflag |= (PARODD | PARENB);
			new_cfg.c_iflag |= INPCK;
		}		
		break;
 
		case 'e': //偶校验
		case 'E':
		{
			new_cfg.c_cflag |=  PARENB;
			new_cfg.c_cflag &= ~PARODD;
			new_cfg.c_iflag |= INPCK;
		}
		break;
		
	}
 
   /*设置停止位*/
   switch(stop_bits)
   {
		default:
		case 1:
			new_cfg.c_cflag &= ~CSTOPB;
			break;

		case 2:
			new_cfg.c_cflag |= CSTOPB;
			break;
   }
 
	/*设置等待时间和最小接收字符*/
	new_cfg.c_cc[VTIME] = 1; /* 读取一个字符等待1*(1/10)s */
	new_cfg.c_cc[VMIN] = 0; /* 读取字符的最少个数为1 */
 
	/*处理未接收字符*/
	tcflush(fd, TCIFLUSH); //溢出数据可以接收,但不读
 
	/* 激活配置 (将修改后的termios数据设置到串口中)
	* TCSANOW:所有改变立即生效
	*/
	if((tcsetattr(fd, TCSANOW, &new_cfg))!= 0)
	{
		perror("tcsetattr");
		return -1;
	}

	return 0;
}
 
int Uart_Send(int fd, char *data, int data_len)  
{  
	int len = 0;  
   	len = write(fd, data, data_len);

	if(len > 0){
	#if 0
		printf("Tx: ");
		for(int i=0;i<len;i++)
		{
			printf("%02x ",data[i]);
		}
		printf("n");	
		
	#endif
	}



   	
    if(len == data_len) {  

        	return len;  
    } else {  
        	tcflush(fd, TCOFLUSH); //TCOFLUSH刷新写入的数据但不传送  
        	return -1;  
    }  
} 
 
int Uart_Recv(int fd, char *rev_buf, int data_len)
{
	int len, fs_sel;  
	fd_set fs_read;  
	struct timeval tv_timeout;  

	FD_ZERO(&fs_read); //清空集合
	FD_SET(fd,&fs_read); // 将一个给定的文件描述符加入集合之中 

	tv_timeout.tv_sec = 0;  
	tv_timeout.tv_usec = 5000;  

	//使用select实现串口的多路通信  
	fs_sel = select(fd + 1, &fs_read, NULL, NULL, &tv_timeout); //如果select返回值大于0,说明文件描述符发生了变化
	//printf("fs_sel = %dn",fs_sel);  //如果返回0,代表在描述符状态改变前已超过timeout时间,错误返回-1  

	if(fs_sel)  
	{  	
		len = read(fd, rev_buf, data_len);  		
		//printf("len = %d, fs_sel = %dn", len, fs_sel);  
		return len;  
	}  
	else  
	{  
		return 0;  
	}       
}  
 
int Uart_Set(int fd, int speed, int databits, int parity, int stopbits)
{
    	//设置串口数据帧格式  
   	 if (Set_Com_Config(fd, speed, databits, parity, stopbits) == 0)  
	{                                                           
		return 0;  
	}  
    else  
	{  
		return  -1;  
	}  
}


/*数据接收到缓冲区*/
int Uart_Receive_thread(void)
{
	int len,ret;
	char Rxbuf[1];
	while(1)
	{
		pthread_mutex_lock(&mutex);//加锁
		len = Uart_Recv(uart_fd, Rxbuf, 1);	
		pthread_mutex_unlock(&mutex);//解锁
		
		if(len)
            ret=uart_recv_protocal(Rxbuf[0],len);//数据解析
//			ret=Write_RingBuff(Rxbuf[0]);
		else
			usleep(5000);
	}
}
 
bool ReplyFlag=0;

/*从缓冲区读取数据,解析*/
void Uart_Handle_thread(void)
{
    int ret;
    char rev[1];
    uint8_t s_count = 0;
    while(1)
    {

        if(ReplyFlag==1)
        {
            pthread_mutex_lock(&mutex);
            s_count = Uart_Send(uart_fd, uart_Tx.data, uart_Tx.len);
            pthread_mutex_unlock(&mutex);
            ReplyFlag=0;

        }
        else
            {
        usleep(5000);
        }

    
//    	ret=Read_RingBuff(rev);
//    	if(ret)
//    		uart_recv_protocal(rev[0],ret);
//    	else 
//    		usleep(5000);

    }
}



void pthread() 
{  
	pthread_t id_Uart_Receive,id_Uart_Handle;
	int ret1,ret2;
	
	pthread_mutex_init(&mutex,NULL);  /*互斥锁*/
	
	ret1 = pthread_create(&id_Uart_Receive, NULL, (void *) Uart_Receive_thread, NULL);
	ret2 = pthread_create(&id_Uart_Handle, NULL, (void *) Uart_Handle_thread, NULL);
	
	if(ret1!=0){
		printf ("Create Uart_Receive_thread error!n");
		close(uart_fd);
		exit (1);
	}
	
	if(ret2!=0){
		printf ("Create Uart_Handle_thread error!n");
		exit (1);
	}
	printf("Create pthreadn");
}



int Uart_init(SerialInfo* info) 
{
	uart_fd=open(&info->dev_name, O_RDWR | O_NOCTTY);
	
	printf("串口设备名%sn",&info->dev_name);
    printf("串口初始化 %dn",uart_fd);
    if (uart_fd< 0) return FALSE;
	Uart_Set( uart_fd, 9600, 8, 0, 1);    //串口设备,波特率,数据位,奇偶性,停止位

    return uart_fd;
}

#if 1
/*******************************************************************************
  * @FunctionName: Write_RingBuff
  * @Author:       
  * @DateTime:     2022年6月14日
  * @Purpose:		向缓冲区的末尾存储一个字节
  * @param:        data               
  * @return:
*******************************************************************************/
unsigned char Write_RingBuff(unsigned char data)
{
    if(RingBuff.Length >= RINGBUFF_LEN) //判断缓冲区是否已满
    {
        printf("缓冲区已满!!!  RingBuff.Length==%dn",RingBuff.Length);
        return false;
    }
    RingBuff.Ring_Buff[RingBuff.Tail] = data;
    RingBuff.Tail = (RingBuff.Tail+1)%RINGBUFF_LEN;//防止越界非法访问
    RingBuff.Length++;
    return true;
}


/*******************************************************************************
  * @FunctionName: Read_RingBuff
  * @Author:       
  * @DateTime:     2022年6月14日
  * @Purpose:   	读取缓冲区一个字节
  * @param:        rData              
  * @return:
*******************************************************************************/
unsigned char Read_RingBuff(unsigned char *rData)
{
	if(RingBuff.Length == 0)//判断非空
	{
		return false;
	}
	*rData = RingBuff.Ring_Buff[RingBuff.Head];//先进先出FIFO,从缓冲区头出
	
	RingBuff.Head = (RingBuff.Head+1)%RINGBUFF_LEN;//防止越界非法访问
	RingBuff.Length--;
	return true;
}


void RingBuff_Init(void)
{
   //初始化相关信息
   RingBuff.Head = 0;
   RingBuff.Tail = 0;
   RingBuff.Length = 0;
   memset(RingBuff.Ring_Buff,0,sizeof(RingBuff.Ring_Buff));
   printf("RingBuff_Initn");
}

#endif

serialcode.h

#ifndef SERIALCODE_H
#define SERIALCODE_H

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

#define TRUE 0
#define FALSE -1



typedef struct Serial_Info {
    char* dev_name;
    int baudrate;
    int databit;
    int stopbit;
    char parity;
    int vtime;
    int vmin;
} SerialInfo;



int set_serial_attr(int fd, SerialInfo* serialinfo);
int serial_init(SerialInfo* info);
int serial_send(int fd, char* send_buf, int data_len);

int Uart_Set(int fd, int speed, int databits, int parity, int stopbits);
int Uart_init(SerialInfo* info);
int Uart_Send(int fd, char *data, int data_len) ;
int Uart_Recv(int fd, char *rev_buf, int data_len);
void pthread();

int uart_fd;
pthread_mutex_t mutex ;




#define RINGBUFF_LEN  		1024   //串口缓冲区大小
typedef struct
{
  unsigned short Head;
  unsigned short Tail;
  unsigned short Length;
  unsigned char Ring_Buff[RINGBUFF_LEN];
}Uart_RingBuff_t;
extern Uart_RingBuff_t RingBuff;
void RingBuff_Init(void);












#endif

最后

以上就是无辜眼神为你收集整理的Uart 配置的全部内容,希望文章能够帮你解决Uart 配置所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部