一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

手把手教你打造最簡(jiǎn)STM32F0 USB開(kāi)發(fā)板

 知芯世界 2023-07-17 發(fā)布于黑龍江
想學(xué)STM32,不知道從哪開(kāi)始的有木有?想學(xué)ARM單片機(jī),嫌買開(kāi)發(fā)板、調(diào)試器費(fèi)錢(qián)的有木有?買了STM32開(kāi)發(fā)板沒(méi)有資料不會(huì)玩,放在那里吃灰的有木有?買了開(kāi)發(fā)板,照著例子跑通了幾個(gè)程序,依然一頭霧水的有木有? 
我是個(gè)非常摳門(mén)的人,搞DIY也省得很——一切從簡(jiǎn)。(太復(fù)雜了的搞不定,軟件硬件都是如此) 所以正在玩的STM32也簡(jiǎn)化到底了,有興趣的看看吧。
?這是剛完成的STM32F072 USB開(kāi)發(fā)板,使用48腳LQFP的STM32F072C8T6,也可以使用其它封裝兼容的帶USB型號(hào),甚至是M3系的STM32F103C8T6這種。上半年從論壇買了塊STM32F091 Nucleo, 但是不帶USB,所以為了學(xué)習(xí)USB自己做一塊咯。下面是電?路圖,除了一片1117 3.3V LDO,外圍器件少到極致了吧,晶振不用的話是可以不裝的。板子可以直接通過(guò) USB mini口供電。外圍引出的插針有一路 SPI, 一路 I2S, 一路 UART, 一路 I2C, 一路 8-bit GPIO, 一路 UART/I2C共用,以及幾個(gè)零星的GPIO。這些已方便開(kāi)發(fā)簡(jiǎn)單的USB設(shè)備了。
 
?PCB layout 示意圖
 
 
 
??好,STM32F072 10塊錢(qián)以內(nèi)就可以搞定,整個(gè)開(kāi)發(fā)板成本很低了吧。如果你有ST-Link, 或者是帶有ST-Link的STM32 Discovery/Nucleo開(kāi)發(fā)板,用SWD調(diào)試線連上就可以下載程序了。如果沒(méi)有ST-Link, 還可以從串口下載程序,只需要把BOOT0跳線接上即可,因?yàn)镾TM32內(nèi)帶了Bootloader.  如果連串口線都沒(méi)有?呵呵,要是像F072這樣帶USB的,還可以從USB直接下載,別的硬件也省了,怎么樣,夠簡(jiǎn)吧?
OK,來(lái)寫(xiě)第一個(gè)測(cè)試程序:定時(shí)控制LED閃爍。
  1. #include "stm32f0xx.h"

  2. int main(void)

  3. {

  4.     RCC->AHBENR |= RCC_AHBENR_GPIOAEN;  // enable GPIO port A & B clock

  5.     GPIOA->MODER = GPIO_MODER_MODER8_0; // PA8 as general output (LED)

  6.     RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;     // enable basic timer 6

  7.     TIM6->PSC = 9999;       // prescaler

  8.     TIM6->ARR = 399;        // auto reload value

  9.     TIM6->CR1 = TIM_CR1_URS|TIM_CR1_CEN;    // start counter

  10.     while(1)

  11.     {

  12.         static char a=0;

  13.         if(TIM6->SR & TIM_SR_UIF)   // check if overflow

  14.         {

  15.             TIM6->SR &= ~TIM_SR_UIF;    // clear flag

  16.             if(a==0)

  17.             {

  18.                 GPIOA->BSRR = (1<<8);

  19.                 a=1;

  20.             }

  21.             else

  22.             {

  23.                 GPIOA->BRR = (1<<8);

  24.                 a=0;

  25.             }

  26.         }

  27.     }

  28. }

