我尝试在荔枝派中读取gps的信息,我用的gps模块是NEO-6M。
以下是我的程序
#include <stdio.h> #include <stdlib.h> #include <common.h> char GPS_Data_Temp[256]= {0}; //送去解析的GPS数据 gps_process_data gps;//gps数据结构体 #pragma pack (4) unsigned char outbuf[50];//用于规范打印的buf #pragma pack () int s,bufflen,uartfd=-1; int gpsbuflen=0;//避免线程间错误 static sem_t semA;//设置信号量 void GPS_Show() { // float tp; // tp=gps.longitude; // sprintf((char *)outbuf,"Longitude:%.5f %1c \r\n",tp/=100000,gps.ewhemi); //得到经度字符串 // // tp=gps.latitude; // sprintf((char *)outbuf,"Latitude:%.5f %1c \r\n",tp/=100000,gps.nshemi); //得到纬度字符串 // // sprintf((char *)outbuf,"Valid satellite:%02d\r\n",gps.posslnum); //用于定位的卫星数 // // sprintf((char *)outbuf,"Visible satellite:%02d\r\n",gps.svnum%100); //可见卫星数 } static void *threadRead(void *arg)//串口读取线程 { int i,Bufcnt=0;//设置一个计数器 char RecvBuff[33];//接受数据缓存,因为一次最多只能读到32个字节 char Storebuf[256]={0};//数据暂存,用于分割线程之间的联系 while(1) { bufflen=UART_Recv(uartfd,RecvBuff,33); if(bufflen>0) { if((Bufcnt+bufflen)<255) { for(i=0; i<bufflen; i++) { Storebuf[i+Bufcnt]=RecvBuff[i];//赋值 } Bufcnt+=bufflen;//用于确定下一次赋值的偏移量 } else //发出条件信号 { memcpy(GPS_Data_Temp,Storebuf,Bufcnt);//数据拷贝,再清零 memset(Storebuf,0,256); gpsbuflen=Bufcnt; Bufcnt=0; for(i=0; i<bufflen; i++) { Storebuf[i+Bufcnt]=RecvBuff[i];//把剩下的数据重新赋值到buf } Bufcnt+=bufflen;//用于确定下一次赋值的偏移量 sem_post(&semA); } } } return NULL; } static void *threadSend(void *arg) { int i; while(1) { sem_wait(&semA);//等待信号量 for(i=0;i<gpsbuflen;i++) { printf("%c",GPS_Data_Temp[i]);//输出数据,并将计数器清零 } memset(GPS_Data_Temp,0,256); gpsbuflen=0; } return NULL; } int main() { pthread_t Rec,Snd; uartfd=UART_Open(uartfd,UART_PORT2);//打开串口1 if(uartfd==0) errExit("open"); if(UART_Init(uartfd,9600,0,8,1,'N')==0)//串口初始化 errExit("set uart"); sem_init(&semA,0,0); //信号量初始化 s=pthread_create(&Rec,NULL,threadRead,"read");//线程初始化 if(s!=0) errExitEN(s,"pthread_create"); s=pthread_create(&Snd,NULL,threadSend,"Send");//线程初始化 if(s!=0) errExitEN(s,"pthread_create"); //死循环 while(1) { } s=pthread_join(Rec,NULL); if(s!=0) errExitEN(s,"pthread_join"); s=pthread_join(Snd,NULL); if(s!=0) errExitEN(s,"pthread_join"); sem_destroy(&semA); exit(EXIT_SUCCESS); }
我现在就是开了两个线程,一个线程用于读取串口数据,一个线程用于解析gps数据,当然我目前只是把数据printf出来。
遇到几个问题,线程之间的数据的传递,是一个很难解决的问题,主要在于我没有找到合适的方法。
如果都使用全局变量,那么两个线程,姑且称读取线程为生产者,解析线程为消费者。在生产和消费的过程中,就需要两个线程进行同步。
线程同步,我想到两个方法,一个用互斥锁+条件变量,一个是用信号量。
开始我用第一个方法,但是写的时候又发现有个问题,我一次性只能读取32字节的数据,我需要多读几个字节才可以送去解析。这个时候,就需要分情况考虑,
那么互斥锁加条件变量的方法就显得非常麻烦。
目前我用第二个方法,当数据读满的时候,发出信号量来提醒消费者进行消费。但是这个时候问题又来了,现在我没有互斥锁,无法避免消费者去使用全局变量的时候产生错误。所以我就讲生产者中的局部变量赋值到全局变量中,让消费者独自使用。
总的来说这两个方法都很不爽,我在想有没有可以直接在线程中等待,并且传递数据的方法。类似freeRTOS中的信号量+消息队列。
我测试的数据如下
接收到的如下