zoukankan      html  css  js  c++  java
  • ARM-LINUX自动采集温湿度传感器数据

    开机root自动登录

    如果想在超级终端输入回车,登录后执行,则可以在/etc/profile中加入命令;

    如果实现开机自动登录,在/etc/inittab中修改,每个开发板修改的方式可能都不同。

    http://blog.chinaunix.net/uid-27717694-id-3543938.html

    开机自动运行应用程序

    绕过登录,只需要直接修改/etc/init.d/rcS 一个文件,加入程序或者脚本命令即可实现开机自动运行:

    类似与windows系统中的autobat自动批处理文件,在/etc/init.d/rcS加一行

    /usr/arm/./hello

    以上的应用程序所在的位置

    测试程序:

    hello.c

    #include<stdio.h>
    
    int main(){
    
    printf("Hello,test arm-linux!
    ");
    
    return 0;
    
    } 
    

     编译#arm-linux-gcc -o hello hello.c

     定时运行程序

    用crontab(类似于windows的任务计划服务)

    http://www.cnblogs.com/gzggyy/archive/2012/08/07/2626574.html

    自动采集温湿度程序:

    /*
     ============================================================================
     Name        : RS485.c
     Author      : 
     Version     :
     Copyright   : Your copyright notice
     Description :传感器与ARM以RS232 MODBUS协议进行串口通信,
     第一步:打开串口init_com()
     第二步:循环:发送命令:buff
     读取数据:采用select异步阻塞方式查询,流程为:
     设置超时时间,如果select出错,报错,如果超时,提示read timeout
     在超时时间内,阻塞,读取缓冲区的内容,写到文件里
     格式:时间  温度 湿度
     ============================================================================
     */
    
    #include     <stdio.h>      /*标准输入输出定义*/
    #include     <stdlib.h>     /*标准函数库定义*/
    #include     <unistd.h>     /*Unix 标准函数定义*/
    #include     <sys/types.h>
    #include     <sys/stat.h>
    #include     <fcntl.h>      /*文件控制定义*/
    #include     <termios.h>    /*PPSIX 终端控制定义*/
    #include     <errno.h>      /*错误号定义*/
    #include	 <sys/ioctl.h>
    #include	 <termios.h>
    #include	<time.h>
    
    #define BUFFER_SIZE 1024
    
    int fd;
    unsigned char buff[8] = { 0x01, 0x03, 0, 0, 0, 0x02, 0x01, 0x01 };
    unsigned char buffer[BUFFER_SIZE];
    FILE *pFile;
    
    void init_com() {
    	struct termios attr;
    
    	/*以读写方式打开串口*/
    	fd = open("/dev/ttyUSB0", O_RDWR);
    	if (-1 == fd) {
    		/* 不能打开串口一*/
    		perror(" 提示错误!");
    	}
    	// 读取串口当前属性
    	tcgetattr(fd, &attr);
    	// 设置最少接收字符个数为0
    	attr.c_cc[VMIN] = 0; //读取数据时等待时间,ms为单位
    	attr.c_cc[VTIME] = 20; //缓冲区里面数据的个数
    
    	cfsetispeed(&attr, B9600);
    	cfsetospeed(&attr, B9600);
    
    	attr.c_cflag |= (CLOCAL | CREAD);
    	attr.c_cflag &= ~CRTSCTS; //将硬件流控制位CRTSCTS清0,其他位不变
    	attr.c_cflag &= ~CSIZE;
    	attr.c_cflag |= CS8;
    	attr.c_cflag &= ~(PARENB | CSTOPB); //使用1位停止位,停用奇偶校验
    
    	attr.c_iflag &= ~(IXON | IXOFF | IXANY);
    
    	attr.c_iflag |= INPCK;
    
    	attr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //Raw Mode
    	attr.c_oflag &= ~OPOST;
    
    	// 设置串口属性
    	tcflush(fd, TCIOFLUSH);
    	tcsetattr(fd, TCSANOW, &attr);
    
    	pFile = fopen("//usr//arm//data.txt", "ab+");
    }
    
    /*两位十六进制表示,参考以下十六进制与十进制的转化*/
    int join(unsigned char a, unsigned char b) {
    	int num;
    	int hl=a;
    	int ll=b;
         num =hl*256+ll;
       return num;
    }
    
    
    //十六进制字符转十进制 三/四位
    long fun(unsigned char*s) {
    	int i, t;
    	long sum = 0;
    	for (i = 0; s[i]; i++) {
    		if (s[i] <= '9')
    			t = s[i] - '0';
    		else
    			t = s[i] - 'a' + 10;
    		sum = sum * 16 + t;
    	}
    	return sum;
    }
    
    
    //获取当前时间
    char *GetTime(char *timeStr) {
    	time_t timep;
    	struct tm *p;
    	time(&timep);
    	p = gmtime(&timep);
    	int year = (1900 + p->tm_year);
    	int mon = (1 + p->tm_mon);
    	int day = p->tm_mday;
    	int hour = p->tm_hour;
    	int min = p->tm_min;
    	int sec = p->tm_sec;
    	//sprintf将格式化字符串赋给一个变量
    	sprintf(timeStr, "%d-%d-%d %d:%d:%02d	", year, mon, day, hour, min, sec);
    	return timeStr;
    }
    
    char *Line(unsigned char *buffer) {
    
    	int i;
    	char joinLine[20];
    	char temp[4];
    	char humid[4];
    	char timeStr[10];
    	int temps,humids;
    	for (i = 0; i < 8; i++) {
    		printf("0x%x	", buffer[i]);
    	}
    	printf("
    ");
    	/*此处在ARM-linux下不能用sprintf将十六进制赋给字符串,不知是什么原因
    		long temps,humids;
    		sprintf(temp, "%x%x", buffer[3], buffer[4]);
    		sprintf(humid, "%x%x", buffer[5], buffer[6]);
    		temps = fun(temp); //"0cf"
    		humids = fun(humid); //"1e0"
    	 **/
    
        temps=join(buffer[3],buffer[4]);//温度
        humids=join(buffer[5],buffer[6]);//湿度
    	GetTime(timeStr);//时间
    	sprintf(joinLine, "%s	%d	%d
    ", timeStr, temps, humids);
    	printf("the standard line is: %s", joinLine);//一条记录
    	//将记录写到文件里,pFile为全局变量,需要提前定义和打开文件
    	fwrite(joinLine, 1, strlen(joinLine), pFile);
    	//刷新缓冲区
    	fflush(pFile);
    	return joinLine;
    }
    
    void writeRS() {
    	//往串口写命令
    	write(fd, (int*) buff, 8);
    	usleep(5000000); //粗糙定时5s
    }
    
    //异步定时读取数据
    void readRS() {
    	int nread, max_fd, ret_select, wait, i = 0;
    	fd_set input;
    	struct timeval timeout;
    
    	FD_ZERO(&input); //每次操作都清空集合,否则不能检测描述符变化
    	FD_SET(fd, &input); //添加描述符
    	max_fd = fd + 1; //描述符最大加1
    
    	//设置超时时间为1秒,
    	timeout.tv_sec = 1;
    	timeout.tv_usec = 0;
    	ret_select = select(max_fd, &input, NULL, NULL, &timeout);
    
    	//select等待1秒,1秒轮询,要非阻塞就置0
    	if (ret_select < 0)
    		perror("select failed");
    	else if (ret_select == 0) {
    		//如果超时一秒,则写read timeout作为提示
    		fwrite("read timeout
    ", 1, strlen("read timeout
    "), pFile);
    		fflush(pFile);
    		printf("read timeout
    ");
    	} else {
    		if (FD_ISSET(fd, &input)) {
    			wait = 0;
    			//阻塞监听
    			//ioctl获取串口缓冲中的信息
    			ioctl(fd, FIONREAD, &nread);
    			if (nread == 0) {
    				//如果没有读到数据,则以read missing作为提示
    				printf("read missing");
    				fwrite("read missing", 1, strlen("read missing"), pFile);
    				fflush(pFile);
    			} else if ((nread = read(fd, buffer, 512)) > 0) {//此处设置定时器if---while
    				//采集的是十六进制的数据,转化为存储格式
    				//定时1秒阻塞读取数据,如果读到则写到文件里fwrite
    				 char *sLine = Line(buffer);
    				printf("the output is : %s", sLine);
    				printf("
    Len %d
    ", nread);
    				for (i = 0; i < 8; i++) {
    					printf("0x%x	", buffer[i]);
    				}
    				printf("
    ");
    			}
    		}
    	}
    }
    
    
    int main(void) {
    	//初始化串口
    	init_com();
    	while (1) //循环读取数据,定时5秒
    	{
    		writeRS();
    		readRS(pFile);
    	}
    
    	close(fd);
    	fclose(pFile);
    	return EXIT_SUCCESS;
    }
    

     相关的测试程序作为备用

    十六进制转十进制,好好研究一下

    //scanf和sprintf拼接
    void Sptest() {
    	char s[100] = { 0 };
    	unsigned char buffer[2] = { 0x01, 0xce };
    	sprintf(s, "%x%x", buffer[0], buffer[1]);
    	printf("%s
    ", s); // 7fffffff
    	long temp;
    	temp = fun(s);
    	printf("%lld
    ", temp);
    	char str[100] = "01ce";
    	int i = 0;
    	sscanf(str, "%x", &i);
    	printf("%d
    ", i); // 2147483647
    
    }
    
    #include <stdio.h>
    #include <string.h>
    void main()
    {
       int i=0,j=0,result=0,index=0,cindex=0;
    //char a[100]="2B4AFF8071",b[100],c[4];
       char a[100],b[100],c[4];
       gets(a);//输入数据 
    
        
       for(i=0 ; i<strlen(a); i++)
       {
               /*将16进制转换成10进制*/
               if(a[i]>='a' && a[i]<='z')
                            result = result*16 + a[i]-'a'+10;
               else if(a[i]>='A' && a[i]<='Z')
                            result = result*16 + a[i]-'A'+10;
               else
                            result = result*16 + a[i]-'0';
               /*每两位处理一次*/
               if(i%2!=0)
               {
                         cindex = 0;
                         do
                         {
                                   c[cindex++] = result%10 + '0';//倒序存放在c中 
                                   result/=10;
                         }while(result!=0);
                         for(j=cindex-1; j>=0; j--)//翻转后存放在b中 
                                         b[index++] = c[j];
               }
       } 
       b[index] = '';//加上串结束符 
       puts(b);//输出 
    }
    

     十六进制字符数组转十进制(超过两位)

    #include <stdlib.h>
    #include <stdio.h>
    
    char *method1(char *c){
    	long i;
    	char s[10];
    		//256相当于8个字节
    		i=((c[0]*256+c[1])*256+c[2])*256+c[3];
    		sprintf(s,"%d",i);
    		printf("the num is %s
    ",s);
    		return s;
    }
    
    char *method2(char *c){
    	long  result=0;
    	int i=0;
    	for (i=0; i<4; i++)
    	{
    	  result<<8;
    	  result+=c[i];
    	}
    	printf("the num2 is %d
    ",result);
    }
    
    char *method3(char *c){
    	char s[10];
    	char t;
    	t=c[0],c[0]=c[3],c[3]=t;    // 交换 0,3
    	t=c[1],c[1]=c[2],c[2]=t;    //  交换 1,2
    	int i=*(int *)c;
    	sprintf(s,"%d",i);
    	printf("the num is %s",s);
    	return s;
    }
    
    char *method4(){
    	char s[10];
    	    sprintf(s,"%d",0x0100&0xffff);
    	    printf("the num is %s",s);
    	    return s;
    }
    
    int main(void)
    {
    	char c[4]={0x01,0x02,0x03,0x04};
    	char *s=method1(c);
    	method2(c);
    	method3(c);
    	method4();
    }
    

    在centos上能运行,在ARM上运行出错的

    //输出标准字符串
    char *Line(unsigned char *buffer) {
    	int i;
    	char joinLine[20];
    	char temp[4];
    	char humid[4];
    	char timeStr[10];
    	long temps;
    	long humids;
    	for (i = 0; i < 8; i++) {
    		printf("0x%x	", buffer[i]);
    	}
    //	{ 0x1, 0x3, 0x4, 0x0, 0xcf, 0x1, 0xe0, 0xca };
    	sprintf(temp, "%x%x", buffer[3], buffer[4]);
    	sprintf(humid, "%x%x", buffer[5], buffer[6]);
    	printf("the temp is: %s", temp);
    	printf("the humid is: %s", humid);
    	temps = fun(temp);        //"0cf"
    	humids = fun(humid);        //"1e0"
    	GetTime(timeStr);
    	sprintf(joinLine, "%s	%lld	%lld
    ", timeStr, temps, humids);
    	printf("the standard line is: %s", joinLine);
    	return joinLine;
    }
    

     注意:如果函数在main函数之后定义,要在开头先声明,如:

    char *Line(unsigned char *);

  • 相关阅读:
    Openlayers2中vector扩展FeatureLayer
    点图层叠加与事件响应
    geoserver服务wfs之GetFeature
    Echart在Openlayers的应用-航班的炫光特效
    Echart在Openlayers的应用-热力图
    Echart在Openlayers的应用
    WMS图例展示
    Java新手锻炼
    Java动手又动脑
    java递归问题小程序
  • 原文地址:https://www.cnblogs.com/kxdblog/p/4157461.html
Copyright © 2011-2022 走看看