基于stm32的多功能時(shí)鐘10——數(shù)據(jù)采集與藍(lán)牙控制

????????嘿,我的小可愛們芋簿!

????????在《藍(lán)牙串口通信》這一章中峡懈,小編帶著大家編寫了藍(lán)牙串口通信程序,測試了藍(lán)牙通信正常与斤。由于我后來又找到了《藍(lán)牙調(diào)試器》軟件肪康,功能強(qiáng)大,可自定義控件撩穿,所以下面將編寫通信協(xié)議磷支,通過這款軟件,來實(shí)現(xiàn)數(shù)據(jù)采集和藍(lán)牙控制食寡。而我們?cè)谏弦徽轮形肀罚瓿闪怂{(lán)牙監(jiān)控界面的設(shè)計(jì),所以這一章中冻河,我們開始講解程序的編寫箍邮。


????????首先,我們要將數(shù)據(jù)包設(shè)置成結(jié)構(gòu)體的形式叨叙,便于后面的操作和管理锭弊,同時(shí)定義接收數(shù)據(jù)堆棧和發(fā)送數(shù)據(jù)堆棧。之所以這樣做擂错,是因?yàn)橥ㄐ艆f(xié)議規(guī)定味滞,數(shù)據(jù)包必須包括起始字節(jié)、數(shù)據(jù)字節(jié)钮呀、校驗(yàn)字節(jié)和結(jié)束字節(jié)剑鞍,這樣做的目的就是確保數(shù)據(jù)傳輸?shù)恼_性和穩(wěn)定性。關(guān)于通信方面的知識(shí)爽醋,我以后用到的話蚁署,還會(huì)介紹的,例如ESP8266等模塊蚂四。

/*定義串口發(fā)送數(shù)據(jù)堆棧*/

typedef struct

{

? ? u8 head;//定義起始字節(jié)

? ? u8 getdata[8];//定義采集數(shù)據(jù),包括溫度(1字節(jié))光戈、濕度(1字節(jié))、是否報(bào)警(1字節(jié))遂赠、電機(jī)運(yùn)行狀態(tài)(1字節(jié))久妆、空氣質(zhì)量(2字節(jié))和測量距離(2字節(jié))

? ? u8 verify;//定義校驗(yàn)字節(jié)

? ? u8 tail;//定義結(jié)束字節(jié)

}TX_STACK;//定義串口發(fā)送數(shù)據(jù)堆棧

/*定義串口接收數(shù)據(jù)堆棧*/

typedef struct

{

? ? u8 head;//定義起始字節(jié)

? ? u8 control[10];//定義閾值存放區(qū),溫濕度上下限(4字節(jié)),空氣質(zhì)量、安全距離(4字節(jié)),取消報(bào)警和啟停電機(jī)(2字節(jié))

? ? u8 verify;//定義校驗(yàn)字節(jié)

? ? u8 tail;//定義結(jié)束字節(jié)

? ? u8 ptr;//定義接收數(shù)據(jù)指針

? ? u8 lock_flag;//定義數(shù)據(jù)接收完畢標(biāo)志位

}RX_STACK;//定義串口接收數(shù)據(jù)堆棧

TX_STACK tx_stack;//定義發(fā)送數(shù)據(jù)緩存區(qū)

RX_STACK rx_stack;//定義接收數(shù)據(jù)緩存區(qū)

關(guān)于藍(lán)牙串口的配置代碼跷睦,在前面已經(jīng)講述過筷弦。下面,我們分為兩個(gè)模塊來講解抑诸。

(1)數(shù)據(jù)采集烂琴,實(shí)時(shí)顯示

這一部分爹殊,是單片機(jī)發(fā)送數(shù)據(jù),通過藍(lán)牙傳輸給手機(jī)奸绷,在手機(jī)界面上顯示單片機(jī)采集到的數(shù)據(jù)边灭。

/*發(fā)送堆棧初始化*/

void tx_init(void)

{

? ? u8 i;

? ? tx_stack.head = 0xa5;//起始字節(jié)

? ? for(i=0; i<8; i++)

? ? {

? ? ? ? tx_stack.getdata[i] = 0x00;//采集數(shù)據(jù)

? ? }

? ? tx_stack.verify = 0x00;

? ? tx_stack.tail = 0x5a;//結(jié)束字節(jié)

}

