1 、智能手環(huán)簡(jiǎn)介
智能手環(huán)是一種穿戴式智能設(shè)備。通過該設(shè)備,用戶可以記錄日常生活中的鍛煉、睡眠等實(shí)時(shí)數(shù)據(jù),并將這些數(shù)據(jù)與手機(jī)、平板同步,起到通過數(shù)據(jù)指導(dǎo)健康生活的作用。另外,智能手環(huán)還具有社交功能,能夠?qū)㈠憻捛闆r和睡眠質(zhì)量發(fā)送到社交網(wǎng)絡(luò)進(jìn)行分享。
?
圖 1_1某款智能手環(huán)
一個(gè)智能手環(huán)最小系統(tǒng)一般包括:可充電的電源模塊、控制模塊(圖1_2中左邊芯片)、藍(lán)牙模塊(右邊芯片)、存儲(chǔ)模塊和加速計(jì)模塊(上面芯片)。其中加速計(jì)是為了獲得佩戴者在運(yùn)動(dòng)或睡眠過程中的加速度數(shù)據(jù),通過分析這些數(shù)據(jù)則能夠判斷佩戴者的運(yùn)動(dòng)情況和睡眠質(zhì)量;存儲(chǔ)模塊主要負(fù)責(zé)將實(shí)時(shí)數(shù)據(jù)暫存,接著在適當(dāng)?shù)臅r(shí)刻借助藍(lán)牙模塊將數(shù)據(jù)同步到手機(jī)端。方便起見本次要自制的記步手環(huán)將不采用存儲(chǔ)器暫存,而是將數(shù)據(jù)實(shí)時(shí)地傳送到手機(jī)端。同時(shí)為了便于大家對(duì)記步算法的理解,客戶端將采用一個(gè)折線圖的形式實(shí)時(shí)展示記步手環(huán)收集的數(shù)據(jù)。
?
圖 1_2某款智能手環(huán)核心電路板
2 、如何實(shí)現(xiàn)記步
看了上面的分析大家可能會(huì)疑惑——僅僅用一個(gè)加速計(jì)怎么能實(shí)現(xiàn)記步和睡眠質(zhì)量檢測(cè)呢?其實(shí)確實(shí)可以!因?yàn)榧铀儆?jì)可以實(shí)時(shí)獲取自身的XY三個(gè)軸向的加速度。當(dāng)其靜止時(shí)合加速度會(huì)在重力加速度附近波動(dòng);當(dāng)佩戴者處于深度睡眠過程中時(shí),其合加速度將呈現(xiàn)出長(zhǎng)時(shí)間的穩(wěn)定于重力加速度附近;當(dāng)其隨著運(yùn)動(dòng)的佩戴者手臂而做周期性擺動(dòng)時(shí),其數(shù)據(jù)也是有一定規(guī)律可循的。這樣,設(shè)計(jì)時(shí)只要通過分析從加速計(jì)獲的數(shù)據(jù)就能實(shí)現(xiàn)對(duì)運(yùn)動(dòng)或睡眠質(zhì)量的記錄。
3、 預(yù)期效果構(gòu)思
上面已經(jīng)提到:為了方便,我們并未采用存儲(chǔ)器實(shí)現(xiàn)記步手環(huán)的離線記錄,而是實(shí)時(shí)地將數(shù)據(jù)發(fā)送到客戶端由一個(gè)可視化的折線圖動(dòng)態(tài)繪制結(jié)果。如圖3_1所示系統(tǒng)中記步手環(huán)部分包含單片機(jī)模塊、藍(lán)牙模塊、加速計(jì)模塊和電源模塊,這樣通過單片機(jī)的協(xié)調(diào)可以實(shí)現(xiàn)將加速計(jì)模塊的數(shù)據(jù)通過藍(lán)牙實(shí)時(shí)地傳送給客戶端程序。在客戶端部分則負(fù)責(zé)將收集到的實(shí)時(shí)數(shù)據(jù)以折線圖的形式動(dòng)態(tài)地展示出來(lái),此外客戶端中也加入一個(gè)滑動(dòng)條來(lái)控制記步閾值來(lái)真正讓大家明白其設(shè)計(jì)思想(真正商業(yè)化的智能手環(huán)多數(shù)采用的是先將有效數(shù)據(jù)保存在手環(huán)的小型存儲(chǔ)器中,上位機(jī)周期性地將數(shù)據(jù)收集并同步到服務(wù)器端)。

