CC2540 OSAL 學習其中原理,以及 給任務 添加 一個事件(定時發送串口消息)


參考學習大神博客: 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,結果如下:(不清楚問什么 漢子亂碼)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM