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!\n"); 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\t", buffer[i]); } printf("\n"); /*此处在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\t%d\t%d\n", 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\n", 1, strlen("read timeout\n"), pFile); fflush(pFile); printf("read timeout\n"); } 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("\nLen %d\n", nread); for (i = 0; i < 8; i++) { printf("0x%x\t", buffer[i]); } printf("\n"); } } } } 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\n", s); // 7fffffff long temp; temp = fun(s); printf("%lld\n", temp); char str[100] = "01ce"; int i = 0; sscanf(str, "%x", &i); printf("%d\n", 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] = '\0';//加上串结束符 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\n",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\n",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\t", 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\t%lld\t%lld\n", timeStr, temps, humids); printf("the standard line is: %s", joinLine); return joinLine; }
注意:如果函数在main函数之后定义,要在开头先声明,如:
char *Line(unsigned char *);
坚持不懈