圖 3_1 預(yù)期效果圖
4 、硬件整體設(shè)計(jì)
如圖4_1,相比于上一個(gè)無(wú)線小風(fēng)扇該硬件構(gòu)成反而比較簡(jiǎn)單:藍(lán)牙模塊依然采用我們比較熟悉的HC-06模塊,對(duì)于加速度的測(cè)量采用四周飛行器上常采用的MPU6050模塊。該模塊不僅含有加速計(jì)的功能,還具有陀螺儀的功能,其在汽車防側(cè)翻、相機(jī)云臺(tái)穩(wěn)定、機(jī)器人平衡、空中鼠標(biāo)、姿態(tài)識(shí)別等眾多領(lǐng)域都有應(yīng)用,這里我們只是利用了它的加速計(jì)功能。此外要注意:圖4_1所示的單片機(jī)模塊的電源引腳被隱藏了,在真正設(shè)計(jì)連接時(shí)一定不要忽略這兩個(gè)引腳!

圖 4_1 硬件電路圖
5 、MPU6050介紹
MPU-60X0是全球首例9軸運(yùn)動(dòng)處理器。它集成了3軸MEMS陀螺儀,3軸MEMS加速計(jì),以及1個(gè)可擴(kuò)展的數(shù)字運(yùn)動(dòng)處理器DMP(Digital Motion Processor)。如圖5_1所示軸向是相對(duì)于加速計(jì)說(shuō)的,當(dāng)芯片水平靜止放置時(shí)x軸和y軸的加速度分量幾乎為0,z軸的加速度分量約為當(dāng)?shù)氐闹亓铀俣?;而旋轉(zhuǎn)極性則是對(duì)陀螺儀來(lái)說(shuō)的,本次先不介紹。

圖 5_1 MPU-60X0軸向和旋轉(zhuǎn)的極性(來(lái)自MPU6050數(shù)據(jù)手冊(cè))
為何上面說(shuō)9軸信號(hào)呢?因?yàn)镸PU-60X0可用I2C接口連接一個(gè)第三方的數(shù)字傳感器,比如磁力計(jì)。擴(kuò)展之后就可以通過其I2C或SPI接口輸出一個(gè)9軸的信號(hào)。也可以通過其I2C接口連接非慣性的數(shù)字傳感器,比如壓力傳感器。(為什么特別提磁力計(jì)和壓力傳感器呢?因?yàn)樵陲w控方面,利用陀螺儀和加速計(jì)可以計(jì)算飛行器的傾角,從而調(diào)節(jié)飛行器平衡。但是只是調(diào)節(jié)平衡對(duì)方向沒有概念也不能執(zhí)行復(fù)雜任務(wù),因此需要配備磁力計(jì)(也即電子羅盤傳感器)。此外,由于飛行器在不同高度作業(yè)時(shí),其周圍的重力加速度也不同,這樣會(huì)影響傾角的準(zhǔn)確性,因此通過氣壓計(jì)計(jì)算所處高度然后計(jì)算實(shí)時(shí)加速度達(dá)到精確控制的效果。)

圖 5_2 MPU-60X0典型工作電路(來(lái)自MPU6050數(shù)據(jù)手冊(cè))
MPU-60X0對(duì)陀螺儀和加速計(jì)分別用了三個(gè)16位的ADC,將其測(cè)量的模擬量轉(zhuǎn)化為可輸出的數(shù)字量。為了精確跟蹤快速和慢速運(yùn)動(dòng),傳感器的測(cè)量范圍是可控的,陀螺儀可測(cè)范圍為±250,±500,±1000,±2000°/秒(dps),加速計(jì)可測(cè)范圍為±2,±4,±8,±16g(重力加速度)。如圖5_3是直接從16位ADC中讀出的6軸的數(shù)據(jù)(從左到右依次為加速計(jì)X軸數(shù)據(jù)、Y軸數(shù)據(jù)、Z軸數(shù)據(jù)、陀螺儀X極數(shù)據(jù)、Y極數(shù)據(jù)、Z極數(shù)據(jù)):

圖 5_3 MPU6050輸出加速計(jì)和陀螺儀6軸的原始數(shù)據(jù)
但是這里的輸出值并不是真正的加速度和角速度的值,上面說(shuō)過,MPU是一個(gè)16位AD量程可程控的設(shè)備,這里設(shè)置的加速度傳感器的測(cè)量量程為正負(fù)2g(這里的g為重力加速度),陀螺儀的量程為正負(fù)2000°/s。所以要用下面的公式進(jìn)行轉(zhuǎn)化:

