Lab3 : 自行車碼表 - 點燈比實驗難

多圖殺貓。實驗環境為Windows。

咳咳,本次實驗感覺環境好難配啊,實驗倒是感覺起來容易一些(果然有攻略就是舒服)

實驗準備 - 點燈

1. STM32CubeMX

接下來把文末下載區的幾個全部先下載下來備用。

首先安裝主程序STM32CubeMX,就一路下一步下一步下一步就好了,看得懂的比如說安裝目錄之類的改一下就好了,不需要防備360安全套餐、百度全家桶等。

打開程序之后界面長這樣。

STM32CubeMX

萌新上來什么都不懂,跟著教程直接新建工程,選擇了核心板的型號STM32F103C8之后直接點OK。

new project

點擊Project選項卡中的setting,進入到項目設置。填寫完項目名稱、位置以及工具鏈。在圖中,我選的是MDK-ARM V5,下載列表中有相關工具下載(Keil)。

Project Settings

全部設置好之后,點擊下方OK按鈕。說時遲那時快,只聽砰的一聲,一個討厭的警示框跳出來了。告訴我們,有個依賴沒有滿足。

找不到依賴啊找不到

此時可以直接點擊Yes開啟自動下載模式,全自動安裝,你值得擁有!

下載中 ...

但是由于各種原因斷在70M這個位置兩次之后我心灰意冷選擇放棄,各種查找資料之后發現還可以進行本地安裝。

首先是從Help選型卡中的Install New Libraries進入庫管理界面。

進入Libraries Manager

此時,左下角有一個** From Local ... **按鈕,將下載的V1.3.0包以及V1.3.1補丁順序打入即可。安裝完畢后可以看到安裝的是當前最新版本。

Libraries Manager

接下來為了點亮小燈,需要找一個引腳輸出高電平形成電流。在此,我選擇將PA9接口置為GPIO_Output模式。多說一句,實際上這個地方的配置不是必須的,因為這里的配置最終也是由MX轉譯成為C的代碼,而在Keil中才是真正的編譯,即可以在代碼中直接編寫相應的流程。不過,話說回來,能自動干的東西為啥要碼代碼。

引腳設置

而后,點擊代碼生成按鈕。

生成按鈕

生成結束后后會在項目的文件夾下生成一個由設置所決定的工程文件夾。而Open Project目前點了還沒有作用,因為還沒有裝相應的軟件。

Code Generation

至此,STM32CubeMX的流程就結束了。

2. Keil

STM32CubeMX生成出了整個工程的目錄,但是需要一個軟件將其打開。我選擇使用Keil v5(其實是先選的v5,上面的Project Setting中有設置)。

Keil的安裝就沒有上面那個這么麻煩,直接下一步下一步下一步,注冊碼也有注冊機直接可以搞定。過程一如參考資料里的安裝教程。

話接上集,直接點擊Open Project按鈕,打開項目工程文件。中間還會需要安裝一個依賴包,繼續同意即可。

可以從圖中看到,STM32CubeMX已經幫我們生成好了一系列的基礎文件,從中進行修改以滿足我們的要求即可。

項目結構

由于我們在MX中已經有進行過設置,修改了PA9為輸出引腳,在代碼中就得到了體現。下方即為生成的GPIO初始化代碼。

自動生成的GPIO初始化代碼

main函數中調用了GPIO初始化函數之后,PA9就開始持續輸出高電平。而為了讓小燈閃爍,自然不能一直高電平下去,而是需要輸出一個矩形波。

閃爍代碼

至此,代碼已經全部寫完。而在下載之前,需要在Flash -> Configure Flash Tools -> Utilities中,將Use Debug Driver的勾去掉,轉而使用ST-LINK V/2。

配置圖

按F7進行模塊編譯,按F8下載到板子吧!

值得一提的是,下載之后,并不會立刻有反應。而是需要斷電重啟或者使用板子上帶的RST按鈕進行重置之后程序才會正式開始運行。

注意注意,我圖中是將小燈直接連入GND以及VCC,但是有的小燈比較脆弱,這么做會直接燒掉。所以穩妥的做法應該在連接電路中再加一個電阻。s

小燈直接接入GND及3.3V
小燈閃爍

實驗步驟

0. 連接圖

按照Lab3攻略上說的連好圖,先假裝自己連對了確實連對了。

其中,ST-LINK接四根線3.3V、GND、SWDIO、SWCLK分別對應STM32板子上的3.3V、GND、DIO、DCLK。此為燒錄用的線路。而PA9、PA10為串口通信所用的線路。所以圖中使用了兩個USB口。

面包板上線的連接方式為從引腳出來之后經過按鈕到GND。

連接圖

