nRF51822藍牙學習 進程記錄 3:藍牙協議學習--簡單使用

  三天打魚兩天曬網,又學起了藍牙,不過還好的是終於開始學習藍牙協議部分了。數組

  可是,一看起來增長了藍牙協議的例程,真是沒頭緒啊。自己的教程資料解說太差了,看青風的藍牙原理詳解也是一頭霧水。緩存

  通過不斷地看各類資料,終於決定,無論他了,先學會例程修改再說。函數

  例程裏面有個 藍牙綜合例程,就它了。oop

  使用的是LP電子的手環學習開發板。按照教程下載了協議,而後下載了編譯文件,最後手機上安裝了對應的LP的安卓軟件。很好,啓動成功,能夠點燈,可是溫度和授時按鈕沒用。並且這個例程和其餘基於藍牙協議的例程沒有一個帶OLED顯示的例子。還想之後能手機控制開發板來操控OLED顯示呢,怎麼辦,只有本身一步一步試試了。學習

  先到這個例程的main函數中看看。ui

 

 1 int main(void)
 2 {
 3     uint32_t err_code;
 4     uint8_t  start_string[] = START_STRING;
 5     led_init();
 6     DS18B20_Init();
 7     // Initialize.
 8     APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);//時鐘初始化
 9     usart_init();    //串口初始化
10     ble_stack_init();  //協議初始化
11     gap_params_init();    //參數設置
12     services_init();    //通訊服務
13     advertising_init();    //廣播設置
14     conn_params_init();  //鏈接參數
15     
16     printf("%s\r\n",start_string);
17 
18     err_code = ble_advertising_start(BLE_ADV_MODE_FAST);  //¿ªÊ¼¹ã²¥
19     APP_ERROR_CHECK(err_code);
20     
21     // Enter main loop.
22     for (;;)
23     {
24         power_manage();
25     }
26 }

額........沒發現有啥基礎性的東西.......spa

再找找吧。往上轉了轉,哎,發現個東西。調試

 1 static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length)//藍牙接收
 2 {
 3       printf("p_data=%s\r\n",p_data);
 4     uint32_t err_code;
 5     short temp=0;
 6     uint8_t data[3];
 7     switch(p_data[0])
 8         {
 9             case 0x31:   
10                      nrf_gpio_pin_toggle(8);  //控制LED
11             break;
12             case 0x32:   // 
13                nrf_gpio_pin_toggle(9);
14             break;
15             case 0x34:   // 
16                nrf_gpio_pin_toggle(10);
17             break;
18             case 0x33:   // 溫度接收
19                temp=DS18B20_Get_Temp();
20                data[0]=temp/100+0x30;
21                data[1]=temp/10%10+0x30;
22                data[2]=temp%10+0x30;
23                err_code = ble_nus_string_send(&m_nus, data, 3);
24         if (err_code != NRF_ERROR_INVALID_STATE)
25         {
26             APP_ERROR_CHECK(err_code);
27         }
28             break;
29         
30         }
31 }

  這個不就是我要找的!!雖然咱還不明白藍牙協議到底怎麼用的,可是用人家寫好的仍是能夠的。code

  有了人家按鈕接收對應的協議,那拿來直接用就完了。orm

  上面的第三行有個串口輸出,輸出的是p_data,這個是幹什麼使的?試一試吧。

  插上串口線,打開串口調試助手,發現按一個按鈕顯示一個數,轉換爲16進制正好和 case 後的數同樣。這不就是輸出按鈕協議的嗎。很好。但是很快又發現,在switch 中,p_data 是個數組!看樣只是個一維數組,那這個數組到底都包括啥?都是幹啥使得?仿照上面的printf 在後面加幾行,將整個數組全輸出,將原來的字符串輸出%s換爲數據輸出%d,以下:

 1 //用於電腦串口輸出查看p_data
 2 printf("p_data[0]=%d\r\n",p_data[0]);
 3 printf("p_data[1]=%d\r\n",p_data[1]);
 4 printf("p_data[2]=%d\r\n",p_data[2]);
 5 printf("p_data[3]=%d\r\n",p_data[3]);
 6 printf("p_data[4]=%d\r\n",p_data[4]);
 7 printf("p_data[5]=%d\r\n",p_data[5]);
 8 printf("p_data[6]=%d\r\n",p_data[6]);

 

獲得相似數據:(這個是點擊授時按鈕得到的)

p_data[0]=53
p_data[1]=168
p_data[2]=250
p_data[3]=170
p_data[4]=88
p_data[5]=0
p_data[6]=0

多按幾個按鈕對比可得:p_data[0]爲按鈕對應的協議數據,p_data[1]、p_data[2]、p_data[3]與相應的按鈕有關,p_data[4]都是88.

  好了,手機上的幾個按鈕對應的數據弄清楚了,那就將上面幾個按鈕沒實現的功能加上去吧。好比 授時 和溫度顯示 按鈕都沒用,而 亮度顯示 按鈕由於開發板上沒有光敏電阻,就沒管它。

  首先,它的讀取溫度函數不知哪兒有毛病,也沒工夫再找一遍了,直接刪除,將我本身的ds18b20的函數移植進去。好了,串口和手機顯示溫度正常。能夠發現, ble_nus_string_send(&m_nus, data, 3)這個函數是藍牙的數據發送函數,頗有用,只是目前還不會用,先標記着。(目前的目標是先會移植使用人家的)。

  再加入OLED顯示函數吧。照着以前的移植方法將周立功的ZLG_GUI再移植上。簡單寫一個初始化函數並加入main()函數中,放在 協議初始化 以前。而後將OLED顯示溫度函數showtemp(x,y) 加在讀取溫度的 case 0x33:  後面,並加上緩存顯示函數GUI_Exec();運行能夠發現只有點擊了 溫度 按鈕,屏幕纔會更新數據,由於看main()函數能夠發現,無限運行的  for (;;) 中只有一個低電量運行的函數(24行),此時的case 猜想是利用中斷來運行得,因此只有觸發了case 纔會運行裏面的函數。