圖5_4 實(shí)際值計(jì)算公式
最后給大家推薦一款比較容易買到的MPU6050,如圖5_5該模塊將核心芯片和外圍電路集成到一個(gè)模塊上并留出八個(gè)引腳,本次使用只需用到上面四個(gè)即可(具體連接參考圖4_1)。
?
圖5_5 MPU6050模塊
6 、一個(gè)簡(jiǎn)單的記步算法設(shè)計(jì)
第二小節(jié)講到當(dāng)MPU6050隨著運(yùn)動(dòng)的佩戴者手臂而做周期性擺動(dòng)時(shí),其數(shù)據(jù)也是有一定規(guī)律可循的。簡(jiǎn)單起見我們只分析合加速度:一個(gè)擺臂周期其合加速度會(huì)在重力加速度上下波動(dòng),如圖6_1只要選取合適的閾值(黑線代表閾值),每次檢測(cè)出合加速度大于該閾值則認(rèn)為是一次擺臂,從而可以實(shí)現(xiàn)記步的功能。這里要特別說(shuō)明下:如果想把你的手環(huán)推向市場(chǎng),就要通過大量分析擺臂數(shù)據(jù)建立一套更好的記步算法,如果偷懶只用樓主的簡(jiǎn)單算法,小心產(chǎn)品推出后被用戶的口水淹死(哈哈)!

圖 6_1 擺臂時(shí)合加速度變化圖
7 、I2C總線介紹
上次我們?cè)谑褂盟{(lán)牙串口模塊時(shí)使用過串口通信,由于51系列單片機(jī)將串口通信很多細(xì)節(jié)都封裝到芯片內(nèi)部,所以我們即使設(shè)計(jì)了串口驅(qū)動(dòng)模塊,也并沒有真正了解串口通信的核心思想。其實(shí)串口協(xié)議的出現(xiàn)是為了構(gòu)成一個(gè)總線線路,這樣單片機(jī)只要使用比較少的引腳就能和比較多的設(shè)備進(jìn)行通信了,這里要用到的I2C總線也具有相同的效果但又有些不同。

圖 7_1I2C總線掛接多個(gè)設(shè)備圖
I2C(Inter-Integrated Circuit)總線是由PHILIPS公司開發(fā)的兩線式串行總線,用于連接微控制器及其外圍設(shè)備。是微電子通信控制領(lǐng)域廣泛采用的一種總線標(biāo)準(zhǔn)。它是同步通信的一種特殊形式,具有接口線少,控制方式簡(jiǎn)單,器件封裝形式小,通信速率較高等優(yōu)點(diǎn)。如圖7_1采用I2C總線后CPU只要使用2個(gè)引腳便可和多個(gè)設(shè)備進(jìn)行通信(其實(shí)每個(gè)采用I2C通信方式的設(shè)備都具有唯一的地址碼,這樣在總線中便能夠被唯一識(shí)別),從而大大減少了引腳的使用。
在I2C總線中使用的兩線為時(shí)鐘線SCL和數(shù)據(jù)線SDA。所有的I2C主從設(shè)備都是只被這兩根線連接起來(lái)的。每一個(gè)設(shè)備既可以作為發(fā)送方,也可以作為接收方,或者既可以作為發(fā)送發(fā)也可以作為接收方。在總線中的主設(shè)備一般起產(chǎn)生時(shí)鐘信號(hào)和初始化通信的作用,從設(shè)備則負(fù)責(zé)響應(yīng)主設(shè)備發(fā)出的命令。為了在總線上區(qū)分每一個(gè)設(shè)備,每一個(gè)從設(shè)備必須有一個(gè)唯一的地址。主設(shè)備一般不需要地址(一般為微處理器),因?yàn)閺脑O(shè)備不能發(fā)送命令給主設(shè)備。

