當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式云IOT技術(shù)圈
[導(dǎo)讀]在MTK的機(jī)器中,如果不用特定的工具燒寫MAC地址,在開機(jī)后打開WIFI后會(huì)顯示: “NVRAM WARNING: Err=0x10” 這就是沒(méi)有燒寫mac地址的原因,所以每次打開wifi,wifi的MAC地址都是一個(gè)隨機(jī)產(chǎn)生的值,為什么會(huì)這樣?


微信公眾號(hào):morixinguan
關(guān)注可了解更多的教程。問(wèn)題或建議,請(qǐng)公眾號(hào)留言;
如果你覺(jué)得本文對(duì)你有幫助,歡迎贊賞

▲長(zhǎng)按圖片保存可分享至朋友圈


MTK的機(jī)器中,如果不用特定的工具燒寫MAC地址,在開機(jī)后打開WIFI后會(huì)顯示: “NVRAM WARNING: Err=0x10” ?這就是沒(méi)有燒寫mac地址的原因,所以每次打開wifi,wifi的MAC地址都是一個(gè)隨機(jī)產(chǎn)生的值,為什么會(huì)這樣?

答案在:

1vendor/mediatek/proprietary/packages/apps/CdsInfo/src/com/mediatek/connnectivity/CdsWifiInfoActivity.java