這樣感受很low(我先加上了時間顯示函數,連同時間都是須要點一下按鈕才更新一下屏幕,沒意思),因此加上之前的中斷刷屏函數試試。添加time.c,將定時器的啓動初始化加到main()函數中,刪去放在showtemp(x,y)後面的GUI_Exec(),運行發現能夠顯示。但因爲溫度讀取仍是和case掛鉤,因此仍是隻有點了溫度 按鈕溫度纔會更新變化。(解決方法和時間函數更新同樣,立刻就說到)。

  加入時鐘函數。按照以前編寫的 萬年曆,添加相應的rtc文件。 原本的歷程中就包含時間函數,經讀取p_data 數組能夠發現,按下 授時 按鈕獲取的p_data[1]、p_data[2]、p_data[3]就是時間數。我還簡單仿寫了時間轉換函數,將時間轉換爲帶年月日的結構體:

 1 int time_thansform(datetime *time_now,uint8_t *now)
 2 {
 3     
 4      uint32_t temp=0,temp_now = 0;
 5     uint16_t temp1 = 0;
 6     uint8_t a,b,c;
 7     
 8 
 9     a=now[1];
10     b=now[2];
11     c=now[3];
12     temp_now=(c<<6)+(b<<3)+a;
13     temp = temp_now / 86400; //獲得天數
14      {
15          temp1 = 1970;    //從1970年開始
16         while(temp >= 365)
17         {
18             if(Is_Leap_Year(temp1))//是閏年
19             {
20                 if(temp >= 366)
21                     temp -= 366; //閏年的秒鐘數
22                 else
23                 {
24                     temp1++;      
25                     break;
26                 }
27             }
28             else
29                 temp -= 365;     //平年
30             temp1++;          
31         }
32         time_now->year = temp1; //獲得年份
33         temp1 = 0;
34         while(temp >= 28) 
35         {
36             if(Is_Leap_Year(time_now->year) && temp1 == 1) //如果閏年
37             {
38                 if(temp >= 29)temp -= 29; //閏年的秒鐘數
39                 else break;
40             }
41             else
42             {
43                 if(temp >= mon_table[temp1])temp -= mon_table[temp1]; //平年
44                 else break;
45             }
46             temp1++;
47         }
48         time_now->month = temp1 + 1;    //獲得月份
49         time_now->day = temp + 1;      //日期
50     }
51     temp = temp_now % 86400;             //秒鐘數
52     time_now->h = temp / 3600;         //小時
53     time_now->m = (temp % 3600) / 60;     //分鐘
54     time_now->s = (temp % 3600) % 60;     //秒鐘
55     time_now->week = rtc_get_week(time_now->year, time_now->month, time_now->day); //»ñÈ¡ÐÇÆÚ
56     return 0;
57     
58 }

不過看了半天仍是沒明白怎麼設置它的時鐘。索性將main中的時鐘初始化函數刪去,加上我以前學習外設時用的時鐘初始化函數和時間設置函數(見源文件中的MY_Init()函數),並在timer.c的中斷函數中的屏幕刷新函數以前添加以前編寫的時間顯示函數 showtime(x,y),也能夠替換爲編寫好的模擬時鐘函數,固然,還能夠利用手機的按鈕函數來進行模擬時鐘和數字時鐘的切換,稍微加點函數就好 ,此處只用數字時鐘。在switch 中添加 授時 按鈕對應的操做:

 1     case 0x35:        //按鈕 授時 對應的協議,由上面的printf測得
 2             rtc_date_get(time_now1);        //本身的時鐘對應的時間函數
 3             //ble_time_set(time_now1,p_data);//本行能夠得出只修改p_data的數據是沒法修改例子中的計時器的底層函數的
 4             time_thansform(time_now1,p_data);
 5             printf("year:%d\r\n",time_now1->year);
 6             printf("month:%d\r\n",time_now1->month);
 7             printf("day:%d\r\n",time_now1->day);
 8             //printf("weak:%d\r\n",time_now1->week);
 9             printf("h:%d\r\n",time_now1->h);
10             printf("m:%d\r\n",time_now1->m);
11             printf("s:%d\r\n",time_now1->s);
12             
13                 
14                 break;
15                     

 

添加好頭文件和文件後,編譯經過,下載能夠看到時間不斷更新,按手機的 授時 按鈕串口顯示時間,按溫度 溫度也更新。

  本文源文件

 

  藍牙協議的詳細功能還有待慢慢發現,如今只是簡單地是用別人寫好的東西來入門。詳細的使用還要慢慢學習。

 

本文水平有限,內容不少詞語因爲知識水平問題不嚴謹或很離譜,但主要做爲記錄做用,能理解就行了,但願之後的本身和路過的大神對必要的錯誤提出批評與指點,對好笑的錯誤不要嘲笑,指出來我會改正的。謝謝。我是執念執戰,轉載請註明出處,謝謝。-------------隨夢,隨心,隨願,執念執戰,執戰蒼天!

相關文章
相關標籤/搜索