圖 7_2 I2C總線中主從設(shè)備
這里要先介紹I2C總線中幾個(gè)專有名詞:
l 發(fā)送者:將數(shù)據(jù)發(fā)送到總線的設(shè)備
l 接收者:從總線接收數(shù)據(jù)的設(shè)備
l 主設(shè)備:產(chǎn)生時(shí)鐘信號(hào)、啟動(dòng)通信、發(fā)送I2C命令和終止通信的設(shè)備
l 從設(shè)備:監(jiān)聽總線、能被主設(shè)備尋址的設(shè)備
l 多主設(shè)備:I2C能夠擁有多個(gè)主設(shè)備,而且每個(gè)主設(shè)備都能夠發(fā)送命令
l 仲裁:當(dāng)多個(gè)主設(shè)備請(qǐng)求使用總線時(shí),決定哪一個(gè)主設(shè)備可以占用的一個(gè)過程
l 同步:同步多個(gè)設(shè)備時(shí)鐘信號(hào)的一個(gè)過程
上面是從宏觀上對(duì)I2C總線介紹了下,接下來(lái)將深入細(xì)節(jié)研究其通信過程:
n 串行數(shù)據(jù)傳送:
在總線備用時(shí)SDA和SCL都必須保持高電平狀態(tài),只有關(guān)閉I2C總線時(shí)才能使SCL鉗位在低電平。在I2C總線數(shù)據(jù)傳輸時(shí),在時(shí)鐘線高電平期間,數(shù)據(jù)線上必須保持有穩(wěn)定的邏輯電平(也就是說(shuō)在數(shù)據(jù)傳輸期間只有時(shí)鐘線低電平期間,才允許數(shù)據(jù)線上的電平發(fā)生變化)。

圖 7_3 串行數(shù)據(jù)發(fā)送
因此在如圖7_3中對(duì)于每一個(gè)時(shí)鐘脈沖期間一比特的數(shù)據(jù)將會(huì)被傳送,SDA只能在時(shí)鐘信號(hào)為低電平時(shí)才能改變。下面是代碼中發(fā)送一字節(jié)的函數(shù):在循環(huán)體內(nèi)每次將dat內(nèi)的最高位移出到CY中,進(jìn)而賦值給SDA(這時(shí)SCL為低,SDA可改變)。接著拉高SCL并保持5us,最后再拉低SCL實(shí)現(xiàn)一個(gè)時(shí)鐘脈沖將dat中最高位送出。依此循環(huán)8次實(shí)現(xiàn)將dat全部傳出。
//------------------------------------------------
//向I2C總線發(fā)送一個(gè)字節(jié)數(shù)據(jù)
//------------------------------------------------
void I2C_SendByte(uchar dat)
{
uchar i;
for (i=0; i《8; i++) //8位計(jì)數(shù)器
{
dat 《《= 1; //移出數(shù)據(jù)的最高位
SDA = CY; //送數(shù)據(jù)口
SCL = 1; //拉高時(shí)鐘線
Delay5us(); //延時(shí)
SCL = 0; //拉低時(shí)鐘線
Delay5us(); //延時(shí)
}
I2C_RecvACK();
}
n 開始和結(jié)束條件:
命令不會(huì)沒有任何預(yù)兆直接發(fā)送的,每一個(gè)I2C命令的發(fā)送總是開始于開始條件并結(jié)束于終止條件。這里所謂的開始條件和終止條件起始也是由SCL和SDA組合形成的(如圖7_4)。

圖 7_4 開始和結(jié)束條件
如果時(shí)鐘線保持高電平期間,數(shù)據(jù)線出現(xiàn)由高到低的電平變化,則會(huì)啟動(dòng)I2C總線,此時(shí)為I2C的起始信號(hào):
//------------------------------------------------
//I2C起始信號(hào)
//------------------------------------------------
void I2C_Start()
{
SDA = 1; //拉高數(shù)據(jù)線
SCL = 1; //拉高時(shí)鐘線
Delay5us(); //延時(shí)
SDA = 0; //產(chǎn)生下降沿
Delay5us(); //延時(shí)
SCL = 0; //拉低時(shí)鐘線
}
若在時(shí)鐘線保持高電平期間,數(shù)據(jù)線出現(xiàn)由低到高的電平變化,則會(huì)停止I2C總線的數(shù)據(jù)傳輸,此時(shí)為I2C的終止信號(hào):
//------------------------------------------------
//I2C停止信號(hào)
//------------------------------------------------
void I2C_Stop()
{
SDA = 0; //拉低數(shù)據(jù)線
SCL = 1; //拉高時(shí)鐘線
Delay5us(); //延時(shí)
SDA = 1; //產(chǎn)生上升沿
Delay5us(); //延時(shí)
}
開始條件之后I2C總線被認(rèn)為是忙狀態(tài),只有當(dāng)停止信號(hào)之后其他主設(shè)備才能使用該總線。此外,當(dāng)開始條件之后主設(shè)備能夠多次發(fā)出開始信號(hào)。這些開始信號(hào)和第一次發(fā)出的開始信號(hào)類似,他們后面經(jīng)常會(huì)跟從設(shè)備的地址。這樣可以方便實(shí)現(xiàn)在I2C總線忙期間,當(dāng)前占線的主設(shè)備可以和不同的從設(shè)備進(jìn)行通信。
n I2C數(shù)據(jù)傳送:
I2C總線上傳送的每一個(gè)字節(jié)均為8位,但是每啟動(dòng)一次I2C總線,其后的數(shù)據(jù)傳送字節(jié)數(shù)是沒有限制的。同時(shí)每傳送一字節(jié)的數(shù)據(jù)后面都要跟隨一個(gè)接收者回應(yīng)的應(yīng)答位(低電平為應(yīng)答信號(hào),高電平為非應(yīng)答信號(hào)),當(dāng)全部數(shù)據(jù)發(fā)送完畢后主設(shè)備發(fā)送終止信號(hào)。