1. UART串口輸出

首先進入STM32CubeMX。按照實驗中的要求,在右側芯片設置中,將PA12、PA11定為輸入(接按鈕),PA10、PA9分別定為TX、RX(接電腦串口)。

引腳配置

同時,在左側的配置中,將USART1的模式定為Half-Duplex。這步所對應生成的代碼與實驗攻略中的代碼略有差別。但是在不指定模式的情況下,PA9以及PA10會被認為是GPIO_Output而與PA11一起進行初始化,而不是TX、RX口。所以在此選擇一個模式。

USART1半雙工模式

配置完畢,接下來是代碼生成,點擊按鈕靜靜等待即可。

少女祈禱中。。。

代碼生成完之后,基本的函數已經都有了。但是還需要自己手動填寫一些代碼,如UART0_Init()等。而stm32f1xx_hal_msp.c中所需填寫的函數與Half-Duplex模式一致,所以不需要進行大幅度改動。只需要將攻略的幾行代碼填入即可。

void UART0_Init(UART_HandleTypeDef* UartHandle){
    UartHandle->Instance = USART1;
    UartHandle->Init.BaudRate = 9600;
    UartHandle->Init.WordLength = UART_WORDLENGTH_8B;
    UartHandle->Init.StopBits = UART_STOPBITS_1;
    UartHandle->Init.Parity = UART_PARITY_NONE;
    UartHandle->Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UartHandle->Init.Mode = UART_MODE_TX_RX;
    
    HAL_UART_Init(UartHandle);
}

int main(void) {
...
    UART_HandleTypeDef UartHandle;
    UART0_Init(&UartHandle);

    while (1) {
        HAL_UART_Transmit(&UartHandle, (uint8_t*)"press\r\n", 7, 500);
        HAL_Delay(100); 
    }
}

HAL_UART_Transmit有4個參數,第一個參數是串口的句柄,第二個參數是一個二進制數組(char*),第三個參數是要發送的數據長度,第四個是發送超時的判定時間。

運行結果

2. 接入開關

在0中已經將線連好。

3. 檢測按鈕被按下

由于按鈕接地,所以,當按鈕被按下時,PA11應該可以檢測到一個低電平的輸入。編寫程序的時候,可以根據這一點,讀取PA11的引腳值,并據此判斷。

但是,在實驗過程中結果并不理想。測試結果如下。

PA11引腳讀取

注意到按鈕的狀態是不斷變化的,而我并沒有去接觸按鍵。這種情況可能是由于電路本身不精密所導致的。~~~~(Update:做了第4項實驗之后,發現同樣的接法PA12沒問題,看來主要是因為按鈕的問題才導致了抖動)(Update: 突然覺得可能是面包板的問題)

硬件難改,但實驗也不能這么停止。仿照計算機組成實驗的思想,嘗試著使用按鍵防抖動的方法檢測按鍵是否被按下。具體方法是檢測按鍵被穩定按下某幾個周期之后,才表示真正檢測到了按鍵事件。

但是實際測試結果并不理想,由圖可以看出。我依然沒有按任何的按鍵,而串口卻一直有輸出。

按鍵防抖動

思考了一下,發現可能是由于兩次檢測時間間隔太短,導致跳變的引腳值被記錄多次。此時,使用延時檢測即可,即兩次檢測之間間隔拉大。

下方代碼為最終版本,即加了anti_jitter即HAL_Delay的結果。

#define MAX_BITCOUNT 0xff
#define CHECK_DELAY 10

void anti_jitter(int *bitcount, int state){
    *bitcount <<= 1;
    *bitcount &= MAX_BITCOUNT;
    *bitcount += state & 1;
}

int main(void)
{
    int total, bitcount;
    char str[64];
    int send = 0;
// something for initialization.
    total = 0; bitcount = MAX_BITCOUNT ;
    while (1) {
        int cnt;
        GPIO_PinState state;
        state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
        HAL_Delay(CHECK_DELAY);
        anti_jitter(&bitcount, state);
        if (bitcount == 0){
            if (!send){
                send = 1;
                total++;
                cnt = sprintf(str, "Press 11 %d times\r\n", total);
                HAL_UART_Transmit(&UartHandle, (uint8_t*)str, cnt, 500);
            }
        }else{
            send = 0;
        }
    }
}

最終代碼能夠做到無誤檢測,同時在按鍵被按下之后,響應時間較短。

PA11按鈕事件

4. PA12中斷響應

PA12引腳的下降沿觸發將會觸發中斷,進入函數EXTI15_10_IRQHandler,此時在函數中調用HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12)表示查看PA12的值,如果符合條件,則觸發HAL_GPIO_EXTI_Callback函數。

