TI 26x2R1藍(lán)牙BLE開發(fā)板初體驗(yàn)及如何獲取RSSI

背景

本文主要工作為獲取穩(wěn)定的RSSI,以為下一步的藍(lán)牙信號(hào)穩(wěn)定性評(píng)測(cè),藍(lán)牙測(cè)距提供數(shù)據(jù)宜肉。

本文主要分為兩部分:

第一部分介紹TI開發(fā)板環(huán)境的安裝,基本使用翎碑,如何查找或?yàn)g覽TI資料的方法谬返,基本操作大多概略,一方面篇幅不至于過于龐大日杈,另一方面授不如授漁

第二部分介紹基于TI提供的一個(gè)sample工程進(jìn)行修改遣铝,實(shí)現(xiàn)定時(shí)獲取RSSI信號(hào)的功能佑刷,附源碼

大致采集了幾個(gè)距離的數(shù)據(jù),寫了個(gè)腳本大致分析一下酿炸,藍(lán)牙一致性真的不太好(iqoo手機(jī))

5米處的原始信號(hào)和濾波后信號(hào)對(duì)比圖

均值濾波all和卡爾曼濾波效果基本一致瘫絮,后續(xù)可專門寫一篇說明一下如何數(shù)據(jù)分析
不同距離下的藍(lán)牙RSSI靜態(tài)均值, 標(biāo)準(zhǔn)差和方差

第一部分 TI開發(fā)環(huán)境基本操作

TI屬于比較open的了,資料相對(duì)很齊全填硕,還有官方翻譯的中文可以看麦萤,相對(duì)友好,基本上都從官網(wǎng)獲取就好扁眯,只不過最近一只登錄失敗壮莹,無法獲取如SDK這些代碼及文檔,不知是不是中國(guó)郵箱都被禁了姻檀,解決方法:搜一搜垛孔,外部網(wǎng)站下一個(gè)即可。
開發(fā)板官方鏈接:LAUNCHXL-CC26X2R1 評(píng)估板 | TI.com.cn

藍(lán)牙開發(fā)板外觀

基本流程一 下載安裝

本部分僅列需要安裝的工具:

  1. TI CCS集成工具施敢,IDE,集成了瀏覽器狭莱,編譯器僵娃,燒錄器,調(diào)試器腋妙,調(diào)試串口等默怨,還是很方便的

  2. 開發(fā)板對(duì)應(yīng)的SDK,如我下載的當(dāng)前最新版本:simplelink_cc13xx_cc26xx_sdk_6_40_00_13

安裝完畢后重啟一下

Tips. 這兩個(gè)工具都很大骤素,選擇合適的位置安裝匙睹。

實(shí)際上這兩部,在SDK的文檔里也有济竹,但是先有雞還是先有蛋


SDK內(nèi)文檔--下載安裝基本操作

本步驟遇到的問題及解決方法

問題一痕檬,下載SDK賬號(hào)被禁

解決方法:外部搜一個(gè)

基本流程二 如何選擇合適自己的sample工程及導(dǎo)入

TI的SDK里面提供了很多sample工程,凡爾賽地說送浊,選擇多了梦谜,也是負(fù)擔(dān)。

文檔入口:<install dir>\simplelink_cc13xx_cc26xx_sdk_6_40_00_13\docs\

Tips. html的文檔袭景,還可以查找唁桩,非常方便,文檔寫得很細(xì)耸棒,花了功夫的荒澡,可以先大致瀏覽一下,用到哪部分的時(shí)候再精讀与殃。

1. 選擇合適的工程

以本文需求為例目尖,要讀取RSSI,安裝后的SDK里面牺陶,找到藍(lán)牙sample文檔缀皱,工程的差別,實(shí)際從名字能看出來重窟,具體也可以在文檔中找到介紹

如下:

樣例工程路徑

找到介紹的文檔,結(jié)合我們的需求,考慮選擇簡(jiǎn)單做從的sample:simple_peripheral辩棒,理由如下:

1. 需求中我們用手機(jī)查找并連接開發(fā)板,此時(shí)手機(jī)為主膨疏,開發(fā)板為從

