linux驱动.之 tty uart应用层例子(二)

本文探讨了Linux串口通信中数据的流方式发送和读取,强调了非阻塞和阻塞读取的区别,以及如何避免丢弃数据。通过举例说明在读取传感器数据时,不应假设固定字节数,而应将数据存入缓存,以确保完整性和效率。同时,文章提到了串口通信与TCP的相似性,都是面向流的,与UDP的面向报文不同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、linux 串口应用程序的编写,设置uart

后面回来补充的很重要的一句话,串口是流的方式发送,读取数据,不是包,这很重要,当去读取1000个字节所谓一包时,如果是非阻塞的,不一定能读到1000个,如果是阻塞的,需要一种等待。

一般读取传感器,不会去阻塞,如果读取固定字节,可能读不到这么多,这时候容易犯错,判断字节没有那么长,而丢弃,这是非常愚蠢的,没有搞清串口是流,不是包,如一个gsensor一直在发数据,以0x63开头,64个字节为一包发送出来,这时去读100个字节,如果能读到大于64个字节一包的数据,则去找63开头的一包,如果不能小于64个,则丢弃,这样效率是非常低的,

所以,需要把数据读到缓存器,一个也不能丢,读取多少个,就扔进缓存区,去找一包数据,其实和tcp一样,是流的方式,tcp一样,按流的方式发送,读取,不一定能读到想要的数据长度,不能丢弃,需拼接起来。udp是可以按包发送读取的,面向报文的。tcp,uart是面向流的。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <stdio.h>       
#include <stdlib.h>
#include <termios.h>
#include <string.h>

#define bufsize 202
#define filename "/dev/ttyAMA2" //打开某个tty ,uart设备驱动

#define Ture 1
#define False 0

#if 1
typedef struct // 60 bytes这些是操作一个uart外接的三轴传感器的,姿态角,数据结构
{
	unsigned int time;	
	int pose_translation[3];	
	unsigned short int pose_rotation[9];
	unsigned short int frameNo;	
	short int accelData[3];
	short int gyroData[3];
	short int magData[3];
	unsigned char device_map_state;
	unsigned char confidence_level;
	unsigned char reserved[4];
} HIDInfoStruct;
#endif

int g_fd1 = -1;
static unsigned char g_device_status = False;
int Reinitialize_HeadDisplay = False;

int pitch=0,yaw=0,roll=0;

unsigned short int pitch_high=0,pitch_low=0;
unsigned short int yaw_high=0,yaw_low=0;
unsigned short int roll_high=0,roll_low=0;


int Start_Read_Head_Display_Commond();
int Find_Valid_Data(char *buf_source ,char *buf_destine);
int Stop_Head_Display();

//打开一个uart文件设备

int open_Uart2()
{
	g_fd1 = open(filename, O_RDWR);
   	if (g_fd1 < 0) {
        	printf("app open %s fail \r\n", filename);
        	return -1;
    	} else {
		printf("app open  %s success\r\n",filename);
    	}
	return 1;
}

初始化uart,比如波特率,数据位,停止位,等等

int Uart2_Init()
{
	struct termios options;

	if(tcgetattr(g_fd1,&options)  !=  0) {  
		printf("get serial attibute fail\r\n");
		close(g_fd1);     
		return(-1);   
	}	

	cfsetispeed(&options, B115200);   
	cfsetospeed(&options, B115200);   

  	//set control model 
    	options.c_cflag |= CLOCAL;  
    	options.c_cflag |= CREAD;
		options.c_cflag &= ~CRTSCTS;  

    	//select data bit   
    	options.c_cflag &= ~CSIZE; 	
		options.c_cflag |= CS8;  
	
	//select parity bit   
        options.c_cflag &= ~PARENB;   
        options.c_iflag &= ~INPCK;
	
	// set stopbit  
	options.c_cflag &= ~CSTOPB;  

	//set raw data output 
	options.c_oflag &= ~OPOST;     
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  
	//options.c_lflag &= ~(ISIG | ICANON);  
     
	//set wait time  
	options.c_cc[VTIME] = 1;    
	options.c_cc[VMIN] = 1; 
     
	tcflush(g_fd1,TCIFLUSH);  
     
	//set the attribute to HiSerial device 
	if (tcsetattr(g_fd1,TCSANOW,&options) != 0) {  
   		printf("set serial attibute fail\r\n");
		close(g_fd1);
		return (-1);   
	}
	
	return 1;	
}

