參考學習大神博客: http://blog.csdn.net/feilusia/article/details/51083953
: http://blog.csdn.net/xiaoleiacmer/article/details/41723583
1、TI 的 CC2540跑了一個 OSAL (Operating System Abstraction Layer)
心得:大概 就是 一個循環查看任務 是否 產生事件,產生就 處理事件,每個任務有16個事件,其實就是一個16位的宏定義,每一位代表一個事件,其中0x8000 是固定 的代表 SYS_EVENT_MSG。(這句話看不懂,可以往下看)
(sdk的安裝請百度,工程路徑:C:\Texas Instruments\BLE-CC254x-1.4.1.43908\Projects\ble\SimpleBLEObserver\CC2540DB)
2、在 TI 提供 的 SDK 中 ,打開 一個 觀察者工程,找到任務初始化的地方。(可通過 菜單->Edit->Find and Replace->Find in Files 這個全局查找 功能 進行找到這個函數osalInitTasks)
這里 有很多任務 的初始化 ,按順序執行,每個任務 有一個 對應 一個 事件處理函數(任務產任務生事件,就去執行這個事件處理函數),這句話很重要哦,一定要理解,記住。
任務列表:
任務對應的 事件處理 函數 :如下
3、前面的任務 都不管 ,現在我 們值關心 最后一個任務(因為這個任務 是 應用任務 ,TI 就是做這個任務 就是供我們使用的。)
/* Application */
SimpleBLEObserver_Init( taskID );
對應 的事件處理函數是:
SimpleBLEObserver_ProcessEvent( uint8 task_id, uint16 events );
4、先看看這個任務SimpleBLEObserver_Init的初始化都做了什么。
5、看看這個任務的 事件處理函數SimpleBLEObserver_ProcessEvent 都 做了什么。
6、我們要在這個應用任務中添加一個事件(定時處理某些事情,比如LED燈 比如定時檢測傳感器數據等等)做法如下。
第一步:在這個任務中,添加一個事件,名稱叫:(其實就是添加一個宏定義)
(因為事件 的變量(16位) 每一位代表一個事件,因此事件的可能值 只能是2^16,2^15,2^14,2^13,2^12,2^11,2048,1024,512,256, 128,64,32,16,8,4,2,1)
#define SBO_PERIODIC_EVT 0x0004//至於為啥是 0x0004 而不是0x0002 因為0x0002 已經存在了
添加結果如下:
第二步:在事件處理函數中,添加這個事件的處理:結果如下。
具體的 處理函數 如下:
/********************************************************************* * @fn performPeriodicTask 執行 周期 任務 * * @brief 輸出一個任務正在執行的語句。 * * 2017年4月17日13:57:35,GXP * * @param none * * @return none */ static void performPeriodicTask( void ) { printf("定時器任務正在運行。\r\n"); }
事件添加好了:怎么啟動這個事件 ,或者意思 是說怎么讓系統執行這個事件那。下面就講兩種方法:(我也就會這兩種目前,2017年4月17日20:24:25)
第一種方法:
把這個事件設置為就緒狀態,這樣下次輪詢任務時就會看這個應用任務 產生了一個 事件,具體調用的API 是
osal_set_event( task_id, SBO_PERIODIC_EVT);//第一個 參數是任務ID ,第二個參數是事件名稱。
因為我們這個事件 就是定時處理某些事情,因此要使用到系統的軟件定時器,第二個辦法就是使用系統軟件定時來啟動這個事件。
// Set timer for first periodic event
osal_start_timerEx( task_id, SBO_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );
下面 我 們 要 打開 CC2540 的 串口 ,進行收發數據: 參考博客: http://blog.csdn.net/feilusia/article/details/47431659
1、第一步 在 工程 的 屬性 里 ,添加 HAL_UART=TRUE,進行 使能 串口
2、添加頭文件(npi.c中), #include "OSAL.h"
3、新增兩個串口發送函數(npi.c中)
/********************************************************************* * @fn NPI_PrintString * * @brief 打印字符串 * * 2017年4月20日16:22:27,GXP * * @param str:字符串 * * @return none */ void NPI_PrintString(uint8 *str) { NPI_WriteTransport(str, osal_strlen((char*)str)); } /********************************************************************* * @fn NPI_PrintValue 打印指定的格式的數值 * * @brief 打印指定的格式的數值 * * 2017年4月20日16:22:27,GXP * * @param title:前綴字符串 * value:需要顯示的數值 * format:需要顯示的進制,10或16 * * @return none */ void NPI_PrintValue(char *title, uint16 value, uint8 format) { uint8 tmpLen; uint8 buf[128]; uint32 err; tmpLen = (uint8)osal_strlen( (char*)title ); osal_memcpy( buf, title, tmpLen ); buf[tmpLen] = ' '; err = (uint32)(value); _ltoa( err, &buf[tmpLen+1], format ); NPI_PrintString(buf); }
4、函數聲明(npi.h中)
extern void NPI_PrintValue(char *title, uint16 value, uint8 format); extern void NPI_PrintString(uint8 *str);
5、關閉低功耗模式,順便關掉 LCD,2017年4月20日16:39:44
6、因為要在simpleBLEObserver.c中調用 上面添加 的 兩個串口打印函數,因此 需要 在 simpleBLEObserver.c中 添加#include "npi.h"
#include "npi.h" //SuoZhang,ADD,2017年4月20日16:42:58
7、定義並聲明一個串口回調函數,在 simpleBLEObserver.c中,這個回調函數什么時候進入那?
答:
1)正常串口端無發送、無接收時,是不會進回調函數的。如果這種情況會進回調函數,TX、RX端外接上拉電阻穩定電平。
2)如果接收端有數據,立馬就會進回調。事件是“接收超時事件”。
3)2541 or 2540 發送端發送完數據,會進回調函數。事件是“發送緩沖區空事件”。
/********************************************************************* * @fn NPI_SerialCallback * * @brief 串口回調函數,2016年12月15日08:59:13,GXP * * 1、如果接收端有數據,立馬就會進回調。事件是“接收超時事件”。 * 2、2541 or 2540 發送端發送完數據,會進回調函數。事件是“發送緩沖區空事件”。 * * @param port: 串口1 還是串口2 * events: 事件類型(“接收超時事件”,“發送緩沖區空事件”) * * @return none */ static void NPI_SerialCallback( uint8 port, uint8 events ) { (void)port;//加個 (void),是未了避免編譯告警,明確告訴緩沖區不用理會這個變量 if (events & (HAL_UART_RX_TIMEOUT | HAL_UART_RX_FULL)) //串口有數據 { uint8 numBytes = 0; numBytes = NPI_RxBufLen(); //讀出串口緩沖區有多少字節 if(numBytes == 0) { return; } else { //申請緩沖區buffer uint8 *buffer = osal_mem_alloc(numBytes); if(buffer) { //讀取讀取串口緩沖區數據,釋放串口數據 NPI_ReadTransport(buffer,numBytes); //把收到的數據發送到串口-實現回環 NPI_WriteTransport(buffer, numBytes); //釋放申請的緩沖區 osal_mem_free(buffer); } } } }
8、添加上面 串口回調函數的聲明,simpleBLEObserver.c中
static void NPI_SerialCallback( uint8 port, uint8 events );//SuoZhang,ADD,2017年4月20日16:55:25
9、新增初始化代碼(simpleBLEObserver.c的SimpleBLEObserver_Init中)
/********************************************************************* * @fn SimpleBLEObserver_Init * * @brief Initialization function for the Simple BLE Observer App Task. * This is called during initialization and should contain * any application specific initialization (ie. hardware * initialization/setup, table initialization, power up * notification). * * @param task_id - the ID assigned by OSAL. This ID should be * used to send messages and set timers. * * @return none */ void SimpleBLEObserver_Init( uint8 task_id ) { simpleBLETaskId = task_id; //初始化串口0,作為串口打印數據使用,2017年4月20日16:57:31 { //注冊串口回調函數 NPI_InitTransport(NPI_SerialCallback); // 按長度輸出測試 //NPI_WriteTransport("SimpleBLETest_Init\r\n", 20); // 按字符串輸出 NPI_PrintString("SimpleBLEObserver_Init.\r\n"); // 可以輸出一個值,用10進制表示 NPI_PrintValue("測試10進制輸出 = ", 168, 10); NPI_PrintString("\r\n"); // 可以輸出一個值,用16進制表示 NPI_PrintValue("測試16進制輸出 = 0x", 0x88, 16); NPI_PrintString("\r\n"); } // Setup Observer Profile { uint8 scanRes = DEFAULT_MAX_SCAN_RES; GAPObserverRole_SetParameter ( GAPOBSERVERROLE_MAX_SCAN_RES, sizeof( uint8 ), &scanRes ); } // Setup GAP GAP_SetParamValue( TGAP_GEN_DISC_SCAN, DEFAULT_SCAN_DURATION ); GAP_SetParamValue( TGAP_LIM_DISC_SCAN, DEFAULT_SCAN_DURATION ); // Register for all key events - This app will handle all key events RegisterForKeys( simpleBLETaskId ); // makes sure LEDs are off HalLedSet( (HAL_LED_1 | HAL_LED_2), HAL_LED_MODE_OFF ); // Setup a delayed profile startup osal_set_event( simpleBLETaskId, START_DEVICE_EVT ); }
10、關閉流控(流控是用於防止串口阻塞的,需要多兩根線用於流控。),通常串口只使用三根線 TX,RX,GND, (npi.h中)
#if !defined( NPI_UART_FC ) #define NPI_UART_FC FALSE //TRUE #endif // !NPI_UART_FC
11、編譯並且接上串口0,波特率115200,結果如下:(不清楚問什么 漢子亂碼)