2. 該工程中有調(diào)用觸發(fā)獲取RSSI接口的代碼一睁,方便參考使用

文檔總?cè)肟?/div>
BLE5協(xié)議棧快速使用入口
提供的samples介紹(實(shí)際例子比文檔里多佃却,應(yīng)該是沒更新上去)

2. 導(dǎo)入樣例工程

Project -> import 即可者吁,這里主要想說明一下幾點(diǎn)提示:

Tips. 導(dǎo)入后的樣例代碼,會(huì)復(fù)制一份到自己的workspace饲帅,修改SDK代碼是沒有作用的复凳,要修改自己workspace里面的代碼。

Tips. 看開發(fā)板代碼時(shí)灶泵,關(guān)注workspace目錄下復(fù)制過來的部分(APP)和SDK下協(xié)議棧源碼育八。

workspace目錄:(workspace目錄是自己建的,打開ccs的時(shí)候赦邻,會(huì)讓選擇工作空間目錄)
SDK目錄

3. 編譯調(diào)試

先編譯髓棋,load調(diào)試一把,保證基礎(chǔ)工程及環(huán)境OK惶洲,手機(jī)可以下載一個(gè)nrf connect APK按声,方便連接調(diào)試。

調(diào)試:USB口插上板子恬吕,CCS IDE里選擇工程签则,點(diǎn)擊debug圖標(biāo) ,load完后需要手動(dòng)點(diǎn)擊運(yùn)行鍵運(yùn)行

Tips. 每次點(diǎn)擊debug币呵,會(huì)編譯一把(增量編譯怀愧,除第一次外,速度還是很快的)余赢,但是如果勾選了后臺(tái)運(yùn)行芯义,編譯即使失敗,也會(huì)執(zhí)行l(wèi)oad 操作妻柒,會(huì)有自己的修改沒生效的假象扛拨。凡是不合理的事情,總有原因举塔,大膽假設(shè)绑警,小心求證即可求泰。

查看:ccs帶了串口工具,選擇 view -> terminal计盒,波特率115200渴频,啟動(dòng)會(huì)有日志

串口配置

4. 修改代碼,定時(shí)獲取藍(lán)牙RSSI

大約修改十幾處北启,新增100行代碼即可完成卜朗,吐槽一句,TI的樣例代碼比較無拘束咕村,各種全局變量场钉,讓人看了就忍不住要重構(gòu)。

背景知識(shí)及設(shè)計(jì)思路:藍(lán)牙連接后懈涛,鏈路層主從設(shè)備之間逛万,是會(huì)通過連接事件進(jìn)行交互的,從個(gè)人的設(shè)想上注冊(cè)該事件的回調(diào)即可實(shí)現(xiàn)定時(shí)獲取RSSI批钠;但實(shí)際上沒找到如何通過注冊(cè)獲取RSSI的例子或接口(后續(xù)如果找到了補(bǔ)充該方法)宇植,因此通過定時(shí)主動(dòng)調(diào)用HCI接口獲取RSSI。

另外埋心,我們能獲取到的RSSI的頻率当纱,并不一定就是我們觸發(fā)的次數(shù),如果觸發(fā)過于頻繁踩窖,可能獲取到連續(xù)幾個(gè)一樣的RSSI值。這是由于RSSI的底層測(cè)量晨横,也是要基于主從設(shè)備鏈路層之間交換報(bào)文來實(shí)現(xiàn)的洋腮,正常至少有連接事件即可測(cè)量到,這里和連接的間隔手形,延時(shí)事件配置都有關(guān)聯(lián)啥供,這些參數(shù)是由主機(jī)側(cè)(我們的場(chǎng)景,主機(jī)是手機(jī)库糠,nrf connect軟件設(shè)置了三種模式伙狐,可以根據(jù)自己需求選擇,我們這里選擇最高優(yōu)先級(jí)瞬欧,零延遲贷屎,最小最大間隔15ms,即12個(gè)1.25ms)

代碼中收到主機(jī)請(qǐng)求調(diào)整連接設(shè)置請(qǐng)求后下發(fā)到控制器