源碼描述如下:

 1public class CdsWifiInfoActivity extends Activity {  2  3 private static final String?TAG?= "CDSINFO/WifiInfo";  4  5 private static final int MAC_ADDRESS_ID?= 30;  6 private static final int MAC_ADDRESS_DIGITS?= 6;  7 private static final int MAX_ADDRESS_VALUE?= 0xff;  8 private static final int INVALID_RSSI?=?-200;  9//定義了MAC地址存儲(chǔ)的文件的絕對(duì)路徑 10 private static final String?MAC_ADDRESS_FILENAME?= "/data/nvram/APCFG/APRDEB/WIFI"; 11 12 private static final String[]?WIFI_SYSTEM_PROPERTY?= new String[]?{ 13 "net.hostname", 14 "dhcp.wlan0.ipaddress", 15 "net.dns1", 16 "net.dns2", 17。。。。。

以下是獲取mac地址的方法:

 1//獲取mac地址的方法  2 private void getMacAddr() {  3  4  5 try {  6 IBinder?binder?=?ServiceManager.getService("NvRAMAgent");  7 NvRAMAgent?agent?=?NvRAMAgent.Stub.asInterface(binder);  8  9 mRandomMacAddr?= new short[MAC_ADDRESS_DIGITS]; 10 11 if (mUserMode)?{ 12 mMacAddrLabel.setVisibility(View.GONE); 13 mMacAddrEdit.setVisibility(View.GONE); 14 mMacAddBtn.setVisibility(View.GONE); 15 } else { 16 StringBuilder?sb?= new StringBuilder(); 17 Random?rand?= new Random(); 18 NumberFormat?formatter?= new DecimalFormat("00"); 19 int end1?=?rand.nextInt(100); 20 int end2?=?rand.nextInt(100); 21 String?num1?=?formatter.format(end1); 22 String?num2?=?formatter.format(end2); 23 //這幾位是固定的值 24 sb.append("00:08:22:11:"); 25 sb.append(num1).append(":").append(num2); 26 27 mMacAddrLabel.setVisibility(View.VISIBLE); 28 mMacAddrEdit.setVisibility(View.VISIBLE); 29 mMacAddBtn.setVisibility(View.VISIBLE); 30 System.out.println("string?buffer:" +?sb); 31 mMacAddrEdit.setText(sb); 32 MacAddressRandom?=?sb.toString(); 33 34 } 35 } catch (Exception?e)?{ 36 e.printStackTrace(); 37 } 38 }

更新mac地址的方法:

 1//更新mac地址  2 private void updateMacAddr() {  3  4 try {  5 int i?= 0;  6 IBinder?binder?=?ServiceManager.getService("NvRAMAgent");  7 NvRAMAgent?agent?=?NvRAMAgent.Stub.asInterface(binder);  8  9 //parse?mac?address?firstly 10 StringTokenizer?txtBuffer?= new StringTokenizer(mMacAddrEdit.getText().toString(), ":"); 11 12 while (txtBuffer.hasMoreTokens())?{ 13 mRandomMacAddr[i]?=?(short)?Integer.parseInt(txtBuffer.nextToken(), 16); 14 System.out.println(i?+ ":" +?mRandomMacAddr[i]); 15 i++; 16 } 17 18 if (i?!= 6)?{ 19 mToast.setText("The?format?of?mac?address?is?not?correct"); 20 mToast.show(); 21 return; 22 } 23 24 byte[]?buff?= null; 25 26 try { 27 buff?=?agent.readFileByName(MAC_ADDRESS_FILENAME); 28 } catch (Exception?e)?{ 29 e.printStackTrace(); 30 } 31 32 //隨機(jī)產(chǎn)生的buff[i+4]開始就是mac地址存儲(chǔ)的位置 33 for (i?= 0;?i?< MAC_ADDRESS_DIGITS; i ++) { 34 buff[i?+ 4]?=?(byte)?mRandomMacAddr[i]; 35 } 36 37 int flag?= 0; 38 39 try { 40 flag?=?agent.writeFileByName(MAC_ADDRESS_FILENAME,?buff); 41 } catch (Exception?e)?{ 42 e.printStackTrace(); 43 } 44 45 if (flag?> 0)?{ 46 mToast.setText("Update?successfully.\r\nPlease?reboot?this?device"); 47 mToast.show(); 48 } else { 49 mToast.setText("Update?failed"); 50 mToast.show(); 51 } 52 53 } catch (Exception?e)?{ 54 mToast.setText(e.getMessage()?+ ":" +?e.getCause()); 55 mToast.show(); 56 e.printStackTrace(); 57 } 58 }

從這個(gè)代碼中可以分析得知,此時(shí)的Wifi MAC地址除了前面幾位是固定值,而后面都是隨機(jī)產(chǎn)生的。 ?但只有一個(gè)文件才是正確的WIFI MAC地址保存的值。如果沒(méi)有燒寫WIFI MAC地址,那么這個(gè)文件的第4到第9個(gè)字節(jié)是固定為0的,只有燒寫了MAC地址,這6個(gè)字節(jié)才是有數(shù)據(jù)的。 ?通過(guò)代碼分析,得知燒寫mac地址后的文件是保存在: /data/nvram/APCFG/APRDEB/WIFI 這個(gè)文件中。

通過(guò)adb pull /data/nvram/APCFG/APRDEB/WIFI獲取這個(gè)文件到我當(dāng)前的系統(tǒng),打開一看:


????是一堆亂碼,那么如何正確打開查看呢?可以上百度去下一個(gè)WinHex打開,其實(shí)這個(gè)文件里面保存的是十六進(jìn)制的數(shù)據(jù)。打開后可以看到:

從這段數(shù)據(jù)中:,格式是這樣的:04 01 00 00 CC 79 CF FF 35 54 44 。。偏移從0開始一直往后依次類推,分析代碼得知:

CC 79 CF FF 35 54 44就是通過(guò)特定工具刷寫進(jìn)去的WIFI MAC地址,如果不刷,那么這6個(gè)字節(jié)的數(shù)據(jù)默認(rèn)為0。關(guān)于這個(gè)表,我們可以參考MTK的文檔得知:


NVRAM在EMMC中是只讀數(shù)據(jù),一般存儲(chǔ)在data分區(qū)中,所以格式化機(jī)器是會(huì)將NVRAM中的數(shù)據(jù)擦除的。

當(dāng)然Nvram中不止存放wifi的MAC地址,也存放Gsensor校準(zhǔn)的數(shù)據(jù),這點(diǎn)以后我們?cè)賮?lái)寫怎么獲取。

下面就是NVRAM,WIFI的春初數(shù)值對(duì)應(yīng)的。

我的機(jī)器上對(duì)應(yīng)的是MT6628這個(gè)驅(qū)動(dòng)模塊,所以是下面這個(gè)宏:

在MAC地址沒(méi)有刷寫的時(shí)候,默認(rèn)的6個(gè)字節(jié)都是0x00。

 1#if defined(MT6628)  2WIFI_CFG_PARAM_STRUCT?stWifiCfgDefault?=  3{  4 0x0104, /*?Own?Version?For?MT6628*/  5 0x0000, /*?Peer?Version?*/  6 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*?MAC?ADDRESS?*/ ........................

