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 *);

  • 相关阅读:
    iOS 苹果开发证书失效的解决方案(Failed to locate or generate matching signing assets)
    iOS NSArray数组过滤
    App Store2016年最新审核规则
    iOS 根据字符串数目,自定义Label等控件的高度
    iOS 证书Bug The identity used to sign the executable is no longer valid 解决方案
    Entity FrameWork 增删查改的本质
    EF容器---代理类对象
    Entity FrameWork 延迟加载本质(二)
    Entity FrameWork 延迟加载的本质(一)
    Entity FrameWork 增删查改
  • 原文地址:https://www.cnblogs.com/kxdblog/p/4157461.html
Copyright © 2011-2022 走看看