設(shè)計(jì)思路:通過增加一個(gè)定時(shí)任務(wù)艘虎,遍歷連接句柄列表(connList)中所有連接去定時(shí)觸發(fā)調(diào)用HCI_ReadRssiCmd異步接口唉侄,上報(bào)RSSI事件,利用當(dāng)前simple_peripheral樣例工程處理協(xié)議棧事件的線程已實(shí)現(xiàn)異步獲取RSSI的功能野建,修改一下打印格式即可属划。

當(dāng)前simple_peripheral樣例工程實(shí)現(xiàn)架構(gòu):跟蹤解析 協(xié)議棧事件 -> 解析狀態(tài) -> 解析命令碼 -> HCI_READ_RSSI 命令碼下執(zhí)行RSSI打印輸出

定時(shí)器也參照樣例中Clock_Struct模塊恬叹,新建一個(gè)定時(shí)時(shí)鐘即可。

時(shí)鐘模塊可參看文檔

時(shí)鐘模塊文檔

Tips. 不可直接在時(shí)鐘回調(diào)函數(shù)中執(zhí)行HCI命令同眯,可能與處理協(xié)議棧事件的線程沖突導(dǎo)致掛死绽昼,用事件方式放到一個(gè)線程中處理(樣例已實(shí)現(xiàn),此處只需新增事件id和實(shí)現(xiàn)即可)须蜗。

遍歷connList進(jìn)行觸發(fā)
串口打印

Tips. 關(guān)于如何學(xué)習(xí)藍(lán)牙開發(fā)的過程硅确,文檔中也有建議

image

Tips. 關(guān)于如何使用,文檔里非常仔細(xì)唠粥,一步步手把手了

學(xué)習(xí)建議

相關(guān)網(wǎng)站

TI論壇:https://e2echina.ti.com/

附件

基于樣例工程修改的代碼匯總疏魏,文件太大,放一下diff吧

--- simple_peripheral.c 2022-12-20 00:51:10.000000000 +0800
+++ ../simple_peripheral.c  2023-02-19 20:50:30.442816500 +0800
@@ -90,11 +90,10 @@
 #include "npi_task.h"               // To allow RX event registration
 #include "npi_ble.h"                // To enable transmission of messages to UART
 #include "icall_hci_tl.h"   // To allow ICall HCI Transport Layer
 #endif // PTM_MODE
 
-
 /*********************************************************************
  * MACROS
  */
 
 /*********************************************************************
@@ -119,10 +118,11 @@
 #define SP_PASSCODE_EVT                      5
 #define SP_PERIODIC_EVT                      6
 #define SP_READ_RPA_EVT                      7
 #define SP_SEND_PARAM_UPDATE_EVT             8
 #define SP_CONN_EVT                          9
+#define SP_GET_RSSI_EVT                      10
 
 // Internal Events for RTOS application
 #define SP_ICALL_EVT                         ICALL_MSG_EVENT_ID // Event_Id_31
 #define SP_QUEUE_EVT                         UTIL_QUEUE_EVENT_ID // Event_Id_30
 
@@ -373,11 +373,11 @@
 static void SimplePeripheral_processConnEvt(Gap_ConnEventRpt_t *pReport);
 #ifdef PTM_MODE
 void simple_peripheral_handleNPIRxInterceptEvent(uint8_t *pMsg);  // Declaration
 static void simple_peripheral_sendToNPI(uint8_t *buf, uint16_t len);  // Declaration
 #endif // PTM_MODE
-
+static void getRssiCycleTaskInit(void); // add myn
 /*********************************************************************
  * EXTERN FUNCTIONS
  */
 extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
 
@@ -524,10 +524,11 @@
 
   // Create one-shot clock for internal periodic events.
   Util_constructClock(&clkPeriodic, SimplePeripheral_clockHandler,
                       SP_PERIODIC_EVT_PERIOD, 0, false, (UArg)&argPeriodic);
 
+  getRssiCycleTaskInit(); // add by myn
   // Set the Device Name characteristic in the GAP GATT Service
   // For more information, see the section in the User's Guide:
   // http://software-dl.ti.com/lprf/ble5stack-latest/
   GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
 