我們先將發(fā)送堆棧初始化,然后通過下面的發(fā)送程序發(fā)送出去健盒。

/*發(fā)送采集數(shù)據(jù)*/

void send_collected_data(void)

{

? ? u8 i;

? ? //發(fā)送起始字節(jié)

? ? USART_SendData(USART2,tx_stack.head);

? ? while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);

? ? //發(fā)送采集數(shù)據(jù)

? ? for(i=0; i<8; i++)

? ? {

? ? ? ? USART_SendData(USART2, tx_stack.getdata[i]);

? ? ? ? while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);

? ? ? ? tx_stack.verify += tx_stack.getdata[i];

? ? }

? ? //發(fā)送校驗(yàn)字節(jié)

? ? USART_SendData(USART2,tx_stack.verify);

? ? while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);

? ? //發(fā)送結(jié)束字節(jié)

? ? USART_SendData(USART2,tx_stack.tail);

? ? while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);

? ? tx_init();

}

????????在發(fā)送采集數(shù)據(jù)函數(shù)里绒瘦,我們根據(jù)協(xié)議,依次發(fā)送起始字節(jié)扣癣、采集數(shù)據(jù)字節(jié)惰帽、校驗(yàn)字節(jié)和結(jié)束字節(jié)。這樣父虑,在藍(lán)牙軟件里该酗,就會(huì)對(duì)單片機(jī)發(fā)送過來的數(shù)據(jù)進(jìn)行分析處理。首先士嚎,判斷數(shù)據(jù)包是否符合通信協(xié)議呜魄,如果符合(起始字節(jié)、結(jié)束字節(jié)等正確莱衩,數(shù)據(jù)結(jié)構(gòu)正確)爵嗅。再對(duì)接收的數(shù)據(jù)進(jìn)行校驗(yàn),如果校驗(yàn)成功笨蚁,則數(shù)據(jù)有效睹晒,藍(lán)牙軟件就會(huì)顯示對(duì)應(yīng)的數(shù)據(jù),包括文本括细、圖表等形式伪很。如果校驗(yàn)不成功,則數(shù)據(jù)失效奋单,不予處理锉试。(注意:這里只要單片機(jī)依次發(fā)數(shù)據(jù)即可,判斷數(shù)據(jù)包是否符合協(xié)議以及數(shù)據(jù)校驗(yàn)等操作是上位機(jī)軟件程序完成的)

????????temp = distance/100;

? ? ? ? tx_stack.getdata[0] = temperature;

? ? ? ? tx_stack.getdata[1] = humidity;

? ? ? ? tx_stack.getdata[2] = cancel;

? ? ? ? tx_stack.getdata[3] = state;

? ? ? ? tx_stack.getdata[4] = value%256;

? ? ? ? tx_stack.getdata[5] = value/256;

? ? ? ? tx_stack.getdata[6] = temp%256;

? ? ? ? tx_stack.getdata[7] = temp/256;

? ? ? ? send_collected_data();

在主程序里览濒,對(duì)發(fā)送數(shù)據(jù)包的每個(gè)元素采集到的數(shù)值呆盖,再調(diào)用該發(fā)送程序即可。

(2)藍(lán)牙控制匾七,參數(shù)調(diào)整

????????這一部分絮短,是單片機(jī)接收程序江兢,單片機(jī)接收手機(jī)發(fā)出的指令昨忆,并做相關(guān)的處理。

????????我們先要在串口中斷函數(shù)里編寫數(shù)據(jù)包接收語句杉允,相較于發(fā)送(此項(xiàng)目采集數(shù)據(jù)邑贴,實(shí)時(shí)性強(qiáng))席里,接收不是每時(shí)每刻都進(jìn)行的,用中斷的方式可能會(huì)更好些拢驾。在接收中斷函數(shù)里奖磁,我們只要依次接收數(shù)據(jù),將數(shù)據(jù)存放在相應(yīng)的接收數(shù)據(jù)結(jié)構(gòu)體里即可繁疤。

void USART2_IRQHandler(void)