//一个外接的姿态角传感器,发送,探测命令,确认设备是否存在,连接正常

设置为不阻塞,不能阻塞,而是选择1s,来查询一次,不是阻塞,read,一直在获取数据

int Detect_Head_Display_Device()
{
	int len = -1;
	int ret = -1;
	int flags =  0;
	char buf1[bufsize];
	char buf2[bufsize] = {0x02 ,0x19 ,0x95 ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 
			      ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 
			      ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00};

	memset(buf1,0x0,sizeof(buf1));
	g_device_status = False;


	flags = fcntl(g_fd1, F_GETFL, 0);
	fcntl(g_fd1, F_SETFL, flags | O_NONBLOCK);  //set noblock
	sleep(1);
	Reinitialize_HeadDisplay = Ture;

	len = write(g_fd1,buf2,63);
	if(len < 0) {
			
			printf("uart2 device error \r\n");
			g_device_status = False;
			return (-1);
	} else {			
			printf("send Detect Head_Display Device commond success\r\n");
	}

	return 1;
}

一次性读很多数据

int Find_Valid_Data(char *buf_source ,char *buf_destine)
{
 	int i = 0, j = 0;

	memset(buf_destine,0x0,bufsize);

	for(i; i < 200; i++)
	{
		if(i > 136) {   // 137 + 63 > 200  buf[200] cat't overflow
			return (-1);
		}

		if((buf_source[i] == 0x01) && (buf_source[i+1] == 0xA2) && (buf_source[i+2] == 0x33))
		{
		   if((buf_source[i+63] == 0x01) && (buf_source[i+64] == 0xA2) && (buf_source[i+65] == 0x33))
		   {
	
			pitch_low  = buf_source[i+45];			
			pitch_high = buf_source[i+46];

			yaw_low    = buf_source[i+47];
			yaw_high   = buf_source[i+48];

			roll_low   = buf_source[i+49];
			roll_high  = buf_source[i+50];

			pitch_high = (unsigned short int)pitch_high;
			pitch_low  = (unsigned short int)pitch_low;
			pitch_high = pitch_high << 8;
			pitch_high = pitch_high | pitch_low;
			pitch =  (pitch_high & 0x7fff) >> 7;


			yaw_high = (unsigned short int)yaw_high;
			yaw_low  = (unsigned short int)yaw_low;
			yaw_high = yaw_high << 8;
			yaw_high = yaw_high | yaw_low;
			yaw =  (yaw_high & 0x7fff) >> 7;


				
			roll_high = (unsigned short int)roll_high;
			roll_low  = (unsigned short int)roll_low;
			roll_high = roll_high << 8;
			roll_high = roll_high | roll_low;
			roll =  (roll_high & 0x7fff) >> 7;

		   }
		}

	}
	return (1);
}
int main()
{  	
	int ret = -1;

	ret = open_Uart2();
	if(ret < 0) {
		printf(" open_Uart2 fail \r\n");
		return (-1);
	}	
	
	ret = Uart2_Init();
	if(ret < 0) {
		printf(" Uart2_Init fail \r\n");
		return (-1);
	}
	
	while(1)
	{
		// Reinitialize device
		while(!g_device_status) //while(!g_device_status && stop commond == 0)
		{
			Detect_Head_Display_Device();
			sleep(1);
			printf(" g_device_status 1   :  %d \r\n",g_device_status);
		}
		
		//send start commond ready to receiv data			
		if(g_device_status && Reinitialize_HeadDisplay == Ture) 
		{
			Reinitialize_HeadDisplay = False;
			ret =Start_Read_Head_Display_Commond();    
			if(ret < 0) {
				g_device_status = False;
			}
			
			sleep(1);//wait 1s, headplay not ready to send data
		}

		//receiv data
		if(g_device_status) {
			Read_Head_Display_Data();
		}
	}

	close(g_fd1);
   	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值