@@ -616,10 +617,11 @@
   SimplePeripheral_initPHYRSSIArray();
 
   // The type of display is configured based on the BOARD_DISPLAY_USE...
   // preprocessor definitions
   dispHandle = Display_open(Display_Type_ANY, NULL);
+  // dispHandle = Display_open(Display_Type_UART, NULL); // myn  實(shí)際我們使用物理uart晤愧,配置UART也可以
 
   // Initialize Two-Button Menu module
   TBM_SET_TITLE(&spMenuMain, "Simple Peripheral");
   tbm_setItemStatus(&spMenuMain, TBM_ITEM_NONE, TBM_ITEM_ALL);
 
@@ -727,11 +729,10 @@
 {
   // Always dealloc pMsg unless set otherwise
   uint8_t safeToDealloc = TRUE;
 
   BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : Stack msg status=%d, event=0x%x\n", pMsg->status, pMsg->event);
-
   switch (pMsg->event)
   {
     case GAP_MSG_EVENT:
       SimplePeripheral_processGapMessage((gapEventHdr_t*) pMsg);
       break;
@@ -763,10 +764,11 @@
           hciEvt_CommandStatus_t *pMyMsg = (hciEvt_CommandStatus_t *)pMsg;
           switch ( pMyMsg->cmdOpcode )
           {
             case HCI_LE_SET_PHY:
             {
+#if 0 // myn
               if (pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE)
               {
                 Display_printf(dispHandle, SP_ROW_STATUS_1, 0,
                         "PHY Change failure, peer does not support this");
               }
@@ -774,10 +776,11 @@
               {
                 Display_printf(dispHandle, SP_ROW_STATUS_1, 0,
                                "PHY Update Status Event: 0x%x",
                                pMyMsg->cmdStatus);
               }
+#endif
 
               SimplePeripheral_updatePHYStat(HCI_LE_SET_PHY, (uint8_t *)pMsg);
               break;
             }
 
@@ -794,10 +797,11 @@
             (hciEvt_BLEPhyUpdateComplete_t*) pMsg;
 
           // A Phy Update Has Completed or Failed
           if (pPUC->BLEEventCode == HCI_BLE_PHY_UPDATE_COMPLETE_EVENT)
           {
+#if 0 // myn
             if (pPUC->status != SUCCESS)
             {
               Display_printf(dispHandle, SP_ROW_STATUS_1, 0,
                              "PHY Change failure");
             }
@@ -809,11 +813,11 @@
                              "PHY Updated to %s",
                              (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_1M) ? "1M" :
                              (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_2M) ? "2M" :
                              (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_CODED) ? "CODED" : "Unexpected PHY Value");
             }
-
+#endif
             SimplePeripheral_updatePHYStat(HCI_BLE_PHY_UPDATE_COMPLETE_EVENT, (uint8_t *)pMsg);
           }
           break;
         }
 
@@ -900,10 +904,76 @@
 
   // It's safe to free the incoming message
   return (TRUE);
 }
 
