一、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;
}