現(xiàn)在我們可以寫一個(gè)程序?qū)⑺x出來(lái),很簡(jiǎn)單:

 1#include    2#include    3#include    4#include    5#include   6#define WIFI_FILE "WIFI"   7int main(void)  8{  9 int fd?= -1 ; 10 int ret?; 11 int i?; 12 char buffer[512]?=?{0}; 13 char Nvram_wifi_mac_address[6]?=?{0}; 14 char d_buf[100]?=?{0}; 15 char dd_buf[100]?=?{0}; 16 fd?=?open(WIFI_FILE,O_RDWR); 17 if(fd?< 0){ 18 printf("open?fair!\n"); 19 return -1 ; 20 } 21 22 ret?=?read(fd?,?buffer?, 512); 23 if(ret?< 0){ 24 printf("read?wifi?mac?fair!\n"); 25 } 26 27 for(i?= 4;?i?< 10 ;?i++) 28 Nvram_wifi_mac_address[i-4]?=?buffer[i]?; 29 //為什么要?&?0xff,因?yàn)橛行C(jī)器是64位的,為了保證和32位的機(jī)器顯示一致,故只取低8位。  30 sprintf(d_buf,"%02x:%02x:%02x:%02x:%02x:%02x", 31 Nvram_wifi_mac_address[0]&0xff,Nvram_wifi_mac_address[1]&0xff, 32 Nvram_wifi_mac_address[2]&0xff,Nvram_wifi_mac_address[3]&0xff, 33 Nvram_wifi_mac_address[4]&0xff,Nvram_wifi_mac_address[5]&0xff 34 ); 35 printf("%s\n",d_buf); 36 for(i?= 0 ;?i?< strlen(d_buf)?;?i++) 37 { 38 dd_buf[i]?= toupper(d_buf[i]); //字符串中小寫轉(zhuǎn)大寫 39 } 40 printf("dd_buf:%s\n",dd_buf)?; 41 42 return 0 ; 43}

????MTKAndroid系統(tǒng)的Gsensor校準(zhǔn)的數(shù)據(jù)其實(shí)也是存儲(chǔ)在NVRAM中的,Gsensor隸屬于傳感器系統(tǒng)架構(gòu)。

接下來(lái)我們來(lái)看下Gsensor校準(zhǔn)的基準(zhǔn)圖像:

那么如何來(lái)校準(zhǔn)Gsensor的X,Y,Z三個(gè)方向呢?我們可以參考MTK提供的工廠測(cè)試factroymode的代碼:

位置在:vendor\mediatek\proprietary\factory\src\test\ftm_gs_cali.c ftm_gsensor.c

ftm_gs_cali.c就是校準(zhǔn)的源碼,我們可以打開來(lái)看看它具體的實(shí)現(xiàn)原理:

在ftm_gs_cali.c的static void*gs_cali_update_iv_thread(void *priv)這個(gè)函數(shù)中,我們可以分析得知如何校準(zhǔn)Gsensor數(shù)值的過(guò)程,由于源碼太長(zhǎng),這里只說(shuō)流程:

(1) ? ?打開Gsensor

(2) ? ?使能Gsensor

(3) ? ?執(zhí)行校準(zhǔn)的動(dòng)作

(4) ? ?設(shè)置校準(zhǔn)的Cail,讓校準(zhǔn)的數(shù)據(jù)生效

(5) ? ?將校準(zhǔn)得到的數(shù)據(jù)寫入到nvram中

(6) ? ?關(guān)閉Gsensor

核心流程我們已經(jīng)清楚了,那么接下來(lái)如何來(lái)寫這個(gè)程序呢?我們要弄明白,這些函數(shù)上哪個(gè)文件里去找這是第一步:

通過(guò)grep命令搜索相關(guān)函數(shù),最終確定,這些函數(shù)的頭文件在:

./pskyed/libs/em_emmc_comm/libhwm/include/libhwm.h這里,在這個(gè)頭文件中有相關(guān)的函數(shù)可以給我們使用:

 1extern int gsensor_calibration(int fd, int period, int count, int tolerance, int trace,?HwmData?*cali);  2extern int gsensor_write_nvram(HwmData?*dat);  3extern int gsensor_read_nvram(HwmData?*dat);  4extern int gsensor_rst_cali(int fd);  5extern int gsensor_set_cali(int fd,?HwmData?*dat);  6extern int gsensor_get_cali(int fd,?HwmData?*dat);  7extern int gsensor_read(int fd,?HwmData?*dat);  8extern int gsensor_init(int fd);  9extern int gsensor_close(int fd); 10extern int gsensor_open(int *fd); 11extern int gyroscope_calibration(int fd, int period, int count, int tolerance, int trace,?HwmData?*cali); 12extern int gyroscope_write_nvram(HwmData?*dat); 13extern int gyroscope_read_nvram(HwmData?*dat); 14extern int gyroscope_rst_cali(int fd); 15extern int gyroscope_set_cali(int fd,?HwmData?*dat); 16extern int gyroscope_get_cali(int fd,?HwmData?*dat); 17extern int gyroscope_read(int fd,?HwmData?*dat); 18extern int gyroscope_close(int fd); 19extern int gyroscope_open(int *fd); 20extern int gyroscope_init(int fd);

那么這些函數(shù)的源碼在哪里呢?源碼是沒(méi)有的,因?yàn)镸TK廠商將這部分代碼給封裝成了so動(dòng)態(tài)庫(kù)文件,所以,我們需要找到這個(gè)頭文件對(duì)應(yīng)的so文件,這樣我們才能使用這個(gè)頭文件,調(diào)用到so動(dòng)態(tài)庫(kù)中的函數(shù)。

通過(guò)搜索得知,這個(gè)so動(dòng)態(tài)庫(kù)文件在以下路徑:

./pskyed/libs/em_emmc_comm/libhwm/libhwm.so

知道這些以后,下面我們就可以寫一個(gè)簡(jiǎn)單的程序來(lái)驗(yàn)證這個(gè)過(guò)程了,這個(gè)留給讀者自己去測(cè)試,接口我已經(jīng)寫好了,我的項(xiàng)目源碼不便于公開,請(qǐng)讀者自己拿去修改驗(yàn)證,流程是一樣的,接口沒(méi)有改過(guò),至于想實(shí)現(xiàn)什么樣的效果請(qǐng)讀者自己去嘗試添加,移植我的程序進(jìn)行修改。

下面實(shí)現(xiàn)這個(gè)校準(zhǔn)程序:

gs_cali.c

 1#include   2#include   3#include   4#include   5#include   6#include   7#include   8#include   9#include   10#include   11#include   12#include   13#include   14#include   15#include   16#include   17#include   18#include "Keypad.h"  19#include "libhwm.h"  20  21#define GSENSOR_NAME "/dev/gsensor"  22#define OPEN_FILE_FAIR?-1   23#define OPEN_SUCCESS?0  24#define RETURE_SUCCESS?0  25#define ENABLED_SUCCESS?0  26#define GSENSOR_CALIBRATION_SUCCESS?0  27#define ENABLED_FAIR?-2   28#define CALIBRATION_FAIR?-3   29#define SET_CALIBRATION_FAIR?-4  30#define WRITE_NVRAM_FAIR??-5   31  32int gs_fd?;  33  34//打開gsensor  35int gs_open(char *gs_name) ;  36//關(guān)閉gsensor  37int gs_close(int fd) ;  38//gsensor開始工作  39int gs_enable(unsigned int command) ;  40//校準(zhǔn)gsensor  41int gs_calibration(unsigned int cali_delay?,unsigned int cali_num?,unsigned int cali_tolerance) ;  42  43int main(void)  44{  45 int gs_ret?= 0 ;  46 int cali_delay?= 50;  47int cali_num?= 20;  48//這里的20表示把校準(zhǔn)的數(shù)值做20次平均  49//如果想要更精確,也可以做40次平均計(jì)算  50 int cali_tolerance?= 20 ; //40  51 //打開gsensor  52 gs_ret?=?gs_open(GSENSOR_NAME);  53 if(gs_ret?!= 0){  54 printf("gs?open?fair!\n")?;  55 return -1 ;  56 }  57 //使能gsensor  58 gs_ret?=?gs_enable(GSENSOR_IOCTL_INIT);  59 if(gs_ret?!= 0){  60 printf("gs?enable?fair!\n")?;  61 return -2 ;  62 }  63 //校準(zhǔn)---->包括:執(zhí)行校準(zhǔn)的動(dòng)作、設(shè)置校準(zhǔn)數(shù)值、將校準(zhǔn)數(shù)值寫入nvram  64 gs_ret?=?gs_calibration(cali_delay,cali_num,cali_tolerance);  65 if(gs_ret?!= 0){  66 printf("gs_calibration?fair!\n")?;  67 return -3 ;  68 }  69 //關(guān)閉gsensor  70 gs_ret?=?gs_close(gs_fd);  71 if(gs_ret?!= 0){  72 printf("gs_close?fair!\n");  73 return -4 ;  74 }  75 printf("runexec?call?gsensorCalibrate?end\n");  76 return 0 ;  77}  78  79//1、open  80int gs_open(char *gs_name)  81{  82 gs_fd?=?open(gs_name,O_RDONLY)?;  83 if(gs_fd?< 0)  84 {  85 printf("open?gsensor?dev?fair!\n")?;  86 return OPEN_FILE_FAIR?;  87 }  88 printf("gsensor?open?success!\n");  89 return OPEN_SUCCESS?;  90}  91  92//2、enable?gsensor  93int gs_enable(unsigned int command)  94{  95 int err?= 0;  96 unsigned int flags?= 1;  97 int max_retry?= 3,?retry_period?= 100,?retry=0;  98 while ((err?=?ioctl(gs_fd,?command,?&flags))?&&?(retry?++?< max_retry)) ;  99 usleep(retry_period*1000); 100 if (err)?{ 101 printf("enable?g-sensor?fail:?%s",?strerror(errno)); 102 return ENABLED_FAIR; 103 } 104 printf("enable?gsensor?success!\n"); 105 return ENABLED_SUCCESS?; 106} 107//3、校準(zhǔn) 108int gs_calibration(unsigned int cali_delay?,unsigned int cali_num?,unsigned cali_tolerance) 109{ 110 int err?; 111 int flag?= 0; 112 HwmData?dat; //dat.x??dat.y??dat.z  113 HwmData?cali; 114 HwmData?cali_nvram; 115 while(1) 116 { 117 //執(zhí)行校準(zhǔn)的動(dòng)作 118 err?=?gsensor_calibration(gs_fd?,?cali_delay?,?cali_num?,?cali_tolerance?, 0 ,?&cali); 119 if(err?!= 0) 120 { 121 printf("calibrate?acc:?%d\n",?err); 122 return CALIBRATION_FAIR?; 123 } 124 //設(shè)置校準(zhǔn)cali,讓校準(zhǔn)數(shù)據(jù)生效 125 err?=?gsensor_set_cali(gs_fd,&cali)?; 126 if(err?!= 0) 127 { 128 printf("set?calibration?fail:?(%s)?%d\n",?strerror(errno),?err); 129 return SET_CALIBRATION_FAIR?; 130 } 131 //將校準(zhǔn)數(shù)據(jù)寫入nvram中 132 err?=?gsensor_write_nvram(&cali)?; 133 if(err?!= 0) 134 { 135 printf ("write?nvram?fail:?(%s)?%d\n",?strerror(errno),?err); 136 return WRITE_NVRAM_FAIR?; 137 } 138 flag?= 1 ; 139 if(flag?== 1) 140 { 141 printf("Gsensor?calibrate?success!\n")?; 142 break ; 143 } 144 } 145 return GSENSOR_CALIBRATION_SUCCESS?; 146} 147 148//關(guān)閉 149int gs_close(int fd) 150{ 151 close(fd)?; 152 return 0 ; 153}

然后寫一個(gè)簡(jiǎn)單的Android.mk

 1LOCAL_PATH:=$(call my-dir)  2include $(CLEAR_VARS)  3LOCAL_MODULE_TAGS?:=?optional  4LOCAL_SHARED_LIBRARIES?+=?libcutils?libutils???libhwm  5LOCAL_STATIC_LIBRARIES?+=?libz?libstdc++  6LOCAL_SRC_FILES:=?\  7 gs_cali.c  8  9LOCAL_MODULE:=?gsensor_calibrate 10include $(BUILD_EXECUTABLE) 