+/**
+ * @brief Add by nansen.Mo, foreach every handle to read rssi back
+ * 
+*/
+static void TriggerAllValidConnectRssiRead(void)
+{
+  static unsigned int count = 0;
+  count++;
+  for (uint8_t index = 0; index < MAX_NUM_BLE_CONNS; index++) {
+    if (connList[index].connHandle == SP_INVALID_HANDLE) {
+      continue;
+    }
+
+    int ret = HCI_ReadRssiCmd(connList[index].connHandle);
+    // Display_printf(dispHandle, SP_ROW_RPA, 0, "myn %d Read the RSSI for 0, ret = %d", count, ret);
+  }
+}
+/**
+ * @brief Add by myn for clock, task by cycle
+ * 
+ * @param arg 
+ */
+
+#define GET_RSSI_PERIODIC_EVT_PERIOD 200 // (in ms)
+// #define GET_RSSI_PERIODIC_EVT 1
+
+// Clock instances for internal periodic events.
+static Clock_Struct getRssiClkPeriodic; // myn
+
+spClockEventData_t getRssiEventList =
+{ .event = SP_GET_RSSI_EVT };
+/*
+Step 2 in Triggering Clock objects, after the Clock object’s timer expired, 
+       it will execute Application_clockHandler() within a Swi context. 
+      As this call cannot be blocked and blocks all Tasks, 
+      it is kept short by invoking an Event_post(APP_PERIODIC_EVT) for post processing in the application task.
+*/
+static void GetRssiApplication_clockHandler(UArg arg)
+{
+    spClockEventData_t *pData = (spClockEventData_t *)arg;
+    if (pData->event == SP_GET_RSSI_EVT) {
+      // Start the next period
+      Util_startClock(&getRssiClkPeriodic);
+      SimplePeripheral_enqueueMsg(SP_GET_RSSI_EVT, NULL);
+    }
+}
+
+static void GetRssiClkPeriodicStart(void)
+{
+  static int getRssiClkStarted = 0;
+  if (getRssiClkStarted == 0) {
+    Util_startClock(&getRssiClkPeriodic);
+    getRssiClkStarted = 1;
+  }
+}
+/* Step 1 in Triggering Clock objects constructs the Clock object using the Clock_construct API. 
+   When the application desires, it will then start the Clock object via the Clock_start() API. 
+   */
+
+static void getRssiCycleTaskInit(void)
+{
+  // Create one-shot clocks for internal periodic events.
+  Util_constructClock(&getRssiClkPeriodic, GetRssiApplication_clockHandler,
+      GET_RSSI_PERIODIC_EVT_PERIOD, 0, false, (UArg)&getRssiEventList);
+}
+
 /*********************************************************************
  * @fn      SimplePeripheral_processAppMsg
  *
  * @brief   Process an incoming callback from a profile.
  *
@@ -921,11 +991,11 @@
   }
   else
   {
     BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : App msg status=%d, event=0x%x\n", 0, pMsg->event);
   }
-
+  // Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "myn pMsg->event: %d", pMsg->event);
   switch (pMsg->event)
   {
     case SP_CHAR_CHANGE_EVT:
       SimplePeripheral_processCharValueChangeEvt(*(uint8_t*)(pMsg->pData));
       break;
@@ -968,10 +1038,14 @@
 
     case SP_CONN_EVT:
       SimplePeripheral_processConnEvt((Gap_ConnEventRpt_t *)(pMsg->pData));
       break;
 
+    case SP_GET_RSSI_EVT:
+      // myn Trigger rssi read for all valid connect
+      TriggerAllValidConnectRssiRead();
+      break;
     default:
       // Do nothing.
       break;
   }
 
@@ -1112,16 +1186,19 @@
         SimplePeripheral_addConn(pPkt->connectionHandle);
 
         // Display the address of this connection
         Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Connected to %s",
                        Util_convertBdAddr2Str(pPkt->devAddr));
-
+        Display_printf(dispHandle, SP_ROW_DEBUG, 0, "\nmyn Connected to %s, handle=0x%x\n",
+                       Util_convertBdAddr2Str(pPkt->devAddr), pPkt->connectionHandle);
         // Enable connection selection option
         tbm_setItemStatus(&spMenuMain, SP_ITEM_SELECT_CONN,SP_ITEM_AUTOCONNECT);
 
         // Start Periodic Clock.
         Util_startClock(&clkPeriodic);
+
+        GetRssiClkPeriodicStart();
       }
       if ((numActive < MAX_NUM_BLE_CONNS) && (autoConnect == AUTOCONNECT_DISABLE))
       {
         // Start advertising since there is room for more connections
         GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
@@ -1181,10 +1258,13 @@
 
       // Only accept connection intervals with slave latency of 0
       // This is just an example of how the application can send a response
       if(pReq->req.connLatency == 0)
       {
+        Display_printf(dispHandle, SP_ROW_DEBUG, 0, 
+                      "myn GAP_UPDATE_LINK_PARAM_REQ_EVENT, 0x%x, 0x%x, 0x%x, 0x%x\n",
+                      pReq->req.intervalMin, pReq->req.intervalMax, pReq->req.connLatency, pReq->req.connTimeout);
         rsp.intervalMin = pReq->req.intervalMin;
         rsp.intervalMax = pReq->req.intervalMax;
         rsp.connLatency = pReq->req.connLatency;
         rsp.connTimeout = pReq->req.connTimeout;
         rsp.accepted = TRUE;
@@ -1205,11 +1285,11 @@
       gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg;
 
       // Get the address from the connection handle
       linkDBInfo_t linkInfo;
       linkDB_GetInfo(pPkt->connectionHandle, &linkInfo);
-
+#if 0 // myn
       if(pPkt->status == SUCCESS)
       {
         // Display the address of the connection update
         Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Link Param Updated: %s",
                        Util_convertBdAddr2Str(linkInfo.addr));
@@ -1219,11 +1299,11 @@
         // Display the address of the connection update failure
         Display_printf(dispHandle, SP_ROW_STATUS_2, 0,
                        "Link Param Update Failed 0x%x: %s", pPkt->opcode,
                        Util_convertBdAddr2Str(linkInfo.addr));
       }
-
+#endif
       // Check if there are any queued parameter updates
       spConnHandleEntry_t *connHandleEntry = (spConnHandleEntry_t *)List_get(&paramUpdateList);
       if (connHandleEntry != NULL)
       {
         // Attempt to send queued update now
@@ -1757,10 +1837,11 @@
 static void SimplePeripheral_processConnEvt(Gap_ConnEventRpt_t *pReport)
 {
   // Get index from handle
   uint8_t connIndex = SimplePeripheral_getConnIndex(pReport->handle);
 
+  Display_printf(dispHandle, SP_ROW_DEBUG, 0, "myn pReport->handle, connIndex = %d\n", connIndex);
   if (connIndex >= MAX_NUM_BLE_CONNS)
   {
     Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Connection handle is not in the connList !!!");
     return;
   }
@@ -2254,16 +2335,26 @@
               }
 
             } // end of if ((phyRq != SP_PHY_NONE) && ...
           } // end of if (connList[index].phyCngRq == FALSE)
         } // end of if (rssi != LL_RSSI_NOT_AVAILABLE)
-
+#if 0 // myn
         Display_printf(dispHandle, SP_ROW_RSSI, 0,
                        "RSSI:%d dBm, AVG RSSI:%d dBm",
                        (uint32_t)(rssi),
                        connList[index].rssiAvg);
-
+#else // myn
+        static unsigned int receivedRssiCount = 0;
+        if (rssi != LL_RSSI_NOT_AVAILABLE) {
+          receivedRssiCount++;
+          Display_printf(dispHandle, SP_ROW_RSSI, 0,
+                        " nansen.mo RSSI:%d dBm, AVG RSSI:%d dBm, count: %u\n",
+                        (uint32_t)(rssi),
+                        connList[index].rssiAvg,
+                        receivedRssiCount);
+        }
+#endif // myn
      } // end of if (status == SUCCESS)
       break;
     }
 
     case HCI_LE_READ_PHY:
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末大莫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子官份,更是在濱河造成了極大的恐慌只厘,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舅巷,死亡現(xiàn)場(chǎng)離奇詭異羔味,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)钠右,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門赋元,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人飒房,你說我怎么就攤上這事搁凸。” “怎么了狠毯?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵护糖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我嚼松,道長(zhǎng)嫡良,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任献酗,我火速辦了婚禮寝受,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘罕偎。我一直安慰自己羡蛾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著痴怨,像睡著了一般忙干。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浪藻,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天捐迫,我揣著相機(jī)與錄音,去河邊找鬼爱葵。 笑死施戴,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的萌丈。 我是一名探鬼主播赞哗,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼辆雾!你這毒婦竟也來了肪笋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤度迂,失蹤者是張志新(化名)和其女友劉穎藤乙,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惭墓,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坛梁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了腊凶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片划咐。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖钧萍,靈堂內(nèi)的尸體忽然破棺而出尖殃,到底是詐尸還是另有隱情,我是刑警寧澤划煮,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站缔俄,受9級(jí)特大地震影響弛秋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜俐载,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一蟹略、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧遏佣,春花似錦挖炬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)馅巷。三九已至,卻和暖如春草姻,著一層夾襖步出監(jiān)牢的瞬間钓猬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工撩独, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留敞曹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓综膀,卻偏偏與公主長(zhǎng)得像澳迫,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子剧劝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

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