{

? ? static u8 i = 0;

? ? if(USART_GetITStatus(USART2, USART_IT_RXNE)!=RESET)

? ? {

? ? ? ? rev_data = USART_ReceiveData(USART2);? ? ? ? ? ? //接收數(shù)據(jù)

? ? ? ? if(rx_stack.lock_flag == UNLOCK)

? ? ? ? {

? ? ? ? ? ? switch(i)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? case 0:rx_stack.head = rev_data;i++;break;

? ? ? ? ? ? ? ? case 1:rx_stack.control[rx_stack.ptr++] = rev_data;i++;break;

? ? ? ? ? ? ? ? case 2:rx_stack.control[rx_stack.ptr++] = rev_data;i++;break;

? ? ? ? ? ? ? ? case 3:rx_stack.control[rx_stack.ptr++] = rev_data;i++;break;

? ? ? ? ? ? ? ? case 4:rx_stack.control[rx_stack.ptr++] = rev_data;i++;break;

? ? ? ? ? ? ? ? case 5:rx_stack.control[rx_stack.ptr++] = rev_data;i++;break;

? ? ? ? ? ? ? ? case 6:rx_stack.control[rx_stack.ptr++] = rev_data;i++;break;

? ? ? ? ? ? ? ? case 7:rx_stack.control[rx_stack.ptr++] = rev_data;i++;break;

? ? ? ? ? ? ? ? case 8:rx_stack.control[rx_stack.ptr++] = rev_data;i++;break;

? ? ? ? ? ? ? ? case 9:rx_stack.control[rx_stack.ptr++] = rev_data;i++;break;

? ? ? ? ? ? ? ? case 10:rx_stack.control[rx_stack.ptr++] = rev_data;i++;break;

? ? ? ? ? ? ? ? case 11:rx_stack.verify = rev_data;i++;break;

? ? ? ? ? ? ? ? case 12:rx_stack.tail = rev_data;i++;break;

? ? ? ? ? ? ? ? default:rx_stack.lock_flag = LOCKED;i=0;break;

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? USART_ClearITPendingBit(USART2, USART_IT_RXNE);? ? ? //清除接收中斷標(biāo)志

}

????????接收手機(jī)發(fā)送的數(shù)據(jù)包后咖为,我們要對(duì)數(shù)據(jù)包進(jìn)行解析。當(dāng)然在解析之前稠腊,先要判斷數(shù)據(jù)能不能校驗(yàn)成功躁染,如果校驗(yàn)成功,則接收的數(shù)據(jù)正確架忌,做相關(guān)的處理吞彤;否則,接收的數(shù)據(jù)錯(cuò)誤叹放,不做任何處理饰恕。這里,我們需要判斷起始字節(jié)井仰、結(jié)束字節(jié)(固定值0xa5和0x5a)是否符合協(xié)議埋嵌,以及校驗(yàn)字節(jié)是否和數(shù)據(jù)字節(jié)之和低8位是否相等。這里俱恶,由于采用軟件里的自定義控件進(jìn)行數(shù)據(jù)命令的發(fā)送莉恼,所以起始字節(jié)和結(jié)束字節(jié)可不必校驗(yàn)(肯定是固定值0xa5和0x5a)。如果是通過文本框發(fā)送數(shù)據(jù)速那,那么就要校驗(yàn)這兩個(gè)字節(jié)(手動(dòng)輸入俐银,不能確保)。

/*發(fā)送藍(lán)牙控制數(shù)據(jù)*/

void send_control_data(void)

{

? ? u8 sum = 0,i;

? ? if(rx_stack.lock_flag == LOCKED)

? ? {

? ? ? ? for(i=0; i<10; i++)

? ? ? ? {

? ? ? ? ? ? sum += rx_stack.control[i];

? ? ? ? }

? ? ? ? /*檢驗(yàn)成功*/

? ? ? ? if(rx_stack.verify==sum)

? ? ? ? {

? ? ? ? ? ? temper_H = rx_stack.control[0];

? ? ? ? ? ? temper_L = rx_stack.control[1];

? ? ? ? ? ? humid_H = rx_stack.control[2];

? ? ? ? ? ? humid_L = rx_stack.control[3];

? ? ? ? ? ? cancel = rx_stack.control[4];

? ? ? ? ? ? motor_flag = rx_stack.control[5];

? ? ? ? ? ? air_upperlimit = rx_stack.control[6]+rx_stack.control[7]*256;

? ? ? ? ? ? length = rx_stack.control[8]+rx_stack.control[9]*256;

? ? ? ? }

? ? ? ? else

? ? ? ? {

? ? ? ? ? ? ;//校驗(yàn)失敗,不操作

? ? ? ? }

? ? ? ? rx_stack.lock_flag = UNLOCK;

? ? ? ? rx_init();

? ? }

}

當(dāng)然端仰,我們?cè)诖酥靶枰獙?duì)接收數(shù)據(jù)堆棧進(jìn)行初始化捶惜,然后再主函數(shù)中調(diào)用解析函數(shù)即可。