圖 7_5 數(shù)據(jù)傳送圖
所以在上面向I2C總線發(fā)送一字節(jié)的數(shù)據(jù)的代碼的最后有一個(gè)I2C_RecvACK()函數(shù)。(如下)該函數(shù)負(fù)責(zé)接收接收者發(fā)送過來(lái)的應(yīng)答信號(hào),也即圖7_5中的第9個(gè)時(shí)鐘脈沖的期間的相應(yīng)操作。
//------------------------------------------------
//I2C接收應(yīng)答信號(hào)
//------------------------------------------------
bit I2C_RecvACK()
{
SCL = 1; //拉高時(shí)鐘線
Delay5us(); //延時(shí)
CY = SDA; //讀應(yīng)答信號(hào)
SCL = 0; //拉低時(shí)鐘線
Delay5us(); //延時(shí)
return CY;
}
要特別說(shuō)明下:所有的數(shù)據(jù)位包括應(yīng)答位都需要主設(shè)備產(chǎn)生時(shí)鐘脈沖。如果從設(shè)備沒有應(yīng)答意味著將沒有更多的數(shù)據(jù)要傳送或者設(shè)備沒有準(zhǔn)備好傳送。這時(shí),主設(shè)備要么產(chǎn)生停止信號(hào),要么重新發(fā)出開始條件。

圖 7_6 應(yīng)答信號(hào)
n I2C的7-bit地址:
上面說(shuō)過每一個(gè)從設(shè)備都應(yīng)該具有唯一的地址,這樣主設(shè)備才能準(zhǔn)確的尋址到每一個(gè)設(shè)備,而這些地址被統(tǒng)一規(guī)定為7比特。但是上面講過I2C總線傳輸數(shù)據(jù)都是8比特傳送,地址7比特豈不是少一位!其實(shí)緊跟地址還有一位用來(lái)表示是讀操作還是寫操作的標(biāo)志位。如果該位為0表示主設(shè)備將要向從設(shè)備寫數(shù)據(jù),否則表示主設(shè)備將要從從設(shè)備讀數(shù)據(jù)。在這8比特被發(fā)送后主設(shè)備能夠持續(xù)地進(jìn)行讀或者寫。如果主設(shè)備想和其他從設(shè)備進(jìn)行通信,只要再次發(fā)送一個(gè)新的開始信號(hào)就可以而不必發(fā)送終止信號(hào)。