在callback函數中,將檢測標志位置1即可被while循環中的if識別并輸出。代碼如下。


// ---------- stm32f1xx_it.c ---------- 
void EXTI15_10_IRQHandler(void){
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
}

//  ---------- main.c ---------- 
void NVIC_Init(){
    // 使能中斷
    HAL_NVIC_SetPriority(EXTI15_10_IRQn,0,0);
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}

int PA12count = 0, PA12flag = 0;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    if (GPIO_Pin == GPIO_PIN_12){
        PA12flag = 1;
        PA12count ++;
    }else{
        UNUSED(GPIO_Pin);
    }
}

int main(void) {
    int total, bitcount;
    char str[64];
    int send = 0;
    NVIC_Init();
......
    while (1) {
        int cnt;
......
        if (PA12flag == 1){
            PA12flag = 0;
            cnt = sprintf(str, "Press 12 %d times\r\n", PA12count);
            HAL_UART_Transmit(&UartHandle, (uint8_t*)str, cnt, 500);    
        }
    }
}

void MX_GPIO_Init(void) {
......  
  GPIO_InitStruct.Pin = GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
......
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
中斷響應

5. 定時器中斷

定時器中斷的實現思路與引腳涉及的中斷基本一致。不同的是需要設置中斷觸發的時間。因為不同于外部中斷,時鐘中斷是內部觸發,所以需要預先設定好觸發時間。

而后,同樣的,需要覆寫中斷觸發函數TIM3_IRQHandler,而后在其中對時鐘進行判斷后觸發HAL_TIM_PeriodElapsedCallback。并在callback中真正處理邏輯。


// ---------- stm32f1xx_hal_msp.c ---------- 

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim){
    __TIM3_CLK_ENABLE();
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htime){
    __TIM3_CLK_DISABLE();
}

// main.c

void NVIC_Init(){
...
    HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM3_IRQn);
}

TIM_HandleTypeDef TIM_Handle;

int TIMflag = 0;
void TIM3_IRQHandler(void){
    HAL_TIM_IRQHandler(&TIM_Handle);
}

void TIM_Init(){
    TIM_Handle.Instance = TIM3;
    TIM_Handle.Init.Prescaler = 8000;
    TIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    TIM_Handle.Init.Period = 199;
    HAL_TIM_Base_Init(&TIM_Handle);
    HAL_TIM_Base_Start_IT(&TIM_Handle);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
    TIMflag = 1;
}

int main(void){
......
    total = 0; bitcount = MAX_BITCOUNT;
    while (1) {
        int cnt;
        GPIO_PinState state;

        HAL_Delay(CHECK_DELAY);
        state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
        anti_jitter(&bitcount, state);  
        if (bitcount == 0){
            if (send != 2){
                send = 1;
            }
        }else if (send == 2){
            send = 0;
        }
        if (TIMflag == 1){
            TIMflag = 0;
            if (send == 1){
                send = 2;
                total++;
                cnt = sprintf(str, "Press 11 %d times\r\n", total);
                HAL_UART_Transmit(&UartHandle, (uint8_t*)str, cnt, 500);
            }
            if (PA12flag == 1){
                PA12flag = 0;
                cnt = sprintf(str, "Press 12 %d times\r\n", PA12count);
                HAL_UART_Transmit(&UartHandle, (uint8_t*)str, cnt, 500);            
            }
        }
    }
}

定時器中斷

6. 自行車碼表

碼表有兩個模式,里程模式以及速度模式,兩個模式有區別也有聯系。

首先是最基礎的里程模式,該模式只對應PA12按鈕的事件。在每次PA12被按下(輪子走了一圈)的時候算好里程即可,或者使用圈數*輪子周長的方式也行。在本程序中,將輪子周長表示為3.14m。

其次是速度模式。速度模式不能單單使用總里程/總時間,這樣得到的總速度是沒有意義的,而近似實時的速度計算法應該是通過計算在一定時間內所行駛的里程數推算出短時間內的速度。在本程序中,使用1.6s作為計算的時間長度,即8個周期。

里程模式
速度模式

代碼清單
main.c


#define MAX_BITCOUNT 0xff
#define CHECK_DELAY 10
#define PERIMETER 3.14

UART_HandleTypeDef UartHandle;
TIM_HandleTypeDef TIM_Handle;
int cnt;
int total, bitcount, dispMode = 0;
int PA12count = 0, PA12flag = 0;
int TIMflag = 0, TIMcount = 0;
float RouteTick[10];
char str[64];
int send = 0;