/*接收堆棧初始化*/

void rx_init(void)

{

? ? rx_stack.head = 0x00;//起始字節(jié)

? ? rx_stack.control[0] = temper_H;//數(shù)據(jù)接收控制4字節(jié)

? ? rx_stack.control[1] = temper_L;

? ? rx_stack.control[2] = humid_H;

? ? rx_stack.control[3] = humid_L;

? ? rx_stack.control[4] = cancel;

? ? rx_stack.control[5] = motor_flag;

? ? rx_stack.control[6] = air_upperlimit%256;

? ? rx_stack.control[7] = air_upperlimit/256;

? ? rx_stack.control[8] = length%256;

? ? rx_stack.control[9] = length/256;

? ? rx_stack.verify = 0x00;//數(shù)據(jù)校驗(yàn)字節(jié)

? ? rx_stack.tail = 0x00;//結(jié)束字節(jié)

? ? rx_stack.lock_flag = UNLOCK;

? ? rx_stack.ptr = 0x00;

}

通信確認(rèn)
藍(lán)牙通信正常
藍(lán)牙界面1


藍(lán)牙界面2

????????到這里荔烧,我們的藍(lán)牙串口通信協(xié)議就編寫完成了吱七,當(dāng)然過程肯定沒有這么簡單,不信你也可以試試鹤竭。此時(shí)踊餐,我們連接好藍(lán)牙,打開之前的多功能時(shí)鐘工程臀稚,就可以在工程界面里看到實(shí)時(shí)采集的數(shù)據(jù)吝岭,并且不斷的更新。同時(shí),你也可以設(shè)置相關(guān)的參數(shù)窜管,UI界面也會(huì)隨著你的操作而會(huì)發(fā)生變化散劫,單片機(jī)也會(huì)做相關(guān)的處理,是不是很神奇幕帆,是不是很有趣获搏,那就一起來開發(fā)多功能時(shí)鐘吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末失乾,一起剝皮案震驚了整個(gè)濱河市常熙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碱茁,老刑警劉巖症概,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異早芭,居然都是意外死亡彼城,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門退个,熙熙樓的掌柜王于貴愁眉苦臉地迎上來募壕,“玉大人,你說我怎么就攤上這事语盈〔障冢” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵刀荒,是天一觀的道長代嗤。 經(jīng)常有香客問我,道長缠借,這世上最難降的妖魔是什么干毅? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮泼返,結(jié)果婚禮上硝逢,老公的妹妹穿的比我還像新娘。我一直安慰自己绅喉,他們只是感情好渠鸽,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著柴罐,像睡著了一般徽缚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上革屠,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天凿试,我揣著相機(jī)與錄音排宰,去河邊找鬼。 笑死红省,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的国觉。 我是一名探鬼主播吧恃,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼麻诀!你這毒婦竟也來了痕寓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤蝇闭,失蹤者是張志新(化名)和其女友劉穎呻率,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呻引,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡礼仗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逻悠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片元践。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖童谒,靈堂內(nèi)的尸體忽然破棺而出单旁,到底是詐尸還是另有隱情,我是刑警寧澤饥伊,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布象浑,位于F島的核電站,受9級(jí)特大地震影響琅豆,放射性物質(zhì)發(fā)生泄漏愉豺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一茫因、第九天 我趴在偏房一處隱蔽的房頂上張望粒氧。 院中可真熱鬧,春花似錦节腐、人聲如沸外盯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饱苟。三九已至,卻和暖如春狼渊,著一層夾襖步出監(jiān)牢的瞬間箱熬,已是汗流浹背类垦。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留城须,地道東北人蚤认。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像糕伐,于是被迫代替她去往敵國和親砰琢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容