圖 7_7 一個(gè)完整的數(shù)據(jù)讀寫操作
8 、MPU6050驅(qū)動(dòng)設(shè)計(jì)
至此,我們基本上已經(jīng)將I2C的知識(shí)學(xué)完了,下面將結(jié)合MPU6050的驅(qū)動(dòng)進(jìn)一步講解其原理(該部分的代碼參見工程的mpu6050.c部分)。我們首先來(lái)看一下它的頭文件mpu6050.h:從第6到25行上來(lái)就是一大串內(nèi)部地址的定義,對(duì)于初學(xué)者可能一頭霧水!如果樓主再引入寄存器等數(shù)字電路的知識(shí)可能又要說(shuō)幾頁(yè)了,于是這里準(zhǔn)備只用一個(gè)簡(jiǎn)單的例子闡述下這些地址的作用。
#include“i2c.h”
//-----------------------------------------
// 定義MPU6050內(nèi)部地址
//-----------------------------------------
#define SMPLRT_DIV 0x19 //陀螺儀采樣率,典型值:0x07(125Hz)
#define CONFIG 0x1A //低通濾波頻率,典型值:0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺儀自檢及測(cè)量范圍,典型值:0x18(不自檢,2000deg/s)
#define ACCEL_CONFIG 0x1C //加速計(jì)自檢、測(cè)量范圍及高通濾波頻率,典型值:0x01(不自檢,2G,5Hz)
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B //電源管理,典型值:0x00(正常啟用)
#define WHO_AM_I 0x75 //IIC地址寄存器(默認(rèn)數(shù)值0x68,只讀)
#define SlaveAddress 0xD0 //IIC寫入時(shí)的地址字節(jié)數(shù)據(jù),+1為讀取
//-----------------------------------------
// 通過I2C和MPU6050通信的函數(shù)
//-----------------------------------------
void Single_WriteI2C(uchar REG_Address,uchar REG_data);//向I2C設(shè)備寫入一個(gè)字節(jié)數(shù)據(jù)
uchar Single_ReadI2C(uchar REG_Address); //從I2C設(shè)備讀取一個(gè)字節(jié)數(shù)據(jù)
void InitMPU6050(); //初始化MPU6050
int GetData(uchar REG_Address); //合成數(shù)據(jù)
上面講到在I2C總線中主設(shè)備可以通過固定的7-bit地址尋找到相應(yīng)的從設(shè)備(這里的7-bit地址為第26行的SlaveAddress,想必大家也能夠理解后面注釋的意義了吧~不加1表示緊跟著地址的一位為0,表示向該設(shè)備寫數(shù)據(jù);加1則表示緊跟著的一位為1,表示主設(shè)備從從設(shè)備讀數(shù)據(jù))。雖然采用這種方式能夠準(zhǔn)確找到從設(shè)備,但是從設(shè)備里面又有比較多的寄存器。這就好比你知道了某個(gè)要找的東西在具體的某個(gè)大柜子里,但是來(lái)到大柜子前又發(fā)現(xiàn)有許多小抽屜。這里的7-bit地址就好像指明了哪個(gè)柜子,而從第6到25行的內(nèi)部地址就像柜子上的抽屜編號(hào),而不一樣之處是位于mpu6050內(nèi)的“小抽屜”一部分存放著其采集的實(shí)時(shí)數(shù)據(jù),另一部分等著外部放一些數(shù)據(jù)來(lái)設(shè)置其采樣屬性。
這樣,如上面的第6行的SMPLRT_DIV(0x19)是用來(lái)設(shè)置陀螺儀采樣率的寄存器地址,只要向該地址所指的寄存器寫入相應(yīng)的值則可以設(shè)置陀螺儀采樣率。因此下面MPU6050初始化函數(shù)就是調(diào)用封裝的I2C寫函數(shù)向相應(yīng)的小抽屜內(nèi)寫屬性數(shù)據(jù),設(shè)置MPU6050采樣屬性。
//------------------------------------------------
//初始化MPU6050
//------------------------------------------------
void InitMPU6050()
{
Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠狀態(tài)
Single_WriteI2C(SMPLRT_DIV, 0x07);
Single_WriteI2C(CONFIG, 0x06);
Single_WriteI2C(GYRO_CONFIG, 0x18);
Single_WriteI2C(ACCEL_CONFIG, 0x01);
}
再如第10~11行的ACCEL_XOUT_H、ACCEL_XOUT_L是用來(lái)存放最新的陀螺儀X極的數(shù)值,因?yàn)椴捎?6位ADC所以這里需要用兩個(gè)寄存器。所以下面合成數(shù)據(jù)函數(shù)負(fù)責(zé)連續(xù)讀取REG_Address開始的兩字節(jié)數(shù)據(jù)組成一個(gè)16位數(shù)據(jù)。當(dāng)函數(shù)的參數(shù)為ACCEL_XOUT_H時(shí),則獲取的是實(shí)時(shí)的陀螺儀X極的數(shù)值,同樣地可以獲得實(shí)時(shí)的6軸數(shù)據(jù)。
//------------------------------------------------
//合成數(shù)據(jù)
//------------------------------------------------
int GetData(uchar REG_Address)
{
uchar H,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return (H《《8)+L; //合成數(shù)據(jù)
}
電子發(fā)燒友App






評(píng)論