將.c和Android.mk一并放在external下的一個(gè)自己定義的文件夾中,比如gs_cali文件夾,然后最后編譯會(huì)在out目錄下生成gsensor_calibrate這個(gè)二進(jìn)制文件。

特別需要注意一點(diǎn):使用這種方法進(jìn)行校準(zhǔn)后,需要將gsensor驅(qū)動(dòng)的自動(dòng)校準(zhǔn)功能屏蔽,具體屏蔽方法還需要分析驅(qū)動(dòng)源代碼。

但這僅僅只是校準(zhǔn)數(shù)值而已,如何把校準(zhǔn)完的數(shù)值讀出來(lái)呢?參考ftm_gsensor.c這個(gè)文件源代碼,最終得知是通過(guò)打開/dev/gsensor這個(gè)節(jié)點(diǎn),然后通過(guò)總線訪問(wèn)機(jī)制獲?。?

/sys/bus/platform/drivers/gsensor/sensordata這個(gè)文件存放的數(shù)據(jù)。

讀取Gsensor的x,y,z的數(shù)據(jù)的方法可以參考static int gsensor_read(struct acc_priv *acc)這個(gè)函數(shù)的實(shí)現(xiàn)方法,但它的方法和我的是有區(qū)別的,MTK中實(shí)現(xiàn)的gsensor_read方法是讀取從驅(qū)動(dòng)中讀取已經(jīng)轉(zhuǎn)化成十進(jìn)制的數(shù)據(jù),而我讀取的是原始數(shù)據(jù)十六進(jìn)制,所以必須要做進(jìn)制轉(zhuǎn)換,我們可以來(lái)看下這個(gè)函數(shù):

 1static int?gsensor_read(struct?acc_priv?*acc)  2{  3 static char?buf[128];  4 int?x,?y,?z,?err;  5  6 if(acc->fd?== -1)  7 {  8 FTGLOGE("invalid?file?descriptor\n");  9 err?=?-EINVAL; 10 } 11 else if((acc->support_selftest?== 1)?&&?(!acc->selftest)?&&?(err?=?gsensor_selftest(acc, 10, 20))) 12 { 13 FTGLOGE("selftest?fail:?%s(%d)\n",?strerror(errno),?errno); 14 } 15 else 16 { 17 //使用GSENSOR_IOCTL_READ_SENSORDATA命令獲取sensor的數(shù)據(jù),并存儲(chǔ)在buf里 18 err?=?ioctl(acc->fd,?GSENSOR_IOCTL_READ_SENSORDATA,?buf); 19 if(err) 20 { 21 FTGLOGE("read?data?fail:?%s(%d)\n",?strerror(errno),?errno); 22 } 23 //從buf中將x,y,z三個(gè)值取出來(lái) 24 else if(3 !=?sscanf(buf, "%x?%x?%x",?&x,?&y,?&z)) 25 { 26 FTGLOGE("read?format?fail:?%s(%d)\n",?strerror(errno),?errno); 27 } 28 else 29 { 30 //除以1000,并轉(zhuǎn)成浮點(diǎn)數(shù) 31 acc->evt.x?=?(float)(x)/1000; 32 acc->evt.y?=?(float)(y)/1000; 33 acc->evt.z?=?(float)(z)/1000; 34 err?= 0; 35 gsensor_statistic(acc); 36 //返回gsensor數(shù)據(jù) 37 //add?sensor?data?to?struct?sp_ata_data?for?PC?side 38 return_data.gsensor.g_sensor_x?=?acc->evt.x; 39 return_data.gsensor.g_sensor_y?=?acc->evt.y; 40 return_data.gsensor.g_sensor_z?=?acc->evt.z; 41 return_data.gsensor.accuracy?= 3; 42 43 } 44 } 45 return err; 46}

預(yù)知詳情,可以去分析MTK factory工廠測(cè)試的源碼,看看具體實(shí)現(xiàn),這里就簡(jiǎn)單的一筆帶過(guò)了。

當(dāng)然我們也可以采用:

./pskyed/libs/em_emmc_comm/libhwm/include/libhwm.h這里面的讀取gsensor數(shù)據(jù)的接口,如果要用就需要在Android.mk中包含相關(guān)的動(dòng)態(tài)庫(kù)。

使用adb進(jìn)入Android根文件系統(tǒng),此時(shí),通過(guò)cat命令可以得知/sys/bus/platform/drivers/gsensor/sensordata這個(gè)文件存放的數(shù)據(jù)并不是字符串,而是十六進(jìn)制數(shù)據(jù),以下是機(jī)器平放在桌子上讀取的x,y,z的數(shù)值:

Sensordata文件的數(shù)值: ? ?算法轉(zhuǎn)換:

x,y,z數(shù)值的校準(zhǔn)范圍是(0,0,9.8),以上數(shù)值說(shuō)明機(jī)器校準(zhǔn)后的數(shù)值是正確的,誤差比較小。

在Window上用Notepad++打開這個(gè)文件看到里面的數(shù)據(jù)如下。

以下是我實(shí)現(xiàn)的方法:

//Gsensor讀取

//這個(gè)文件存放的數(shù)據(jù)不是字符串,而是十六進(jìn)制數(shù)據(jù),所以必須做進(jìn)制轉(zhuǎn)換,然后才能轉(zhuǎn)成浮點(diǎn)數(shù)

 1#define GSENSOR_NAME?"/sys/bus/platform/drivers/gsensor/sensordata"  2//存儲(chǔ)gsensor節(jié)點(diǎn)數(shù)據(jù)的結(jié)構(gòu)體  3struct gsensor_info  4{  5 //x,y,z坐標(biāo)值  6 char x[10]?;  7 char y[10]?;  8 char z[10]?;  9}; 10int Hex_to_dec(const char*?str) ; 11static int check_flag?; 12int Gsensor_Test() 13{ 14 struct gsensor_info?g?; 15 char ln[80];//用于存取讀出數(shù)據(jù)的數(shù)組 16 FILE?*f; 17 int i,n; 18 char *p; 19 int x,y,z?; 20 float x1,y1,z1?; 21 int xv?= 0 ,?yv?= 0 ,?zv?= 0 ; 22 while(1) 23 { 24 f=fopen(GSENSOR_NAME,"r");//打開txt文件 25 if(NULL==f){ 26 printf("Can?not?open?file?sensordata!\n");//判斷是否可以打開文件 27 return 1; 28 } 29 i=0; 30 while (1) 31 { 32 //從文件中讀取一行數(shù)據(jù) 33 if (NULL==fgets(ln,80,f)) 34 break; 35 p?=?ln?; 36 sscanf(p,"%s%s%s",g.x,g.y,g.z); 37 i++; 38 } 39 //存儲(chǔ)的數(shù)據(jù)是十六進(jìn)制,需要做數(shù)據(jù)轉(zhuǎn)換 40 x?=?Hex_to_dec(g.x); 41 y?=?Hex_to_dec(g.y); 42 z?=?Hex_to_dec(g.z); 43 x1?=?(float)x?/ 1000 ; 44 y1?=?(float)y?/ 1000 ; 45 z1?=?(float)z?/ 1000 ; 46 printf("x:?%4.2f???y:%4.2f??z:%4.2f\n",x1,y1,z1); 47 break ; 48 } 49 return 0 ; 50 while_r: 51 while(1); 52} 53//16進(jìn)制轉(zhuǎn)10進(jìn)制算法實(shí)現(xiàn) 54int Hex_to_dec(const char*?str) 55{ 56 int value; 57 58 if (!?str) 59 { 60 return 0; 61 } 62 value = 0; 63 while (1) 64 { 65 if ((*str?>= '0')?&&?(*str?<= '9')) 66 { 67 value = value*16 +?(*str?- '0'); 68 } 69 else if ((*str?>= 'A')?&&?(*str?<= 'F')) 70 { 71 value = value*16 +?(*str?- 'A')?+ 10; 72 } 73 else if ((*str?>= 'a')?&&?(*str?<= 'f')) 74 { 75 value = value*16 +?(*str?- 'a')?+ 10; 76 } 77 else 78 { 79 break; 80 } 81 str++; 82 } 83 return value; 84}


長(zhǎng)期商務(wù)合作服務(wù):


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