上面這個(gè)程序所做的事情,先是初始化GPIO, 設(shè)置PA8為輸出口(板子上連了一個(gè)LED),然后是設(shè)置定時(shí)器Timer 6, 這是一個(gè)自動(dòng)重裝的計(jì)數(shù)器,我把它調(diào)到0.5秒中溢出一次。在下面的循環(huán)里面,就是檢測(cè)溢出標(biāo)志,然后切換LED的亮和滅狀態(tài)。學(xué)過(guò)C語(yǔ)言的,都應(yīng)該看得懂;至于RCC, GPIOA, TIM6 這幾個(gè)結(jié)構(gòu)指針的定義,都在#include的頭文件里面,這是和硬件相關(guān)的,具體請(qǐng)查閱"RM0091 STM32F0x1/STM32F0x2/STM32F0x8 Reference Manual"編程手冊(cè)。
如何編譯上面這個(gè) C 程序,且聽(tīng)下回分解。這里暫且假定編譯成功了,得到一個(gè) HEX 文件,也就是要燒寫(xiě)的二進(jìn)制代碼。
如果你是使用KEIL, IAR等集成開(kāi)發(fā)環(huán)境,那么用自帶的燒寫(xiě)工具就可以進(jìn)行寫(xiě)入了。如果是像我cruelfox這樣追求精簡(jiǎn),僅使用GCC命令行工具的,就需要再找下載程序用的軟件了。
如果是使用ST-Link,可以使用ST自己的STVP (Visual Programmer),這個(gè)東東在ST網(wǎng)站上可以下載到,不過(guò)是包含在九十兆左右的一個(gè)大包"ST Toolset"里面。(下載URL http://www./web/catalog/tools/FM147/CL1794/SC961/SS1533/PF210568 )這個(gè)軟件的界面是這個(gè)樣子的:
 
主菜單上面 Erase, Program, Verify, Read 功能很明了了,F(xiàn)ile-->Open可以加載HEX文件。第一次運(yùn)行STVP的時(shí)候,要選擇ST-LINK調(diào)試器,和 SWD接口。
如果沒(méi)有ST-Link, 使用串口下載的話,需要"Flash Loader Demostrator"軟件,這個(gè)也可以從ST網(wǎng)站直接下載(URL http://www./st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/demo_and_example/stsw-mcu005.zip)。下載前要把BOOT0跳線接上,使STM32進(jìn)入Bootloader模式,USART1連接到PC的串口(我用的是FT232RL USB轉(zhuǎn)串口),把MCU加電。運(yùn)行軟件,界面是這樣的:
 
選擇串口,然后點(diǎn)"Next",如果成功連上了,則界面變成下面這樣
 
點(diǎn)"Next"繼續(xù)
 
這時(shí)已顯示出識(shí)別出的STM32型號(hào),點(diǎn)"Next"到下一步進(jìn)行具體的操作。
 
OK, 下載HEX,擦除,上載(讀Flash內(nèi)容) 功能都一看就明白了吧。
第三種下載方式,從USB,需要ST的"DFUSe Demo"軟件,也是從ST網(wǎng)站下載的(URL http://www./st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/demo_and_example/stsw-stm32080.zip)。也需要把BOOT0跳線接上,還必須連接USB口,然后PC提示找到了新硬件。安裝好驅(qū)動(dòng)以后,再啟動(dòng)軟件,界面如下:
 
不過(guò)現(xiàn)在不能把HEX文件直接寫(xiě)入,而需要先生成dfu文件,使用一起安裝得到的"DFU File Manager"程序,從HEX生成dfu.
 
至于 VID, PID 我還是保留和原來(lái)的一致,不然得重新安裝驅(qū)動(dòng)(為什么要使用DFU文件我還沒(méi)理解清楚)。得到dfu文件就可以用上面的軟件燒寫(xiě)了。
怎么樣,我的開(kāi)發(fā)板夠精簡(jiǎn)吧?
STM32F0xx 系列是ARM Cortex-M0架構(gòu),地址空間32位,也就是4G Bytes的訪問(wèn)范圍。數(shù)據(jù)和代碼使用同一編址,下圖是地址空間的布局:
 

實(shí)際上單片機(jī)用到的資源很少,地址空間大部分都沒(méi)有內(nèi)容。我使用的STM32F072C8T6帶有64kB的Flash ROM, 16kB的SRAM,起始分別是 0x08000000 和 0x20000000. (由于有硬件映射功能,在0x00000000也就是最低地址,還可以訪問(wèn)ROM或者RAM的內(nèi)容). 單片機(jī)片上外設(shè)的寄存器,則分布在更高的地址空間。讀寫(xiě)這些寄存器,在CPU看來(lái)和讀寫(xiě)內(nèi)存(RAM)操作是一樣的。
所以,C語(yǔ)言訪問(wèn)設(shè)備寄存器,和訪問(wèn)內(nèi)存中的一個(gè)變量一樣。只要知道寄存器的地址,通過(guò)一個(gè)指針訪問(wèn)就可以實(shí)現(xiàn)讀寫(xiě)。上一貼子我的程序中引用了 RCC, GPIOA, TIM6 這三個(gè)(結(jié)構(gòu))指針,它們的值(也就是地址)以及類型(代表訪問(wèn)的內(nèi)容)定義在 stm32f0xx.h 這個(gè)頭文件中。因?yàn)樵O(shè)備寄存器太多了哇,如果每一個(gè)都定義一個(gè)指針就太煩瑣了,所以把按功能劃分定義成組,每組用一個(gè)C語(yǔ)言的結(jié)構(gòu)類型表示,寫(xiě)起來(lái)也更清晰。而寄存器里面的位描述也可以定義成一些宏,在讀程序的時(shí)候就知道是什么意思了。如果有興趣,可以把 stm32f0xx.h 文件和STM32F0的手冊(cè)對(duì)照著閱讀。
好,假設(shè)已經(jīng)熟悉寄存器操作了,知道怎么配置寄存器實(shí)現(xiàn)想要的功能,那么就可以寫(xiě)C程序讓STM32工作了?,F(xiàn)在需要一個(gè)工具來(lái)將C程序翻譯成機(jī)器代碼——編譯器,或者是叫做工具鏈(Tool chain)。Keil MDK-ARM 或者 IAR-EWARM 開(kāi)發(fā)環(huán)境都帶有各自的編譯器,不過(guò)我更偏向于用開(kāi)源的GCC-ARM. 在launchpad.net上可以下載到編譯好的arm-gcc工具鏈zip包,將它解壓縮,加到PATH里面就可以直接用了,很方便(很精簡(jiǎn)吧)。
OK,現(xiàn)在來(lái)編譯上面那個(gè)mini.c文件,命令行:
arm-none-eabi-gcc -c -Os -mcpu=cortex-m0 -mthumb mini.c
gcc的參數(shù) -c 是表示僅編譯,-Os 是優(yōu)化代碼大小,-mcpu=cortex-m0 -mthumb 是指定指令集的,因?yàn)锳RM有不同的版本。對(duì)了,include的頭文件還沒(méi)弄到呢。要編譯通過(guò)需要把 stm32f0xx.h 這個(gè)文件找來(lái)。我的建議是下載ST提供的 "STM32F0x2 USB FS Device Library" 程序庫(kù)(URL http://www./st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/firmware/stsw-stm32092.zip),把里面需要的頭文件等等扒出來(lái)。在 stm32f0xx.h 中還包含了另外幾個(gè)頭文件,一并弄出來(lái)放到工程目錄下。
如果編譯成功,將得到 mini.o 目標(biāo)文件??梢杂?/span> arm-none-eabi-objdump -S mini.o 反匯編看看翻譯成什么代碼了。
  1. E:\arm\test072\mini>arm-none-eabi-objdump -S mini.o

  2. mini.o:     file format elf32-littlearm

  3. Disassembly of section .text.startup:

  4. 00000000 <main>:

  5.    0:   4b16            ldr     r3, [pc, #88]   ; (5c <main+0x5c>)

  6.    2:   2280            movs    r2, #128        ; 0x80

  7.    4:   6959            ldr     r1, [r3, #20]

  8.    6:   0292            lsls    r2, r2, #10

  9.    8:   430a            orrs    r2, r1

  10.    a:   b510            push    {r4, lr}

  11.    c:   2180            movs    r1, #128        ; 0x80

  12.    e:   615a            str     r2, [r3, #20]

  13.   24:   851a            strh    r2, [r3, #40]   ; 0x28

  14.   26:   2290            movs    r2, #144        ; 0x90

  15.   28:   32ff            adds    r2, #255        ; 0xff

  16.   2a:   62da            str     r2, [r3, #44]   ; 0x2c

  17. 完整代碼請(qǐng)點(diǎn)擊閱讀原文

  18.   50:   6184            str     r4, [r0, #24]

  19.   52:   1c0a            adds    r2, r1, #0

  20.   54:   e7ee            b.n     34 <main+0x34>

  21.   56:   8504            strh    r4, [r0, #40]   ; 0x28

  22.   58:   2200            movs    r2, #0

  23.   5a:   e7eb            b.n     34 <main+0x34>

  24.   5c:   40021000        .word   0x40021000

  25.   60:   40001000        .word   0x40001000

  26.   64:   0000270f        .word   0x0000270f

  27.   68:   00000000        .word   0x00000000


如上,其實(shí)里面就一個(gè)main函數(shù)。但是 main 的入口地址還沒(méi)有確定,而且它還使用了一個(gè)static型的內(nèi)存變量,地址也還沒(méi)有確定。可以用 arm-none-eabi-nm mini.o 來(lái)查看模塊里面的全局符號(hào)表:
  1. E:\arm\test072\mini>arm-none-eabi-nm mini.o

  2. 00000000 b a.4686

  3. 00000000 T main

那么,怎么讓程序放到ROM中合適的地址,并運(yùn)行呢?如果熟悉C語(yǔ)言編程就知道還有一步——鏈接,才能確定符號(hào)的地址。但是,到目前為止我們還沒(méi)有告訴GCC地址的布局,也就是RAM從哪里開(kāi)始,代碼放在哪里。因?yàn)锳RM的器件很多,這并不是統(tǒng)一的,所以需要提供一些信息給鏈接程序。具體地,需要一個(gè)Linker Script, 可以從軟件包中找到 STM32F072C8_FLASH.ld (或者用近似的來(lái)修改得到)
  1. /*

  2. *****************************************************************************

  3. **  File        : stm32_flash.ld

  4. *****************************************************************************

  5. */

  6. /* Entry Point */

  7. ENTRY(Reset_Handler)

  8. /* Highest address of the user mode stack */

  9. _estack = 0x20003FFF;    /* end of RAM */

  10. 完整代碼請(qǐng)點(diǎn)擊閱讀原文

  11.   /DISCARD/ :

  12.   {

  13.     libc.a ( * )

  14.     libm.a ( * )

  15.     libgcc.a ( * )

  16.   }

  17.   .ARM.attributes 0 : { *(.ARM.attributes) }

  18. }


OK,下面就是鏈接了,使用命令 arm-none-eabi-ld mini.o -Le:\arm-2014q3\arm-none-eabi\lib\armv6-m -Le:\arm-2014q3\lib\gcc\arm-none-eabi\4.8.4\armv6-m -T STM32F072C8_FLASH.ld -o mini.elf
這里面 -L 參數(shù)是添加標(biāo)準(zhǔn)庫(kù)文件的搜索路徑,雖然暫時(shí)并沒(méi)有用到C標(biāo)準(zhǔn)庫(kù)里面的東西,但是Linker Script里面引用了標(biāo)準(zhǔn)庫(kù)文件。-o 指定輸出的目標(biāo)文件。這么就快要得到最終的機(jī)器碼了,不過(guò)好象還缺少了什么……
arm-none-eabi-ld: warning: cannot find entry symbol Reset_Handler; defaulting to  08000000
linker給了一個(gè)警告:找不到入口地址 Reset_Handler 的值,設(shè)成了默認(rèn) 0x08000000. 下面再用objdump -S反匯編看一下
  1. E:\arm\test072\mini>arm-none-eabi-objdump -S mini.elf

  2. mini.elf:     file format elf32-littlearm

  3. Disassembly of section .text:

  4. 08000000 <main>:

  5. 8000000:       4b16            ldr     r3, [pc, #88]   ; (800005c <main+0x5c>)

  6. 8000002:       2280            movs    r2, #128        ; 0x80

  7. 8000004:       6959            ldr     r1, [r3, #20]

  8. 8000006:       0292            lsls    r2, r2, #10

  9. 8000008:       430a            orrs    r2, r1

  10. 800000a:       b510            push    {r4, lr}

  11. 完整代碼請(qǐng)點(diǎn)擊閱讀原文

  12. 8000050:       6184            str     r4, [r0, #24]

  13. 8000052:       1c0a            adds    r2, r1, #0

  14. 8000054:       e7ee            b.n     8000034 <main+0x34>

  15. 8000056:       8504            strh    r4, [r0, #40]   ; 0x28

  16. 8000058:       2200            movs    r2, #0

  17. 800005a:       e7eb            b.n     8000034 <main+0x34>

  18. 800005c:       40021000        .word   0x40021000

  19. 8000060:       40001000        .word   0x40001000

  20. 8000064:       0000270f        .word   0x0000270f

  21. 8000068:       20000000        .word   0x20000000


現(xiàn)在 main() 被放到ROM最開(kāi)始去了,這好象是對(duì)的?如果了解ARM Cortex-M0下就知道這樣錯(cuò)了,因?yàn)?/span>最開(kāi)始應(yīng)該是中斷向量表。我們還沒(méi)有編寫(xiě)Linker Script中的 .isr_vectors 段的內(nèi)容。而且,一上來(lái)初始化堆棧指針等工作都沒(méi)有做就直接運(yùn)行 main() 了也不合適吧?還缺少了初始化代碼。
在軟件包中搜刮一個(gè) startup_stm32f072.s 匯編文件
  1. /**

  2.   ******************************************************************************

  3.   * @file      startup_stm32f072.s

  4.   * @author    MCD Application Team

  5.   ******************************************************************************

  6.   */

  7.   .syntax unified

  8.   .cpu cortex-m0

  9.   .fpu softvfp

  10.   .thumb

  11. .global g_pfnVectors

  12. .global Default_Handler

  13. 完整代碼請(qǐng)點(diǎn)擊閱讀原文

  14.   .weak USART2_IRQHandler

  15.   .thumb_set USART2_IRQHandler,Default_Handler

  16.   .weak USART3_4_IRQHandler

  17.   .thumb_set USART3_4_IRQHandler,Default_Handler

  18.   .weak CEC_CAN_IRQHandler

  19.   .thumb_set CEC_CAN_IRQHandler,Default_Handler

  20.   .weak USB_IRQHandler

  21.   .thumb_set USB_IRQHandler,Default_Handler

  22. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


原來(lái)是這樣,中斷向量表在這里進(jìn)行了描述,還有設(shè)置堆棧,初始化全局變量的代碼,然后跳轉(zhuǎn)到 main 執(zhí)行。好了,這樣就該差不多了。這個(gè)匯編程序是GNU AS的語(yǔ)法,可以用 arm-none-eabi-gcc 來(lái)直接匯編
arm-none-eabi-gcc -c startup_stm32f072.s
鏈接兩個(gè)目標(biāo)模塊
arm-none-eabi-ld mini.o startup_stm32f072.o -Le:\arm-2014q3\arm-none-eabi\lib\armv6-m -Le:\arm-2014q3\lib\gcc\arm-none-eabi\4.8.4\armv6-m -T STM32F072C8_FLASH.ld -o mini.elf
最后轉(zhuǎn)換出一個(gè) HEX 文件
arm-none-eabi-objcopy -Oihex mini.elf mini.hex
可以進(jìn)行燒寫(xiě)了。
我這個(gè)是最簡(jiǎn)化的例子,使用最簡(jiǎn)化的軟件工具,不過(guò)已經(jīng)包含了基本的C語(yǔ)言框架。
第一個(gè)USB工程例子:USB存儲(chǔ)盤(pán)。因?yàn)槭诌厸](méi)有SPI或I2C接口的Flash, 就權(quán)且用單片機(jī)的RAM虛擬一下吧。這個(gè)"U盤(pán)"容量標(biāo)成160kB, 實(shí)際上有效的存儲(chǔ)只有10kB,用一點(diǎn)扇區(qū)映射的技巧騙過(guò)操作系統(tǒng),當(dāng)然存放文件只能幾kB了。

ST官方提供了一個(gè) STM32F0 的USB固件庫(kù),(
URL http://www./st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/firmware/stsw-stm32092.zip),包括了硬件庫(kù)、核心庫(kù)和類庫(kù)的C頭文件和源文件。我cruelfox琢磨了一整天,還是沒(méi)搞清楚怎么調(diào)用這些函數(shù),只好照著個(gè)Example改吧。

于是就用MassStorage類的例子來(lái)下手了,這個(gè)目錄里面的主文件 app.c 非常簡(jiǎn)單
  1. /**

  2.   * @file    app.c

  3.   */ 

  4. /* Includes ------------------------------------------------------------------*/ 

  5. #include  "usbd_msc_core.h"

  6. #include  "usbd_usr.h"

  7. USB_CORE_HANDLE  USB_Device_dev ;

  8. int main(void)

  9. {

  10.   USBD_Init(&USB_Device_dev,

  11.             &USR_desc, 

  12.             &USBD_MSC_cb, 

  13.             &USR_cb);

  14.   while (1)

  15.   {

  16.   }


  17. #ifdef USE_FULL_ASSERT

  18. void assert_failed(uint8_t* file, uint32_t line)

  19. {

  20.   while (1)

  21.   {}

  22. }

  23. #endif

一切USB相關(guān)的東西都在 USBD_init() 這個(gè)函數(shù)里面了。追查源代碼,可以發(fā)現(xiàn)這個(gè)函數(shù)調(diào)用其實(shí)是向庫(kù)函數(shù)提供了一堆回調(diào)函數(shù)的接口,也就是說(shuō)寫(xiě)一些子程序,讓驅(qū)動(dòng)程序在需要的時(shí)候調(diào)用。這樣開(kāi)發(fā)USB的我們就不用去管中斷什么的了,要做的就是實(shí)現(xiàn)各種USB的請(qǐng)求——其實(shí)程序庫(kù)里面已經(jīng)把大部分的請(qǐng)求應(yīng)答都實(shí)現(xiàn)了,而具體的類庫(kù)(比如我這里用的MassStorage類)又處理了剩余的大部分,所以只剩下功能性的需要自己寫(xiě)。
在 usbd_desc.c 這個(gè)程序里面可以看到描述符是怎么創(chuàng)建和返回的
  1. /**

  2.   ******************************************************************************

  3.   * @file    usbd_desc.c

  4.   * @author  MCD Application Team

  5.   * @version V1.0.0

  6.   * @date    31-January-2014

  7.   * @brief   This file provides the USBD descriptors and string formating method.

  8.   ******************************************************************************

  9.   * @attention

  10.   *

  11.   * <h2><center>? COPYRIGHT 2014 STMicroelectronics</center></h2>

  12.   *

  13.   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");

  14.   * You may not use this file except in compliance with the License.

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    午夜日韩在线观看视频| 国产精品超碰在线观看| 久久精品国产亚洲av麻豆| 开心久久综合激情五月天| 国产精品九九九一区二区| 成年人免费看国产视频| 年轻女房东2中文字幕| 亚洲av秘片一区二区三区| 亚洲伦理中文字幕在线观看| 精品国产亚洲一区二区三区| 亚洲一区二区三区三州| 九九热这里只有免费精品| 欧美韩日在线观看一区 | 国产原创中文av在线播放 | 日韩色婷婷综合在线观看| 国产专区亚洲专区久久| 国产精品熟女乱色一区二区 | 日本午夜免费福利视频| 久久99热成人网不卡| 国产精品一区二区有码| 91日韩在线观看你懂的| 国产毛片不卡视频在线| 又黄又爽禁片视频在线观看| 亚洲一区二区三区日韩91| 五月天婷亚洲天婷综合网| 东京热加勒比一区二区三区| 久久精品国产在热久久| 精品精品国产自在久久高清| 日韩美女偷拍视频久久| 欧美日韩国产的另类视频| 国内胖女人做爰视频有没有| 国产欧美日韩一级小黄片| 好吊日在线视频免费观看| 久久精品国产第一区二区三区| 冬爱琴音一区二区中文字幕| 白白操白白在线免费观看| 国产又黄又爽又粗视频在线| 99久久精品免费精品国产| 午夜国产成人福利视频| 日本一品道在线免费观看| 91老熟妇嗷嗷叫太91|