一、簡介
本篇以SimpleBLEPeripheral工程爲例,介紹如何添加一個電池電量服務。
二、實驗平臺
協議棧版本:BLE-CC254x-1.4.0
編譯軟件: IAR 8.20.2
硬件平臺: Smart RF開發板
手機平臺: 紅米1S
安卓系統: Android 4.3
APP: BLE Device Monitor
三、版權聲明
博主:甜甜的大香瓜
聲明:喝水不忘挖井人,轉載請註明出處。
原文地址:http://blog.csdn.net/feilusia
聯繫方式:[email protected]
技術交流QQ羣:127442605
四、CC2541的電池電量服務簡介
1、電池電量服務是什麼?
答:它是電池電量專用的服務,手機能通過這個服務獲取到CC2541的電池電量。
2、爲什麼需要電池電量服務?
答:CC2541一般通過USB直接供電或鈕釦電池供電。其中通過鈕釦電池供電的方式,鈕釦電池的電量使用情況是用戶必須知道的數據。
否則手機與CC2541通信不成功,到底是CC2541死機了還是沒電了,就說不清楚了。
3、通過什麼方式獲取電池電量?
答:
方法一、通過內部的10bit的adc通道採集電池電量(最高位是符號位,所以實際是9bit精度)。
方法二、通過最高12bit的adc通道採集電池電量(最高位是符號位,所以實際是11bit精度)。
4、採集電池電量是如何計算的?
答:
把CC2541的鈕釦電池電壓從2.0v~3.0v,當做電量的0%~100%。(香瓜猜測這麼做是因爲2~3V正好是CC2541的正常工作電壓)
而CC2541的內部帶符號的10bit的adc通道,量程範圍爲0~511,使用的參考電壓爲1.25v。
由於adc只有1.25v的參考電壓,不能採集到2~3v的電壓,因此我們把電池電壓經過分壓後採集,也就是採集1/3的電池電壓,adc把2v/3~3v/3當做電壓的0%~100%。
因此,由以上信息獲得一個公式:(v/3)/ 1.25 = adc/511
其中,v是電池的實際鈕釦電池的電壓,adc是2541採集到的數值。
當v= 2時,adc=273。也就是CC2541採集到的adc值爲273時,電壓值爲2v,是0%的電量。
當v= 3時,adc=409。也就是CC2541採集到的adc值爲409時,電壓值爲3v,是100%的電量。
假設2v~3v時的變化是線性的,則可得到下圖:
其中上圖的Xadc和percentage是當前讀到的adc值和當前電量的百分比。
利用兩個相似三角形的特性,可以得到公式:
Percentage / (X – 273) = 100 / 136
變換後爲:
Percentage = (X - 273) * 25 / 34
由上式四捨五入提高計算精度則有:
Percentage = [(X - 273) * 25 + 33] / 34
五、代碼修改
1、保證項目中有hal_adc.c和hal_adc.h
2、在工程的PROFILES分類中添加battservice.c與battservice.h兩個文件
兩文件路徑:C:\Texas Instruments\BLE-CC254x-1.4.0\Projects\ble\Profiles\Batt
3、IAR設置中添加倆路徑
4、開啓ADC的宏
5、添加電池服務的頭文件(simpleBLEPeripheral.c中)
- #include "battservice.h"
6、定義一個電池默認臨界值的宏(simpleBLEPeripheral.c中)
- #define DEFAULT_BATT_CRITICAL_LEVEL 6
定義爲6,也就是電量低於6%時CC2541會主動notify通知主機電量過低。
7、添加初始化電池電量的代碼(simpleBLEPeripheral.c的SimpleBLEPeripheral_Init()函數中)
- void SimpleBLEPeripheral_Init( uint8 task_id )
- {
- simpleBLEPeripheral_TaskID = task_id;
- //電池服務
- {
- uint8 critical = DEFAULT_BATT_CRITICAL_LEVEL;
- Batt_SetParameter( BATT_PARAM_CRITICAL_LEVEL, sizeof (uint8 ), &critical );/* 設置默認臨界電量 */
- }
- Batt_AddService(); /* 添加電池服務 */
- Batt_Register(BattCB); /* 註冊電池服務的應用回調函數 */
- ……
- }
8、定義電池電量服務的回調函數(simpleBLEPeripheral.c中)
- //******************************************************************************
- //name: BattCB
- //introduce: 電池電量服務的回調函數
- //parameter: event:事件
- //return: none
- //author: 甜甜的大香瓜
- //changetime: 2015.12.13
- //******************************************************************************
- static void BattCB(uint8 event)
- {
- if (event == BATT_LEVEL_NOTI_ENABLED)
- {
- if (gapProfileState == GAPROLE_CONNECTED)
- {
- }
- }
- else if (event == BATT_LEVEL_NOTI_DISABLED)
- {
- }
- }
回調函數的作用只是在開、關通知時告知應用層。
回調函數是在下面的情況被調用的:
- static void BattCB(uint8 event);
10、添加一段週期監測電量的代碼(simpleBLEPeripheral.c中)
- static void performPeriodicTask( void )
- {
- if ( gapProfileState == GAPROLE_CONNECTED )
- {
- // perform battery level check
- Batt_MeasLevel( );
- }
- }
當電量小於我們設置的DEFAULT_BATT_CRITICAL_LEVEL(本篇設置爲6)時,會在Batt_MeasLevel( )函數裏主動notify告知主機。
六、實驗結果
1、仿真查看adc採集到的電量
單步執行查看內部adc採集到的電源值爲459
將adc=459,代入公式“(v/3)/ 1.25 = adc/511”中,得到v=3.36839530332681
2、萬用表測試開發板的電源電壓
實測VCC=3.20V
3、用手機app查看電源電量百分比
由於暫時使用USB供電,所以實測電壓在3.20V,大於3V的都算100%電量。
因此讀出了默認值0x64,也就是電量100%。
七、相關問題
1、實測外部電壓2V時,對應爲10%的電量,偏差太大怎麼辦?
答:
1)實測2V、3V時的ADC值(假設測出2V對應爲287、3V對應爲425)。
2)修改宏定義(Battservice.c中)
- // ADC voltage levels
- #define BATT_ADC_LEVEL_3V 425//409
- #define BATT_ADC_LEVEL_2V 287//273