void UART0_Init(){
    UartHandle.Instance = USART1;
    UartHandle.Init.BaudRate = 9600;
    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
    UartHandle.Init.StopBits = UART_STOPBITS_1;
    UartHandle.Init.Parity = UART_PARITY_NONE;
    UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UartHandle.Init.Mode = UART_MODE_TX_RX;
    
    HAL_UART_Init(&UartHandle);
}

void NVIC_Init(){
    HAL_NVIC_SetPriority(EXTI15_10_IRQn,0,0);
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
    HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM3_IRQn);
}

void anti_jitter(int *bitcount, int state){
    *bitcount <<= 1;
    *bitcount &= MAX_BITCOUNT;
    *bitcount += state & 1;
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    if (GPIO_Pin == GPIO_PIN_12){
        PA12flag = 1;
        PA12count ++;
    }else{
        UNUSED(GPIO_Pin);
    }
}

void EXTI15_10_IRQHandler(void){
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
}

void TIM3_IRQHandler(void){
    HAL_TIM_IRQHandler(&TIM_Handle);
}

void TIM_Init(){
    TIM_Handle.Instance = TIM3;
    TIM_Handle.Init.Prescaler = 8000;
    TIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    TIM_Handle.Init.Period = 199;
    HAL_TIM_Base_Init(&TIM_Handle);
    HAL_TIM_Base_Start_IT(&TIM_Handle);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
    TIMflag = 1;
    TIMcount++;
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
    UART0_Init();
    NVIC_Init();
    TIM_Init();
    total = 0; bitcount = MAX_BITCOUNT;
    dispMode = 0;
    while (1) {
        int cnt;
        GPIO_PinState state;
        HAL_Delay(CHECK_DELAY);
        state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
        anti_jitter(&bitcount, state);  
        if (bitcount == 0){
            send = 1;
        }else{
            if (send == 2){
                send = 0;
            }
        }
        if (send == 1){
            send = 2;
            dispMode = 1 - dispMode;
        }
        if (TIMflag == 1){
            int head = (TIMcount - 1) % 8;
            int nexHead = (head + 1) % 8;
            float route = PA12count * PERIMETER;
            RouteTick[head] = route;
            TIMflag = 0;
            if (dispMode == 0){
                cnt = sprintf(str, "You traveled %.2f m\r\n", route);
            }else{
                float inThisTime = RouteTick[head] - RouteTick[nexHead];
                cnt = sprintf(str, "You traveled in %.2f m/s\r\n", inThisTime / 1.6);
            }
            HAL_UART_Transmit(&UartHandle, (uint8_t*)str, cnt, 500);
        }
    }
}

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pins : PA11 PA12 */
  GPIO_InitStruct.Pin = GPIO_PIN_11;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
  GPIO_InitStruct.Pin = GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

stm32f1xx_hal_msp.c

void HAL_MspInit(void)
{
  __HAL_RCC_AFIO_CLK_ENABLE();
    
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  /* System interrupt init*/
  /* MemoryManagement_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0);
  /* BusFault_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0);
  /* UsageFault_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0);
  /* DebugMonitor_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0);
  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim){
    __TIM3_CLK_ENABLE();
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim){
    __TIM3_CLK_DISABLE();
}

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==USART1)
  {
    __HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
      
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }

}

void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{

  if(huart->Instance==USART1)
  {
    __HAL_RCC_USART1_CLK_DISABLE();
    __HAL_RCC_USART1_FORCE_RESET();
    __HAL_RCC_USART1_RELEASE_RESET();
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
  }
}

7. PA11的按鈕也采用中斷方式檢測,主程序只檢測標識做串口發送

有了PA12的經驗,修改PA11按鈕的檢測方式也比較容易。(假設PA11沒有抖動問題)

首先,需要在初始化PA11的時候,將其設置為中斷觸發,我設置的是下降沿觸發。

  GPIO_InitStruct.Pin = GPIO_PIN_11;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

而后,在中斷處理函數內添加對PA11的處理。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    if (GPIO_Pin == GPIO_PIN_12){
        PA12flag = 1;
        PA12count ++;
    }else if(GPIO_Pin == GPIO_PIN_11){
        PA11flag = 1;
    }else{
        UNUSED(GPIO_Pin);
    }
}

void EXTI15_10_IRQHandler(void){
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
}

最后,只需要在主循環中對PA11flag進行檢測即可。

        if (PA11flag == 1){
            PA11flag = 0;
            dispMode = 1 - dispMode;
        }

當然,由于PA11flag只是涉及到狀態的改變,可以直接在中斷觸發函數中進行模式的切換。

參考資料:

下載鏈接

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,732評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,214評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,781評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,588評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,315評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,699評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,698評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,882評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,441評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,189評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,388評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,933評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,613評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,023評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,310評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,112評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,334評論 2 377

推薦閱讀更多精彩內容